diff --git a/rootfs/usr/share/d3m0n/src/Makefile b/rootfs/usr/share/d3m0n/src/Makefile deleted file mode 100644 index 4bc5ccbc..00000000 --- a/rootfs/usr/share/d3m0n/src/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -SRC=*.cpp lib/*.c -OUT=d3m0n -CFLAGS:=-std=c++17 -lstdc++ -lstdc++fs -lm -DBCM -lglfw -lGL -lGLEW -lGLU -lOpenGL -LDFLAGS=-Llib -Ilib -I. -# CFLAGS= -lm -DBCM -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -WARNINGS_IGNORE=-Wno-all -Wno-unused-result -Wno-unused-parameter -Wno-unused-variable -Wno-format-security -Wno-write-strings -GCC=g++ -LIBS:=-I/usr/include/opencv4 -lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_line_descriptor -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_shape -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_highgui -lopencv_datasets -lopencv_text -lopencv_plot -lopencv_ml -lopencv_videostab -lopencv_videoio -lopencv_viz -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core -# $(shell pkg-config --cflags --libs opencv4) - - -all: $(OUT) - -$(OUT): $(SRC) - $(GCC) $(LDFLAGS) $(WARNINGS_IGNORE) -o $@ $? $(LIBS) $(CFLAGS) - -debug: - gdb $(OUT) - -clean: - $(RM) $(OUT) - diff --git a/rootfs/usr/share/d3m0n/src/README.md b/rootfs/usr/share/d3m0n/src/README.md deleted file mode 100644 index fd81ea94..00000000 --- a/rootfs/usr/share/d3m0n/src/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# d3m0n C main software - -## Startup steps -for each .d3m0n file in `/usr/share/d3m0n` and subfolder, unzip it into /usr/share/d3m0n/temp/RANDOM_TOKEN - -[example .d3m0n app](https://github.com/d3m0n-project/d3m0n_os/tree/main/rootfs/usr/share/d3m0n/apps/test_app/source) - -## App handler -Phone loads apps from temp directory created when startup, - -then reads manifest file located at `/usr/share/d3m0n/temp/APP_TOKEN/app` -- Gets app name, description, category, icon (format "key: value") -then reads main layout file (.layout) in `/usr/share/d3m0n/temp/APP_TOKEN/layouts/main.layout` (example [here](https://github.com/d3m0n-project/d3m0n_os/blob/main/rootfs/usr/share/d3m0n/apps/test_app/source/layouts/main.layout)) - -then execute code (.src) in `/usr/share/d3m0n/temp/APP_TOKEN/src/main.src` (example [here](https://github.com/d3m0n-project/d3m0n_os/blob/main/rootfs/usr/share/d3m0n/apps/test_app/source/src/main.src)) \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/Type.h b/rootfs/usr/share/d3m0n/src/Type.h deleted file mode 100644 index f32ae2e5..00000000 --- a/rootfs/usr/share/d3m0n/src/Type.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef CTRL_TYPE -#define CTRL_TYPE -#include -#include -#include -#include -#include -#include -#include -using namespace std; - - -namespace DataTypes -{ - struct Rect { - int X; - int Y; - int X2; - int Y2; - - Rect() { - this->X = 0; - this->Y = 0; - this->X2 = 0; - this->Y2 = 0; - } - - Rect(int x, int y, int x2, int y2) { - this->X = x; - this->Y = y; - this->X2 = x2; - this->Y2 = y2; - } - }; - - struct Point { - int X; - int Y; - Point(int x, int y) { - this->X = x; - this->Y = y; - } - Point() : X(0), Y(0) {} - - Point operator+(int x){ - return Point(this->X + x, this->Y + x); - } - }; - struct Size { - int Width; - int Height; - Size(int x, int y) { - this->Width = x; - this->Height = y; - } - Size() : Width(0), Height(0) {} - }; - struct Control { - // display* display1; - string name; - DataTypes::Point Location = DataTypes::Point(0, 0); - DataTypes::Size size = DataTypes::Size(100, 50); - bool Visible=true; - bool Enabled=true; - ushort BackColor = 0x0000; - ushort ForeColor = 0xffff; - - Control() {} - - virtual void draw() {}; // Draws the control on screen. - - Rect getRect() - { - int x1 = 240-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - x1-=this->size.Width; - x2-=this->size.Width; - - return Rect(x2, y1, x1, y2); - } - }; - struct Window { - DataTypes::Size size; - ushort BackColor = 0x0000; - ushort ForeColor = 0xffff; - - vector Controls; - - void Add(Control* ctrl) { - Controls.push_back(ctrl); - } - - void Update() { - printf("Updating window\n"); - // lcdFillScreen(BackColor); - size_t size = Controls.size(); - printf("Size of Window's Controls vector: %zu\n", size); - - for (Control* control : Controls) { - if(control != nullptr) { - printf(("name: "+control->name+"\n").c_str()); - printf(("X: "+to_string(control->Location.X)+"\n").c_str()); - printf(("Y: "+to_string(control->Location.Y)+"\n").c_str()); - printf(("Width: "+to_string(control->size.Width)+"\n").c_str()); - printf(("Height: "+to_string(control->size.Height)+"\n").c_str()); - - - control->draw(); - } - } - } - - }; - - struct BitmapPoint { - int x; - int y; - ushort color; - }; - struct Bitmap { - vector points; - DataTypes::Size size; - }; -}; -#endif \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/appManager.cpp b/rootfs/usr/share/d3m0n/src/application/appManager.cpp deleted file mode 100644 index eb393c10..00000000 --- a/rootfs/usr/share/d3m0n/src/application/appManager.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include "../settings.h" -#include -#include "layout/layoutHandler.cpp" -#include "source/sourceHandler.cpp" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -namespace fs = filesystem; -using namespace std; - -class appManager { -public: - vector appsPaths; - vector appsPackages; - - void unzipFile(string path, string output) - { - string command = (string)"unzip '"+path+(string)"' -d '"+output+(string)"' > /dev/null"; - system(command.c_str()); - } - - - Application loadApp(char* appPath) - { - // loads app by unziping appPath file into /usr/share/d3m0n/temp/RANDOM_TOKEN - - const char* directory = GetPath().c_str(); // Directory to search .d3m0n files in - // long randomToken = rand(); // Simple random token, consider a better random generation method - random_device rd; - mt19937 gen(rd()); // Mersenne Twister pseudo-random number generator - - // Define a distribution (e.g., uniform distribution between 0 and 99) - uniform_int_distribution dis(0, 1316134911); - - long randomToken = dis(gen); - - - char temp_path[256]; - snprintf(temp_path, sizeof(temp_path), (GetPath()+(string)"/temp/%lu").c_str(), randomToken); - - log((string)"Unpacking '"+appPath+(string)"' ==> '"+temp_path+(string)"'", LogStatus::Info); - - if(!filesystem::exists(appPath)) - { - log("Application not found.", LogStatus::Error); - return Application{}; - } - - - // Create the output directory - mkdir(temp_path, 0777); // Note: Check return value in real code for errors - - unzipFile(appPath, temp_path); - - // TODO: add unzip - // for (const auto & entry : fs::directory_iterator(directory)) { - - // string test = (string)entry.path(); - // printf(test.c_str()); - // } - - - - Application newApp; - //logn((string)temp_path, ConsoleColor::Red); - string path2 = (string)temp_path+(string)"/app"; - char* path = new char[path2.length() + 1]; - strcpy(path, path2.c_str()); - - - string package = (string)getSetting("package", path); - - - // adds app to list of apps - appsPaths.push_back(temp_path); - appsPackages.push_back(package); - - - - - newApp.name = (string)getSetting("name", path); - newApp.description = (string)getSetting("description", path); - newApp.package = package; - newApp.icon = (string)getSetting("icon", path); - newApp.perms = (string)getSetting("perms", path); - newApp.start_path = (string)getSetting("start_path", path); - newApp.category = (string)getSetting("category", path); - newApp.temp_path = (string)temp_path; - - return newApp; - } - string GetAppPathByPackage(string package) { - int i=0; - for (const string& str : appsPackages) { - if(str == package) { - return appsPaths.at(i); - } - i++; - } - return "not found"; - } - void runApp(display* display1, Application* app) - { - // runs app from Application struct. Gets path, runs /layout/main.layout then /src/main.src - - if(fs::exists((app->temp_path+(string)"/layouts/main.layout").c_str())) { - log("Main layout found, Running...", LogStatus::Success); - log((string)" Name => '"+app->name+(string)"'", LogStatus::Info); - log((string)" Desc => '"+app->description+(string)"'", LogStatus::Info); - log((string)" Icon => '"+app->icon+(string)"'", LogStatus::Info); - log((string)" Package => '"+app->package+(string)"'", LogStatus::Info); - log((string)" Perms => '"+app->perms+(string)"'", LogStatus::Info); - log((string)" Category => '"+app->category+(string)"'", LogStatus::Info); - log((string)" Path => '"+app->temp_path+(string)"'", LogStatus::Info); - log((string)" Start => '"+app->start_path+(string)"'", LogStatus::Info); - logn("", ConsoleColor::Reset); - } else { - log("main.layout not found for app '"+app->name+"'/'"+app->package+"'", LogStatus::Error); - return; - } - - // init Window - DataTypes::Window* window = new Window(); - window->size = DataTypes::Size(240, 320); - app->mainWindow = window; - app->windows.push_back(window); - - // starts displaying app - layoutHandler::runLayout(display1, app, app->temp_path+(string)"/layouts/main.layout"); - sourceHandler::runSource(display1, app, app->temp_path+(string)"/src/main.src"); - - - } - string GetAppList() { - string to_return=""; - to_return+=logn("Current loaded apps", ConsoleColor::Blue); - int i=0; - for (const string& package : appsPackages) { - string appFile = appsPaths.at(i)+"/app"; - to_return+=logn(" => "+(string)(getSetting("name", appFile.data()))+", package: "+package, ConsoleColor::Blue); - i++; - } - return to_return; - - } - void launchApp(Application* app) { - log("CLICKED !!! "+app->name, LogStatus::Critical); - } - - void mainScreenInit(display* display1) { - printf("\n"); - - // init main desktop screen - string wallpaper = GetPath()+"/wallpapers/"+getSetting("wallpaper", (char*)GetConfig())+".png"; - display1->drawImage(DataTypes::Point(0, 0), wallpaper, SCREEN_WIDTH, SCREEN_HEIGHT, false); - log("DESKTOP initiated wallpaper => '"+wallpaper+"'", LogStatus::Success); - - logn("Loaded applications: ", ConsoleColor::Cyan); - - int app_count=0; - Application temp; - string appicon; - int slot_x, slot_y = 0; - int app_padding = 10; - int appPerRow = 2; - int appPerColumn = 4; - int icon_size = SCREEN_WIDTH/appPerRow-20; - - slot_x = 0; - - for (const auto & entry : fs::directory_iterator(GetAppPath())) { - if(endsWith(entry.path(), ".d3m0n")) { - if(slot_x >= appPerRow) { - slot_y++; - slot_x=0; - } - - - logn(" => "+(string)entry.path(), ConsoleColor::Cyan); - printf(" "); - temp = loadApp(((string)entry.path()).data()); - logn(" x: "+to_string(slot_x)+", y: "+to_string(slot_y), ConsoleColor::Grey); - - if(contains(temp.icon, "/")) { - appicon=temp.icon; - } else { - appicon=display1->GetThemeIcon(temp.icon); - } - - - DataTypes::Point appRect = DataTypes::Point(slot_x*(icon_size+app_padding)+20, slot_y*(icon_size+app_padding)); - - // display1->drawRect(appRect.X, appRect.Y, appRect.X+icon_size+10, appRect.Y+icon_size+10, Colors::Cyan, true); - display1->drawImage(appRect+10, appicon, icon_size-20, icon_size-20, false); - display1->drawText(20+slot_x*(icon_size+app_padding), slot_y*(icon_size+app_padding)+icon_size-8, 1, temp.name, false, Colors::White); - - display1->registerEvent(Event::OnClick, DataTypes::Rect(appRect.X, appRect.Y, appRect.X+icon_size, appRect.Y+icon_size+20), [this](Application* app) { this->launchApp(app); }, &temp); - - slot_x++; - } - } - - - printf("\n"); - } -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls.cpp deleted file mode 100644 index ca22be49..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "./Controls/GeneralAttributes.cpp" -#include "./Controls/Window.cpp" -#include "./Controls/Text.cpp" -#include "./Controls/Image.cpp" -#include "./Controls/TextBox.cpp" -#include "./Controls/Button.cpp" -#include "./Controls/Rect.cpp" - -namespace Controls { - const int Window = 0; - const int Text = 1; - const int RawHtml = 2; - const int TextBox = 3; - const int ListView = 4; - const int ProgressBar = 5; - const int CheckBox = 6; - const int RadioButton = 7; - const int Rect = 8; - const int Switch = 9; - const int Image = 10; - const int Button = 11; - const int Vscroll = 12; - const int Hscroll = 13; - const int RoundButton = 14; -} -template -void parseAttributes(T* ctrl, string controlAttributes, void (&function)(T* ctrl2, string key2, string value2)) { - istringstream iss(controlAttributes); - string token; - string token2; - - // extract attributes from the attribute string - bool FirstLine = true; - while (getline(iss, token, ';')) { - // create pairs of key=value - istringstream line(token); - - string Key; - while (getline(line, token2, '=')) { - if(FirstLine) { - Key = delete_space(token2.c_str()); - } - else - { - function(ctrl, Key, token2); - // cout << " Value: " << token2 << endl; - } - FirstLine=!FirstLine; - } - - } -} - -Control* loadControl(display* display1, string controlName, string controlAttributes) { - Control* controlElement = nullptr; - - if(controlName == "Window") { - layout::Window(display1, controlName, controlAttributes); - } - else if(controlName=="Text") { - layout::Text* temp = new layout::Text(controlAttributes.c_str()); - temp->display1 = display1; - controlElement = temp->Get(); - parseAttributes(temp, controlAttributes, layout::Text::parseAttributes); - } - // else if(controlName=="RawHtml") { - // return layout.RawHtml(controlAttributes); - // } - else if(controlName=="TextBox") { - layout::TextBox* temp = new layout::TextBox(controlAttributes.c_str()); - temp->display1 = display1; - controlElement = temp->Get(); - parseAttributes(temp, controlAttributes, layout::TextBox::parseAttributes); - } - // else if(controlName=="ListView") { - // return layout.ListView(controlAttributes, this, ctrl as ListView); - // } - // else if(controlName=="ProgressBar") { - // return layout.ProgressBar(controlAttributes, this, ctrl as ProgressBar); - // } - // else if(controlName=="CheckBox") { - // return layout.CheckBox(controlAttributes, this, ctrl as CheckBox); - // } - // else if(controlName=="RadioButton") { - // return layout.RadioButton(controlAttributes, this, ctrl as RadioButton); - // } - else if(controlName=="Rect") { - layout::Rect* temp = new layout::Rect(controlAttributes.c_str()); - temp->display1 = display1; - controlElement = temp->Get(); - parseAttributes(temp, controlAttributes, layout::Rect::parseAttributes); - } - // else if(controlName=="Switch") { - // return layout.Switch(controlAttributes, this, ctrl as CheckBox); - // } - else if(controlName=="Image") { - layout::Image* temp = new layout::Image(controlAttributes.c_str()); - temp->display1 = display1; - controlElement = temp->Get(); - parseAttributes(temp, controlAttributes, layout::Image::parseAttributes); - } - else if(controlName=="Button") { - layout::Button* temp = new layout::Button(controlAttributes.c_str()); - temp->display1 = display1; - controlElement = temp->Get(); - parseAttributes(temp, controlAttributes, layout::Button::parseAttributes); - } - // else if(controlName=="Vscroll") { - // return layout.Vscroll(controlAttributes, this, ctrl as Panel); - // } - // else if(controlName=="Hscroll") { - // return layout.Hscroll(controlAttributes, this, ctrl as Panel); - // } - // else if(controlName=="RoundButton") { - // return layout.RoundButton(controlAttributes, this, ctrl as RoundButton); - // } - return controlElement; -} \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Button.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/Button.cpp deleted file mode 100644 index 9a1cee0d..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Button.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; -using namespace DataTypes; - -namespace layout { -class Button : public Control { - public: - display* display1; - string text=""; - Bitmap image; - ushort BackColor = Colors::Black; - ushort ForeColor = Colors::White; - int FontSize = 10; - bool Center = false; - int FontPadding = 0; - DataTypes::Size defaultSize = DataTypes::Size(100, 50); - bool Bold = false; - - Control* Get() { - return this; - } - - void draw() override - { - - int x1 = 240-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - // check if size not changed - if(defaultSize.Width == this->size.Width && defaultSize.Height == this->size.Height) - { - // then define width with text size - this->size.Width = this->text.length()*(this->FontSize+this->FontPadding); - } - - - // ili9340.lcdDrawFillRect((ushort)(x2-Padding), (ushort)(y1-Padding), (ushort)(x1+Padding), (ushort)(y2+Padding), this->BackColor); - // // text size pad x y center - // font.WriteString(this->Text, this->FontSize, this->FontPadding, (ushort)x1, (ushort)y1, this->ForeColor, this->Center, (ushort)this->Size.Width, (ushort)this->Size.Height); - - // // debug top-right - // ili9340.lcdDrawPixel((ushort)x2, (ushort)y1, Colors.Yellow); - // // and bottom-left pixels - // ili9340.lcdDrawPixel((ushort)x1, (ushort)y2, Colors.Green); - } - - - Button(string args) { - // printf("Button loaded with arguments: %s\n", args.c_str()); - - } - static void parseAttributes(Button* ctrl, string key, string value) { - GeneralAttributes::parseAttributes(ctrl->Get(), key, value); - - if(key == "content") { - ctrl->text=value; - } else if(key == "font_size") { - ctrl->FontSize = stod(value); - } else if(key == "text_align") { - // TODO - printf("TODO text_align\n"); - } else if(key == "image") { - // TODO - printf("TODO image\n"); - } - else if(key == "bold") { - // TODO - printf("TODO bold\n"); - ctrl->Bold = true; - } - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/GeneralAttributes.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/GeneralAttributes.cpp deleted file mode 100644 index e3350de0..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/GeneralAttributes.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; - - -namespace layout { -class GeneralAttributes { - public: - template - static T parseAttributes(T ctrl, string key, string value) { - removeQuotes(value); - // parent="ControlName"; - - // color="255, 255, 255"; - // bg_color="0, 0, 0"; - - - try { - // name - if(key == "name") { - ctrl->name = value; - } - // visible - else if(key == "visible") { - ctrl->Visible = value == "true" ? true : false; - } - // width, height - else if(startsWith(key,"width")) { - if(endsWith(value, "%")) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->size.Width = round(percent*SCREEN_WIDTH); - } else { - ctrl->size.Width = stoi(value); - } - } else if(startsWith(key,"height")) { - if(endsWith(value, "%")) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->size.Height = round(percent*SCREEN_HEIGHT); - } else { - ctrl->size.Height = stoi(value); - } - } - // margin - else if(startsWith(key,"margin")) { - if(key == "margin_top") { printf("TODO margin\n"); } - else if(key == "margin_left") { printf("TODO margin\n"); } - else if(key == "margin_right") { printf("TODO margin\n"); } - else if(key == "margin_bottom") { printf("TODO margin\n"); } - } - // position - else if(key == "location") { - if(value.find(",") != string::npos) { - string posX = delete_space(Split(value, ',', true)); - string posY = delete_space(Split(value, ',', false)); - - // enable percentage ratio for X - if(posX.find("%") != string::npos) { - float percent = stof(posX.substr(0, value.length()))/100; - ctrl->Location.X = round(percent*SCREEN_WIDTH); - } - else { - ctrl->Location.X = stoi(posX); - } - // do the same but for Y - if(posY.find("%") != string::npos) { - float percent = stof(posY.substr(0, value.length()))/100; - ctrl->Location.Y = round(percent*SCREEN_HEIGHT); - } - else { - ctrl->Location.Y = stoi(posY); - } - } - else { - // handle arbitrary locations - if(value == "top") { - ctrl->Location.X = (SCREEN_WIDTH/2)-(ctrl->size.Width/2); - ctrl->Location.Y = 0; - } else if(value == "top_left") { - ctrl->Location.X = 0; - ctrl->Location.Y = 0; - } else if(value == "top_right") { - ctrl->Location.X = SCREEN_WIDTH-ctrl->size.Width; - ctrl->Location.Y = 0; - } else if(value == "bottom") { - ctrl->Location.X = SCREEN_WIDTH/2-ctrl->size.Width/2; - ctrl->Location.Y = SCREEN_HEIGHT-ctrl->size.Height; - } else if(value == "bottom_left") { - ctrl->Location.X = 0; - ctrl->Location.Y = SCREEN_HEIGHT-ctrl->size.Height; - } else if(value == "bottom_right") { - ctrl->Location.X = SCREEN_WIDTH-ctrl->size.Width; - ctrl->Location.Y = SCREEN_HEIGHT-ctrl->size.Height; - } else if(value == "left") { - ctrl->Location.X = 0; - ctrl->Location.Y = (SCREEN_HEIGHT/2)-(ctrl->size.Height/2); - } else if(value == "right") { - ctrl->Location.X = SCREEN_WIDTH-ctrl->size.Width; - ctrl->Location.Y = (SCREEN_HEIGHT/2)-(ctrl->size.Height/2); - } else if(value == "center") { - ctrl->Location.X = (SCREEN_WIDTH/2)-(ctrl->size.Width/2); - ctrl->Location.Y = (SCREEN_HEIGHT/2)-(ctrl->size.Height/2); - } - } - } - // margins - else if(key == "margin_top") { - if(value.find("%") != string::npos) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->Location.Y += round(percent*SCREEN_HEIGHT); - } else { - ctrl->Location.Y += stoi(value); - } - } - else if(key == "margin_left") { - if(value.find("%") != string::npos) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->Location.X += round(percent*SCREEN_HEIGHT); - } else { - ctrl->Location.X += stoi(value); - } - } - else if(key == "margin_right") { - if(value.find("%") != string::npos) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->Location.X -= round(percent*SCREEN_HEIGHT); - } else { - ctrl->Location.X -= stoi(value); - } - } - else if(key == "margin_bottom") { - if(value.find("%") != string::npos) { - float percent = stof(value.substr(0, value.length()))/100; - ctrl->Location.Y -= round(percent*SCREEN_HEIGHT); - } else { - ctrl->Location.Y -= stoi(value); - } - } - // color, bg_color - else if(key == "color") { - ctrl->ForeColor = (ushort)GetColor(value); - logn("Set ForeColor to '"+value+"' => "+to_string(ctrl->ForeColor), ConsoleColor::Red); - } else if(key == "bg_color") { - ctrl->BackColor = (ushort)GetColor(value); - logn("Set BackColor to '"+value+"' => "+to_string(ctrl->BackColor), ConsoleColor::Red); - } - // enabled - else if(key == "enabled") { - ctrl->Enabled = value == "true" ? true : false; - } - } - catch(exception e) { - log("Error in layout '"+key+"': "+e.what(), LogStatus::Error); - } - - return ctrl; - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Image.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/Image.cpp deleted file mode 100644 index 6ed9bc8f..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Image.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; - -namespace layout { -class Image : public Control { - public: - display* display1; - string src; - ushort BackColor = Colors::Black; - bool reverse = false; - - Control* Get() { - return this; - } - - DataTypes::Rect getRect() - { - int x1 = 240-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - x1-=this->size.Width; - x2-=this->size.Width; - - return DataTypes::Rect(x2, y1, x1, y2); - } - - void draw() override - { - this->display1->drawImage(DataTypes::Point(this->Location.X, this->Location.Y), this->src, this->size.Width, this->size.Height, false); - log("Drawing image!", LogStatus::Warning); - } - - - Image(string args) { - // printf("Image loaded with arguments: %s\n", args.c_str()); - - } - static void parseAttributes(Image* ctrl, string key, string value) { - // logn(to_string(ctrl->ForeColor)+" <= color", ConsoleColor::Yellow); - ctrl = static_cast(GeneralAttributes::parseAttributes(ctrl, key, value)); - // logn(to_string(ctrl->ForeColor)+" <= color", ConsoleColor::Yellow); - - if(key == "src") { - // TODO - removeQuotes(value); - if(startsWith(value, "http")){ - string command = "curl -o '"+GetPath()+"/temp/image.png' '"+value+"'"; - system(command.c_str()); - ctrl->src=GetPath()+"/temp/image.png"; - } - else if(filesystem::exists(value)) { - ctrl->src=value; - } - else { - ctrl->src=display::GetThemeIcon(value); - } - - } else if(key == "mode") { - // TODO - printf("TODO mode\n"); - // ctrl->FontSize = 0; - } - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Rect.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/Rect.cpp deleted file mode 100644 index 4404483f..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Rect.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; - - -namespace layout { -class Rect : public Control { - public: - display* display1; - ushort BackColor = Colors::Black; - DataTypes::Size size = DataTypes::Size(100, 100); // Default size is 100x100 - bool scroll = false; - - Control* Get() { - return this; - } - - void draw() override - { - int x1 = SCREEN_WIDTH-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - - this->display1->drawRect(x2, y1, x1, y2, this->BackColor, true); - logn("DISPLAYING Rect '"+this->name+"' color: "+to_string(this->BackColor), ConsoleColor::DarkMagenta); - } - - - Rect(string args) { - // printf("Rect loaded with arguments: %s\n", args.c_str()); - - } - static void parseAttributes(Rect* ctrl, string key, string value) { - ctrl = static_cast(GeneralAttributes::parseAttributes(ctrl, key, value)); - - if(key == "scroll") { - ctrl->scroll=(value=="true")?true:false; - } - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Text.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/Text.cpp deleted file mode 100644 index 73f3a099..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Text.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; -using namespace DataTypes; - - - -namespace layout { -class Text : public Control { - public: - display* display1; - string text = ""; - ushort BackColor = Colors::White; - ushort ForeColor = Colors::Black; - bool Bold = false; - int FontSize = 10; - bool Center = false; - int FontPadding = 0; - - Control* Get() { - return this; - } - - void draw() override - { - int x1 = 240-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - // Get text width and height - int text_width = this->FontSize*this->text.length(); - int text_height = this->FontSize*2; - - - // sets width&height to text size if not changed - // log("Text size not def", LogStatus::Critical); - if(this->size.Width == 100 && this->size.Height == 50) { - log("SIZE NOT DEF => OVERRIDE", LogStatus::Critical); - this->size = DataTypes::Size(text_width, text_height); - } - else { - // removes extra chars that are out of rect - if(this->size.Width > text_width) { - log("TOO LONG FOR TEXT", LogStatus::Critical); - logn(this->text, ConsoleColor::DarkGreen); - this->text.substr(0, this->text.length()-(this->size.Width-text_width)/FontSize); - logn(this->text, ConsoleColor::DarkGreen); - } - } - - if(isDebugMode()) { - this->Location.Y += this->size.Height; - } - - - // display BackGround if not default - // log("Disabled backcolor: Text", LogStatus::Critical); - if(this->BackColor != Colors::White) { - this->display1->drawRect(x1, y1, x2, y2, this->BackColor, true); - } - this->display1->drawText(this->Location.X, this->Location.Y, this->FontSize, this->text, this->Bold, this->ForeColor); - // font.WriteString(this.Text, this.FontSize, this.FontPadding, (ushort)x1, (ushort)y1, this.ForeColor, this.Center, (ushort)this.Size.Width, (ushort)this.Size.Height); - } - - - Text(string args) { - // printf("Text loaded with arguments: %s\n", args.c_str()); - - } - static void parseAttributes(Text* ctrl, string key, string value) { - ctrl = static_cast(GeneralAttributes::parseAttributes(ctrl, key, value)); - - if(key == "content") { - removeQuotes(value); - ctrl->text = value; - } else if(key == "font_size") { - // TODO - try { - removeQuotes(value); - ctrl->FontSize = stoi(value); - } catch(exception) { - log("Bad FontSize (should be a int)", LogStatus::Error); - } - } - else if(key == "text_align") { - // TODO - printf("TODO text_align\n"); - ctrl->Center = true; - } - else if(key == "bold") { - // TODO - printf("TODO bold\n"); - ctrl->Bold = true; - } - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/TextBox.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/TextBox.cpp deleted file mode 100644 index c11d0c5e..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/TextBox.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "Type.h" -#include - -using namespace std; - - -namespace layout { -class TextBox : public Control { - public: - display* display1; - string text=""; - ushort BackColor = Colors::Black; - ushort ForeColor = Colors::White; - int FontSize = 10; - bool Center = false; - int FontPadding = 0; - bool Bold = false; - - Control* Get() { - return this; - } - - void draw() override - { - int x1 = 240-this->Location.X; - int y1 = this->Location.Y; - - int x2 = x1-this->size.Width; - int y2 = y1+this->size.Height; - - - // font.WriteString(this->Text, this->FontSize, this->FontPadding, (ushort)x1, (ushort)y1, this->ForeColor, this->Center, (ushort)this->Size.Width, (ushort)this->Size.Height); - } - - - TextBox(string args) { - // printf("TextBox loaded with arguments: %s\n", args.c_str()); - - } - static void parseAttributes(TextBox* ctrl, string key, string value) { - GeneralAttributes::parseAttributes(ctrl->Get(), key, value); - - if(key == "content") { - ctrl->text=value; - } else if(key == "font_size") { - ctrl->FontSize = stod(value); - } else if(key == "text_align") { - // TODO - printf("TODO text_align\n"); - } - else if(key == "bold") { - // TODO - printf("TODO bold\n"); - ctrl->Bold = true; - } - - } - - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Window.cpp b/rootfs/usr/share/d3m0n/src/application/layout/Controls/Window.cpp deleted file mode 100644 index 8e4f4ccb..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/Controls/Window.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "../../../settings.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace std; - - -namespace layout { -class Window { - public: - display* display1; - Window(display* display1, string key, string value) { - if(key == "bg_color") { - removeQuotes(value); - display1->drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GetColor(value), true); - } - } - }; -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/layout/layoutHandler.cpp b/rootfs/usr/share/d3m0n/src/application/layout/layoutHandler.cpp deleted file mode 100644 index 28a29abd..00000000 --- a/rootfs/usr/share/d3m0n/src/application/layout/layoutHandler.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "../../settings.h" -#include -#include "Controls.cpp" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace fs = filesystem; -using namespace std; - -class layoutHandler { -public: - static void parseLayout(string path) - { - fstream file(path, ios::in | ios::out); // Open file in read-write mode - if (!file.is_open()) { - log("Failed to parse (error while opening file)", LogStatus::Error); - return; - } - - stringstream buffer; - buffer << file.rdbuf(); - string fileContent = buffer.str(); - - // parse into one-liners - replaceAll(fileContent, ";\r\n", ";"); - replaceAll(fileContent, ":\r\n", ":"); - file.close(); - - - // write out - system(((string)"rm -rf '"+path+(string)"' && cat /dev/null > '"+path+"'").c_str()); - fstream file2(path, ios::in | ios::out); // Open file in read-write mode - if (!file2.is_open()) { - log("Failed to parse (error while opening file)", LogStatus::Error); - return; - } - - file2 << fileContent << endl; - file2.close(); - - // logn(fileContent, ConsoleColor::Green); - log((string)"Parsed '"+path+(string)"'", LogStatus::Success); - } - static void runLayout(display* display1, Application* app, string path) - { - // parsing layout - parseLayout(path); - - - ifstream file(path); - if (!file.is_open()) { - log("Failed to open the layout file.", LogStatus::Error); - return; - } - - string line; - int line_number = 0; - while (getline(file, line)) { - line_number++; - if(line[0] == '#') continue; // Skip comments - if(line.empty() || line[0] == '\n' || line[0] == '\r') continue; // Empty lines are skipped as well - - string delimiter = ":"; - size_t pos = line.find(delimiter); - - if (pos != string::npos) { // If delimiter found - // Extract substrings - string controlName = line.substr(0, pos); - string controlAttributes = line.substr(pos + delimiter.length()); - - // loads controls and add it to current window - Control* control = loadControl(display1, controlName, controlAttributes); - - if (control != nullptr) { - app->mainWindow->Add(control); - // log("New CTRL -> " + control->name, LogStatus::Critical); - } - } else { - log("Error in layoutFile '"+path+"', invalid Control definition structure\nCause by '"+line+"' at l."+to_string(line_number), LogStatus::Error); - } - } - - file.close(); // Close the file - - } -}; diff --git a/rootfs/usr/share/d3m0n/src/application/source/script.cpp b/rootfs/usr/share/d3m0n/src/application/source/script.cpp deleted file mode 100644 index f5e47dcd..00000000 --- a/rootfs/usr/share/d3m0n/src/application/source/script.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "../../settings.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fs = filesystem; -using namespace std; - -class script -{ - public: - static void callFunction(string name, list args) { - try { - if(name == "log") { log(args.front(), LogStatus::Info); return; } - else if(name == "logn") { logn(args.front(), ConsoleColor::get(args.back())); return; } - else if(name == "print") { printf((args.front()+"\n").c_str()); return; } - else if (name == "sleep") { this_thread::sleep_for(chrono::milliseconds(stoi(args.front()))); return; } - } - catch(exception e) - { - log("Error while calling Function \""+name+"\": "+e.what(), LogStatus::Error); - } - } -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/source/source.cpp b/rootfs/usr/share/d3m0n/src/application/source/source.cpp deleted file mode 100644 index 500a3eb5..00000000 --- a/rootfs/usr/share/d3m0n/src/application/source/source.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "../../settings.h" -#include -#include "script.cpp" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace fs = filesystem; -using namespace std; - -void WriteSource(string path, string data) { - ofstream outputFile(path); - - if (!outputFile.is_open()) { - log("Error opening Event def sourceFile for writing!", LogStatus::Error); - return; - } - outputFile << data.c_str() << endl; - outputFile.close(); -} - -void loadEvent(Application* app, string eventName, string eventCode) -{ - log("Saving Event: \""+eventName+"\"", LogStatus::Loading); - system(("mkdir '"+app->temp_path+"/events/'").c_str()); - WriteSource(app->temp_path+"/events/"+eventName, eventCode); -} -void execute(Application* app, string line) -{ - string app_path = app->temp_path; - // printf((line+"\n").c_str()); - - if(line[0] == '#') - {} - else if(startsWith(line, "def ")) - { - // string def_name = line.Replace("def ", "").TrimEnd('}').Split("{")[0]; - // string def_script = line.Replace("def ", "").TrimEnd('}').Split("{")[1].Replace(" ", "\r\n"); - // if(!Directory.Exists(app_path+"/defs")) - // { - // Directory.CreateDirectory(app_path+"/defs"); - // } - // File.WriteAllText(app_path+"/defs/"+def_name, def_script); - // logn("[o] created def "+def_name, ConsoleColor::Green); - printf("TODO: def script\n"); - } - else if(startsWith(line, "use")) - { - printf("TODO: use > script\n"); - string path="TODO"; - // string path = line.Split(">")[1]; - log("using "+path, LogStatus::Info); - // script.importLib(getString(path).Replace(";", "")); - } - else if(contains(line, "=")) - { - string name = delete_space(Split(line, '=')); - string value = Split(line, '=', false); - log("Def new var '"+name+"' => '"+value+"'", LogStatus::Warning); - // script.setVariable(name, value); - } - else if(contains(line, "(") && endsWith(line, ")")) - { - string name = Split(line, '('); - string value2 = Split(line, '(', false); - replaceAll(value2, ")", ""); - - std::list value; - // get two first args - value.push_back(Split(value2, ',')); - value.push_back(Split(value2, ',', false)); - - script::callFunction(name, value); - // printf("Calling function %s with args %s\n", name.c_str(), value.front().c_str()); - } - -} -void callEvent(Application* app, string eventName) -{ - string eventPath = app->temp_path+"/events/"+eventName; - if(!filesystem::exists(eventPath)) - { - log("Event '"+eventName+"' does not exists in app '"+app->name+"'", LogStatus::Error); - return; - } - ifstream inputFile(eventPath); - - if (!inputFile.is_open()) { - log("Error opening Event def sourceFile for reading!", LogStatus::Error); - return; - } - - string line; - while (getline(inputFile, line)) { - istringstream iss(line); - string token; - - // extract attributes from the attribute string - while (getline(iss, token, ';')) { - deleteLeadingSpaces(token); - execute(app, token); - } - } - - inputFile.close(); -} -string getString(string raw) -{ - // string app_path = Interpreter.currentRunningAppPath; - // string ressources = app_path+"/ressources"; - // string source = app_path+"/src"; - // string layouts = app_path+"/layouts"; - // string to_return=raw.TrimStart(' ').TrimStart('"').TrimEnd('"').Replace("$d3m0n", utils.getPath()).Replace("$source", source).Replace("$layouts", layouts).Replace("$ressources", ressources); - // // utils.logn(to_return, ConsoleColor.Magenta); - // foreach(string word in to_return.Split(" ")) - // { - // if(word.StartsWith('$') && varExists(word.TrimStart('$'))) - // { - // // MessageBox.Show(word); - // to_return=to_return.Replace(word, getVariable(word.TrimStart('$'))); - // } - // } - return ""; - // return to_return; -} \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/application/source/sourceHandler.cpp b/rootfs/usr/share/d3m0n/src/application/source/sourceHandler.cpp deleted file mode 100644 index 34318843..00000000 --- a/rootfs/usr/share/d3m0n/src/application/source/sourceHandler.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "../../settings.h" -#include -#include "source.cpp" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace fs = filesystem; -using namespace std; - -class sourceHandler { -public: - static void parseSource(string path) - { - fstream file(path, ios::in | ios::out); // Open file in read-write mode - if (!file.is_open()) { - log("Failed to parse (error while opening file)", LogStatus::Error); - return; - } - - stringstream buffer; - buffer << file.rdbuf(); - string fileContent = buffer.str(); - - // parse into one-liners - replaceAll(fileContent, "; ", ";"); - replaceAll(fileContent, "; ", ";"); - replaceAll(fileContent, "; ", ";"); - replaceAll(fileContent, "; ", ";"); - replaceAll(fileContent, "; ", ";"); - replaceAll(fileContent, ";\r\n", ";"); - replaceAll(fileContent, "=>\r\n", "=>"); - file.close(); - - - // write out - system(((string)"rm -rf '"+path+(string)"' && cat /dev/null > '"+path+"'").c_str()); - fstream file2(path, ios::in | ios::out); // Open file in read-write mode - if (!file2.is_open()) { - log("Failed to parse (error while opening file)", LogStatus::Error); - return; - } - - file2 << fileContent << endl; - file2.close(); - - // logn(fileContent, ConsoleColor::Green); - log((string)"Parsed '"+path+(string)"'", LogStatus::Success); - } - static void runSource(display* display1, Application* app, string path) - { - // parse source file - parseSource(path); - - ifstream file(path); - if (!file.is_open()) { - log("Failed to open the source file.", LogStatus::Error); - return; - } - - string line; - int line_number = 0; - while (getline(file, line)) { - line_number++; - if(line[0] == '#') continue; // Skip comments - if(line.empty() || line[0] == '\n' || line[0] == '\r') continue; // Empty lines are skipped as well - - string delimiter = "=>"; - size_t pos = line.find(delimiter); - - if (pos != string::npos) { // If delimiter found - // Extract substrings - string eventName = line.substr(0, pos); - string eventCode = line.substr(pos + delimiter.length()); - - // loads event - loadEvent(app, delete_space(eventName), eventCode); - } else { - log("Error in sourceFile '"+path+"', \nCaused by '"+line+"' at l."+to_string(line_number), LogStatus::Error); - } - } - - file.close(); // Close the file - - } -}; \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/ascii.txt b/rootfs/usr/share/d3m0n/src/ascii.txt deleted file mode 100644 index e77731a6..00000000 --- a/rootfs/usr/share/d3m0n/src/ascii.txt +++ /dev/null @@ -1,27 +0,0 @@ -╔═╗ ║ ╚═╝ ╩ ╦ ╠═╣ ╬ - - - - ║ ╔═╗ ╔═╦═╗ ╔═╗ ╔═╗ - ╔═╣ ═╣ ║ ║ ║ ║ ║ ║ ║ - ╚═╝ ╚═╝ ╩ ╩ ╩ ╚═╝ ╩ ╩ - ══════════╦═══════════════╦══════════ - ╔════════════════╩═══════════════╩═════════════════╗ -╔══════════════╝ Help command ╚═══════════════╗ -║ command ║ permissions ║ description ║ -╠════════════════════════════════╬═════════════╬══════════════════════════════════╣ -║ help ║ none ║ display this list ║ -║ exit ║ none ║ quit ║ -║ config [get/set] name (value) ║ admin ║ config your phone ║ -║ load ║ none ║ loads new app ║ -║ list ║ none ║ list currently loaded apps ║ -║ run ║ none ║ run app by package name ║ -║ update [all/package_installer] ║ none ║ update d3m0n OS components ║ -║ fetch ║ none ║ download package from repository ║ -║ clear ║ none ║ clear console ║ -║ clean ║ none ║ clean scripts & applications ║ -║ version ║ none ║ get current version ║ -║ display [clear/draw] ║ none ║ manual display debug commands ║ -║ info ║ none ║ get debug informations ║ -║ shutdown ║ none ║ stop d3m0n shell ║ -╚════════════════════════════════╩═════════════╩══════════════════════════════════╝ \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/build.bat b/rootfs/usr/share/d3m0n/src/build.bat deleted file mode 100644 index b4066b82..00000000 --- a/rootfs/usr/share/d3m0n/src/build.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off - -set path=%path%;C:\Users\celcm\MinGW\lib\gcc\x86_64-w64-mingw32\13.2.0 - -set homepath=%cd% - -cd C:\Users\celcm\MinGW\bin\ - -call gcc "%homepath%\*.c" -o d3m0n.exe - -pause - -mv d3m0n.exe "%homepath%\d3m0n.exe" - -cd "%homepath%" - -call d3m0n.exe - -pause \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/build.sh b/rootfs/usr/share/d3m0n/src/build.sh deleted file mode 100644 index c63b178f..00000000 --- a/rootfs/usr/share/d3m0n/src/build.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# solved bcm2835.h error by addind static_cast( void* ) - -clear - -cd ./test -./build.sh -cd .. - - -# setting lib var -# LD_LIBRARY_PATH=$(pwd)/lib - -make clean -make -j 4 - -#gcc *.cpp *.c -Ilibs/ili9340/ -Wall -std=c99 -o d3m0n | grep "error" - -sudo chmod 777 ./d3m0n - -sudo ./d3m0n diff --git a/rootfs/usr/share/d3m0n/src/d3m0n b/rootfs/usr/share/d3m0n/src/d3m0n deleted file mode 100644 index cd5db27c..00000000 Binary files a/rootfs/usr/share/d3m0n/src/d3m0n and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/d3m0n.cpp b/rootfs/usr/share/d3m0n/src/d3m0n.cpp deleted file mode 100644 index d51c1611..00000000 --- a/rootfs/usr/share/d3m0n/src/d3m0n.cpp +++ /dev/null @@ -1,316 +0,0 @@ -#include -#include "settings.h" -#include -#include "application/appManager.cpp" -#include -#include -#include -#include -#include -#include -#include - - -#define COMMAND_HELP "d3m0n shell - help\n| command | permissions | description |\n|--------------------------------|-------------|----------------------------------|\n| help | none | display this list |\n| exit | none | quit |\n| config [get/set] name (value) | admin | config your phone |\n| load | none | loads new app |\n| list | none | list currently loaded apps |\n| run | none | run app by package name |\n| update [all/package_installer] | none | update d3m0n OS components |\n| fetch | none | download package from repository |\n| clear | none | clear console |\n| clean | none | clean scripts & applications |\n| version | none | get current version |\n| display [clear/draw] | none | manual display debug commands |\n| info | none | get debug informations |\n| shutdown | none | stop d3m0n shell |" -#define VERSION (string)"1.5 beta" - -void ShellHandle(display* display1, appManager manager) { - // Create socket - int serverSocket = socket(AF_INET, SOCK_STREAM, 0); - if (serverSocket == -1) { - log("Error creating d3m0n shell server", LogStatus::Error); - return; - } - // Fill in the sockaddr_in structure - struct sockaddr_in serverAddr; - serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = INADDR_ANY; - // default port - int port = 3849; - try { - port = stoi(getSetting("shell_port", GetConfig())); - } - catch(exception e) {} - // close service running - log("Stopping services running on port "+to_string(port), LogStatus::Info); - system(("sudo fuser -k "+to_string(port)+"/tcp").c_str()); - - serverAddr.sin_port = htons(port); // Port to listen on - - // Bind socket - if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { - log("Error binding d3m0n shell server", LogStatus::Error); - close(serverSocket); - return; - } - - // Listen for incoming connections - if (listen(serverSocket, 5) == -1) { - log("Error listening for d3m0n shell connections", LogStatus::Error); - close(serverSocket); - return; - } - - // get server IP - char srvIP[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(serverAddr.sin_addr), srvIP, INET_ADDRSTRLEN); - - log("Listening on "+(string)srvIP+":"+to_string(port), LogStatus::Error); - - bool serverRunning=true; - - while (serverRunning) { - int clientSocket = accept(serverSocket, NULL, NULL); - if (clientSocket == -1) { - log("Can't accept connection", LogStatus::Error); - continue; - } - - // move cursor one line up: \033[F - // move cursor char 5: \033[5G - // color \033[38;5;$(echo $iter)m - - char buffer[1024]; - int bytesReceived; - - // Send welcome&login message to client - string welcomeMessage = "\xE2\x98\xA0 Welcome to the server\n"+log("d3m0n shell loaded, type 'help' to display main commands\n\n", LogStatus::Info)+ - bashGradient(196, " USERNAME \n")+ - bashGradient(196, "╔════════════════╗\n")+ - bashGradient(196, "╚> "); - - send(clientSocket, welcomeMessage.data(), welcomeMessage.size(), 0); - - // recieve username - bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0); - buffer[bytesReceived] = '\0'; - string username=removeUnwantedChars((string)buffer); - username=Trim(username); - - printf("requesting password...\n"); - // recieve password - welcomeMessage = bashGradient(196, "\n PASSWORD \n")+ - bashGradient(196, "╔════════════════╗\n")+ - bashGradient(196, "╚> "); - send(clientSocket, welcomeMessage.data(), welcomeMessage.size(), 0); - bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0); - buffer[bytesReceived] = '\0'; - string password=removeUnwantedChars((string)buffer); - password=Trim(password); - log("new login => '"+username+":"+password+"'", LogStatus::Info); - - if((string)getSetting(username.data(), (GetPath()+"/configs/users").data()) == password) - { - send(clientSocket, "Connected successfully!\n\e[1;32m[d3m0n shell]>\e[0m ", strlen("Connected successfully!\n\e[1;32m[d3m0n shell]>\e[0m "), 0); - } - else { - send(clientSocket, "Invalid username or password\n", strlen("Invalid username or password\n"), 0); - close(clientSocket); - } - - - - bool running=true; - char command[64]; - string downloader_path = GetPath()+"/d3m0n_package_installer.sh"; - - // send(clientSocket, "\e[1;32m[d3m0n shell]>\e[0m ", strlen("\e[1;32m[d3m0n shell]>\e[0m "), 0); - - string output; - while (running && (bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0)) > 0) { - // end carriage - buffer[bytesReceived] = '\0'; - - string temp = Trim((string)buffer).data(); - temp.copy(command, std::min(temp.size(), sizeof(command) - 1)); // Ensure null termination - command[std::min(temp.size(), sizeof(command) - 1)] = '\0'; // Ensure null termination - - if(command != "") { - if(delete_space(command)=="exit") running=false; - else if(delete_space(command)=="shutdown") { send(clientSocket, "Session closed\n", strlen("Session closed\n"), 0); running=false; serverRunning=false;} - else if(startsWith(command, "display")) { - output += display1->displayCommand(command); - } - else if(delete_space(command)=="info") { output = printInfos(); } - else if(delete_space(command)=="version") output = log("Current version: "+VERSION, LogStatus::Info); - else if(delete_space(command)=="clear") output = exec("clear"); - else if(delete_space(command)=="help") output = logn(COMMAND_HELP, ConsoleColor::DarkGreen); - else if(delete_space(command)=="list") output = manager.GetAppList(); - else if(command == "clean") { - string remove_files = "rm -rf '"+downloader_path+"' && rm -rf '"+GetPath()+"/temp/*'"; - output = log("Cleaning scripts & loaded applications...", LogStatus::Loading); - manager.appsPackages = {}; - manager.appsPaths = {}; - output += exec(remove_files.c_str()); - output += log("Done!", LogStatus::Success); - } - else if(startsWith(command, "update")) { - string arg1 = Split(command, ' ', false); - if(arg1 == "package_installer") { - output = log("Updating d3m0n package installer...", LogStatus::Loading); - int status = system(("rm -rf '"+downloader_path+"' && curl -o '"+downloader_path+"' 'https://raw.githubusercontent.com/d3m0n-project/d3m0n_os/main/rootfs/usr/share/applications/d3m0n_package_installer.sh' && chmod 777 '"+downloader_path+"'").c_str()); - if(status != 0) { output += log("Update failed!", LogStatus::Error); } - } - else { - output = log("Usage 'update [all/package_installer]", LogStatus::Error); - } - } else if (startsWith(command, "load")) { - string path = Split(command, ' ', false); - manager.loadApp(path.data()); - output = log("Loading '"+path+"'...", LogStatus::Loading); - } else if (startsWith(command, "run")) { - string package = Split(command, ' ', false); - Application newApp; - newApp.temp_path = manager.GetAppPathByPackage(package.data()); - manager.runApp(display1, &newApp); - output = log("Running app...", LogStatus::Loading); - } else if (startsWith(command, "fetch")) { - - string package_or_name = Split(command, ' ', false); - output = logn(" Downloading ==> "+package_or_name, ConsoleColor::Blue); - - // downloads installer if missing - if(!filesystem::exists(downloader_path)) - { - output += log("Downloading package installer script...", LogStatus::Loading); - output += exec(("curl -o '"+downloader_path+"' 'https://raw.githubusercontent.com/d3m0n-project/d3m0n_os/main/rootfs/usr/share/applications/d3m0n_package_installer.sh'").c_str()); - } - - int status = system(("chmod 777 '"+downloader_path+"' && '"+downloader_path+"' '"+package_or_name+"'").c_str()); - // display run command - output += logn("Run this app by loading it using '\e[1;33mload "+GetPath()+"/../applications/"+package_or_name+"\e[38;5;208m' \nand then run it using '\e[1;33mrun "+package_or_name+"\e[38;5;208m'", ConsoleColor::Orange); - // handle errors - if(status != 0) - { - output += log("Failed to fetch remote repository: are you offline?", LogStatus::Error); - } - } - else { output = log("Invalid command '"+(string)command+"' (help for list of available commands)", LogStatus::Error); } - } - output+="\n\e[1;32m[d3m0n shell]>\e[0m "; - if(output!="") { - send(clientSocket, output.c_str(), strlen(output.c_str()), 0); - } - } - - // Close client socket - close(clientSocket); - } - - close(serverSocket); -} - -int main(int argc, char *argv[]) -{ - // init path - string d3m0n_path = GetPath(); - - // create configs folder - system(("sudo mkdir '"+d3m0n_path+"/configs'").c_str()); - - // if no users, create one "d3m0n:d3m0n" - if(!filesystem::exists(d3m0n_path+"/configs/users")) { - // create user - // format: username: password - // default: d3m0n: d3m0n - string users_command = "echo 'd3m0n: d3m0n' > '"+d3m0n_path+"/configs/users'"; - system(users_command.c_str()); - - } - - system("clear"); - string command = (string)"rm -rf '"+d3m0n_path+(string)"/temp/' && mkdir '"+d3m0n_path+(string)"/temp/'"; - system(command.c_str()); - - // init display - display *display1 = new display(); - - - - // loads apps launcher - // load topbar - // load background - - - // init banner - logn(" ██████╗ ██████╗ ███╗ ███╗ ██████╗ ███╗ ██╗", ConsoleColor::Reset); - logn(" ██╔══██╗╚════██╗████╗ ████║██╔═████╗████╗ ██║", ConsoleColor::Reset); - logn(" ██║ ██║ █████╔╝██╔████╔██║██║██╔██║██╔██╗ ██║", ConsoleColor::Reset); - logn(" ██║ ██║ ╚═══██╗██║╚██╔╝██║████╔╝██║██║╚██╗██║", ConsoleColor::Reset); - logn(" ██████╔╝██████╔╝██║ ╚═╝ ██║╚██████╔╝██║ ╚████║", ConsoleColor::Reset); - logn(" ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝", ConsoleColor::Reset); - logn(" made by 4re5 group ", ConsoleColor::Reset); - logn(" the first hacking cellular phone ", ConsoleColor::Reset); - printf("\n"); - - - - if(isDebugMode()) { - string input; - log("DEBUG mode is enabled wan't to continue? [y/N] ", LogStatus::Critical); - cin >> input; - if(input == "n" || input == "N") - { - return 0; - } - } - - sleep(1); - display1->init(SCREEN_WIDTH, SCREEN_HEIGHT); - // setup display - // std::thread displayThread(&display::init, display1, SCREEN_WIDTH, SCREEN_HEIGHT); - // std::thread wmThread(display1.init(SCREEN_WIDTH, SCREEN_HEIGHT)); - // displayThread.join(); - thread displayThread(&display::getClick, display1); - - sleep(1); - - display1->drawImage(DataTypes::Point(0, 0), GetPath()+"/splash/splash.png", SCREEN_WIDTH, SCREEN_HEIGHT, false); - display::PlaySound("boot"); - log("Splash loaded... Waiting "+(string)getSetting("splash_time", GetConfig())+"ms", LogStatus::Loading); - // setting up splash image - sleep(stoi(getSetting("splash_time", GetConfig()))/1000); - - // hide splashscreen - display1->Clear(); - - // color 245, 124, 0 don't displays as dark orange but yellow/green - //display1->drawImage(DataTypes::Point(100, 100), "/home/kali/2d-game/player/back/walking-0.png", 100, 100, false); - // display1->drawImage(DataTypes::Point(0, 0), "/home/kali/d3m0n_os_debian/rootfs/usr/share/d3m0n/themes/default_dark/icons/contacts.png", 100, 100, false); - - // display1->drawRect(0, 0, 100, 100, RGBtoRGB565(245, 124, 0), true); - // display1->drawCircle(50, 50, 50, Colors::Black, true); - - // load apps in memory - appManager manager; - manager.mainScreenInit(display1); - - - // display1->drawLine(100, 100, 100, 200, Colors::Red); - // display1->drawRect(10, 10, 100, 100, Colors::Green, false); - - // Application gallery = manager.loadApp("./test/test.d3m0n"); - // manager.runApp(display1, &gallery); - - // callEvent(&gallery, "Window.OnCreate"); - - // gallery.mainWindow->Update(); - log("Updated!", LogStatus::Success); - - ShellHandle(display1, manager); - - - // logn("Name: "+gallery.mainWindow->Controls.at(0)->name, ConsoleColor::Cyan); - // logn("Width: "+to_string(gallery.mainWindow->Controls.at(0)->Width), ConsoleColor::Cyan); - // logn("Hight: "+to_string(gallery.mainWindow->Controls.at(0)->Height), ConsoleColor::Cyan); - // logn("Location.X: "+to_string(gallery.mainWindow->Controls.at(0)->Location.X), ConsoleColor::Cyan); - // logn("Location.Y: "+to_string(gallery.mainWindow->Controls.at(0)->Location.Y), ConsoleColor::Cyan); - // logn("BG_Color: "+to_string(gallery.mainWindow->Controls.at(0)->BackColor), ConsoleColor::Cyan); - - // load apps in grid - - - printf("\n"); - - return 0; -} \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/d3m0n_package_installer.sh b/rootfs/usr/share/d3m0n/src/d3m0n_package_installer.sh deleted file mode 100644 index c9282cad..00000000 --- a/rootfs/usr/share/d3m0n/src/d3m0n_package_installer.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# d3m0n app remote installer -# usage 'fetch ' inside d3m0n shell - -PACKAGE=$1 -GET_PATH="/home/kali/d3m0n_os_debian/rootfs/usr/share/d3m0n" - -COLOR1="\e[1;35m" -COLOR2="\e[0;35m" - -process_file() { - local json="$1" - local name=$(echo "$json" | jq -r ".name") - local download_url=$(echo "$json" | jq -r ".download_url") - - if [[ "$name" == "$PACKAGE" ]]; then - mkdir -p "$GET_PATH/../applications" - sudo chmod 777 "$GET_PATH/../applications" - curl "$download_url" -o "$GET_PATH/../applications/$name" - clear - echo -e "$COLOR2 Found $COLOR1$PACKAGE$COLOR2 inside d3m0n repository" - echo -e "$COLOR2 Url: $COLOR1$download_url" - echo -e "$COLOR2 " - echo -e "\n\nDownloaded $name successfully!" - fi -} - -process_directory() { - local path="$1" - local entries=$(curl "https://api.github.com/repos/d3m0n-project/d3m0n_os/contents/$path" | jq -c '.[]') - - # Iterate over each entry - while IFS= read -r entry; do - local type=$(echo "$entry" | jq -r '.type') - local name=$(echo "$entry" | jq -r '.name') - - if [[ "$type" == "file" ]]; then - process_file "$entry" - elif [[ "$type" == "dir" ]]; then - process_directory "$path/$name" - fi - done <<< "$entries" -} - -# Start processing from the root directory -process_directory "rootfs/usr/share/applications" diff --git a/rootfs/usr/share/d3m0n/src/lib/README.md b/rootfs/usr/share/d3m0n/src/lib/README.md deleted file mode 100644 index d6199666..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/README.md +++ /dev/null @@ -1,355 +0,0 @@ -# Raspberry-ili9340spi -ILI9340 SPI TFT Library for Raspberry Pi. -This may works with other boards like OrangePi/NanoPi. - -You can show a chart to ILI9340/ILI9341/ILI9163C/ST7735 SPI TFT. -You can choose bmc2835 library/WiringPi library. - -I tested these TFT. -1.44 inch 128x128 ST7735 -1.44 inch 128x128 ILI9163C -1.8 inch 128x160 ST7735 -2.2 inch 240x320 ILI9340 -2.4 inch 240x320 ILI9341 -2.4 inch 240x320 ILI9341 - -This project can be built with either: -- Build using bcm2835 library -- Build using Hardware SPI of the WiringPi library -- Build using Software SPI of the WiringPi library - ---- - -# Wirering - -|TFT||GPIO Header|| -|:-:|:-:|:-:|:-:| -|VCC|--|3.3V|*4| -|GND|--|GND|| -|CS|--|Pin#24(SPI CS0)|*2 *3| -|RES|--|Pin#12|*1| -|D/C|--|Pin#11|*1| -|MOSI|--|Pin#19(SPI MOSI)|*3| -|SCK|--|Pin#23(SPI SCLK)|*3| -|LED|--|3.3V|*4| -|MISO|--|N/C|| - -(*1) You can change it to any pin by changing source. - -(*2) You can use CS1 by specifying compilation flags. - -(*3) For Software SPI, you can change it to any pin by changing source. - -(*4) SPI TFTs require a lot of current. -If it is supplied from the Raspberry Pi's 3.3V pin, it may run out of current. -Use the 5V pin and the regulator to power it and it will be stable. -I used AMS1117. - ---- - -# Build using bcm2835 library -RPi Only, Very fast - -### Install bcm2835 library - -``` -wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.56.tar.gz -tar zxvf bcm2835-1.56.tar.gz -cd bcm2835-1.56 -./configure -make -sudo make check -sudo make install -``` - -__\* This tool require 1.56 or later.__ -__\* Because this tool uses bcm2835_spi_write.__ - -### Using other GPIO -You can change GPIO to any pin by changing here. -``` -#ifdef BCM -#include -#define D_C 17 // BCM IO17=Pin#11 -#define RES 18 // BCM IO18=Pin#12 -#endif -``` - -### Using SPI0 -Use Pin#24 as ChipSelect. -``` -cd $HOME -git clone https://github.com/nopnop2002/Raspberry-ili9340spi -cd Raspberry-ili9340spi -make lib -cc -o demo demo.c fontx.c ili9340.c jpeg.a png.a -lbcm2835 -lm -DBCM -sudo ./demo -``` - -### Using SPI1 -Use Pin#26 as ChipSelect. -``` -cd $HOME -git clone https://github.com/nopnop2002/Raspberry-ili9340spi -cd Raspberry-ili9340spi -make lib -cc -o demo demo.c fontx.c ili9340.c jpeg.a png.a -lbcm2835 -lm -DBCM -DSPI1 -sudo ./demo -``` - -### SPI bus speed for bcm2835 -By default it uses 7.8125MHz on Rpi2, 12.5MHz on RPI3. -Can be changed at compile time. -- -DSPI_SPEED16 : 15.625MHz on Rpi2, 25MHz on RPI3. -- -DSPI_SPEED32 : 31.25MHz on Rpi2, 50MHz on RPI3. - -___50MHz is an overclock.___ - -### SPI Bus speed comparison -||7.8125MHz|15.625MHz|31.25MHz| -|:-:|:-:|:-:|:-:| -|ColorBarTest|245|160|107| -|ArrowTest|286|193|155| -|LineTest|595|397|294| -|CircleTest|558|373|282| -|RoundRectTest|560|371|273| -|DirectionTest|304|199|153| -|HorizontalTest|430|283|209| -|VerticalTest|438|290|214| -|FillRectTest|448|285|221| -|ColorTest|500|327|234| -|JPEGTest|1607|1076|816| -|PNGTest|1742|1231|974| - ---- - -# Build using Hardware SPI of the WiringPi library -WiringPi library initializes GPIO in one of the following ways: -- int wiringPiSetup (void); -- int wiringPiSetupGpio (void); -- int wiringPiSetupPhys (void); -- int wiringPiSetupSys (void); - -This project by default uses the ```wiringPiSetup()``` function to initialize GPIOs. -Then use the wiringPiSPISetup() function to initialize the SPI. -If you use it on a board other than the RPI board, you may need to change the WiringPi number. -``` -#define D_C 0 // wPi IO00=Pin#11 -#define RES 1 // wPi IO01=Pin#12 -``` - -As far as I know, there are these WiringPi libraries. -- WiringPi for OrangePi -- WiringPi for BananaPi -- WiringPi for NanoPi -- WiringPi for Pine-64 - -If you want to initialize GPIO with ```wiringPiSetupGpio()```, Use the -DGPIO compilation flag. -In this case, use the following GPIOs. -``` -#define D_C 17 // BCM IO17=Pin#11 -#define RES 18 // BCM IO18=Pin#12 -``` - - - -### Using SPI0 -Use Pin#24 as ChipSelect. -``` -git clone https://github.com/nopnop2002/Raspberry-ili9340spi -cd Raspberry-ili9340spi -make lib -cc -o demo demo.c fontx.c ili9340.c jpeg.a png.a -lwiringPi -lm -pthread -DWPI -sudo ./demo -``` - -### Using SPI1 -Use Pin#26 as ChipSelect. -``` -git clone https://github.com/nopnop2002/Raspberry-ili9340spi -cd Raspberry-ili9340spi -make lib -cc -o demo demo.c fontx.c ili9340.c jpeg.a png.a -lwiringPi -lm -pthread -DWPI -DSPI1 -sudo ./demo -``` - -___Note for OrangePi___ -Opi have only 1 SPI. -OPi-PC has SPI0 on pin 24. -OPi-ZERO has SPI1 on pin 24. - -### SPI bus speed for WiringPi -By default it uses 8MHz on all Rpi. -Can be changed at compile time. -- -DSPI_SPEED16 : 16MHz on all Rpi. -- -DSPI_SPEED32 : 32MHz on all Rpi. - -### SPI Bus speed comparison -||8MHz|16MHz|32MHz| -|:-:|:-:|:-:|:-:| -|ColorBarTest|208|116|93| -|ArrowTest|389|296|239| -|LineTest|1800|1637|1560| -|CircleTest|1630|1481|1393| -|RoundRectTest|1633|1490|1412| -|DirectionTest|461|354|315| -|HorizontalTest|878|723|663| -|VerticalTest|909|769|702| -|FillRectTest|454|246|148| -|ColorTest|558|234|159| -|JPEGTest|6292|5862|5640| -|PNGTest|6439|5989|5803| - ---- - -# Build using Software SPI of the WiringPi library -WiringPi library initializes GPIO in one of the following ways: -- int wiringPiSetup (void); -- int wiringPiSetupGpio (void); -- int wiringPiSetupPhys (void); -- int wiringPiSetupSys (void); - -This project by default uses the ```wiringPiSetup()``` function to initialize GPIOs. -Then use the wiringPiSPISetup() function to initialize the SPI. -If you use it on a board other than the RPI board, you may need to change the WiringPi number. -``` -#define D_C 0 // wPi IO00=Pin#11 -#define RES 1 // wPi IO01=Pin#12 -#define MOSI 12 // wPi IO12=Pin#19 -#define SCLK 14 // wPi IO14=Pin#23 -#define CS 10 // wPi IO10=Pin#24 -``` - -If you want to initialize GPIO with ```wiringPiSetupGpio()```, Use the -DGPIO compilation flag. -In this case, use the following GPIOs. -``` -#define D_C 17 // BCM IO17=Pin#11 -#define RES 18 // BCM IO18=Pin#12 -#define MOSI 10 // BCM IO10=Pin#19 -#define SCLK 11 // BCM IO11=Pin#23 -#define CS 24 // BCM IO24=Pin#24 -``` -``` -git clone https://github.com/nopnop2002/Raspberry-ili9340spi -cd Raspberry-ili9340spi -make lib -cc -o demo demo.c fontx.c ili9340.c jpeg.a png.a -lwiringPi -lm -pthread -DWPI -DSOFT_SPI -sudo ./demo -``` - - ---- - -# TFT resolution and GRAM offset -TFT resolution is set to tft.conf. - -If your TFT doesn't use a memory from 0th address in GRAM, -It use GRAM offset which set to tft.conf. - -``` -#width=128 height=128 -width=240 height=320 -#width=240 height=400 - -#If TFT have GRAM offset -#offsetx=2 -#offsety=1 -``` - - ----- - -![ili9340-11](https://user-images.githubusercontent.com/6020549/58363270-668e0880-7edc-11e9-8f5a-ad00c60c5d4d.JPG) -![ili9340-12](https://user-images.githubusercontent.com/6020549/58363271-668e0880-7edc-11e9-80f9-4019c53c334d.JPG) -![ili9340-13](https://user-images.githubusercontent.com/6020549/58363272-668e0880-7edc-11e9-8ced-64367179c509.JPG) -![ili9340-14](https://user-images.githubusercontent.com/6020549/58363273-668e0880-7edc-11e9-84c1-779bd70a9ac4.JPG) -![ili9340-15](https://user-images.githubusercontent.com/6020549/58363274-67269f00-7edc-11e9-874e-b96165374809.JPG) -![ili9340-16](https://user-images.githubusercontent.com/6020549/58363275-67269f00-7edc-11e9-9664-2e7a2fe6d6bf.JPG) -![ili9340-17](https://user-images.githubusercontent.com/6020549/58363276-67269f00-7edc-11e9-9fc4-579a03e6bfd2.JPG) -![ili9340-18](https://user-images.githubusercontent.com/6020549/58363277-67269f00-7edc-11e9-9d77-2ebacc8666c5.JPG) -![ili9340-19](https://user-images.githubusercontent.com/6020549/58363278-67bf3580-7edc-11e9-9e95-c9daaa85c4b1.JPG) -![ili9340-20](https://user-images.githubusercontent.com/6020549/58363268-65f57200-7edc-11e9-8cc8-af25397d5e24.JPG) -![ili9340-21](https://user-images.githubusercontent.com/6020549/58363269-65f57200-7edc-11e9-89f9-8ad644e0b279.JPG) - -JPEG File -![ili9340-JPEG](https://user-images.githubusercontent.com/6020549/232970130-3241a691-48d6-4b48-b34f-ce7a2e42f6c3.JPG) -PNG File -![ili9340-PNG](https://user-images.githubusercontent.com/6020549/232970139-5b23c012-f678-45fb-bd76-fcb63f6a9c26.JPG) - ---- - -From left to right: -2.8" 240x320 ILI9341 -2.4" 240x320 ILI9341 -2.2" 240x320 ILI9340 - -![ILI9341-A](https://user-images.githubusercontent.com/6020549/232970787-2374f04f-def0-4498-b585-c287b9e31663.JPG) -![ILI9341-B](https://user-images.githubusercontent.com/6020549/232970793-dc0c753a-6da9-4ac9-bab8-c5ebd0752221.JPG) -![ILI9341-C](https://user-images.githubusercontent.com/6020549/232970799-f87800de-a6f4-435e-b9e9-a2a8a6da6b95.JPG) - ---- - -From left to right: -2.2" 240x320 ILI9340 -1.44" 128x128 ST7735 -1.44" 128x128 ILI9163C -1.8" 128x160 ST7735 - -![ili9163-1](https://user-images.githubusercontent.com/6020549/28749424-d9c5af2e-7501-11e7-9e3c-a88376ac015f.JPG) - ---- - -# XPT2046 Touch Screen -There is a TFT equipped with XPT2046. -![XPT2046-3](https://user-images.githubusercontent.com/6020549/144333924-5236bff3-3f4d-4be4-8e99-b6e31878e4f3.jpg) - -A library of XPT2046 Touch Screen is included in this library. -I ported from [here](https://github.com/xofc/xpt2uinput). - -There is a TFT equipped with HR2046. -XPT2046 and HR2046 are very similar. But HR2046 does not work properly. -![XPT2046-2](https://user-images.githubusercontent.com/6020549/144332571-717f33b1-df03-4a0a-9a23-c7c99b9d4d32.JPG) - -Wirering - -|TFT||Rpi|| -|:-:|:-:|:-:|:-:| -|VCC|--|3.3V|| -|GND|--|GND|| -|CS|--|Pin#24(SPI CS0)|| -|RES|--|Pin#12|(*1)| -|D/C|--|Pin#11|(*1)| -|MOSI|--|Pin#19(SPI MOSI)|(*2)| -|SCK|--|Pin#23(SPI SCLK)|(*2)| -|LED|--|3.3V|| -|MISO|--|N/C|| -|T_CLK|--|Pin#23(SPI SCLK)|(*2)| -|T_CS|--|Pin#26(SPI CE1)|| -|T_DIN|--|Pin#19(SPI MOSI)|(*2)| -|T_OUT|--|Pin#21(SPI MISO)|(*2)| -|T_IRQ|--|Pin#22|(*1)| - -(*1) You can change any pin. - -(*2) SPI is shared by TFT and XPT2046. - ---- - -``` -cc -o xpt xpt.c xpt2046.c -lbcm2835 -sudo ./xpt -``` - -If you touch screen, point will show. - -![Touch-11](https://user-images.githubusercontent.com/6020549/232971208-6904db4f-15a8-492b-8e66-89c34c85d8e0.jpg) - ---- -``` -cc -o touch touch.c fontx.c ili9340.c xpt2046.c -lbcm2835 -lm -DBCM -sudo ./touch -``` - -If you touch area, number will show. - -![Touch-12](https://user-images.githubusercontent.com/6020549/232971233-a03cd5e8-f7e9-4f30-957e-b69fa2474b4d.JPG) diff --git a/rootfs/usr/share/d3m0n/src/lib/bcm2835.c b/rootfs/usr/share/d3m0n/src/lib/bcm2835.c deleted file mode 100644 index adf126a8..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/bcm2835.c +++ /dev/null @@ -1,1791 +0,0 @@ -/* bcm2835.c -// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi -// http://elinux.org/RPi_Low-level_peripherals -// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf -// -// Author: Mike McCauley -// Copyright (C) 2011-2013 Mike McCauley -// $Id: bcm2835.c,v 1.25 2018/01/16 21:55:07 mikem Exp mikem $ -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BCK2835_LIBRARY_BUILD -#include "bcm2835.h" - -/* This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) -// You can do some safe, non-destructive testing on any platform with: -// gcc bcm2835.c -D BCM2835_TEST -// ./a.out -*/ -/*#define BCM2835_TEST*/ - -/* Uncommenting this define compiles alternative I2C code for the version 1 RPi -// The P1 header I2C pins are connected to SDA0 and SCL0 on V1. -// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. -*/ -/* #define I2C_V1*/ - -/* Physical address and size of the peripherals block -// May be overridden on RPi2 -*/ -uint32_t *bcm2835_peripherals_base = (uint32_t *)BCM2835_PERI_BASE; -uint32_t bcm2835_peripherals_size = BCM2835_PERI_SIZE; - -/* Virtual memory address of the mapped peripherals block - */ -uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED; - -/* And the register bases within the peripherals block - */ -volatile uint32_t *bcm2835_gpio = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pwm = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_clk = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pads = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc1 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_st = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_aux = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi1 = (uint32_t *)MAP_FAILED; - - -/* This variable allows us to test on hardware other than RPi. -// It prevents access to the kernel memory, and does not do any peripheral access -// Instead it prints out what it _would_ do if debug were 0 -*/ -static uint8_t debug = 0; - -/* I2C The time needed to transmit one byte. In microseconds. - */ -static int i2c_byte_wait_us = 0; - -/* -// Low level register access functions -*/ - -/* Function to return the pointers to the hardware register bases */ -uint32_t* bcm2835_regbase(uint8_t regbase) -{ - switch (regbase) - { - case BCM2835_REGBASE_ST: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_GPIO: - return (uint32_t *)bcm2835_gpio; - case BCM2835_REGBASE_PWM: - return (uint32_t *)bcm2835_pwm; - case BCM2835_REGBASE_CLK: - return (uint32_t *)bcm2835_clk; - case BCM2835_REGBASE_PADS: - return (uint32_t *)bcm2835_pads; - case BCM2835_REGBASE_SPI0: - return (uint32_t *)bcm2835_spi0; - case BCM2835_REGBASE_BSC0: - return (uint32_t *)bcm2835_bsc0; - case BCM2835_REGBASE_BSC1: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_AUX: - return (uint32_t *)bcm2835_aux; - case BCM2835_REGBASE_SPI1: - return (uint32_t *)bcm2835_spi1; - - } - return (uint32_t *)MAP_FAILED; -} - -void bcm2835_set_debug(uint8_t d) -{ - debug = d; -} - -unsigned int bcm2835_version(void) -{ - return BCM2835_VERSION; -} - -/* Read with memory barriers from peripheral - * - */ -uint32_t bcm2835_peri_read(volatile uint32_t* paddr) -{ - uint32_t ret; - if (debug) - { - printf("bcm2835_peri_read paddr %p\n", (void *) paddr); - return 0; - } - else - { - __sync_synchronize(); - ret = *paddr; - __sync_synchronize(); - return ret; - } -} - -/* read from peripheral without the read barrier - * This can only be used if more reads to THE SAME peripheral - * will follow. The sequence must terminate with memory barrier - * before any read or write to another peripheral can occur. - * The MB can be explicit, or one of the barrier read/write calls. - */ -uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) -{ - if (debug) - { - printf("bcm2835_peri_read_nb paddr %p\n", paddr); - return 0; - } - else - { - return *paddr; - } -} - -/* Write with memory barriers to peripheral - */ - -void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) -{ - if (debug) - { - printf("bcm2835_peri_write paddr %p, value %08X\n", paddr, value); - } - else - { - __sync_synchronize(); - *paddr = value; - __sync_synchronize(); - } -} - -/* write to peripheral without the write barrier */ -void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) -{ - if (debug) - { - printf("bcm2835_peri_write_nb paddr %p, value %08X\n", - paddr, value); - } - else - { - *paddr = value; - } -} - -/* Set/clear only the bits in value covered by the mask - * This is not atomic - can be interrupted. - */ -void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) -{ - uint32_t v = bcm2835_peri_read(paddr); - v = (v & ~mask) | (value & mask); - bcm2835_peri_write(paddr, v); -} - -/* -// Low level convenience functions -*/ - -/* Function select -// pin is a BCM2835 GPIO pin number NOT RPi pin number -// There are 6 control registers, each control the functions of a block -// of 10 pins. -// Each control register has 10 sets of 3 bits per GPIO pin: -// -// 000 = GPIO Pin X is an input -// 001 = GPIO Pin X is an output -// 100 = GPIO Pin X takes alternate function 0 -// 101 = GPIO Pin X takes alternate function 1 -// 110 = GPIO Pin X takes alternate function 2 -// 111 = GPIO Pin X takes alternate function 3 -// 011 = GPIO Pin X takes alternate function 4 -// 010 = GPIO Pin X takes alternate function 5 -// -// So the 3 bits for port X are: -// X / 10 + ((X % 10) * 3) -*/ -void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) -{ - /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); - uint8_t shift = (pin % 10) * 3; - uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; - uint32_t value = mode << shift; - bcm2835_peri_set_bits(paddr, value, mask); -} - -/* Set output pin */ -void bcm2835_gpio_set(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -/* Clear output pin */ -void bcm2835_gpio_clr(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -/* Set all output pins in the mask */ -void bcm2835_gpio_set_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Clear all output pins in the mask */ -void bcm2835_gpio_clr_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Read input pin */ -uint8_t bcm2835_gpio_lev(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -/* See if an event detection bit is set -// Sigh cant support interrupts yet -*/ -uint8_t bcm2835_gpio_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -uint32_t bcm2835_gpio_eds_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - uint32_t value = bcm2835_peri_read(paddr); - return (value & mask); -} - -/* Write a 1 to clear the bit in EDS */ -void bcm2835_gpio_set_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_write(paddr, value); -} - -void bcm2835_gpio_set_eds_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Rising edge detect enable */ -void bcm2835_gpio_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Falling edge detect enable */ -void bcm2835_gpio_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* High detect enable */ -void bcm2835_gpio_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Low detect enable */ -void bcm2835_gpio_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Async rising edge detect enable */ -void bcm2835_gpio_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Async falling edge detect enable */ -void bcm2835_gpio_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Set pullup/down */ -void bcm2835_gpio_pud(uint8_t pud) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; - bcm2835_peri_write(paddr, pud); -} - -/* Pullup/down clock -// Clocks the value of pud into the GPIO pin -*/ -void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); -} - -/* Read GPIO pad behaviour for groups of GPIOs */ -uint32_t bcm2835_gpio_pad(uint8_t group) -{ - if (bcm2835_pads == MAP_FAILED) - return 0; - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - return bcm2835_peri_read(paddr); -} - -/* Set GPIO pad behaviour for groups of GPIOs -// powerup value for all pads is -// BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA -*/ -void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) -{ - if (bcm2835_pads == MAP_FAILED) - return; - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); -} - -/* Some convenient arduino-like functions -// milliseconds -*/ -void bcm2835_delay(unsigned int millis) -{ - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; - nanosleep(&sleeper, NULL); -} - -/* microseconds */ -void bcm2835_delayMicroseconds(uint64_t micros) -{ - struct timespec t1; - uint64_t start; - - if (debug) - { - /* Cant access sytem timers in debug mode */ - printf("bcm2835_delayMicroseconds %lld\n", (long long int) micros); - return; - } - - /* Calling nanosleep() takes at least 100-200 us, so use it for - // long waits and use a busy wait on the System Timer for the rest. - */ - start = bcm2835_st_read(); - - /* Not allowed to access timer registers (result is not as precise)*/ - if (start==0) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros); - nanosleep(&t1, NULL); - return; - } - - if (micros > 450) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros - 200); - nanosleep(&t1, NULL); - } - - bcm2835_st_delay(start, micros); -} - -/* -// Higher level convenience functions -*/ - -/* Set the state of an output */ -void bcm2835_gpio_write(uint8_t pin, uint8_t on) -{ - if (on) - bcm2835_gpio_set(pin); - else - bcm2835_gpio_clr(pin); -} - -/* Set the state of a all 32 outputs in the mask to on or off */ -void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) -{ - if (on) - bcm2835_gpio_set_multi(mask); - else - bcm2835_gpio_clr_multi(mask); -} - -/* Set the state of a all 32 outputs in the mask to the values in value */ -void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) -{ - bcm2835_gpio_set_multi(value & mask); - bcm2835_gpio_clr_multi((~value) & mask); -} - -/* Set the pullup/down resistor for a pin -// -// The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on -// the respective GPIO pins. These registers must be used in conjunction with the GPPUD -// register to effect GPIO Pull-up/down changes. The following sequence of events is -// required: -// 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither -// to remove the current Pull-up/down) -// 2. Wait 150 cycles ? this provides the required set-up time for the control signal -// 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to -// modify ? NOTE only the pads which receive a clock will be modified, all others will -// retain their previous state. -// 4. Wait 150 cycles ? this provides the required hold time for the control signal -// 5. Write to GPPUD to remove the control signal -// 6. Write to GPPUDCLK0/1 to remove the clock -// -// RPi has P1-03 and P1-05 with 1k8 pullup resistor -*/ -void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) -{ - bcm2835_gpio_pud(pud); - delayMicroseconds(10); - bcm2835_gpio_pudclk(pin, 1); - delayMicroseconds(10); - bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_pudclk(pin, 0); -} - -int bcm2835_spi_begin(void) -{ - volatile uint32_t* paddr; - - if (bcm2835_spi0 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ - - /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ - - /* Set the SPI CS register to the some sensible defaults */ - paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - bcm2835_peri_write(paddr, 0); /* All 0s */ - - /* Clear TX and RX fifos */ - bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); - - return 1; // OK -} - -void bcm2835_spi_end(void) -{ - /* Set all the SPI0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); /* CLK */ -} - -void bcm2835_spi_setBitOrder(uint8_t __attribute__((unused)) order) -{ - /* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one supported by SPI0 */ -} - -/* defaults to 0, which means a divider of 65536. -// The divisor must be a power of 2. Odd numbers -// rounded down. The maximum SPI clock rate is -// of the APB clock -*/ -void bcm2835_spi_setClockDivider(uint16_t divider) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; - bcm2835_peri_write(paddr, divider); -} - -void bcm2835_spi_setDataMode(uint8_t mode) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CPO and CPHA bits of CS */ - bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); -} - -/* Writes (and reads) a single byte to SPI */ -uint8_t bcm2835_spi_transfer(uint8_t value) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t ret; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Clear TX and RX fifos - */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, value); - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Read any byte that was sent back by the slave while we sere sending to it */ - ret = bcm2835_peri_read_nb(fifo); - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); - - return ret; -} - -/* Writes (and reads) an number of bytes to SPI */ -void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t TXCnt=0; - uint32_t RXCnt=0; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - */ - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Use the FIFO's to reduce the interbyte times */ - while((TXCnt < len)||(RXCnt < len)) - { - /* TX fifo not full, so add some more bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) - { - bcm2835_peri_write_nb(fifo, tbuf[TXCnt]); - TXCnt++; - } - /* Rx fifo not empty, so get the next received bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) - { - rbuf[RXCnt] = bcm2835_peri_read_nb(fifo); - RXCnt++; - } - } - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -/* Writes an number of bytes to SPI */ -void bcm2835_spi_writenb(const char* tbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t i; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Answer: an ISR is required to issue the required memory barriers. - */ - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - for (i = 0; i < len; i++) - { - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, tbuf[i]); - - /* Read from FIFO to prevent stalling */ - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); - } - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); - }; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -/* Writes (and reads) an number of bytes to SPI -// Read bytes are copied over onto the transmit buffer -*/ -void bcm2835_spi_transfern(char* buf, uint32_t len) -{ - bcm2835_spi_transfernb(buf, buf, len); -} - -void bcm2835_spi_chipSelect(uint8_t cs) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CS bits of CS */ - bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); -} - -void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - uint8_t shift = 21 + cs; - /* Mask in the appropriate CSPOLn bit */ - bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); -} - -void bcm2835_spi_write(uint16_t data) { -#if 0 - char buf[2]; - - buf[0] = data >> 8; - buf[1] = data & 0xFF; - - bcm2835_spi_transfern(buf, 2); -#else - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO */ - bcm2835_peri_write_nb(fifo, (uint32_t) data >> 8); - bcm2835_peri_write_nb(fifo, data & 0xFF); - - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -#endif -} - -int bcm2835_aux_spi_begin(void) { - volatile uint32_t* enable = bcm2835_aux + BCM2835_AUX_ENABLE/4; - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - - if (bcm2835_spi1 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ - - /* Set the SPI pins to the Alt 4 function to enable SPI1 access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_ALT4); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_ALT4); /* SPI1_SCLK */ - - bcm2835_aux_spi_setClockDivider(bcm2835_aux_spi_CalcClockDivider(1000000)); // Default 1MHz SPI - - bcm2835_peri_write(enable, BCM2835_AUX_ENABLE_SPI0); - bcm2835_peri_write(cntl1, 0); - bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO); - - return 1; /* OK */ -} - -void bcm2835_aux_spi_end(void) { - /* Set all the SPI1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_INPT); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_INPT); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_INPT); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_INPT); /* SPI1_SCLK */ -} - -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) - -uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz) { - uint16_t divider; - - if (speed_hz < (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN; - } else if (speed_hz > (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX; - } - - divider = (uint16_t) DIV_ROUND_UP(BCM2835_CORE_CLK_HZ, 2 * speed_hz) - 1; - - if (divider > (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX) { - return (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX; - } - - return divider; -} - -static uint32_t spi1_speed; - -void bcm2835_aux_spi_setClockDivider(uint16_t divider) { - spi1_speed = (uint32_t) divider; -} - -void bcm2835_aux_spi_write(uint16_t data) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= 16; // Shift length - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; - - bcm2835_peri_write(io, (uint32_t) data << 16); -} - -void bcm2835_aux_spi_writenb(const char *tbuf, uint32_t len) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *) tbuf; - uint32_t tx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while (tx_len > 0) { - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; - - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) - ; - - (void) bcm2835_peri_read(io); - } -} - -void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *)tbuf; - char *rx = (char *)rbuf; - uint32_t tx_len = len; - uint32_t rx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while ((tx_len > 0) || (rx_len > 0)) { - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) && (tx_len > 0)) { - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_RX_EMPTY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - } -} - -void bcm2835_aux_spi_transfern(char *buf, uint32_t len) { - bcm2835_aux_spi_transfernb(buf, buf, len); -} - -int bcm2835_i2c_begin(void) -{ - uint16_t cdiv; - - if ( bcm2835_bsc0 == MAP_FAILED - || bcm2835_bsc1 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ - -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#endif - - /* Read the clock divider register */ - cdiv = bcm2835_peri_read(paddr); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; - - return 1; -} - -void bcm2835_i2c_end(void) -{ -#ifdef I2C_V1 - /* Set all the I2C/BSC0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#else - /* Set all the I2C/BSC1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#endif -} - -void bcm2835_i2c_setSlaveAddress(uint8_t addr) -{ - /* Set I2C Device Address */ -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; -#endif - bcm2835_peri_write(paddr, addr); -} - -/* defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. -// The divisor must be a power of 2. Odd numbers -// rounded down. -*/ -void bcm2835_i2c_setClockDivider(uint16_t divider) -{ -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; -#endif - bcm2835_peri_write(paddr, divider); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; -} - -/* set I2C clock divider by means of a baudrate number */ -void bcm2835_i2c_set_baudrate(uint32_t baudrate) -{ - uint32_t divider; - /* use 0xFFFE mask to limit a max value and round down any odd number */ - divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; - bcm2835_i2c_setClockDivider( (uint16_t)divider ); -} - -/* Writes an number of bytes to I2C */ -uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, len); - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; - } - - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* Transfer is over when BCM2835_BSC_S_DONE */ - while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) - { - while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) - { - /* Write to FIFO */ - bcm2835_peri_write(fifo, buf[i]); - i++; - remaining--; - } - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read an number of bytes from I2C */ -uint8_t bcm2835_i2c_read(char* buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write_nb(dlen, len); - /* Start read */ - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is received */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read an number of bytes from I2C sending a repeated start after writing -// the required register. Only works if your device supports this mode -*/ -uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, 1); - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); - bcm2835_peri_write(fifo, regaddr[0]); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) - break; - } - - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -/* Sending an arbitrary number of bytes before issuing a repeated start -// (with no prior stop) and reading a response. Some devices require this behavior. -*/ -uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = cmds_len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - - /* Set Data Length */ - bcm2835_peri_write(dlen, cmds_len); - - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { - bcm2835_peri_write_nb(fifo, cmds[i]); - i++; - remaining--; - } - - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) - break; - } - - remaining = buf_len; - i = 0; - - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, buf_len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read the System Timer Counter (64-bits) */ -uint64_t bcm2835_st_read(void) -{ - volatile uint32_t* paddr; - uint32_t hi, lo; - uint64_t st; - - if (bcm2835_st==MAP_FAILED) - return 0; - - paddr = bcm2835_st + BCM2835_ST_CHI/4; - hi = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CLO/4; - lo = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CHI/4; - st = bcm2835_peri_read(paddr); - - /* Test for overflow */ - if (st == hi) - { - st <<= 32; - st += lo; - } - else - { - st <<= 32; - paddr = bcm2835_st + BCM2835_ST_CLO/4; - st += bcm2835_peri_read(paddr); - } - return st; -} - -/* Delays for the specified number of microseconds with offset */ -void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) -{ - uint64_t compare = offset_micros + micros; - - while(bcm2835_st_read() < compare) - ; -} - -/* PWM */ - -void bcm2835_pwm_set_clock(uint32_t divisor) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - /* From Gerts code */ - divisor &= 0xfff; - /* Stop PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); - bcm2835_delay(110); /* Prevents clock going slow */ - /* Wait for the clock to be not busy */ - while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) - bcm2835_delay(1); - /* set the clock divider and enable PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ -} - -void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); - - if (channel == 0) - { - if (markspace) - control |= BCM2835_PWM0_MS_MODE; - else - control &= ~BCM2835_PWM0_MS_MODE; - if (enabled) - control |= BCM2835_PWM0_ENABLE; - else - control &= ~BCM2835_PWM0_ENABLE; - } - else if (channel == 1) - { - if (markspace) - control |= BCM2835_PWM1_MS_MODE; - else - control &= ~BCM2835_PWM1_MS_MODE; - if (enabled) - control |= BCM2835_PWM1_ENABLE; - else - control &= ~BCM2835_PWM1_ENABLE; - } - - /* If you use the barrier here, wierd things happen, and the commands dont work */ - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); - /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ - -} - -void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); -} - -void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); -} - -/* Allocate page-aligned memory. */ -void *malloc_aligned(size_t size) -{ - void *mem; - errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); - return (errno ? NULL : mem); -} - -/* Map 'size' bytes starting at 'off' in file 'fd' to memory. -// Return mapped address on success, MAP_FAILED otherwise. -// On error print message. -*/ -static void *mapmem(const char *msg, size_t size, int fd, off_t off) -{ - void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); - if (map == MAP_FAILED) - fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); - return map; -} - -static void unmapmem(void **pmem, size_t size) -{ - if (*pmem == MAP_FAILED) return; - munmap(*pmem, size); - *pmem = MAP_FAILED; -} - -/* Initialise this library. */ -int bcm2835_init(void) -{ - int memfd; - int ok; - FILE *fp; - - if (debug) - { - bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; - - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - return 1; /* Success */ - } - - /* Figure out the base and size of the peripheral address block - // using the device-tree. Required for RPi2, optional for RPi 1 - */ - if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) - { - unsigned char buf[4]; - fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET); - if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) - bcm2835_peripherals_base = (uint32_t *)((long)buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); - fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET); - if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) - bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); - fclose(fp); - } - /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ - - /* Now get ready to map the peripherals block - * If we are not root, try for the new /dev/gpiomem interface and accept - * the fact that we can only access GPIO - * else try for the /dev/mem interface and get access to everything - */ - memfd = -1; - ok = 0; - if (geteuid() == 0) - { - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) - { - fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals = static_cast(mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t)bcm2835_peripherals_base)); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - - /* Now compute the base addresses of various peripherals, - // which are at fixed offsets within the mapped peripherals block - // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 - */ - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - ok = 1; - } - else - { - /* Not root, try /dev/gpiomem */ - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) - { - fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals_base = 0; - bcm2835_peripherals = static_cast(mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t)bcm2835_peripherals_base)); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - bcm2835_gpio = bcm2835_peripherals; - ok = 1; - } - -exit: - if (memfd >= 0) - close(memfd); - - if (!ok) - bcm2835_close(); - - return ok; -} - -/* Close this library and deallocate everything */ -int bcm2835_close(void) -{ - if (debug) return 1; /* Success */ - - unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); - bcm2835_peripherals = static_cast(MAP_FAILED); - bcm2835_gpio = static_cast(MAP_FAILED); - bcm2835_pwm = static_cast(MAP_FAILED); - bcm2835_clk = static_cast(MAP_FAILED); - bcm2835_pads = static_cast(MAP_FAILED); - bcm2835_spi0 = static_cast(MAP_FAILED); - bcm2835_bsc0 = static_cast(MAP_FAILED); - bcm2835_bsc1 = static_cast(MAP_FAILED); - bcm2835_st = static_cast(MAP_FAILED); - bcm2835_aux = static_cast(MAP_FAILED); - bcm2835_spi1 = static_cast(MAP_FAILED); - return 1; /* Success */ -} - -#ifdef BCM2835_TEST -/* this is a simple test program that prints out what it will do rather than -// actually doing it -*/ -int main(int argc, char **argv) -{ - /* Be non-destructive */ - bcm2835_set_debug(1); - - if (!bcm2835_init()) - return 1; - - /* Configure some GPIO pins fo some testing - // Set RPI pin P1-11 to be an output - */ - bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); - /* Set RPI pin P1-15 to be an input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); - /* with a pullup */ - bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); - /* And a low detect enable */ - bcm2835_gpio_len(RPI_GPIO_P1_15); - /* and input hysteresis disabled on GPIOs 0 to 27 */ - bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); - -#if 1 - /* Blink */ - while (1) - { - /* Turn it on */ - bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); - - /* wait a bit */ - bcm2835_delay(500); - - /* turn it off */ - bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Read input */ - while (1) - { - /* Read some data */ - uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); - printf("read from pin 15: %d\n", value); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Look for a low event detection - // eds will be set whenever pin 15 goes low - */ - while (1) - { - if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) - { - /* Now clear the eds flag by setting it to 1 */ - bcm2835_gpio_set_eds(RPI_GPIO_P1_15); - printf("low event detect for pin 15\n"); - } - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - - if (!bcm2835_close()) - return 1; - - return 0; -} -#endif - - diff --git a/rootfs/usr/share/d3m0n/src/lib/bcm2835.h b/rootfs/usr/share/d3m0n/src/lib/bcm2835.h deleted file mode 100644 index cb7eda84..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/bcm2835.h +++ /dev/null @@ -1,1894 +0,0 @@ -#pragma once -/* bcm2835.h - - C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi - - Author: Mike McCauley - Copyright (C) 2011-2013 Mike McCauley - $Id: bcm2835.h,v 1.23 2018/01/16 21:55:07 mikem Exp mikem $ -*/ - -/*! \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi - - This is a C library for Raspberry Pi (RPi). It provides access to - GPIO and other IO functions on the Broadcom BCM 2835 chip, as used in the RaspberryPi, - allowing access to the GPIO pins on the - 26 pin IDE plug on the RPi board so you can control and interface with various external devices. - - It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, - and for accessing the system timers. - Pin event detection is supported by polling (interrupts are not supported). - - It is C++ compatible, and installs as a header file and non-shared library on - any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with - BCM 2835). - - The version of the package that this documentation refers to can be downloaded - from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.55.tar.gz - You can find the latest version at http://www.airspayce.com/mikem/bcm2835 - - Several example programs are provided. - - Based on data in http://elinux.org/RPi_Low-level_peripherals and - http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf - and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 - - You can also find online help and discussion at http://groups.google.com/group/bcm2835 - Please use that group for all questions and discussions on this topic. - Do not contact the author directly, unless it is to discuss commercial licensing. - Before asking a question or reporting a bug, please read - - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question - - http://www.catb.org/esr/faqs/smart-questions.html - - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html - - Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian - and Occidentalisv01, 2016-02-09 Raspbian Jessie. - CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() - are used and the pin is pulled LOW - it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian - and Occidentalisv01. - Reason for this is not yet determined, but we suspect that an interrupt handler is - hitting a hard loop on those OSs. - If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with - bcm2835_gpio_clr_len() and friends after use. - - \par Running as root - - Prior to the release of Raspbian Jessie in Feb 2016, access to any - peripheral device via /dev/mem on the RPi required the process to - run as root. Raspbian Jessie permits non-root users to access the - GPIO peripheral (only) via /dev/gpiomem, and this library supports - that limited mode of operation. - - If the library runs with effective UID of 0 (ie root), then - bcm2835_init() will attempt to open /dev/mem, and, if successful, it - will permit use of all peripherals and library functions. - - If the library runs with any other effective UID (ie not root), then - bcm2835_init() will attempt to open /dev/gpiomem, and, if - successful, will only permit GPIO operations. In particular, - bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all - other non-gpio operations may fail silently or crash. - - \par Installation - - This library consists of a single non-shared library and header file, which will be - installed in the usual places by make install - - \code - # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: - tar zxvf bcm2835-1.xx.tar.gz - cd bcm2835-1.xx - ./configure - make - sudo make check - sudo make install - \endcode - - \par Physical Addresses - - The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() - are low level peripheral register access functions. They are designed to use - physical addresses as described in section 1.2.3 ARM physical addresses - of the BCM2835 ARM Peripherals manual. - Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus - addresses for peripherals are set up to map onto the peripheral bus address range starting at - 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at - physical address 0x20nnnnnn. - - On RPI 2, the peripheral addresses are different and the bcm2835 library gets them - from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2. - - After initialisation, the base address of the various peripheral - registers are available with the following - externals: - bcm2835_gpio - bcm2835_pwm - bcm2835_clk - bcm2835_pads - bcm2835_spio0 - bcm2835_st - bcm2835_bsc0 - bcm2835_bsc1 - bcm2835_aux - bcm2835_spi1 - - \par Raspberry Pi 2 (RPI2) - - For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel. - You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 - with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29. - - When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, - and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). - Without device tree support enabled and the presence of this file, it will not work on RPI2. - - To enable device tree support: - - \code - sudo raspi-config - under Advanced Options - enable Device Tree - Reboot. - \endcode - - \par Pin Numbering - - The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying - BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs - - RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, - as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the - IDE header. - - RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. - - The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ - the RPi pin number. There are symbolic definitions for each of the available pins - that you should use for convenience. See \ref RPiGPIOPin. - - \par SPI Pins - - The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, - allowing you to send and received data by SPI (Serial Peripheral Interface). - For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - - When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their - default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able - to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). - When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be - configured and controled with the usual bcm2835_gpio_* calls. - - The Raspberry Pi GPIO pins used for SPI are: - - - P1-19 (MOSI) - - P1-21 (MISO) - - P1-23 (CLK) - - P1-24 (CE0) - - P1-26 (CE1) - - Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider()) - you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the - SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines - ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. - Dont expect any speed faster than 31MHz to work reliably. - - The bcm2835_aux_spi_* functions allow you to control the BCM 2835 SPI1 interface, - allowing you to send and received data by SPI (Serial Peripheral Interface). - - The Raspberry Pi GPIO pins used for AUX SPI (SPI1) are: - - - P1-38 (MOSI) - - P1-35 (MISO) - - P1-40 (CLK) - - P1-36 (CE2) - - \par I2C Pins - - The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, - allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . - For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C - - The Raspberry Pi V2 GPIO pins used for I2C are: - - - P1-03 (SDA) - - P1-05 (SLC) - - \par PWM - - The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides - functions for configuring and controlling PWM output on these pins. - - The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of - GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): - \code - GPIO PIN RPi pin PWM Channel ALT FUN - 12 0 0 - 13 1 0 - 18 1-12 0 5 - 19 1 5 - 40 0 0 - 41 1 0 - 45 1 0 - 52 0 1 - 53 1 1 - \endcode - In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. - Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) - on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. - Further it must be set to ALT FUN 5 to get PWM output. - - Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using - bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). - The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. - Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio - - Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware - sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. - In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by - LOW for RANGE-DATA clock pulses. - - The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from - a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* - values of \ref bcm2835PWMClockDivider. - - For example, say you wanted to drive a DC motor with PWM at about 1kHz, - and control the speed in 1/1024 increments from - 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the - clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be - 1.2MHz/1024 = 1171.875Hz. - - \par Interactions with other systems - - In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using: - - \code - sudo raspi-config - under Advanced Options - enable Device Tree - under Advanced Options - disable SPI - Reboot. - \endcode - - Since bcm2835 accesses the lowest level hardware interfaces (in eh intererests of speed and flexibility) - there can be intercations with other low level software trying to do similar things. - - It seems that with "latest" 8.0 Jessie 4.9.24-v7+ kernel PWM just won't - work unless you disable audio. There's a line - \code - dtparam=audio=on - \endcode - in the /boot/config.txt. - Comment it out like this: - \code - #dtparam=audio=on - \endcode - - \par Real Time performance constraints - - The bcm2835 is a library for user programs (i.e. they run in 'userland'). - Such programs are not part of the kernel and are usually - subject to paging and swapping by the kernel while it does other things besides running your program. - This means that you should not expect to get real-time performance or - real-time timing constraints from such programs. In particular, there is no guarantee that the - bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. - In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times - than the one you asked for. So please dont expect to get exactly the time delay you request. - - Arjan reports that you can prevent swapping on Linux with the following code fragment: - - \code - #define - #define - - struct sched_param sp; - memset(&sp, 0, sizeof(sp)); - sp.sched_priority = sched_get_priority_max(SCHED_FIFO); - sched_setscheduler(0, SCHED_FIFO, &sp); - mlockall(MCL_CURRENT | MCL_FUTURE); - \endcode - - \par Bindings to other languages - - mikem has made Perl bindings available at CPAN: - http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm - Matthew Baker has kindly made Python bindings available at: - https: github.com/mubeta06/py-libbcm2835 - Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility - for Raspberry Pi, based on the bcm2835 library. The - utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a - free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ - - \par Open Source Licensing GPL V2 - - This is the appropriate option if you want to share the source code of your - application with everyone you distribute it to, and you also want to give them - the right to share who uses it. If you wish to use this software under Open - Source Licensing, you must contribute all your source code to the open source - community in accordance with the GPL Version 2 when your application is - distributed. See https://www.gnu.org/licenses/gpl-2.0.html and COPYING - - \par Commercial Licensing - - This is the appropriate option if you are creating proprietary applications - and you are not prepared to distribute and share the source code of your - application. Purchase commercial licenses at http://airspayce.binpress.com - - \par Acknowledgements - - Some of this code has been inspired by Dom and Gert. - The I2C code has been inspired by Alan Barr. - - \par Revision History - - \version 1.0 Initial release - - \version 1.1 Minor bug fixes - - \version 1.2 Added support for SPI - - \version 1.3 Added bcm2835_spi_transfern() - - \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. - - \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz - - \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 - Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() - bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now - changes only the pin specified. Other pins that were already previously - enabled stay enabled. - Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() - bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() - to clear the enable for individual pins, suggested by Andreas Sundstrom. - - \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. - - \version 1.8 Improvements to read barrier, as suggested by maddin. - - \version 1.9 Improvements contributed by mikew: - I noticed that it was mallocing memory for the mmaps on /dev/mem. - It's not necessary to do that, you can just mmap the file directly, - so I've removed the mallocs (and frees). - I've also modified delayMicroseconds() to use nanosleep() for long waits, - and a busy wait on a high resolution timer for the rest. This is because - I've found that calling nanosleep() takes at least 100-200 us. - You need to link using '-lrt' using this version. - I've added some unsigned casts to the debug prints to silence compiler - warnings I was getting, fixed some typos, and changed the value of - BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at - http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 - Also added a define for the passwrd value that Gert says is needed to - change pad control settings. - - \version 1.10 Changed the names of the delay functions to bcm2835_delay() - and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. - Macros to map delay()-> bcm2835_delay() and - Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which - can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY - - \version 1.11 Fixed incorrect link to download file - - \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) - - \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 - Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio - bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. - - \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. - Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. - Reported by Ben Simpson. - - \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. - - \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi - to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. - - \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. - - \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: - now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. - No need to link with -lrt now. Contributed by Arjan van Vught. - \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. - Reported by olly. - - \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. - - \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. - Patch courtesy Jeremy Mortis. - - \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set - falling edge events. Reported by Mark Dootson. - - \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. - Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions - to fix ocasional reads not completing. Patched by Mark Dootson. - - \version 1.24 Mark Dootson p[atched a problem with his previously submitted code - under high load from other processes. - - \version 1.25 Updated author and distribution location details to airspayce.com - - \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. - Reported by Hartmut Henkel. - - \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is - now automatically included. - Added suport for PWM mode with bcm2835_pwm_* functions. - - \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than - 64 bytes dues to read buffer filling. Patched by Peter Würtz. - - \version 1.29 Further fix to SPI from Peter Würtz. - - \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for - significant performance improvements, Patch by Alan Watson. - - \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. - - \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. - By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. - Contributed by Malcolm Wiles based on work by Arvi Govindaraj. - - \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. - - \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, - sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. - - \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas. - - \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second - one makes us skip the test when using fakeroot (as used when building - Debian packages). Contributed by Guido Günther. - - \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
- Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
- Added definitions for Raspberry Pi B+ J8 header GPIO pins.
- - \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
- - \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. - Testers please confirm correct operation on RPi2.
- Unneccessary 'volatile' qualifiers removed from all variables and signatures.
- Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
- Minor improvements to spi.c example.
- - \version 1.40 Correct operation on RPi2 has been confirmed.
- Fixed a number of compiler errors and warnings that occur when bcm2835.h is included - in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic. - Reported by tlhackque.
- Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
- Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
- - \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.
- Improvements to peripheral memory barriers as suggested by tlhackque.
- Reinstated some necessary volatile declarations as requested by tlhackque.
- - \version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
- - \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. - Reported and patched by Lars Christensen.
- Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
- - \version 1.44 Added documention about the need for device tree to be enabled on RPI2.
- Improvements to detection of availablity of DMB instruction based on value of __ARM_ARCH macro.
- - \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() - and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido. - - \version 1.46 2015-09-18 - Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2.
- - \version 1.47 2015-11-18 - Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.
- - \version 1.48 2015-12-08 - Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs - and others. - - \version 1.49 2016-01-05 - Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi(). - - \version 1.50 2016-02-28 - Added support for running as non-root, permitting access to GPIO only. Functions - bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root - (which prevents access to the SPI and I2C peripherals, amongst others). - Testing on Raspbian Jessie. - - \version 1.51 2016-11-03 - Added documentation about SPI clock divider and resulting SPI speeds on RPi3. - Fixed a problem where seg fault could occur in bcm2835_delayMicroseconds() if not running as root. Patch from Pok. - - \version 1.52 2017-02-03 - Added link to commercial license purchasing. - - \version 1.53 2018-01-14 - Added support for AUX SPI (SPI1) - Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/) - - \version 1.54 2018-01-17 - Fixed compile errors in new AUX spi code under some circumstances. - - \version 1.55 2018-01-20 - Fixed version numbers. - Fixed some warnings. - - \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS -*/ - - -/* Defines for BCM2835 */ -#ifndef BCM2835_H -#define BCM2835_H - -#include - -#define BCM2835_VERSION 10055 /* Version 1.55 */ - -/* RPi 2 is ARM v7, and has DMB instruction for memory barriers. - Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead. - However, not all versions of gcc in all distros support the dmb assembler instruction even on conmpatible processors. - This test is so any ARMv7 or higher processors with suitable GCC will use DMB. -*/ -#if __ARM_ARCH >= 7 -#define BCM2835_HAVE_DMB -#endif - -/*! \defgroup constants Constants for passing to and from library functions - The values here are designed to be passed to various functions in the bcm2835 library. - @{ -*/ - -/*! This means pin HIGH, true, 3.3volts on a pin. */ -#define HIGH 0x1 -/*! This means pin LOW, false, 0volts on a pin. */ -#define LOW 0x0 - -/*! Return the minimum of 2 numbers */ -#ifndef MIN -#define MIN(a, b) (a < b ? a : b) -#endif - -/*! Speed of the core clock core_clk */ -#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ - -/*! On RPi2 with BCM2836, and all recent OSs, the base of the peripherals is read from a /proc file */ -#define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges" -/*! Offset into BMC2835_RPI2_DT_FILENAME for the peripherals base address */ -#define BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET 4 -/*! Offset into BMC2835_RPI2_DT_FILENAME for the peripherals size address */ -#define BMC2835_RPI2_DT_PERI_SIZE_OFFSET 8 - -/*! Physical addresses for various peripheral register sets - Base Physical Address of the BCM 2835 peripheral registers - Note this is different for the RPi2 BCM2836, where this is derived from /proc/device-tree/soc/ranges - If /proc/device-tree/soc/ranges exists on a RPi 1 OS, it would be expected to contain the - following numbers: -*/ -/*! Peripherals block base address on RPi 1 */ -#define BCM2835_PERI_BASE 0x20000000 -/*! Size of the peripherals block on RPi 1 */ -#define BCM2835_PERI_SIZE 0x01000000 - -/*! Offsets for the bases of various peripherals within the peripherals block - / Base Address of the System Timer registers -*/ -#define BCM2835_ST_BASE 0x3000 -/*! Base Address of the Pads registers */ -#define BCM2835_GPIO_PADS 0x100000 -/*! Base Address of the Clock/timer registers */ -#define BCM2835_CLOCK_BASE 0x101000 -/*! Base Address of the GPIO registers */ -#define BCM2835_GPIO_BASE 0x200000 -/*! Base Address of the SPI0 registers */ -#define BCM2835_SPI0_BASE 0x204000 -/*! Base Address of the BSC0 registers */ -#define BCM2835_BSC0_BASE 0x205000 -/*! Base Address of the PWM registers */ -#define BCM2835_GPIO_PWM 0x20C000 -/*! Base Address of the AUX registers */ -#define BCM2835_AUX_BASE 0x215000 -/*! Base Address of the AUX_SPI1 registers */ -#define BCM2835_SPI1_BASE 0x215080 -/*! Base Address of the AUX_SPI2 registers */ -#define BCM2835_SPI2_BASE 0x2150C0 -/*! Base Address of the BSC1 registers */ -#define BCM2835_BSC1_BASE 0x804000 - - -/*! Physical address and size of the peripherals block - May be overridden on RPi2 -*/ -extern uint32_t *bcm2835_peripherals_base; -/*! Size of the peripherals block to be mapped */ -extern uint32_t bcm2835_peripherals_size; - -/*! Virtual memory address of the mapped peripherals block */ -extern uint32_t *bcm2835_peripherals; - -/*! Base of the ST (System Timer) registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_st; - -/*! Base of the GPIO registers. - Available after bcm2835_init has been called -*/ -extern volatile uint32_t *bcm2835_gpio; - -/*! Base of the PWM registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_pwm; - -/*! Base of the CLK registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_clk; - -/*! Base of the PADS registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_pads; - -/*! Base of the SPI0 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_spi0; - -/*! Base of the BSC0 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_bsc0; - -/*! Base of the BSC1 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_bsc1; - -/*! Base of the AUX registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_aux; - -/*! Base of the SPI1 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_spi1; - - -/*! \brief bcm2835RegisterBase - Register bases for bcm2835_regbase() -*/ -typedef enum -{ - BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ - BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ - BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ - BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ - BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ - BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ - BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ - BCM2835_REGBASE_BSC1 = 8, /*!< Base of the BSC1 registers. */ - BCM2835_REGBASE_AUX = 9, /*!< Base of the AUX registers. */ - BCM2835_REGBASE_SPI1 = 10 /*!< Base of the SPI1 registers. */ -} bcm2835RegisterBase; - -/*! Size of memory page on RPi */ -#define BCM2835_PAGE_SIZE (4*1024) -/*! Size of memory block on RPi */ -#define BCM2835_BLOCK_SIZE (4*1024) - - -/* Defines for GPIO - The BCM2835 has 54 GPIO pins. - BCM2835 data sheet, Page 90 onwards. -*/ -/*! GPIO register offsets from BCM2835_GPIO_BASE. - Offsets into the GPIO Peripheral block in bytes per 6.1 Register View -*/ -#define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */ -#define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */ -#define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */ -#define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */ -#define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */ -#define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */ -#define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */ -#define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */ -#define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */ -#define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */ -#define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */ -#define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */ -#define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */ -#define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */ -#define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */ -#define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */ -#define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */ -#define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */ -#define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */ -#define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */ -#define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */ -#define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */ -#define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */ -#define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */ -#define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */ -#define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */ -#define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */ -#define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */ -#define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */ - -/*! \brief bcm2835PortFunction - Port function select modes for bcm2835_gpio_fsel() -*/ -typedef enum -{ - BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ - BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ - BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ - BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ - BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ - BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ - BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ - BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ - BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ -} bcm2835FunctionSelect; - -/*! \brief bcm2835PUDControl - Pullup/Pulldown defines for bcm2835_gpio_pud() -*/ -typedef enum -{ - BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ - BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ - BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ -} bcm2835PUDControl; - -/*! Pad control register offsets from BCM2835_GPIO_PADS */ -#define BCM2835_PADS_GPIO_0_27 0x002c /*!< Pad control register for pads 0 to 27 */ -#define BCM2835_PADS_GPIO_28_45 0x0030 /*!< Pad control register for pads 28 to 45 */ -#define BCM2835_PADS_GPIO_46_53 0x0034 /*!< Pad control register for pads 46 to 53 */ - -/*! Pad Control masks */ -#define BCM2835_PAD_PASSWRD (0x5A << 24) /*!< Password to enable setting pad mask */ -#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 /*!< Slew rate unlimited */ -#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 /*!< Hysteresis enabled */ -#define BCM2835_PAD_DRIVE_2mA 0x00 /*!< 2mA drive current */ -#define BCM2835_PAD_DRIVE_4mA 0x01 /*!< 4mA drive current */ -#define BCM2835_PAD_DRIVE_6mA 0x02 /*!< 6mA drive current */ -#define BCM2835_PAD_DRIVE_8mA 0x03 /*!< 8mA drive current */ -#define BCM2835_PAD_DRIVE_10mA 0x04 /*!< 10mA drive current */ -#define BCM2835_PAD_DRIVE_12mA 0x05 /*!< 12mA drive current */ -#define BCM2835_PAD_DRIVE_14mA 0x06 /*!< 14mA drive current */ -#define BCM2835_PAD_DRIVE_16mA 0x07 /*!< 16mA drive current */ - -/*! \brief bcm2835PadGroup - Pad group specification for bcm2835_gpio_pad() -*/ -typedef enum -{ - BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ - BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ - BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ -} bcm2835PadGroup; - -/*! \brief GPIO Pin Numbers - - Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. - These can be passed as a pin number to any function requiring a pin. - Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins - and some can adopt an alternate function. - RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. - RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*. - At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively - When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI - and cant be controlled independently. - If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these - symbolic names -*/ -typedef enum -{ - RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ - RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ - RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ - RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ - RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ - RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ - RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ - RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ - RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ - RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ - RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ - RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ - RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ - RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ - - /* RPi Version 2 */ - RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ - RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ - RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ - RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ - RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ - RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ - RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ - RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ - RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ - RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ - RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ - RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ - RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ - RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ - RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ - RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ - RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ - RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ - RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ - RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ - RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ - RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ - - /* RPi Version 2, new plug P5 */ - RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ - RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ - RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ - RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ - - /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ - RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ - RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ - RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ - RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ - RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ - RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ - RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ - RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ - RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ - RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ - RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ - RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ - RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ - RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ - RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ - RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ - RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ - RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ - RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ - RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ - RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ - RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ -} RPiGPIOPin; - -/* Defines for AUX - GPIO register offsets from BCM2835_AUX_BASE. -*/ -#define BCM2835_AUX_IRQ 0x0000 /*! xxx */ -#define BCM2835_AUX_ENABLE 0x0004 /*! */ - -#define BCM2835_AUX_ENABLE_UART1 0x01 /*!< */ -#define BCM2835_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */ -#define BCM2835_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */ - - -#define BCM2835_AUX_SPI_CNTL0 0x0000 /*!< */ -#define BCM2835_AUX_SPI_CNTL1 0x0004 /*!< */ -#define BCM2835_AUX_SPI_STAT 0x0008 /*!< */ -#define BCM2835_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */ -#define BCM2835_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */ -#define BCM2835_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */ - -#define BCM2835_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */ -#define BCM2835_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */ - -#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*! */ -#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*! */ -#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 /*! */ - -#define BCM2835_AUX_SPI_CNTL0_CS0_N 0x000C0000 /*!< CS 0 low */ -#define BCM2835_AUX_SPI_CNTL0_CS1_N 0x000A0000 /*!< CS 1 low */ -#define BCM2835_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */ - -#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*! */ -#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*! */ -#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*! */ -#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*! */ -#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 /*! */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*! */ -#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*! */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*! */ -#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 /*! */ -#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*! */ -#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*! */ - -#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*! */ -#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 /*! */ -#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*! */ -#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*! */ -#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*! */ - -#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 /*! */ -#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 /*! */ -#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 /*! */ -#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*! */ -#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 /*! */ -#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*! */ -#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 /*! */ -#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F /*! */ - -/* Defines for SPI - GPIO register offsets from BCM2835_SPI0_BASE. - Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map -*/ -#define BCM2835_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ -#define BCM2835_SPI0_FIFO 0x0004 /*!< SPI Master TX and RX FIFOs */ -#define BCM2835_SPI0_CLK 0x0008 /*!< SPI Master Clock Divider */ -#define BCM2835_SPI0_DLEN 0x000c /*!< SPI Master Data Length */ -#define BCM2835_SPI0_LTOH 0x0010 /*!< SPI LOSSI mode TOH */ -#define BCM2835_SPI0_DC 0x0014 /*!< SPI DMA DREQ Controls */ - -/* Register masks for SPI0_CS */ -#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 /*!< Enable Long data word in Lossi mode if DMA_LEN is set */ -#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 /*!< Enable DMA mode in Lossi mode */ -#define BCM2835_SPI0_CS_CSPOL2 0x00800000 /*!< Chip Select 2 Polarity */ -#define BCM2835_SPI0_CS_CSPOL1 0x00400000 /*!< Chip Select 1 Polarity */ -#define BCM2835_SPI0_CS_CSPOL0 0x00200000 /*!< Chip Select 0 Polarity */ -#define BCM2835_SPI0_CS_RXF 0x00100000 /*!< RXF - RX FIFO Full */ -#define BCM2835_SPI0_CS_RXR 0x00080000 /*!< RXR RX FIFO needs Reading (full) */ -#define BCM2835_SPI0_CS_TXD 0x00040000 /*!< TXD TX FIFO can accept Data */ -#define BCM2835_SPI0_CS_RXD 0x00020000 /*!< RXD RX FIFO contains Data */ -#define BCM2835_SPI0_CS_DONE 0x00010000 /*!< Done transfer Done */ -#define BCM2835_SPI0_CS_TE_EN 0x00008000 /*!< Unused */ -#define BCM2835_SPI0_CS_LMONO 0x00004000 /*!< Unused */ -#define BCM2835_SPI0_CS_LEN 0x00002000 /*!< LEN LoSSI enable */ -#define BCM2835_SPI0_CS_REN 0x00001000 /*!< REN Read Enable */ -#define BCM2835_SPI0_CS_ADCS 0x00000800 /*!< ADCS Automatically Deassert Chip Select */ -#define BCM2835_SPI0_CS_INTR 0x00000400 /*!< INTR Interrupt on RXR */ -#define BCM2835_SPI0_CS_INTD 0x00000200 /*!< INTD Interrupt on Done */ -#define BCM2835_SPI0_CS_DMAEN 0x00000100 /*!< DMAEN DMA Enable */ -#define BCM2835_SPI0_CS_TA 0x00000080 /*!< Transfer Active */ -#define BCM2835_SPI0_CS_CSPOL 0x00000040 /*!< Chip Select Polarity */ -#define BCM2835_SPI0_CS_CLEAR 0x00000030 /*!< Clear FIFO Clear RX and TX */ -#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 /*!< Clear FIFO Clear RX */ -#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 /*!< Clear FIFO Clear TX */ -#define BCM2835_SPI0_CS_CPOL 0x00000008 /*!< Clock Polarity */ -#define BCM2835_SPI0_CS_CPHA 0x00000004 /*!< Clock Phase */ -#define BCM2835_SPI0_CS_CS 0x00000003 /*!< Chip Select */ - -/*! \brief bcm2835SPIBitOrder SPI Bit order - Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() -*/ -typedef enum -{ - BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ - BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ -}bcm2835SPIBitOrder; - -/*! \brief SPI Data mode - Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() -*/ -typedef enum -{ - BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ - BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ - BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ - BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ -}bcm2835SPIMode; - -/*! \brief bcm2835SPIChipSelect - Specify the SPI chip select pin(s) -*/ -typedef enum -{ - BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ - BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ - BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ - BCM2835_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ -} bcm2835SPIChipSelect; - -/*! \brief bcm2835SPIClockDivider - Specifies the divider used to generate the SPI clock from the system clock. - Figures below give the divider, clock period and clock frequency. - Clock divided is based on nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3. - It is reported that (contrary to the documentation) any even divider may used. - The frequencies shown for each divider have been confirmed by measurement on RPi1 and RPi2. - The system clock frequency on RPi3 is different, so the frequency you get from a given divider will be different. - See comments in 'SPI Pins' for information about reliable SPI speeds. - Note: it is possible to change the core clock rate of the RPi 3 back to 250MHz, by putting - \code - core_freq=250 - \endcode - in the config.txt -*/ -typedef enum -{ - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ - BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ -} bcm2835SPIClockDivider; - -/* Defines for I2C - GPIO register offsets from BCM2835_BSC*_BASE. - Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map -*/ -#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ -#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ -#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ -#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ -#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ -#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ -#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ -#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ - -/* Register masks for BSC_C */ -#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ -#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ -#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ -#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ -#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ -#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ - -/* Register masks for BSC_S */ -#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ -#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ -#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ -#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ -#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ -#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ -#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ -#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ - -#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ - -/*! \brief bcm2835I2CClockDivider - Specifies the divider used to generate the I2C clock from the system clock. - Clock divided is based on nominal base clock rate of 250MHz -*/ -typedef enum -{ - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ - BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ -} bcm2835I2CClockDivider; - -/*! \brief bcm2835I2CReasonCodes - Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. -*/ -typedef enum -{ - BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ - BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ - BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ -} bcm2835I2CReasonCodes; - -/* Defines for ST - GPIO register offsets from BCM2835_ST_BASE. - Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers - The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. - BCM2835_ST_CLO is the System Timer Counter Lower bits register. - The system timer free-running counter lower register is a read-only register that returns the current value - of the lower 32-bits of the free running counter. - BCM2835_ST_CHI is the System Timer Counter Upper bits register. - The system timer free-running counter upper register is a read-only register that returns the current value - of the upper 32-bits of the free running counter. -*/ -#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ -#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ -#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ - -/*! @} */ - - -/* Defines for PWM, word offsets (ie 4 byte multiples) */ -#define BCM2835_PWM_CONTROL 0 -#define BCM2835_PWM_STATUS 1 -#define BCM2835_PWM_DMAC 2 -#define BCM2835_PWM0_RANGE 4 -#define BCM2835_PWM0_DATA 5 -#define BCM2835_PWM_FIF1 6 -#define BCM2835_PWM1_RANGE 8 -#define BCM2835_PWM1_DATA 9 - -/* Defines for PWM Clock, word offsets (ie 4 byte multiples) */ -#define BCM2835_PWMCLK_CNTL 40 -#define BCM2835_PWMCLK_DIV 41 -#define BCM2835_PWM_PASSWRD (0x5A << 24) /*!< Password to enable setting PWM clock */ - -#define BCM2835_PWM1_MS_MODE 0x8000 /*!< Run in Mark/Space mode */ -#define BCM2835_PWM1_USEFIFO 0x2000 /*!< Data from FIFO */ -#define BCM2835_PWM1_REVPOLAR 0x1000 /*!< Reverse polarity */ -#define BCM2835_PWM1_OFFSTATE 0x0800 /*!< Ouput Off state */ -#define BCM2835_PWM1_REPEATFF 0x0400 /*!< Repeat last value if FIFO empty */ -#define BCM2835_PWM1_SERIAL 0x0200 /*!< Run in serial mode */ -#define BCM2835_PWM1_ENABLE 0x0100 /*!< Channel Enable */ - -#define BCM2835_PWM0_MS_MODE 0x0080 /*!< Run in Mark/Space mode */ -#define BCM2835_PWM_CLEAR_FIFO 0x0040 /*!< Clear FIFO */ -#define BCM2835_PWM0_USEFIFO 0x0020 /*!< Data from FIFO */ -#define BCM2835_PWM0_REVPOLAR 0x0010 /*!< Reverse polarity */ -#define BCM2835_PWM0_OFFSTATE 0x0008 /*!< Ouput Off state */ -#define BCM2835_PWM0_REPEATFF 0x0004 /*!< Repeat last value if FIFO empty */ -#define BCM2835_PWM0_SERIAL 0x0002 /*!< Run in serial mode */ -#define BCM2835_PWM0_ENABLE 0x0001 /*!< Channel Enable */ - -/*! \brief bcm2835PWMClockDivider - Specifies the divider used to generate the PWM clock from the system clock. - Figures below give the divider, clock period and clock frequency. - Clock divided is based on nominal PWM base clock rate of 19.2MHz - The frequencies shown for each divider have been confirmed by measurement -*/ -typedef enum -{ - BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ - BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ - BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ - BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ - BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ - BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ - BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ - BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ - BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ - BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ -} bcm2835PWMClockDivider; - -/* Historical name compatibility */ -#ifndef BCM2835_NO_DELAY_COMPATIBILITY -#define delay(x) bcm2835_delay(x) -#define delayMicroseconds(x) bcm2835_delayMicroseconds(x) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - /*! \defgroup init Library initialisation and management - These functions allow you to intialise and control the bcm2835 library - @{ - */ - - /*! Initialise the library by opening /dev/mem (if you are root) - or /dev/gpiomem (if you are not) - and getting pointers to the - internal memory for BCM 2835 device registers. You must call this (successfully) - before calling any other - functions in this library (except bcm2835_set_debug). - If bcm2835_init() fails by returning 0, - calling any other function may result in crashes or other failures. - If bcm2835_init() succeeds but you are not running as root, then only gpio operations - are permitted, and calling any other functions may result in crashes or other failures. . - Prints messages to stderr in case of errors. - \return 1 if successful else 0 - */ - extern int bcm2835_init(void); - - /*! Close the library, deallocating any allocated memory and closing /dev/mem - \return 1 if successful else 0 - */ - extern int bcm2835_close(void); - - /*! Sets the debug level of the library. - A value of 1 prevents mapping to /dev/mem, and makes the library print out - what it would do, rather than accessing the GPIO registers. - A value of 0, the default, causes normal operation. - Call this before calling bcm2835_init(); - \param[in] debug The new debug level. 1 means debug - */ - extern void bcm2835_set_debug(uint8_t debug); - - /*! Returns the version number of the library, same as BCM2835_VERSION - \return the current library version number - */ - extern unsigned int bcm2835_version(void); - - /*! @} */ - - /*! \defgroup lowlevel Low level register access - These functions provide low level register access, and should not generally - need to be used - - @{ - */ - - /*! Gets the base of a register - \param[in] regbase You can use one of the common values BCM2835_REGBASE_* - in \ref bcm2835RegisterBase - \return the register base - \sa Physical Addresses - */ - extern uint32_t* bcm2835_regbase(uint8_t regbase); - - /*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. - This is safe, but slow. The MB before protects this read from any in-flight reads that didn't - use a MB. The MB after protects subsequent reads from another peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); - - /*! Reads 32 bit value from a peripheral address WITHOUT the read barriers - You should only use this when: - o your code has previously called bcm2835_peri_read() for a register - within the same peripheral, and no read or write to another peripheral has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); - - - /*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write - This is safe, but slow. The MB before ensures that any in-flight write to another peripheral - completes before this write is issued. The MB after ensures that subsequent reads and writes - to another peripheral will see the effect of this write. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); - - /*! Writes 32 bit value from a peripheral address without the write barrier - You should only use this when: - o your code has previously called bcm2835_peri_write() for a register - within the same peripheral, and no other peripheral access has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); - - /*! Alters a number of bits in a 32 peripheral regsiter. - It reads the current valu and then alters the bits defines as 1 in mask, - according to the bit value in value. - All other bits that are 0 in the mask are unaffected. - Use this to alter a subset of the bits in a register. - Memory barriers are used. Note that this is not atomic; an interrupt - routine can cause unexpected results. - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write, masked in by mask. - \param[in] mask Bitmask that defines the bits that will be altered in the register. - \sa Physical Addresses - */ - extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); - /*! @} end of lowlevel */ - - /*! \defgroup gpio GPIO register access - These functions allow you to control the GPIO interface. You can set the - function of each GPIO pin, read the input state and set the output state. - @{ - */ - - /*! Sets the Function Select register for the given pin, which configures - the pin as Input, Output or one of the 6 alternate functions. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect - */ - extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - - /*! Sets the specified pin output to - HIGH. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_set(uint8_t pin); - - /*! Sets the specified pin output to - LOW. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_clr(uint8_t pin); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - HIGH. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_set_multi(uint32_t mask); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - LOW. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_clr_multi(uint32_t mask); - - /*! Reads the current level on the specified - pin and returns either HIGH or LOW. Works whether or not the pin - is an input or an output. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return the current level either HIGH or LOW - */ - extern uint8_t bcm2835_gpio_lev(uint8_t pin); - - /*! Event Detect Status. - Tests whether the specified pin has detected a level or edge - as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return HIGH if the event detect status for the given pin is true. - */ - extern uint8_t bcm2835_gpio_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in - the mask have detected a level or edge. - \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \return Mask of pins HIGH if the event detect status for the given pin is true. - */ - extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); - - /*! Sets the Event Detect Status register for a given pin to 1, - which has the effect of clearing the flag. Use this afer seeing - an Event Detect Status on the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_set_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which - is set in the mask. - \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_set_eds_multi(uint32_t mask); - - /*! Enable Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?011? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_ren(uint8_t pin); - - /*! Disable Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_ren(uint8_t pin); - - /*! Enable Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?100? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_fen(uint8_t pin); - - /*! Disable Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_fen(uint8_t pin); - - /*! Enable High Detect Enable for the specified pin. - When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_hen(uint8_t pin); - - /*! Disable High Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_hen(uint8_t pin); - - /*! Enable Low Detect Enable for the specified pin. - When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_len(uint8_t pin); - - /*! Disable Low Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_len(uint8_t pin); - - /*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - rising edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_aren(uint8_t pin); - - /*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_aren(uint8_t pin); - - /*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - falling edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_afen(uint8_t pin); - - /*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_afen(uint8_t pin); - - /*! Sets the Pull-up/down register for the given pin. This is - used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - However, it is usually more convenient to use bcm2835_gpio_set_pud(). - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pud(uint8_t pud); - - /*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - LOW to remove the clock. - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - - /*! Reads and returns the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup - */ - extern uint32_t bcm2835_gpio_pad(uint8_t group); - - /*! Sets the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note - that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this - is automatically included. - */ - extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - - /*! Delays for the specified number of milliseconds. - Uses nanosleep(), and therefore does not use CPU until the time is up. - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - \param[in] millis Delay in milliseconds - */ - extern void bcm2835_delay (unsigned int millis); - - /*! Delays for the specified number of microseconds. - Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - For times less than about 450 microseconds, uses a busy wait on the System Timer. - It is reported that a delay of 0 microseconds on RaspberryPi will in fact - result in a delay of about 80 microseconds. Your mileage may vary. - \param[in] micros Delay in microseconds - */ - extern void bcm2835_delayMicroseconds (uint64_t micros); - - /*! Sets the output state of the specified pin - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - - /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value - \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - - /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than - clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - */ - extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); - - /*! @} */ - - /*! \defgroup spi SPI access - These functions let you use SPI0 (Serial Peripheral Interface) to - interface with an external SPI device. - @{ - */ - - /*! Start SPI operations. - Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - to alternate function ALT0, which enables those pins for SPI interface. - You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to - their default functions. - \sa bcm2835_spi_end() - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - */ - extern int bcm2835_spi_begin(void); - - /*! End SPI operations. - SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_spi_end(void); - - /*! Sets the SPI bit order - NOTE: has no effect. Not supported by SPI0. - Defaults to - \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, - see \ref bcm2835SPIBitOrder - */ - extern void bcm2835_spi_setBitOrder(uint8_t order); - - /*! Sets the SPI clock divider and therefore the - SPI clock speed. - \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, - see \ref bcm2835SPIClockDivider - */ - extern void bcm2835_spi_setClockDivider(uint16_t divider); - - /*! Sets the SPI data mode - Sets the clock polariy and phase - \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - see \ref bcm2835SPIMode - */ - extern void bcm2835_spi_setDataMode(uint8_t mode); - - /*! Sets the chip select pin(s) - When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the - transfer. - \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. - One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect - */ - extern void bcm2835_spi_chipSelect(uint8_t cs); - - /*! Sets the chip select pin polarity for a given pin - When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) - will be asserted to the - value given by active. When transfers are not happening, the chip select pin(s) - return to the complement (inactive) value. - \param[in] cs The chip select pin to affect - \param[in] active Whether the chip select pin is to be active HIGH - */ - extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); - - /*! Transfers one byte to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] value The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() - */ - extern uint8_t bcm2835_spi_transfer(uint8_t value); - - /*! Transfers any number of bytes to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - - /*! Transfers any number of bytes to and from the currently selected SPI slave - using bcm2835_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfern(char* buf, uint32_t len); - - /*! Transfers any number of bytes to the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send - */ - extern void bcm2835_spi_writenb(const char* buf, uint32_t len); - - /*! Transfers half-word to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] value The 8 bit data byte to write to MOSI - \sa bcm2835_spi_writenb() - */ - extern void bcm2835_spi_write(uint16_t data); - - /*! Start AUX SPI operations. - Forces RPi AUX SPI pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - to alternate function ALT4, which enables those pins for SPI interface. - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - */ - extern int bcm2835_aux_spi_begin(void); - - /*! End AUX SPI operations. - SPI1 pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_aux_spi_end(void); - - /*! Sets the AUX SPI clock divider and therefore the AUX SPI clock speed. - \param[in] divider The desired AUX SPI clock divider. - */ - extern void bcm2835_aux_spi_setClockDivider(uint16_t); - - /*! - * Calculates the input for \sa bcm2835_aux_spi_setClockDivider - * @param speed_hz A value between \sa BCM2835_AUX_SPI_CLOCK_MIN and \sa BCM2835_AUX_SPI_CLOCK_MAX - * @return Input for \sa bcm2835_aux_spi_setClockDivider - */ - extern uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz); - - /*! Transfers half-word to and from the AUX SPI slave. - Asserts the currently selected CS pins during the transfer. - \param[in] value The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() - */ - extern void bcm2835_aux_spi_write(uint16_t); - - /*! Transfers any number of bytes to the AUX SPI slave. - Asserts the CE2 pin during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send - */ - extern void bcm2835_aux_spi_writenb(const char *buf, uint32_t len); - - /*! Transfers any number of bytes to and from the AUX SPI slave - using bcm2835_aux_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_aux_spi_transfer() - */ - extern void bcm2835_aux_spi_transfern(char *, uint32_t); - - /*! Transfers any number of bytes to and from the AUX SPI slave. - Asserts the CE2 pin during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - */ - extern void bcm2835_aux_spi_transfernb(const char *, char *, uint32_t); - - /*! @} */ - - /*! \defgroup i2c I2C access - These functions let you use I2C (The Broadcom Serial Control bus with the Philips - I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - @{ - */ - - /*! Start I2C operations. - Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - to alternate function ALT0, which enables those pins for I2C interface. - You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - their default functions - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - \sa bcm2835_i2c_end() - */ - extern int bcm2835_i2c_begin(void); - - /*! End I2C operations. - I2C pins P1-03 (SDA) and P1-05 (SCL) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_i2c_end(void); - - /*! Sets the I2C slave address. - \param[in] addr The I2C slave address. - */ - extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - - /*! Sets the I2C clock divider and therefore the I2C clock speed. - \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - see \ref bcm2835I2CClockDivider - */ - extern void bcm2835_i2c_setClockDivider(uint16_t divider); - - /*! Sets the I2C clock divider by converting the baudrate parameter to - the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - For the I2C standard 100khz you would set baudrate to 100000 - The use of baudrate corresponds to its use in the I2C kernel device - driver. (Of course, bcm2835 has nothing to do with the kernel driver) - */ - extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - - /*! Transfers any number of bytes to the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - - /*! Transfers any number of bytes from the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - - /*! Allows reading from I2C slaves that require a repeated start (without any prior stop) - to read after the required slave register has been set. For example, the popular - MPL3115A2 pressure and temperature sensor. Note that your device must support or - require this mode. If your device does not require this mode then the standard - combined: - \sa bcm2835_i2c_write - \sa bcm2835_i2c_read - are a better choice. - Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] regaddr Buffer containing the slave register you wish to read from. - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - - /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated - start (with no prior stop) and reading a response. - Necessary for devices that require such behavior, such as the MLX90620. - Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] cmds Buffer containing the bytes to send before the repeated start condition. - \param[in] cmds_len Number of bytes to send from cmds buffer - \param[in] buf Buffer of bytes to receive. - \param[in] buf_len Number of bytes to receive in the buf buffer. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); - - /*! @} */ - - /*! \defgroup st System Timer access - Allows access to and delays using the System Timer Counter. - @{ - */ - - /*! Read the System Timer Counter register. - \return the value read from the System Timer Counter Lower 32 bits register - */ - extern uint64_t bcm2835_st_read(void); - - /*! Delays for the specified number of microseconds with offset. - \param[in] offset_micros Offset in microseconds - \param[in] micros Delay in microseconds - */ - extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); - - /*! @} */ - - /*! \defgroup pwm Pulse Width Modulation - Allows control of 2 independent PWM channels. A limited subset of GPIO pins - can be connected to one of these 2 channels, allowing PWM control of GPIO pins. - You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM - documentation on the Main Page. - @{ - */ - - /*! Sets the PWM clock divisor, - to control the basic PWM pulse widths. - \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common - values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider - */ - extern void bcm2835_pwm_set_clock(uint32_t divisor); - - /*! Sets the mode of the given PWM channel, - allowing you to control the PWM mode and enable/disable that channel - \param[in] channel The PWM channel. 0 or 1. - \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. - \param[in] enabled Set true to enable this channel and produce PWM pulses. - */ - extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); - - /*! Sets the maximum range of the PWM output. - The data value can vary between 0 and this range to control PWM output - \param[in] channel The PWM channel. 0 or 1. - \param[in] range The maximum value permitted for DATA. - */ - extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); - - /*! Sets the PWM pulse ratio to emit to DATA/RANGE, - where RANGE is set by bcm2835_pwm_set_range(). - \param[in] channel The PWM channel. 0 or 1. - \param[in] data Controls the PWM output ratio as a fraction of the range. - Can vary from 0 to RANGE. - */ - extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); - - /*! @} */ -#ifdef __cplusplus -} -#endif - -#endif /* BCM2835_H */ - -/*! @example blink.c - Blinks RPi GPIO pin 11 on and off -*/ - -/*! @example input.c - Reads the state of an RPi input pin -*/ - -/*! @example event.c - Shows how to use event detection on an input pin -*/ - -/*! @example spi.c - Shows how to use SPI interface to transfer a byte to and from an SPI device -*/ - -/*! @example spin.c - Shows how to use SPI interface to transfer a number of bytes to and from an SPI device -*/ - -/*! @example pwm.c - Shows how to use PWM to control GPIO pins -*/ - -/*! @example i2c.c -Command line utility for executing i2c commands with the -Broadcom bcm2835. Contributed by Shahrooz Shahparnia. -*/ - -/*! example gpio.c - Command line utility for executing gpio commands with the - Broadcom bcm2835. Contributed by Shahrooz Shahparnia. -*/ \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/lib/display.cpp b/rootfs/usr/share/d3m0n/src/lib/display.cpp deleted file mode 100644 index dc44ff87..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/display.cpp +++ /dev/null @@ -1,563 +0,0 @@ -#ifndef DISPLAY_H -#define DISPLAY_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xpt2046.h" - - - -#include -#include -#include -#include - -#include -#include - - -using namespace std; -using namespace cv; - -#define T_CS BCM2835_SPI_CS1 -#define RES RPI_V2_GPIO_P1_11 -#define T_IRQ RPI_V2_GPIO_P1_22 - -class display { - private: - void setColorFromRGB(int r, int g, int b) { - glColor3f(r / 255.0f, g / 255.0f, b / 255.0f); - } - - public: - GLFWwindow* window; - vector events; - - void registerEvent(short type, DataTypes::Rect rect, function function, Application* app) { - log("Registering new event id:"+to_string(type), LogStatus::Loading); - - Event::Listener listener; - listener.type = type; - listener.rect = rect; - listener.callback = function; - listener.app = app; - - events.push_back(listener); - } - - void getClick() { - if(isDebugMode()) { - double xpos, ypos; - int state; - bool clicking=false; - while(true) { - state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); - - if (state == GLFW_PRESS && !clicking) - { - clicking=true; - glfwGetCursorPos(window, &xpos, &ypos); - - for(Event::Listener event: events) { - if(event.type == Event::OnClick) { - if(checkCollision(DataTypes::Point((int)xpos, (int)ypos), event.rect)) { - event.callback(event.app); - } - } - } - //usleep(10000); - } else if(state == GLFW_RELEASE) { - clicking=false; - } - // cout << to_string(clicking); - - glfwPollEvents(); - } - - - } else { - int x, y; - int pen_irq; - - bcm2835_gpio_write(RES, LOW); - bcm2835_delay(100); - bcm2835_gpio_write(RES, HIGH); - bcm2835_delay(100); - - while(true) { - usleep(10000); /* do it anyway ; settle time when pen goes up */ - pen_irq = bcm2835_gpio_lev(T_IRQ); - if (pen_irq == LOW) { /* P1.22 == PenIRQ is LOW : touch! pen is down */ - xptGetxy(T_CS, &x, &y); - printf("touch !! x=%5d y=%5d\n", x, y); - } - } - - - bcm2835_close(); - } - } - - static bool checkCollision(DataTypes::Point point, DataTypes::Rect rect) { - if(point.X > rect.X && point.X < rect.X2) { - if(point.Y > rect.Y && point.Y < rect.Y2) { - return true; - } - } - return false; - } - static void PlaySound(string name) - { - string theme_path = GetPath()+"/themes/"+getSetting("theme", GetConfig())+"/sounds"; - try - { - if(filesystem::exists(theme_path+"/"+name+".ogg")) - { - exec(("paplay '"+theme_path+"/"+name+".ogg'").c_str()); - log("Playing '"+theme_path+"/"+name+".ogg'...", LogStatus::Info); - } - else - { - log("sound '"+name+"' is not found", LogStatus::Error); - } - } - catch(exception) - { - log("Could not find command 'paplay' >> can't play sound file", LogStatus::Error); - } - } - static string GetThemeIcon(string name) { - string theme_path = GetPath()+"/themes/"+getSetting("theme", GetConfig())+"/icons"; - if(filesystem::exists(theme_path+"/"+name+".png")) - { - return theme_path+"/"+name+".png"; - } - else - { - return GetPath()+"/default.png"; - } - } - string displayCommand(string command) { - string output=""; - - // if(isDebugMode()) { return "Debug Mode, Command not executed."; } - - // clear screen - if(startsWith(command, "display clear")) { - output+=log("Cleared display screen successfully!", LogStatus::Success); - Clear(); - } - // draw Controls on screen - // else if(startsWith(command, "display draw ")) { output+=log("Cleared display screen successfully!", LogStatus::Success); lcdFillScreen(Colors::Black); }; - else { - output+=log("Usage: 'display [clear/draw] ...'", LogStatus::Error); - } - - return output; - } - - - void init(int width, int height) - { - if(isDebugMode()) { - if (!glfwInit()) { - log("Error: Could not start OpenGL!", LogStatus::Critical); - return; - } - - // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - // Create a windowed mode window and its OpenGL context - window = glfwCreateWindow(width, height, window_name.c_str(), NULL, NULL); - if (!window) { - log("Error: Could not create emulator's window!", LogStatus::Critical); - glfwTerminate(); - return; - } - - - glfwMakeContextCurrent(window); - - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - - - // Initialize GLEW - glewExperimental = GL_TRUE; // Needed for core profile - if (glewInit() != GLEW_OK) { - log("Error: Failed to initialize GLEW", LogStatus::Critical); - glfwTerminate(); - return; - } - - - - // Set up orthographic projection - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, width, height, 0.0); - glMatrixMode(GL_MODELVIEW); - - // return window; - } else { - log("Initiating ILI9340 LCD...", LogStatus::Loading); - - if (bcm2835_init() != 1) return; - bcm2835_gpio_fsel(T_IRQ, BCM2835_GPIO_FSEL_INPT); // T_IRQ - bcm2835_gpio_fsel(RES, BCM2835_GPIO_FSEL_OUTP); // RES - - - - - printf("Init\n"); - lcdInit(width, height, 0, 0); - printf("Reset\n"); - lcdReset(); - printf("Setup\n"); - lcdSetup(); - - lcdFillScreen(Colors::Black); - - - - - // FontxFile fx24G[2]; - // FontxFile fx16G[2]; - - // Fontx_init(fx24G,"./lib/fontx/ILGH24XB.FNT","./lib/fontx/ILGZ24XB.FNT"); // 12x24Dot Gothic - // Fontx_init(fx16G,"./lib/fontx/ILGH16XB.FNT","./lib/fontx/ILGZ16XB.FNT"); // 8x16Dot Gothic - - // FontxFile fx32M[2]; - // FontxFile fx24M[2]; - // FontxFile fx16M[2]; - // Fontx_init(fx32M,"./lib/fontx/ILMH32XF.FNT","./lib/fontx/ILMZ32XF.FNT"); // 16x32Dot Mincyo - // Fontx_init(fx24M,"./lib/fontx/ILMH24XF.FNT","./lib/fontx/ILMZ24XF.FNT"); // 12x24Dot Mincyo - // Fontx_init(fx16M,"./lib/fontx/ILMH16XB.FNT","./lib/fontx/ILMZ16XF.FNT"); // 8x16Dot Mincyo - - log("Loaded fonts successfully!", LogStatus::Success); - } - log("Initiated screen!", LogStatus::Info); - } - void drawScreen() { - if(isDebugMode()) { - glfwSwapBuffers(window); - } - } - void Clear() { - if (isDebugMode()) { - glClear(GL_COLOR_BUFFER_BIT); - } else { - lcdFillScreen(Colors::Black); - } - } - // Drawing functions - void drawCircle(int x1, int y1, int radius, ushort color, bool fill=false) { - - if(isDebugMode()) { - float t1 = radius / 16; - float t2; - int x = radius; - int y = 0; - while(x < y) { - drawPixel(x, y, color); - // Pixel (x, y) and all symmetric pixels are colored (8 times) - y = y + 1; - t1 = t1 + y; - t2 = t1 - x; - if(t2 >= 0) { - t1 = t2; - x = x - 1; - } - - } - - - } else { - if (fill) { - lcdDrawFillCircle(static_cast(x1), static_cast(y1), static_cast(radius), static_cast(color)); - return; - } - lcdDrawCircle(static_cast(x1), static_cast(y1), static_cast(radius), static_cast(color)); - } - } - - // round rect - void drawRoundRect(int x1, int y1, int x2, int y2, ushort color, int radius, bool fill=false) - { - - log("RoundRect not def", LogStatus::Critical); - - if(isDebugMode())return; - - lcdDrawRoundRect(static_cast(x1), static_cast(y1), static_cast(x2), static_cast(y2), static_cast(radius), static_cast(color)); - } - // rect - void drawRect(int x1, int y1, int x2, int y2, ushort color, bool fill=false) - { - - if(isDebugMode()) { - // uint8_t r; - // uint8_t g; - // uint8_t b; - // int isfilled=0; - // RGB565toRGB((uint16_t)color, r, g, b); - - if(fill) { - int height=y2-y1; - int width=x2-x1; - for(int y=0; y(x1), static_cast(y1), static_cast(x2), static_cast(y2), static_cast(color)); - return; - } - lcdDrawRect(static_cast(x1), static_cast(y1), static_cast(x2), static_cast(y2), static_cast(color)); - } - } - // line - void drawLine(int x1, int y1, int x2, int y2, ushort color) { - - if(isDebugMode()) { - glBegin(GL_LINES); - uint8_t r,g,b; - RGB565toRGB(color, r, g, b); - setColorFromRGB(r,g,b); - - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glEnd(); - drawScreen(); - } else { - lcdDrawLine(static_cast(x1), static_cast(y1), static_cast(x2), static_cast(y2), static_cast(color)); - } - } - void drawPixel(int x, int y, ushort color) - { - - if(isDebugMode()) { - uint8_t r; - uint8_t g; - uint8_t b; - RGB565toRGB((uint16_t)color, r, g, b); - // logn(to_string(r)+","+to_string(g)+","+to_string(b)+" ==> "+to_string(color), ConsoleColor::Red); - // Vec3b color2((int)r, (int)g, (int)b); // Red color (BGR format) - // // Draw the pixel - // image.at(y, x) = color2; - // // Display the image in the window - // imshow(window_name, image); - glBegin(GL_POINTS); - setColorFromRGB(r, g, b); - glVertex2i(x,y); - glEnd(); - } else { - lcdDrawPixel(static_cast(x), static_cast(y), static_cast(color)); - } - } - - // writing text to the display - void drawText(int x, int y, int fontSize, string text, bool bold, ushort color) - { - - // return; - if(isDebugMode()) { - string filePath = "./lib/fontx/ILGH16XB.FNT"; - - vector data; - - if (readAllBytes(filePath, data)) { - cout << "Successfully read " << data.size() << " bytes from the font file." << endl; - // ofstream myfile; - // myfile.open("output.txt"); - - int line=0; - int font_padding = 2; - for(char c: text) { - int offset = 17+static_cast(c)*16; - - for(int x2=offset; x2 bits(data[x2]); - int bitOffsetInByte = 0; - for(char a: bits.to_string()) { - if(a=='1') { - glBegin(GL_POINTS); - setColorFromRGB(255, 255, 255); - glVertex2i(x+bitOffsetInByte,y+line); - glEnd(); - } - bitOffsetInByte++; - } - // cout << "\n"; - line++; - } - - x+=8; - line=0; - - - } - drawScreen(); - - return; - - int y=0; - for(int x=17+48*16*8; x<17+48*16*8+16*8; x++) { - bitset<8> bits(data[x]); - if(y%8==0) { - cout << bits.to_string(); - // for(char a: bits.to_string()) { - // if(a=='1') { - // cout << "#"; - // } else { - // cout << " "; - // } - // } - cout << endl; - } else { - cout << bits.to_string(); - // for(char a: bits.to_string()) { - // if(a=='1') { - // cout << "#"; - // } else { - // cout << " "; - // } - // } - } - y+=8; - } - - } else { - cerr << "Error reading the file." << endl; - } - - - //get_font("./lib/fontx/ILGH16XB.FNT", static_cast('0')); - } else { - string font1 = GetPath()+"/src/lib/fontx/IL"; - string end_font1 = ""; - string fontName = "MINCYO"; - - if(fontName == "GOTHIC") { font1+="G"; } else { - font1+="M"; - } - if(bold) { - end_font1="XF.FNT"; - } - else{ - end_font1="XB.FNT"; - } - - - FontxFile fx32G[2]; - printf((font1+"H"+to_string(fontSize)+end_font1).c_str()); - Fontx_init(fx32G,(font1+"H"+to_string(fontSize)+end_font1).data(),(font1+"Z"+to_string(fontSize)+end_font1).data()); - - // get font width & height - uint8_t buffer[FontxGlyphBufSize]; - uint8_t fontWidth; - uint8_t fontHeight; - GetFontx(fx32G, 0, buffer, &fontWidth, &fontWidth); - - uint8_t ascii[20]; - - strcpy((char *)ascii, text.c_str()); - lcdSetFontDirection(DIRECTION180); - lcdDrawUTF8String(fx32G, x, y, ascii, static_cast(color)); - } - } - - - // image draw - void drawImage(DataTypes::Point location, string file, int width, int height, bool reverse) { - // logn("img X:" + to_string(location.X) + " Y:" + to_string(location.Y), ConsoleColor::DarkCyan); - // logn("width:" + to_string(width) + " height:" + to_string(height), ConsoleColor::DarkCyan); - - // Load the image (IMREAD_UNCHANGED to keep alpha if any) - Mat image2 = imread(file.c_str(), IMREAD_UNCHANGED); - - if (image2.empty()) { - log("Could not open or find the image.", LogStatus::Error); - return; - } - - // Resize the image - Mat resizedImage; - Size newSize(width, height); - resize(image2, resizedImage, newSize); - - // Determine if the loaded image has an alpha channel - bool hasAlpha = (resizedImage.channels() == 4); - - int x = 0, y = 0; - float alpha = 1.0f; - - for (int i = 0; i < resizedImage.rows; ++i) { - for (int j = 0; j < resizedImage.cols; ++j) { - Vec4b color; - if (hasAlpha) { - color = resizedImage.at(i, j); - } else { - Vec3b color3 = resizedImage.at(i, j); - color = Vec4b(color3[0], color3[1], color3[2], 255); // Set alpha to 255 (fully opaque) - } - - uchar b = color[0]; - uchar g = color[1]; - uchar r = color[2]; - alpha = color[3] / 255.0f; // Normalize alpha to 0-1 - - if (alpha == 0) { - continue; // Skip fully transparent pixels - } - - if (isDebugMode()) { - glBegin(GL_POINTS); - setColorFromRGB(r, g, b); // Assuming setColorFromRGB now also takes alpha - glVertex2i(j + location.X, i + location.Y); - glEnd(); - } else { - ushort color2 = (ushort) ((r << 11) | (g << 5) | b); - lcdDrawPixel(static_cast(SCREEN_WIDTH - (location.X + x)), static_cast(location.Y + y), color2); - } - } - } - drawScreen(); - } -}; -#endif // !DISPLAY_H \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx.c b/rootfs/usr/share/d3m0n/src/lib/fontx.c deleted file mode 100644 index d8341aeb..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/fontx.c +++ /dev/null @@ -1,572 +0,0 @@ -#include -#include -#include -#include -#include -#include "fontx.h" - -#define FontxDebug 0 // for Debug - -// フォントファイルパスを構造体に保存 -void Fontx_addFont(FontxFile *fx, const char *path) -{ - memset(fx,0,sizeof(FontxFile)); - fx->path = path; - fx->opened = false; -} - -// フォント構造体を初期化 -void Fontx_init(FontxFile *fxs,const char *f0,const char *f1) -{ - Fontx_addFont(&fxs[0],f0); - Fontx_addFont(&fxs[1],f1); -} - -// フォントファイルをOPEN -bool Fontx_openFontxFile(FontxFile *fx) -{ - FILE *f; - - if(fx->opened == 0){ - fx->opened = true; -if(FontxDebug)printf("[Fontx_openFontxFile]fx->path=[%s]\n",fx->path); - f = fopen(fx->path,"r"); - if(!f){ - fx->valid = false; - printf("FsFontx:%s not found.\n",fx->path); - } else { -if(FontxDebug)printf("[Fontx_openFontxFile]fopen ok\n"); - fx->file = f; - char buf[18]; - - fread(buf, sizeof buf, 1, fx->file); -if(FontxDebug)printf("[Fontx_openFontxFile]fread ok\n"); -// for(i=0;ifxname,&buf[6],8); - fx->w = buf[14]; - fx->h = buf[15]; - fx->is_ank = (buf[16] == 0); - fx->bc = buf[17]; - fx->fsz = (fx->w + 7)/8 * fx->h; - if(fx->fsz > FontxGlyphBufSize){ - printf("too big font size.\n"); - fx->valid = false; - } else { - fx->valid = true; - } - } - } - return fx->valid; -} - -// フォントファイルをCLOSE -void Fontx_closeFontxFile(FontxFile *fx) -{ - if(fx->opened){ - fclose(fx->file); - fx->opened = false; - } -} - - -/* - フォントファイルからフォントパターンを取り出す - - フォントの並び(16X16ドット) - 00000000 01111111 - 12345678 90123456 - 01 pGlyph[000] pGlyph[001] - 02 pGlyph[002] pGlyph[003] - 03 pGlyph[004] pGlyph[005] - 04 pGlyph[006] pGlyph[007] - 05 pGlyph[008] pGlyph[009] - 06 pGlyph[010] pGlyph[011] - 07 pGlyph[012] pGlyph[013] - 08 pGlyph[014] pGlyph[015] - 09 pGlyph[016] pGlyph[017] - 10 pGlyph[018] pGlyph[019] - 11 pGlyph[020] pGlyph[021] - 12 pGlyph[022] pGlyph[023] - 13 pGlyph[024] pGlyph[025] - 14 pGlyph[026] pGlyph[027] - 15 pGlyph[028] pGlyph[029] - 16 pGlyph[030] pGlyph[031] - - フォントの並び(24X24ドット) - 00000000 01111111 11122222 - 12345678 90123456 78901234 - 01 pGlyph[000] pGlyph[001] pGlyph[002] - 02 pGlyph[003] pGlyph[004] pGlyph[005] - 03 pGlyph[006] pGlyph[007] pGlyph[008] - 04 pGlyph[009] pGlyph[010] pGlyph[011] - 05 pGlyph[012] pGlyph[013] pGlyph[014] - 06 pGlyph[015] pGlyph[016] pGlyph[017] - 07 pGlyph[018] pGlyph[019] pGlyph[020] - 08 pGlyph[021] pGlyph[022] pGlyph[023] - 09 pGlyph[024] pGlyph[025] pGlyph[026] - 10 pGlyph[027] pGlyph[028] pGlyph[029] - 11 pGlyph[030] pGlyph[031] pGlyph[032] - 12 pGlyph[033] pGlyph[034] pGlyph[035] - 13 pGlyph[036] pGlyph[037] pGlyph[038] - 14 pGlyph[039] pGlyph[040] pGlyph[041] - 15 pGlyph[042] pGlyph[043] pGlyph[044] - 16 pGlyph[045] pGlyph[046] pGlyph[047] - 17 pGlyph[048] pGlyph[049] pGlyph[050] - 18 pGlyph[051] pGlyph[052] pGlyph[053] - 19 pGlyph[054] pGlyph[055] pGlyph[056] - 20 pGlyph[057] pGlyph[058] pGlyph[059] - 21 pGlyph[060] pGlyph[061] pGlyph[062] - 22 pGlyph[063] pGlyph[064] pGlyph[065] - 23 pGlyph[066] pGlyph[067] pGlyph[068] - 24 pGlyph[069] pGlyph[070] pGlyph[071] - - フォントの並び(32X32ドット) - 00000000 01111111 11122222 22222333 - 12345678 90123456 78901234 56789012 - 01 pGlyph[000] pGlyph[001] pGlyph[002] pGlyph[003] - 02 pGlyph[004] pGlyph[005] pGlyph[006] pGlyph[007] - 03 pGlyph[008] pGlyph[009] pGlyph[010] pGlyph[011] - 04 pGlyph[012] pGlyph[013] pGlyph[014] pGlyph[015] - 05 pGlyph[016] pGlyph[017] pGlyph[018] pGlyph[019] - 06 pGlyph[020] pGlyph[021] pGlyph[022] pGlyph[023] - 07 pGlyph[024] pGlyph[025] pGlyph[026] pGlyph[027] - 08 pGlyph[028] pGlyph[029] pGlyph[030] pGlyph[031] - 09 pGlyph[032] pGlyph[033] pGlyph[034] pGlyph[035] - 10 pGlyph[036] pGlyph[037] pGlyph[038] pGlyph[039] - 11 pGlyph[040] pGlyph[041] pGlyph[042] pGlyph[043] - 12 pGlyph[044] pGlyph[045] pGlyph[046] pGlyph[047] - 13 pGlyph[048] pGlyph[049] pGlyph[050] pGlyph[051] - 14 pGlyph[052] pGlyph[053] pGlyph[054] pGlyph[055] - 15 pGlyph[056] pGlyph[057] pGlyph[058] pGlyph[059] - 16 pGlyph[060] pGlyph[061] pGlyph[062] pGlyph[063] - 17 pGlyph[064] pGlyph[065] pGlyph[066] pGlyph[067] - 18 pGlyph[068] pGlyph[069] pGlyph[070] pGlyph[071] - 19 pGlyph[072] pGlyph[073] pGlyph[074] pGlyph[075] - 20 pGlyph[076] pGlyph[077] pGlyph[078] pGlyph[079] - 21 pGlyph[080] pGlyph[081] pGlyph[082] pGlyph[083] - 22 pGlyph[084] pGlyph[085] pGlyph[086] pGlyph[087] - 23 pGlyph[088] pGlyph[089] pGlyph[090] pGlyph[091] - 24 pGlyph[092] pGlyph[093] pGlyph[094] pGlyph[095] - 25 pGlyph[096] pGlyph[097] pGlyph[098] pGlyph[099] - 26 pGlyph[100] pGlyph[101] pGlyph[102] pGlyph[103] - 27 pGlyph[104] pGlyph[105] pGlyph[106] pGlyph[107] - 28 pGlyph[108] pGlyph[109] pGlyph[110] pGlyph[111] - 29 pGlyph[112] pGlyph[113] pGlyph[114] pGlyph[115] - 30 pGlyph[116] pGlyph[117] pGlyph[118] pGlyph[119] - 31 pGlyph[120] pGlyph[121] pGlyph[122] pGlyph[123] - 32 pGlyph[124] pGlyph[125] pGlyph[127] pGlyph[128] - -*/ - -bool GetFontx(FontxFile *fxs, uint32_t sjis , uint8_t *pGlyph, - uint8_t *pw, uint8_t *ph) -{ - - int i; -// FontxFile fx; - long offset; - -if(FontxDebug)printf("[GetFontx]sjis=%x %d\n",sjis,sjis); - for(i=0; i<2; i++){ - if(!Fontx_openFontxFile(&fxs[i])) continue; -if(FontxDebug)printf("openFontxFile[%d] end\n",i); - - if(sjis < 0x100){ - if(fxs[i].is_ank){ -if(FontxDebug)printf("[GetFontx]fxs.is_ank fxs.fsz=%d\n",fxs[i].fsz); - offset = 17 + sjis * fxs[i].fsz; -if(FontxDebug)printf("[GetFontx]offset=%ld\n",offset); - if(fseek(fxs[i].file, offset, SEEK_SET)) { - printf("Fontx::fseek(18) failed.\n"); - return false; - } - if(fread(pGlyph, 1, fxs[i].fsz, fxs[i].file) != fxs[i].fsz){ - printf("Fontx::fread failed.\n"); - return false; - } - if(pw) *pw = fxs[i].w; - if(ph) *ph = fxs[i].h; - return true; - } - } - else { - if(!fxs[i].is_ank){ - if(fseek(fxs[i].file, 18, SEEK_SET)) { - printf("Fontx::fseek(18) failed.\n"); - return false; - } - uint16_t buf[2], nc = 0, bc = fxs[i].bc; - - while(bc--){ - if(fread((char *)buf, 1, 4, fxs[i].file) != 4){ - printf("Fontx::fread failed.\n"); - return false; - } -if(FontxDebug)printf("[GetFontx]buf=%x %x\n",buf[0],buf[1]); - if(sjis >= buf[0] && sjis <= buf[1]) { - nc += sjis - buf[0]; - uint32_t pos = 18 + fxs[i].bc * 4 + nc * fxs[i].fsz; - if(fseek(fxs[i].file, pos, SEEK_SET)) { - printf("FsFontx::seek(%u) failed.\n",pos); - return false; - } - if(fread(pGlyph, 1, fxs[i].fsz, fxs[i].file) != fxs[i].fsz){ - printf("Fontx::fread failed.\n"); - return false; - } - if(pw) *pw = fxs[i].w; - if(ph) *ph = fxs[i].h; - return true; - } - nc += buf[1] - buf[0] + 1; - } - } - } - } - return false; -} - - -/* - フォントパターンをビットマップイメージに変換する - - fonts(16X16ドット) - 00000000 01111111 - 12345678 90123456 - 01 pGlyph[000] pGlyph[001] - 02 pGlyph[002] pGlyph[003] - 03 pGlyph[004] pGlyph[005] - 04 pGlyph[006] pGlyph[007] - 05 pGlyph[008] pGlyph[009] - 06 pGlyph[010] pGlyph[011] - 07 pGlyph[012] pGlyph[013] - 08 pGlyph[014] pGlyph[015] - 09 pGlyph[016] pGlyph[017] - 10 pGlyph[018] pGlyph[019] - 11 pGlyph[020] pGlyph[021] - 12 pGlyph[022] pGlyph[023] - 13 pGlyph[024] pGlyph[025] - 14 pGlyph[026] pGlyph[027] - 15 pGlyph[028] pGlyph[029] - 16 pGlyph[030] pGlyph[031] - - line[32*4] - 01 line[000] line[001] line[002] .... line[014] line[015] line[016-031] - | Not Use - 07 line[000] line[001] line[002] .... line[014] line[015] line[016-031] - - 08 line[032] line[033] line[034] .... line[046] line[047] line[048-063] - | Not Use - 16 line[032] line[033] line[034] .... line[046] line[047] line[048-063] - - - - fonts(24X24ドット) - 00000000 01111111 11122222 - 12345678 90123456 78901234 - 01 pGlyph[000] pGlyph[001] pGlyph[002] - 02 pGlyph[003] pGlyph[004] pGlyph[005] - 03 pGlyph[006] pGlyph[007] pGlyph[008] - 04 pGlyph[009] pGlyph[010] pGlyph[011] - 05 pGlyph[012] pGlyph[013] pGlyph[014] - 06 pGlyph[015] pGlyph[016] pGlyph[017] - 07 pGlyph[018] pGlyph[019] pGlyph[020] - 08 pGlyph[021] pGlyph[022] pGlyph[023] - 09 pGlyph[024] pGlyph[025] pGlyph[026] - 10 pGlyph[027] pGlyph[028] pGlyph[029] - 11 pGlyph[030] pGlyph[031] pGlyph[032] - 12 pGlyph[033] pGlyph[034] pGlyph[035] - 13 pGlyph[036] pGlyph[037] pGlyph[038] - 14 pGlyph[039] pGlyph[040] pGlyph[041] - 15 pGlyph[042] pGlyph[043] pGlyph[044] - 16 pGlyph[045] pGlyph[046] pGlyph[047] - 17 pGlyph[048] pGlyph[049] pGlyph[050] - 18 pGlyph[051] pGlyph[052] pGlyph[053] - 19 pGlyph[054] pGlyph[055] pGlyph[056] - 20 pGlyph[057] pGlyph[058] pGlyph[059] - 21 pGlyph[060] pGlyph[061] pGlyph[062] - 22 pGlyph[063] pGlyph[064] pGlyph[065] - 23 pGlyph[066] pGlyph[067] pGlyph[068] - 24 pGlyph[069] pGlyph[070] pGlyph[071] - - line[32*4] - 01 line[000] line[001] line[002] .... line[022] line[023] line[024-031] - | Not Use - 08 line[000] line[001] line[002] .... line[022] line[023] line[024-031] - - 09 line[032] line[033] line[034] .... line[054] line[055] line[056-063] - | Not Use - 16 line[032] line[033] line[034] .... line[054] line[055] line[056-063] - - 17 line[064] line[065] line[066] .... line[086] line[087] line[088-095] - | Not Use - 24 line[064] line[065] line[066] .... line[086] line[087] line[088-095] - - - fonts(32X32ドット) - 00000000 01111111 11122222 22222333 - 12345678 90123456 78901234 56789012 - 01 pGlyph[000] pGlyph[001] pGlyph[002] pGlyph[003] - 02 pGlyph[004] pGlyph[005] pGlyph[006] pGlyph[007] - 03 pGlyph[008] pGlyph[009] pGlyph[010] pGlyph[011] - 04 pGlyph[012] pGlyph[013] pGlyph[014] pGlyph[015] - 05 pGlyph[016] pGlyph[017] pGlyph[018] pGlyph[019] - 06 pGlyph[020] pGlyph[021] pGlyph[022] pGlyph[023] - 07 pGlyph[024] pGlyph[025] pGlyph[026] pGlyph[027] - 08 pGlyph[028] pGlyph[029] pGlyph[030] pGlyph[031] - 09 pGlyph[032] pGlyph[033] pGlyph[034] pGlyph[035] - 10 pGlyph[036] pGlyph[037] pGlyph[038] pGlyph[039] - 11 pGlyph[040] pGlyph[041] pGlyph[042] pGlyph[043] - 12 pGlyph[044] pGlyph[045] pGlyph[046] pGlyph[047] - 13 pGlyph[048] pGlyph[049] pGlyph[050] pGlyph[051] - 14 pGlyph[052] pGlyph[053] pGlyph[054] pGlyph[055] - 15 pGlyph[056] pGlyph[057] pGlyph[058] pGlyph[059] - 16 pGlyph[060] pGlyph[061] pGlyph[062] pGlyph[063] - 17 pGlyph[064] pGlyph[065] pGlyph[066] pGlyph[067] - 18 pGlyph[068] pGlyph[069] pGlyph[070] pGlyph[071] - 19 pGlyph[072] pGlyph[073] pGlyph[074] pGlyph[075] - 20 pGlyph[076] pGlyph[077] pGlyph[078] pGlyph[079] - 21 pGlyph[080] pGlyph[081] pGlyph[082] pGlyph[083] - 22 pGlyph[084] pGlyph[085] pGlyph[086] pGlyph[087] - 23 pGlyph[088] pGlyph[089] pGlyph[090] pGlyph[091] - 24 pGlyph[092] pGlyph[093] pGlyph[094] pGlyph[095] - 25 pGlyph[096] pGlyph[097] pGlyph[098] pGlyph[099] - 26 pGlyph[100] pGlyph[101] pGlyph[102] pGlyph[103] - 27 pGlyph[104] pGlyph[105] pGlyph[106] pGlyph[107] - 28 pGlyph[108] pGlyph[109] pGlyph[110] pGlyph[111] - 29 pGlyph[112] pGlyph[113] pGlyph[114] pGlyph[115] - 30 pGlyph[116] pGlyph[117] pGlyph[118] pGlyph[119] - 31 pGlyph[120] pGlyph[121] pGlyph[122] pGlyph[123] - 32 pGlyph[124] pGlyph[125] pGlyph[127] pGlyph[128] - - line[32*4] - 01 line[000] line[001] line[002] .... line[030] line[031] - | - 08 line[000] line[001] line[002] .... line[030] line[031] - - 09 line[032] line[033] line[034] .... line[062] line[063] - | - 16 line[032] line[033] line[034] .... line[062] line[063] - - 17 line[064] line[065] line[066] .... line[094] line[095] - | - 24 line[064] line[065] line[066] .... line[094] line[095] - - 25 line[096] line[097] line[098] .... line[126] line[127] - | - 32 line[096] line[097] line[098] .... line[126] line[127] - -*/ -void Font2Bitmap(uint8_t *fonts, uint8_t *line, uint8_t w, uint8_t h, uint8_t inverse) { - int x,y; - for(y=0; y<(h/8); y++){ - for(x=0; x> (x % 8))) line[linep] = line[linep] + (1 << mask); - } - mask--; - if (mask < 0) mask = 7; - fontp += (w + 7)/8; - } - - if (inverse) { - for(y=0; y<(h/8); y++){ - for(x=0; x> (x % 8))) { - printf("*"); - } else { - printf("."); - } - } - printf("\n"); - fpos=fpos+(pw+7)/8; - } -} - -// Bitmapの表示 -void ShowBitmap(uint8_t *bitmap, uint8_t pw, uint8_t ph) { - int x,y,fpos; - for (y=0;y<(ph+7)/8;y++) { - for (x=0;x> fpos); - if (bitmap[x+(y/8)*32] & (0x80 >> fpos)) { - printf("*"); - } else { - printf("."); - } - } - printf("\n"); - fpos++; - if (fpos > 7) fpos = 0; - } -} - - -// フォント構造体の表示 -void DumpFX(FontxFile *fxs) -{ - int i; - for(i=0;i<2;i++) { - printf("fxs[%d]->path=%s\n",i,fxs[i].path); - printf("fxs[%d]->opened=%d\n",i,fxs[i].opened); - printf("fxs[%d]->fxname=%s\n",i,fxs[i].fxname); - printf("fxs[%d]->valid=%d\n",i,fxs[i].valid); - printf("fxs[%d]->is_ank=%d\n",i,fxs[i].is_ank); - printf("fxs[%d]->w=%d\n",i,fxs[i].w); - printf("fxs[%d]->h=%d\n",i,fxs[i].h); - printf("fxs[%d]->fsz=%d\n",i,fxs[i].fsz); - printf("fxs[%d]->bc=%d\n",i,fxs[i].bc); - } -} - -// UTF code(3Byte) を SJIS Code(2 Byte) に変換 -uint16_t UTF2SJIS(uint8_t *utf8) { - unsigned char strJIS[3] = {0}; - unsigned char *pi1 = utf8; - unsigned char **pi2 = &pi1; - unsigned char *po1 = strJIS; - unsigned char **po2 = &po1; - size_t ilen = 3; - size_t olen = 2; - iconv_t cd; - uint16_t sjis; - - if((cd = iconv_open("sjis","utf-8")) == (iconv_t)-1){ -if(FontxDebug)printf("iconv open fail \n"); - return 0; - }else { -if(FontxDebug)printf("iconv open ok \n"); - } - - iconv(cd,(char**)pi2,&ilen,(char**)po2,&olen); - iconv_close(cd); - -if(FontxDebug)printf("[UTF2SJIS]strJIS=%x-%x\n",strJIS[0],strJIS[1]); - if (strJIS[0] & 0x80) { - sjis = strJIS[0] << 8; - sjis = sjis + strJIS[1]; - } else { - sjis = strJIS[0]; - } -if(FontxDebug)printf("[UTF2SJIS]sjis=%x\n",sjis); - return sjis; -} - - -// UTFを含む文字列をSJISに変換 -int String2SJIS(unsigned char *str_in, uint8_t stlen, uint16_t *sjis, - uint8_t ssize) { - int i; - uint8_t sp; - uint8_t c1 = 0; - uint8_t c2 = 0; - uint8_t utf8[3]; - uint16_t sjis2; - int spos = 0; - - for(i=0;i> 1; - } - return ch2; -} diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx.h b/rootfs/usr/share/d3m0n/src/lib/fontx.h deleted file mode 100644 index c6907f74..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/fontx.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#define FontxGlyphBufSize (32*32/8) - -typedef struct { - const char *path; - char fxname[9]; - bool opened; - bool valid; - bool is_ank; - uint8_t w; - uint8_t h; - uint16_t fsz; - uint8_t bc; - FILE *file; -} FontxFile; - -void Fontx_addFont(FontxFile *fx, const char *path); -void Fontx_init(FontxFile *fxs,const char *f0,const char *f1); -bool Fontx_openFontxFile(FontxFile *fx); -void Fontx_closeFontxFile(FontxFile *fx); -bool GetFontx (FontxFile *fxs, uint32_t sjis , uint8_t *pGlyph, - uint8_t *pw, uint8_t *ph); -void Font2Bitmap(uint8_t *fonts, uint8_t *line, uint8_t w, uint8_t h, - uint8_t inverse); -void UnderlineBitmap(uint8_t *line, uint8_t w, uint8_t h); -void ReversBitmap(uint8_t *line, uint8_t w, uint8_t h); -void ShowFont(uint8_t *fonts, uint8_t pw, uint8_t ph); -void ShowBitmap(uint8_t *bitmap, uint8_t pw, uint8_t ph); -void DumpFX(FontxFile *fxs); -uint16_t UTF2SJIS(uint8_t *utf8); -int String2SJIS(unsigned char *str_in, uint8_t stlen, uint16_t *sjis, - uint8_t ssize); -uint8_t RotateByte(uint8_t ch); diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/FileList.txt b/rootfs/usr/share/d3m0n/src/lib/fontx/FileList.txt deleted file mode 100644 index e426df26..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/fontx/FileList.txt +++ /dev/null @@ -1,23 +0,0 @@ -ILGH16XB.FNT 16 dot GOTHIC font (Single byte code) -ILGH24XB.FNT 24 dot GOTHIC font (Single byte code) -ILGH24XF.FNT 24 dot GOTHIC bold font (Single byte code) -ILGH32XB.FNT 32 dot GOTHIC font (Single byte code) -ILGH32XF.FNT 32 dot GOTHIC bold font (Single byte code) -ILGZ16XB.FNT 16 dot GOTHIC font (Double byte code) -ILGZ16XF.FNT 16 dot GOTHIC bold font (Double byte code) -ILGZ24XB.FNT 24 dot GOTHIC font (Double byte code) -ILGZ24XF.FNT 24 dot GOTHIC bold font (Double byte code) -ILGZ32XB.FNT 32 dot GOTHIC font (Double byte code) -ILGZ32XF.FNT 32 dot GOTHIC bold font (Double byte code) - -ILMH16XB.FNT 16 dot MINCYO font (Single byte code) -ILMH24XB.FNT 24 dot MINCYO font (Single byte code) -ILMH24XF.FNT 24 dot MINCYO bold font (Single byte code) -ILMH32XB.FNT 32 dot MINCYO font (Single byte code) -ILMH32XF.FNT 32 dot MINCYO bold font (Single byte code) -ILMZ16XB.FNT 16 dot MINCYO font (Double byte code) -ILMZ16XF.FNT 16 dot MINCYO bold font (Double byte code) -ILMZ24XB.FNT 24 dot MINCYO font (Double byte code) -ILMZ24XF.FNT 24 dot MINCYO bold font (Double byte code) -ILMZ32XB.FNT 32 dot MINCYO font (Double byte code) -ILMZ32XF.FNT 32 dot MINCYO bold font (Double byte code) diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH16XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH16XB.FNT deleted file mode 100644 index ff2af0a3..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH16XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XB.FNT deleted file mode 100644 index ba62bb25..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XF.FNT deleted file mode 100644 index eacb8e34..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH24XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XB.FNT deleted file mode 100644 index 3aa145d6..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XF.FNT deleted file mode 100644 index 374468f4..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGH32XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XB.FNT deleted file mode 100644 index c35e9893..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XF.FNT deleted file mode 100644 index 982eb952..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ16XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XB.FNT deleted file mode 100644 index 26ec1bd0..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XF.FNT deleted file mode 100644 index ad11ea47..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ24XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XB.FNT deleted file mode 100644 index 590ffab5..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XF.FNT deleted file mode 100644 index b2e23cc3..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILGZ32XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH16XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH16XB.FNT deleted file mode 100644 index 29bf0f10..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH16XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XB.FNT deleted file mode 100644 index 91151816..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XF.FNT deleted file mode 100644 index 64ebcaf7..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH24XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XB.FNT deleted file mode 100644 index 90230b68..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XF.FNT deleted file mode 100644 index 502b1c9c..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMH32XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XB.FNT deleted file mode 100644 index 8690ef53..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XF.FNT deleted file mode 100644 index ec27f231..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ16XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XB.FNT deleted file mode 100644 index b5cf9441..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XF.FNT deleted file mode 100644 index c11e582b..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ24XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XB.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XB.FNT deleted file mode 100644 index a56a9c59..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XB.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XF.FNT b/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XF.FNT deleted file mode 100644 index 868ca559..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/fontx/ILMZ32XF.FNT and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/fontx/README.md b/rootfs/usr/share/d3m0n/src/lib/fontx/README.md deleted file mode 100644 index 10b50f8e..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/fontx/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Font File -This tool uses an "IL Font" that has been converted from "IPA fonts" to FONTX format fonts. -This distribution is distributed under the license of the original distribution IPA font. -The license of IPA font is in IPA_Font_License_Agreement_v1.0.txt. -In order to modify and redistribute the IPA font, it is named "IL Font" according to the license terms. - -## FONTX format -You can add your original font file. -Please refer [this](http://elm-chan.org/docs/dosv/fontx_e.html) page about FONTX format. - -``` -FontxFile yourFont[2]; -Fontx_init(yourFont,"./fontx/AlphaNumeric_font","./fontx/JAPANESE_font"); -uint8_t ascii[10]; -strcpy((char *)ascii, "MyFont"); -uint16_t color = RED; -lcdDrawUTF8String(yourFont, xpos, ypos, ascii, color); -``` - -## FONTX Editor -[There](http://elm-chan.org/fsw/fontxedit.zip) is FONTX Editor. -This runs on Windows10. -Developer page is [here](http://elm-chan.org/fsw_e.html). - -![FontxEditor](https://user-images.githubusercontent.com/6020549/78731275-3b889800-797a-11ea-81ba-096dbf07c4b8.png) - - -This library uses the following as default fonts: -- fontx/ILGH16XB.FNT fontx/ILGZ16XB.FNT // 8x16Dot Gothic -- fontx/ILGH24XB.FNT fontx/ILGZ24XB.FNT // 12x24Dot Gothic -- fontx/ILGH32XB.FNT fontx/ILGZ32XB.FNT // 16x32Dot Gothic -- fontx/ILMH16XB.FNT fontx/ILMZ16XF.FNT // 8x16Dot Mincyo -- fontx/ILMH24XB.FNT fontx/ILMZ24XF.FNT // 12x24Dot Mincyo -- fontx/ILMH32XB.FNT fontx/ILMZ32XF.FNT // 16x32Dot Mincyo - -Changing this file will change the font. diff --git a/rootfs/usr/share/d3m0n/src/lib/ili9340.c b/rootfs/usr/share/d3m0n/src/lib/ili9340.c deleted file mode 100644 index c6142436..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/ili9340.c +++ /dev/null @@ -1,896 +0,0 @@ -// ili9340.c -// Used by bcm2835 library.(Mike McCauley) -// -// Original is http://imagewriteriij.blogspot.jp/2014/01/raspberry-pi-9-lcd-1.html -// LCD test program 20130103 by ImageWriter -// -// [Pin connection] -// ILI9340-SPI Rpi(pin) -// ------------------------ -// VCC-------------3.3V -// GND-------------GND -// CS--------------CS0 (24) -// RES-------------IO18(12) -// D/C-------------IO17(11) LOW = COMMAND / HIGH = DATA -// MOSI------------MOSI(19) -// SCK-------------SCLK(23) -// LED-------------3.3V -// MISO------------N/C -// ------------------------ -// -// [SPI settings] -// ORDER : MSB First -// MODE : Mode0 -// CLOCK : 31.25MHz on Rpi/Rpi2, 50MHz on RPI3 -// CS : CS0 -// CS_POL : LOW -// -// -#define BCM 1 - -#include -#include -#include -#include -#include - -#ifdef WPI -#include -#include -#include - -#ifdef GPIO -#define D_C 17 // BCM IO17=Pin#11 -#define RES 18 // BCM IO18=Pin#12 -#define MOSI 10 // BCM IO10=Pin#19 -#define SCLK 11 // BCM IO11=Pin#23 -#define CS 24 // BCM IO24=Pin#24 -#else -#define D_C 0 // wPi IO00=Pin#11 -#define RES 1 // wPi IO01=Pin#12 -#define MOSI 12 // wPi IO12=Pin#19 -#define SCLK 14 // wPi IO14=Pin#23 -#define CS 10 // wPi IO10=Pin#24 -#endif -#endif // end WPI - - -#ifdef BCM -#include -#define D_C 17 // BCM IO17=Pin#11 -#define RES 18 // BCM IO18=Pin#12 -#endif - -#include "ili9340.h" - -#define _DEBUG_ 0 - -uint16_t _FONT_DIRECTION_; -uint16_t _FONT_FILL_; -uint16_t _FONT_FILL_COLOR_; -uint16_t _FONT_UNDER_LINE_; -uint16_t _FONT_UNDER_LINE_COLOR_; - -int _width; -int _height; -int _offsetx; -int _offsety; - -#ifdef WPI -// Write Command 8Bit -// D/C=LOW then,write command(8bit) -void lcdWriteCommandByte(uint8_t c){ - digitalWrite(D_C, LOW); -#ifdef SOFT_SPI - digitalWrite(CS, LOW); - shiftOut(MOSI, SCLK, MSBFIRST, c); - digitalWrite(CS, HIGH); -#else - wiringPiSPIDataRW(0, &c, 1); -#endif -} - -// Write Data 8Bit -// D/C=HIGH then,write data(8bit) -void lcdWriteDataByte(uint8_t c){ - digitalWrite(D_C, HIGH); -#ifdef SOFT_SPI - digitalWrite(CS, LOW); - shiftOut(MOSI, SCLK, MSBFIRST, c); - digitalWrite(CS, HIGH); -#else - wiringPiSPIDataRW(0, &c, 1); -#endif -} - -// Write Data 16Bit -void lcdWriteDataWord(uint16_t w){ - uint8_t hi,lo; - hi = (w >> 8) & 0xFF; - lo = w & 0xFF; - lcdWriteDataByte(hi); - lcdWriteDataByte(lo); -} - -// Write Data 16Bit -void lcdWriteColor(uint16_t color, size_t size) { - uint8_t byte[1024]; - int index=0; - int i; - for(i=0;i> 8) & 0xFF; - byte[index++] = color & 0xFF; - } - digitalWrite(D_C, HIGH); -#ifdef SOFT_SPI - digitalWrite(CS, LOW); - for(int index=0;index= _width) return; - if (y >= _height) return; - - uint16_t _x = x + _offsetx; - uint16_t _y = y + _offsety; - lcdWriteCommandByte(0x2A); // set column(x) address - lcdWriteDataWord(_x); - lcdWriteDataWord(_x); - lcdWriteCommandByte(0x2B); // set Page(y) address - lcdWriteDataWord(_y); - lcdWriteDataWord(_y); - lcdWriteCommandByte(0x2C); // Memory Write - lcdWriteDataWord(color); -} - - -// Draw rectangule of filling -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// color:color -void lcdDrawFillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - int i,j; - if (x1 >= _width) return; - if (x2 >= _width) x2=_width-1; - if (y1 >= _height) return; - if (y2 >= _height) y2=_height-1; - - uint16_t _x1 = x1 + _offsetx; - uint16_t _x2 = x2 + _offsetx; - uint16_t _y1 = y1 + _offsety; - uint16_t _y2 = y2 + _offsety; - lcdWriteCommandByte(0x2A); // set column(x) address - lcdWriteDataWord(_x1); - lcdWriteDataWord(_x2); - lcdWriteCommandByte(0x2B); // set Page(y) address - lcdWriteDataWord(_y1); - lcdWriteDataWord(_y2); - lcdWriteCommandByte(0x2C); // Memory Write - for(i=x1;i<=x2;i++){ - size_t size = y2-y1+1; - lcdWriteColor(color, size); -#if 0 - for(j=y1;j<=y2;j++){ - lcdWriteDataWord(color); - } -#endif - } -} - -// Display Off -void lcdDisplayOff(void) { - lcdWriteCommandByte(0x28); //Display OFF -} - -// Display On -void lcdDisplayOn(void) { - lcdWriteCommandByte(0x29); //Display ON -} - -// Display Inversion On -void lcdInversionOn(void) { - lcdWriteCommandByte(0x21); //Display Inversion ON -} - -// Fill screen -// color:color -void lcdFillScreen(uint16_t color) { - lcdDrawFillRect(0, 0, _width-1, _height-1, color); -} - -// Draw line -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// color:color -void lcdDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - int i; - int dx,dy; - int sx,sy; - int E; - - /* distance between two points */ - dx = ( x2 > x1 ) ? x2 - x1 : x1 - x2; - dy = ( y2 > y1 ) ? y2 - y1 : y1 - y2; - - /* direction of two point */ - sx = ( x2 > x1 ) ? 1 : -1; - sy = ( y2 > y1 ) ? 1 : -1; - - /* inclination < 1 */ - if ( dx > dy ) { - E = -dx; - for ( i = 0 ; i <= dx ; i++ ) { - lcdDrawPixel( x1, y1, color ); - x1 += sx; - E += 2 * dy; - if ( E >= 0 ) { - y1 += sy; - E -= 2 * dx; - } - } - /* inclination >= 1 */ - } else { - E = -dy; - for ( i = 0 ; i <= dy ; i++ ) { - lcdDrawPixel( x1, y1, color ); - y1 += sy; - E += 2 * dx; - if ( E >= 0 ) { - x1 += sx; - E -= 2 * dy; - } - } - } -} - -// Draw rectangule -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// color:color -void lcdDrawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - lcdDrawLine(x1,y1,x2,y1,color); - lcdDrawLine(x2,y1,x2,y2,color); - lcdDrawLine(x2,y2,x1,y2,color); - lcdDrawLine(x1,y2,x1,y1,color); -} - -// Draw round -// x0:Central X coordinate -// y0:Central Y coordinate -// r:radius -// color:color -void lcdDrawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { - int x; - int y; - int err; - int old_err; - - x=0; - y=-r; - err=2-2*r; - do{ - lcdDrawPixel(x0-x,y0+y,color); - lcdDrawPixel(x0-y,y0-x,color); - lcdDrawPixel(x0+x,y0-y,color); - lcdDrawPixel(x0+y,y0+x,color); - if ((old_err=err)<=x) err+=++x*2+1; - if (old_err>y || err>x) err+=++y*2+1; - } while(y<0); - -} - -// Draw round of filling -// x0:Central X coordinate -// y0:Central Y coordinate -// r:radius -// color:color -void lcdDrawFillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { - int x; - int y; - int err; - int old_err; - int ChangeX; - - x=0; - y=-r; - err=2-2*r; - ChangeX=1; - do{ - if(ChangeX) { - lcdDrawLine(x0-x,y0-y,x0-x,y0+y,color); - lcdDrawLine(x0+x,y0-y,x0+x,y0+y,color); - } // if - ChangeX=(old_err=err)<=x; - if (ChangeX) err+=++x*2+1; - if (old_err>y || err>x) err+=++y*2+1; - } while(y<=0); - -} - -// Draw rectangule with round corner -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// r:radius -// color:color -void lcdDrawRoundRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t r, uint16_t color) { - int x; - int y; - int err; - int old_err; - unsigned char temp; - - if(x1>x2) { - temp=x1; x1=x2; x2=temp; - } - - if(y1>y2) { - temp=y1; y1=y2; y2=temp; - } - if (x2 - x1 < r) return; // Add 20190517 - if (y2 - y1 < r) return; // Add 20190517 - - x=0; - y=-r; - err=2-2*r; - - do{ - if(x) { - lcdDrawPixel(x1+r-x,y1+r+y,color); - lcdDrawPixel(x2-r+x,y1+r+y,color); - lcdDrawPixel(x1+r-x,y2-r-y,color); - lcdDrawPixel(x2-r+x,y2-r-y,color); - } // if - if ((old_err=err)<=x) err+=++x*2+1; - if (old_err>y || err>x) err+=++y*2+1; - } while(y<0); - - lcdDrawLine(x1+r,y1 ,x2-r,y1 ,color); - lcdDrawLine(x1+r,y2 ,x2-r,y2 ,color); - lcdDrawLine(x1 ,y1+r,x1 ,y2-r,color); - lcdDrawLine(x2 ,y1+r,x2 ,y2-r,color); -} - -// Draw arrow -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// w:Width of the botom -// color:color -// Thanks http://k-hiura.cocolog-nifty.com/blog/2010/11/post-2a62.html -void lcdDrawArrow(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color) { - - double Vx= x1 - x0; - double Vy= y1 - y0; - double v = sqrt(Vx*Vx+Vy*Vy); -// printf("v=%f\n",v); - double Ux= Vx/v; - double Uy= Vy/v; - - uint16_t L[2],R[2]; - L[0]= x1 - Uy*w - Ux*v; - L[1]= y1 + Ux*w - Uy*v; - R[0]= x1 + Uy*w - Ux*v; - R[1]= y1 - Ux*w - Uy*v; -// printf("L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); - -// lcdDrawLine(x0,y0,x1,y1,color); - lcdDrawLine(x1,y1,L[0],L[1],color); - lcdDrawLine(x1,y1,R[0],R[1],color); - lcdDrawLine(L[0],L[1],R[0],R[1],color); -} - - -// Draw arrow of filling -// x1:Start X coordinate -// y1:Start Y coordinate -// x2:End X coordinate -// y2:End Y coordinate -// w:Width of the botom -// color:color -void lcdDrawFillArrow(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color) { - - double Vx= x1 - x0; - double Vy= y1 - y0; - double v = sqrt(Vx*Vx+Vy*Vy); -// printf("v=%f\n",v); - double Ux= Vx/v; - double Uy= Vy/v; - - uint16_t L[2],R[2]; - L[0]= x1 - Uy*w - Ux*v; - L[1]= y1 + Ux*w - Uy*v; - R[0]= x1 + Uy*w - Ux*v; - R[1]= y1 - Ux*w - Uy*v; -// printf("L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); - - lcdDrawLine(x0,y0,x1,y1,color); - lcdDrawLine(x1,y1,L[0],L[1],color); - lcdDrawLine(x1,y1,R[0],R[1],color); - lcdDrawLine(L[0],L[1],R[0],R[1],color); - - int ww; - for(ww=w-1;ww>0;ww--) { - L[0]= x1 - Uy*ww - Ux*v; - L[1]= y1 + Ux*ww - Uy*v; - R[0]= x1 + Uy*ww - Ux*v; - R[1]= y1 - Ux*ww - Uy*v; -// printf("Fill>L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); - lcdDrawLine(x1,y1,L[0],L[1],color); - lcdDrawLine(x1,y1,R[0],R[1],color); - } -} - -// Draw SJIS character -// x:X coordinate -// y:Y coordinate -// sjis: SJIS code -// color:color -int lcdDrawSJISChar(FontxFile *fx, uint16_t x,uint16_t y,uint16_t sjis,uint16_t color) { - uint16_t xx,yy,bit,ofs; - unsigned char fonts[128]; // font pattern - unsigned char pw, ph; - int h,w; - uint16_t mask; - bool rc; - -if(_DEBUG_)printf("_FONT_DIRECTION_=%d\n",_FONT_DIRECTION_); -// sjis = UTF2SJIS(utf8); -//if(_DEBUG_)printf("sjis=%04x\n",sjis); - - rc = GetFontx(fx, sjis, fonts, &pw, &ph); // SJIS -> Font pattern -if(_DEBUG_)printf("GetFontx rc=%d pw=%d ph=%d\n",rc,pw,ph); - if (!rc) return 0; - - uint16_t xd1, yd1; - uint16_t xd2, yd2; - uint16_t xss, yss; - uint16_t xsd, ysd; - int next; - uint16_t x0 = 0; - uint16_t x1 = 0; - uint16_t y0 = 0; - uint16_t y1 = 0; - if (_FONT_DIRECTION_ == 0) { - xd1 = +1; - yd1 = -1; - xd2 = 0; - yd2 = 0; - xss = x; - yss = y + (ph - 1); - xsd = 1; - ysd = 0; - next = x + pw; - - x0 = x; - y0 = y; - x1 = x + (pw-1); - y1 = y + (ph-1); - } else if (_FONT_DIRECTION_ == 2) { - xd1 = -1; - yd1 = +1; - xd2 = 0; - yd2 = 0; - xss = x; - yss = y - (ph + 1); - xsd = 1; - ysd = 0; - next = x - pw; - - x0 = x - (pw-1); - y0 = y - (ph-1); - x1 = x; - y1 = y; - } else if (_FONT_DIRECTION_ == 1) { - xd1 = 0; - yd1 = 0; - xd2 = -1; - yd2 = -1; - xss = x + (ph - 1); // Bug Fix - yss = y; - xsd = 0; - ysd = 1; - next = y - pw; - - x0 = x; - y0 = y - (pw-1); - x1 = x + (ph-1); - y1 = y; - } else if (_FONT_DIRECTION_ == 3) { - xd1 = 0; - yd1 = 0; - xd2 = +1; - yd2 = +1; - xss = x - (ph - 1); // Bug Fix - yss = y; - xsd = 0; - ysd = 1; - next = y + pw; - - x0 = x - (ph-1); - y0 = y; - x1 = x; - y1 = y + (pw-1); - } - if (_FONT_FILL_) lcdDrawFillRect(x0, y0, x1, y1, _FONT_FILL_COLOR_); - - int bits; -if(_DEBUG_)printf("xss=%d yss=%d\n",xss,yss); - ofs = 0; - yy = yss; - xx = xss; - for(h=0;h> 1; - } - ofs++; - } - yy = yy + yd1; - xx = xx + xd2; - - } - - if (next < 0) next = 0; - return next; -} - -// Draw UTF8 character -// x:X coordinate -// y:Y coordinate -// utf8: UTF8 code -// color:color -int lcdDrawUTF8Char(FontxFile *fx, uint16_t x,uint16_t y,uint8_t *utf8,uint16_t color) { - uint16_t sjis[1]; - - sjis[0] = UTF2SJIS(utf8); -if(_DEBUG_)printf("sjis=%04x\n",sjis[0]); - return lcdDrawSJISChar(fx,x,y,sjis[0],color); -} - -// Draw UTF8 string -// x:X coordinate -// y:Y coordinate -// utfs: UTF8 string -// color:color -int lcdDrawUTF8String(FontxFile *fx, uint16_t x,uint16_t y,unsigned char *utfs,uint16_t color) { - -if(_DEBUG_)printf("lcdDrawUTF8String start x=%d y=%d\n",x,y); - int i; - int spos; - uint16_t sjis[64]; - spos = String2SJIS(utfs, strlen((char *)utfs), sjis, 64); -if(_DEBUG_)printf("spos=%d\n",spos); - for(i=0;i> 3)) - -void lcdWriteCommandByte(uint8_t c); -void lcdWriteDataByte(uint8_t c); -void lcdWriteDataWord(uint16_t w); -void lcdWriteColor(uint16_t color, size_t size); - -void lcdInit(int width, int height, int offsetx, int offsety); -void lcdReset(void); -void lcdSetup(void); -void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color); -void lcdDrawFillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); -void lcdDisplayOff(void); -void lcdDisplayOn(void); -void lcdInversionOn(void); -void lcdFillScreen(uint16_t color); -void lcdDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); -void lcdDrawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); -void lcdDrawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); -void lcdDrawFillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); -void lcdDrawRoundRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t r, uint16_t color); -void lcdDrawArrow(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color); -void lcdDrawFillArrow(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color); -int lcdDrawSJISChar(FontxFile *fx, uint16_t x,uint16_t y,uint16_t sjis,uint16_t color); -int lcdDrawUTF8Char(FontxFile *fx, uint16_t x,uint16_t y,uint8_t *utf8,uint16_t color); -int lcdDrawUTF8String(FontxFile *fx, uint16_t x,uint16_t y,unsigned char *utfs,uint16_t color); -void lcdSetFontDirection(uint16_t); -void lcdSetFontFill(uint16_t color); -void lcdUnsetFontFill(void); -void lcdSetFontUnderLine(uint16_t color); -void lcdUnsetFontUnderLine(void); diff --git a/rootfs/usr/share/d3m0n/src/lib/images/RaspberryPi_240x240.jpg b/rootfs/usr/share/d3m0n/src/lib/images/RaspberryPi_240x240.jpg deleted file mode 100644 index 4b5a5a72..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/images/RaspberryPi_240x240.jpg and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/images/Ubuntu_log.png b/rootfs/usr/share/d3m0n/src/lib/images/Ubuntu_log.png deleted file mode 100644 index 56d394cf..00000000 Binary files a/rootfs/usr/share/d3m0n/src/lib/images/Ubuntu_log.png and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.c b/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.c deleted file mode 100644 index b589bf85..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include "pngle.h" - -void png_init(pngle_t *pngle, uint32_t w, uint32_t h) -{ - //printf("png_init w=%d h=%d\n", w, h); - //printf("screenWidth=%d screenHeight=%d\n", pngle->screenWidth, pngle->screenHeight); - pngle->imageWidth = w; - pngle->imageHeight = h; - pngle->reduction = false; - pngle->scale_factor = 1.0; - - // Calculate Reduction - if (pngle->screenWidth < pngle->imageWidth || pngle->screenHeight < pngle->imageHeight) { - pngle->reduction = true; - double factorWidth = (double)pngle->screenWidth / (double)pngle->imageWidth; - double factorHeight = (double)pngle->screenHeight / (double)pngle->imageHeight; - pngle->scale_factor = factorWidth; - if (factorHeight < factorWidth) pngle->scale_factor = factorHeight; - pngle->imageWidth = pngle->imageWidth * pngle->scale_factor; - pngle->imageHeight = pngle->imageHeight * pngle->scale_factor; - } - //printf("reduction=%d scale_factor=%f\n", pngle->reduction, pngle->scale_factor); - //printf("imageWidth=%d imageHeight=%d\n", pngle->imageWidth, pngle->imageHeight); -} - -void png_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) -{ - //printf("png_draw x=%d y=%d w=%d h=%d\n", x,y,w,h); -#if 0 - uint8_t r = rgba[0]; - uint8_t g = rgba[1]; - uint8_t b = rgba[2]; -#endif - - // image reduction - uint32_t _x = x; - uint32_t _y = y; - if (pngle->reduction) { - _x = x * pngle->scale_factor; - _y = y * pngle->scale_factor; - } - if (_y < pngle->screenHeight && _x < pngle->screenWidth) { - pngle->pixels[_y][_x].red = rgba[0]; - pngle->pixels[_y][_x].green = rgba[1]; - pngle->pixels[_y][_x].blue = rgba[2]; - } - -} - -void png_finish(pngle_t *pngle) { - //printf("png_finish\n"); -} diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.h b/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.h deleted file mode 100644 index 47497bea..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/decode_png.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include -#include "pngle.h" - -void png_init(pngle_t *pngle, uint32_t w, uint32_t h); -void png_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); -void png_finish(pngle_t *pngle); - diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.c b/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.c deleted file mode 100644 index ba25314f..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.c +++ /dev/null @@ -1,4931 +0,0 @@ -/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing - See "unlicense" statement at the end of this file. - Rich Geldreich , last updated Oct. 13, 2013 - Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt - - Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define - MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). - - * Change History - 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!): - - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug - would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place() - (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag). - - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size - - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries. - Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice). - - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes - - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed - - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6. - - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti - - Merged MZ_FORCEINLINE fix from hdeanclark - - Fix include before config #ifdef, thanks emil.brink - - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can - set it to 1 for real-time compression). - - Merged in some compiler fixes from paulharris's github repro. - - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3. - - Added example6.c, which dumps an image of the mandelbrot set to a PNG file. - - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more. - - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled - - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch - 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). - 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. - - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. - - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. - - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly - "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). - - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. - - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. - - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. - - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) - - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). - 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. - level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. - 5/28/11 v1.11 - Added statement from unlicense.org - 5/27/11 v1.10 - Substantial compressor optimizations: - - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a - - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). - - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. - - Refactored the compression code for better readability and maintainability. - - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large - drop in throughput on some files). - 5/15/11 v1.09 - Initial stable release. - - * Low-level Deflate/Inflate implementation notes: - - Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or - greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses - approximately as well as zlib. - - Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function - coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory - block large enough to hold the entire file. - - The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. - - * zlib-style API notes: - - miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in - zlib replacement in many apps: - The z_stream struct, optional memory allocation callbacks - deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound - inflateInit/inflateInit2/inflate/inflateEnd - compress, compress2, compressBound, uncompress - CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. - Supports raw deflate streams or standard zlib streams with adler-32 checking. - - Limitations: - The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. - I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but - there are no guarantees that miniz.c pulls this off perfectly. - - * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by - Alex Evans. Supports 1-4 bytes/pixel images. - - * ZIP archive API notes: - - The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to - get the job done with minimal fuss. There are simple API's to retrieve file information, read files from - existing archives, create new archives, append new files to existing archives, or clone archive data from - one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), - or you can specify custom file read/write callbacks. - - - Archive reading: Just call this function to read a single file from a disk archive: - - void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, - size_t *pSize, mz_uint zip_flags); - - For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central - directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. - - - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: - - int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); - - The locate operation can optionally check file comments too, which (as one example) can be used to identify - multiple versions of the same file in an archive. This function uses a simple linear search through the central - directory, so it's not very fast. - - Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and - retrieve detailed info on each file by calling mz_zip_reader_file_stat(). - - - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data - to disk and builds an exact image of the central directory in memory. The central directory image is written - all at once at the end of the archive file when the archive is finalized. - - The archive writer can optionally align each file's local header and file data to any power of 2 alignment, - which can be useful when the archive will be read from optical media. Also, the writer supports placing - arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still - readable by any ZIP tool. - - - Archive appending: The simple way to add a single file to an archive is to call this function: - - mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); - - The archive will be created if it doesn't already exist, otherwise it'll be appended to. - Note the appending is done in-place and is not an atomic operation, so if something goes wrong - during the operation it's possible the archive could be left without a central directory (although the local - file headers and file data will be fine, so the archive will be recoverable). - - For more complex archive modification scenarios: - 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to - preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the - compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and - you're done. This is safe but requires a bunch of temporary disk space or heap memory. - - 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), - append new files as needed, then finalize the archive which will write an updated central directory to the - original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a - possibility that the archive's central directory could be lost with this method if anything goes wrong, though. - - - ZIP archive support limitations: - No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. - Requires streams capable of seeking. - - * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the - below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. - - * Important: For best perf. be sure to customize the below macros for your target platform: - #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 - #define MINIZ_LITTLE_ENDIAN 1 - #define MINIZ_HAS_64BIT_REGISTERS 1 - - * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz - uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files - (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes). -*/ - -#ifndef MINIZ_HEADER_INCLUDED -#define MINIZ_HEADER_INCLUDED - -#include - -// Defines to completely disable specific portions of miniz.c: -// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. - -// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. -#define MINIZ_NO_STDIO - -// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or -// get/set file times, and the C run-time funcs that get/set times won't be called. -// The current downside is the times written to your archives will be from 1979. -#define MINIZ_NO_TIME - -// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. -#define MINIZ_NO_ARCHIVE_APIS - -// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. -#define MINIZ_NO_ARCHIVE_WRITING_APIS - -// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. -#define MINIZ_NO_ZLIB_APIS - -// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. -//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES - -// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. -// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc -// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user -// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. -//#define MINIZ_NO_MALLOC - -// -#define MINIZ_NO_COMPRESSION - - -#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) - // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux - #define MINIZ_NO_TIME -#endif - -#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) - #include -#endif - -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) -// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. -#define MINIZ_X86_OR_X64_CPU 1 -#endif - -#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU -// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. -#define MINIZ_LITTLE_ENDIAN 1 -#endif - -#if MINIZ_X86_OR_X64_CPU -// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. -#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 -#endif - -#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) -// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). -#define MINIZ_HAS_64BIT_REGISTERS 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// ------------------- zlib-style API Definitions. - -// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! -typedef unsigned long mz_ulong; - -// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. -void mz_free(void *p); - -#define MZ_ADLER32_INIT (1) -// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); - -#define MZ_CRC32_INIT (0) -// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); - -// Compression strategies. -enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; - -// Method -#define MZ_DEFLATED 8 - -#ifndef MINIZ_NO_ZLIB_APIS - -// Heap allocation callbacks. -// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. -typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); -typedef void (*mz_free_func)(void *opaque, void *address); -typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); - -#define MZ_VERSION "9.1.15" -#define MZ_VERNUM 0x91F0 -#define MZ_VER_MAJOR 9 -#define MZ_VER_MINOR 1 -#define MZ_VER_REVISION 15 -#define MZ_VER_SUBREVISION 0 - -// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). -enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; - -// Return status codes. MZ_PARAM_ERROR is non-standard. -enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; - -// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. -enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; - -// Window bits -#define MZ_DEFAULT_WINDOW_BITS 15 - -struct mz_internal_state; - -// Compression/decompression stream struct. -typedef struct mz_stream_s -{ - const unsigned char *next_in; // pointer to next byte to read - unsigned int avail_in; // number of bytes available at next_in - mz_ulong total_in; // total number of bytes consumed so far - - unsigned char *next_out; // pointer to next byte to write - unsigned int avail_out; // number of bytes that can be written to next_out - mz_ulong total_out; // total number of bytes produced so far - - char *msg; // error msg (unused) - struct mz_internal_state *state; // internal state, allocated by zalloc/zfree - - mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) - mz_free_func zfree; // optional heap free function (defaults to free) - void *opaque; // heap alloc function user pointer - - int data_type; // data_type (unused) - mz_ulong adler; // adler32 of the source or uncompressed data - mz_ulong reserved; // not used -} mz_stream; - -typedef mz_stream *mz_streamp; - -// Returns the version string of miniz.c. -const char *mz_version(void); - -// mz_deflateInit() initializes a compressor with default options: -// Parameters: -// pStream must point to an initialized mz_stream struct. -// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. -// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. -// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if the input parameters are bogus. -// MZ_MEM_ERROR on out of memory. -int mz_deflateInit(mz_streamp pStream, int level); - -// mz_deflateInit2() is like mz_deflate(), except with more control: -// Additional parameters: -// method must be MZ_DEFLATED -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) -// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); - -// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). -int mz_deflateReset(mz_streamp pStream); - -// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. -// Return values: -// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). -// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) -int mz_deflate(mz_streamp pStream, int flush); - -// mz_deflateEnd() deinitializes a compressor: -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -int mz_deflateEnd(mz_streamp pStream); - -// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); - -// Single-call compression functions mz_compress() and mz_compress2(): -// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); - -// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). -mz_ulong mz_compressBound(mz_ulong source_len); - -// Initializes a decompressor. -int mz_inflateInit(mz_streamp pStream); - -// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). -int mz_inflateInit2(mz_streamp pStream, int window_bits); - -// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. -// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). -// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. -// Return values: -// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. -// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_DATA_ERROR if the deflate stream is invalid. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again -// with more input data, or with more room in the output buffer (except when using single call decompression, described above). -int mz_inflate(mz_streamp pStream, int flush); - -// Deinitializes a decompressor. -int mz_inflateEnd(mz_streamp pStream); - -// Single-call decompression. -// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); - -// Returns a string description of the specified error code, or NULL if the error code is invalid. -const char *mz_error(int err); - -// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. -// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. -#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - typedef unsigned char Byte; - typedef unsigned int uInt; - typedef mz_ulong uLong; - typedef Byte Bytef; - typedef uInt uIntf; - typedef char charf; - typedef int intf; - typedef void *voidpf; - typedef uLong uLongf; - typedef void *voidp; - typedef void *const voidpc; - #define Z_NULL 0 - #define Z_NO_FLUSH MZ_NO_FLUSH - #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH - #define Z_SYNC_FLUSH MZ_SYNC_FLUSH - #define Z_FULL_FLUSH MZ_FULL_FLUSH - #define Z_FINISH MZ_FINISH - #define Z_BLOCK MZ_BLOCK - #define Z_OK MZ_OK - #define Z_STREAM_END MZ_STREAM_END - #define Z_NEED_DICT MZ_NEED_DICT - #define Z_ERRNO MZ_ERRNO - #define Z_STREAM_ERROR MZ_STREAM_ERROR - #define Z_DATA_ERROR MZ_DATA_ERROR - #define Z_MEM_ERROR MZ_MEM_ERROR - #define Z_BUF_ERROR MZ_BUF_ERROR - #define Z_VERSION_ERROR MZ_VERSION_ERROR - #define Z_PARAM_ERROR MZ_PARAM_ERROR - #define Z_NO_COMPRESSION MZ_NO_COMPRESSION - #define Z_BEST_SPEED MZ_BEST_SPEED - #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION - #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION - #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY - #define Z_FILTERED MZ_FILTERED - #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY - #define Z_RLE MZ_RLE - #define Z_FIXED MZ_FIXED - #define Z_DEFLATED MZ_DEFLATED - #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS - #define alloc_func mz_alloc_func - #define free_func mz_free_func - #define internal_state mz_internal_state - #define z_stream mz_stream - #define deflateInit mz_deflateInit - #define deflateInit2 mz_deflateInit2 - #define deflateReset mz_deflateReset - #define deflate mz_deflate - #define deflateEnd mz_deflateEnd - #define deflateBound mz_deflateBound - #define compress mz_compress - #define compress2 mz_compress2 - #define compressBound mz_compressBound - #define inflateInit mz_inflateInit - #define inflateInit2 mz_inflateInit2 - #define inflate mz_inflate - #define inflateEnd mz_inflateEnd - #define uncompress mz_uncompress - #define crc32 mz_crc32 - #define adler32 mz_adler32 - #define MAX_WBITS 15 - #define MAX_MEM_LEVEL 9 - #define zError mz_error - #define ZLIB_VERSION MZ_VERSION - #define ZLIB_VERNUM MZ_VERNUM - #define ZLIB_VER_MAJOR MZ_VER_MAJOR - #define ZLIB_VER_MINOR MZ_VER_MINOR - #define ZLIB_VER_REVISION MZ_VER_REVISION - #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION - #define zlibVersion mz_version - #define zlib_version mz_version() -#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - -#endif // MINIZ_NO_ZLIB_APIS - -// ------------------- Types and macros - -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; -typedef unsigned int mz_uint; -typedef long long mz_int64; -typedef unsigned long long mz_uint64; -typedef int mz_bool; - -#define MZ_FALSE (0) -#define MZ_TRUE (1) - -// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. -#ifdef _MSC_VER - #define MZ_MACRO_END while (0, 0) -#else - #define MZ_MACRO_END while (0) -#endif - -// ------------------- ZIP archive reading/writing - -#ifndef MINIZ_NO_ARCHIVE_APIS - -enum -{ - MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, - MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, - MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 -}; - -typedef struct -{ - mz_uint32 m_file_index; - mz_uint32 m_central_dir_ofs; - mz_uint16 m_version_made_by; - mz_uint16 m_version_needed; - mz_uint16 m_bit_flag; - mz_uint16 m_method; -#ifndef MINIZ_NO_TIME - time_t m_time; -#endif - mz_uint32 m_crc32; - mz_uint64 m_comp_size; - mz_uint64 m_uncomp_size; - mz_uint16 m_internal_attr; - mz_uint32 m_external_attr; - mz_uint64 m_local_header_ofs; - mz_uint32 m_comment_size; - char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; - char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; -} mz_zip_archive_file_stat; - -typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); -typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); - -struct mz_zip_internal_state_tag; -typedef struct mz_zip_internal_state_tag mz_zip_internal_state; - -typedef enum -{ - MZ_ZIP_MODE_INVALID = 0, - MZ_ZIP_MODE_READING = 1, - MZ_ZIP_MODE_WRITING = 2, - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 -} mz_zip_mode; - -typedef struct mz_zip_archive_tag -{ - mz_uint64 m_archive_size; - mz_uint64 m_central_directory_file_ofs; - mz_uint m_total_files; - mz_zip_mode m_zip_mode; - - mz_uint m_file_offset_alignment; - - mz_alloc_func m_pAlloc; - mz_free_func m_pFree; - mz_realloc_func m_pRealloc; - void *m_pAlloc_opaque; - - mz_file_read_func m_pRead; - mz_file_write_func m_pWrite; - void *m_pIO_opaque; - - mz_zip_internal_state *m_pState; - -} mz_zip_archive; - -typedef enum -{ - MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, - MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, - MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 -} mz_zip_flags; - -// ZIP archive reading - -// Inits a ZIP archive reader. -// These functions read and validate the archive's central directory. -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); -#endif - -// Returns the total number of files in the archive. -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); - -// Returns detailed information about an archive file entry. -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); - -// Determines if an archive file entry is a directory entry. -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); - -// Retrieves the filename of an archive file entry. -// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); - -// Attempts to locates a file in the archive's central directory. -// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH -// Returns -1 if the file cannot be found. -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); - -// Extracts a archive file to a memory buffer using no memory allocation. -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); - -// Extracts a archive file to a memory buffer. -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); - -// Extracts a archive file to a dynamically allocated heap buffer. -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); - -// Extracts a archive file using a callback function to output the file's data. -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); - -#ifndef MINIZ_NO_STDIO -// Extracts a archive file to a disk file and sets its last accessed and modified times. -// This function only extracts files, not archive directory records. -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); -#endif - -// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. -mz_bool mz_zip_reader_end(mz_zip_archive *pZip); - -// ZIP archive writing - -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -// Inits a ZIP archive writer. -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); -#endif - -// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. -// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. -// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). -// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. -// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before -// the archive is finalized the file's central directory will be hosed. -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); - -// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. -// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); - -#ifndef MINIZ_NO_STDIO -// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); -#endif - -// Adds a file to an archive by fully cloning the data from another archive. -// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); - -// Finalizes the archive by writing the central directory records followed by the end of central directory record. -// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). -// An archive must be manually finalized by calling this function for it to be valid. -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); - -// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. -// Note for the archive to be valid, it must have been finalized before ending. -mz_bool mz_zip_writer_end(mz_zip_archive *pZip); - -// Misc. high-level helper functions: - -// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); - -// Reads a single file from an archive into a heap block. -// Returns NULL on failure. -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); - -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS - -// ------------------- Low-level Decompression API Definitions - -// Decompression flags used by tinfl_decompress(). -// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. -// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. -// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). -// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. -enum -{ - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 -}; - -// High level decompression functions: -// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. -// On return: -// Function returns a pointer to the decompressed data, or NULL on failure. -// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must call mz_free() on the returned block when it's no longer needed. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. -// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. -#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. -// Returns 1 on success or 0 on failure. -typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; - -// Max size of LZ dictionary. -#define TINFL_LZ_DICT_SIZE 32768 - -// Return status. -typedef enum -{ - TINFL_STATUS_BAD_PARAM = -3, - TINFL_STATUS_ADLER32_MISMATCH = -2, - TINFL_STATUS_FAILED = -1, - TINFL_STATUS_DONE = 0, - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - TINFL_STATUS_HAS_MORE_OUTPUT = 2 -} tinfl_status; - -// Initializes the decompressor to its initial state. -#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END -#define tinfl_get_adler32(r) (r)->m_check_adler32 - -// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. -// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); - -// Internal/private bits follow. -enum -{ - TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS -}; - -typedef struct -{ - mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; -} tinfl_huff_table; - -#if MINIZ_HAS_64BIT_REGISTERS - #define TINFL_USE_64BIT_BITBUF 1 -#endif - -#if TINFL_USE_64BIT_BITBUF - typedef mz_uint64 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (64) -#else - typedef mz_uint32 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (32) -#endif - -struct tinfl_decompressor_tag -{ - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; - mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; -}; - - -#ifndef MINIZ_NO_COMPRESSION -// ------------------- Low-level Compression API Definitions - -// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). -#define TDEFL_LESS_MEMORY 0 - -// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): -// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). -enum -{ - TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF -}; - -// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. -// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). -// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. -// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). -// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) -// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. -// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. -// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. -// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). -enum -{ - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 -}; - -// High level compression functions: -// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of source block to compress. -// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must free() the returned block when it's no longer needed. -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. -// Returns 0 on failure. -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// Compresses an image to a compressed PNG file in memory. -// On entry: -// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. -// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. -// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL -// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pLen_out will be set to the size of the PNG image file. -// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); - -// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); - -// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; - -// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). -#if TDEFL_LESS_MEMORY -enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#else -enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#endif - -// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. -typedef enum -{ - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1, -} tdefl_status; - -// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums -typedef enum -{ - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 -} tdefl_flush; - -// tdefl's compression state structure. -typedef struct -{ - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; -} tdefl_compressor; - -// Initializes the compressor. -// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. -// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. -// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. -// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); - -// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. -// tdefl_compress_buffer() always consumes the entire input buffer. -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); - -// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. -#ifndef MINIZ_NO_ZLIB_APIS -// Create tdefl_compress() flags given zlib-style compression parameters. -// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) -// window_bits may be -15 (raw deflate) or 15 (zlib) -// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); -#endif // #ifndef MINIZ_NO_ZLIB_APIS - -#endif // MINIZ_NO_COMPRESSION - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_INCLUDED - -// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) - -#ifndef MINIZ_HEADER_FILE_ONLY - -typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; -typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; -typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; - -#include -#include - -#define MZ_ASSERT(x) assert(x) - -#ifdef MINIZ_NO_MALLOC - #define MZ_MALLOC(x) NULL - #define MZ_FREE(x) (void)x, ((void)0) - #define MZ_REALLOC(p, x) NULL -#else - #define MZ_MALLOC(x) malloc(x) - #define MZ_FREE(x) free(x) - #define MZ_REALLOC(p, x) realloc(p, x) -#endif - -#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) -#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) -#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) - #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) -#else - #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) - #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) -#endif - -#ifdef _MSC_VER - #define MZ_FORCEINLINE __forceinline -#elif defined(__GNUC__) - #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) -#else - #define MZ_FORCEINLINE inline -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -// ------------------- zlib-style API's - -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) -{ - mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - return (s2 << 16) + s1; -} - -// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) -{ - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) return MZ_CRC32_INIT; - crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } - return ~crcu32; -} - -void mz_free(void *p) -{ - MZ_FREE(p); -} - -#ifndef MINIZ_NO_ZLIB_APIS - -static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } -static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } -static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } - -const char *mz_version(void) -{ - return MZ_VERSION; -} - -#ifndef MINIZ_NO_COMPRESSION - -int mz_deflateInit(mz_streamp pStream, int level) -{ - return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); -} - -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) -{ - tdefl_compressor *pComp; - mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); - - if (!pStream) return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = MZ_ADLER32_INIT; - pStream->msg = NULL; - pStream->reserved = 0; - pStream->total_in = 0; - pStream->total_out = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; - - pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *)pComp; - - if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) - { - mz_deflateEnd(pStream); - return MZ_PARAM_ERROR; - } - - return MZ_OK; -} - -int mz_deflateReset(mz_streamp pStream) -{ - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; - pStream->total_in = pStream->total_out = 0; - tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); - return MZ_OK; -} - -int mz_deflate(mz_streamp pStream, int flush) -{ - size_t in_bytes, out_bytes; - mz_ulong orig_total_in, orig_total_out; - int mz_status = MZ_OK; - - if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; - if (!pStream->avail_out) return MZ_BUF_ERROR; - - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - - if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) - return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; - - orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; - for ( ; ; ) - { - tdefl_status defl_status; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - - defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); - - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; - pStream->total_out += (mz_uint)out_bytes; - - if (defl_status < 0) - { - mz_status = MZ_STREAM_ERROR; - break; - } - else if (defl_status == TDEFL_STATUS_DONE) - { - mz_status = MZ_STREAM_END; - break; - } - else if (!pStream->avail_out) - break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) - { - if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) - break; - return MZ_BUF_ERROR; // Can't make forward progress without some input. - } - } - return mz_status; -} - -int mz_deflateEnd(mz_streamp pStream) -{ - if (!pStream) return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) -{ - (void)pStream; - // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) - return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); -} - -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) -{ - int status; - mz_stream stream; - memset(&stream, 0, sizeof(stream)); - - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_deflateInit(&stream, level); - if (status != MZ_OK) return status; - - status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_deflateEnd(&stream); - return (status == MZ_OK) ? MZ_BUF_ERROR : status; - } - - *pDest_len = stream.total_out; - return mz_deflateEnd(&stream); -} - -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); -} - -mz_ulong mz_compressBound(mz_ulong source_len) -{ - return mz_deflateBound(NULL, source_len); -} - -#endif // MINIZ_NO_COMPRESSION - -typedef struct -{ - tinfl_decompressor m_decomp; - mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; - mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; - tinfl_status m_last_status; -} inflate_state; - -int mz_inflateInit2(mz_streamp pStream, int window_bits) -{ - inflate_state *pDecomp; - if (!pStream) return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; - - pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); - if (!pDecomp) return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *)pDecomp; - - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - pDecomp->m_window_bits = window_bits; - - return MZ_OK; -} - -int mz_inflateInit(mz_streamp pStream) -{ - return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); -} - -int mz_inflate(mz_streamp pStream, int flush) -{ - inflate_state* pState; - mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; - size_t in_bytes, out_bytes, orig_avail_in; - tinfl_status status; - - if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - - pState = (inflate_state*)pStream->state; - if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; - orig_avail_in = pStream->avail_in; - - first_call = pState->m_first_call; pState->m_first_call = 0; - if (pState->m_last_status < 0) return MZ_DATA_ERROR; - - if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - pState->m_has_flushed |= (flush == MZ_FINISH); - - if ((flush == MZ_FINISH) && (first_call)) - { - // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. - decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); - pState->m_last_status = status; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; - - if (status < 0) - return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) - { - pState->m_last_status = TINFL_STATUS_FAILED; - return MZ_BUF_ERROR; - } - return MZ_STREAM_END; - } - // flush != MZ_FINISH then we must assume there's more input. - if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - - if (pState->m_dict_avail) - { - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; - } - - for ( ; ; ) - { - in_bytes = pStream->avail_in; - out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; - - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); - pState->m_last_status = status; - - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); - - pState->m_dict_avail = (mz_uint)out_bytes; - - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - - if (status < 0) - return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) - return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. - else if (flush == MZ_FINISH) - { - // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. - if (status == TINFL_STATUS_DONE) - return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; - // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. - else if (!pStream->avail_out) - return MZ_BUF_ERROR; - } - else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) - break; - } - - return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; -} - -int mz_inflateEnd(mz_streamp pStream) -{ - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - mz_stream stream; - int status; - memset(&stream, 0, sizeof(stream)); - - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_inflateInit(&stream); - if (status != MZ_OK) - return status; - - status = mz_inflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_inflateEnd(&stream); - return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; - } - *pDest_len = stream.total_out; - - return mz_inflateEnd(&stream); -} - -const char *mz_error(int err) -{ - static struct { int m_err; const char *m_pDesc; } s_error_descs[] = - { - { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, - { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } - }; - mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; - return NULL; -} - -#endif //MINIZ_NO_ZLIB_APIS - -// ------------------- Low-level Decompression (completely independent from all compression API's) - -#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) -#define TINFL_MEMSET(p, c, l) memset(p, c, l) - -#define TINFL_CR_BEGIN switch(r->m_state) { case 0: -#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END -#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END -#define TINFL_CR_FINISH } - -// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never -// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. -#define TINFL_GET_BYTE(state_index, c) do { \ - if (pIn_buf_cur >= pIn_buf_end) { \ - for ( ; ; ) { \ - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ - TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ - if (pIn_buf_cur < pIn_buf_end) { \ - c = *pIn_buf_cur++; \ - break; \ - } \ - } else { \ - c = 0; \ - break; \ - } \ - } \ - } else c = *pIn_buf_cur++; } MZ_MACRO_END - -#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) -#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END -#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END - -// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. -// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a -// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the -// bit buffer contains >=15 bits (deflate's max. Huffman code size). -#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ - do { \ - temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) { \ - code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ - break; \ - } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ - } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ - } while (num_bits < 15); - -// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read -// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully -// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. -// The slow path is only executed at the very end of the input buffer. -#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ - int temp; mz_uint code_len, c; \ - if (num_bits < 15) { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) { \ - TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ - } else { \ - bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ - } \ - } \ - if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ - code_len = temp >> 9, temp &= 511; \ - else { \ - code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ - } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END - -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) -{ - static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; - static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - static const int s_min_table_sizes[3] = { 257, 1, 4 }; - - tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; - size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; - - // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } - - num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN - - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - } - - do - { - TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) - { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) - { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)dist; - counter--; - } - while (counter) - { - size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) - { - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - { - TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); - } - else - { - TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); - } - } - n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; - } - } - else if (r->m_type == 3) - { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } - else - { - if (r->m_type == 1) - { - mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; - r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; - } - else - { - for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } - MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } - r->m_table_sizes[2] = 19; - } - for ( ; (int)r->m_type >= 0; r->m_type--) - { - int tree_next, tree_cur; tinfl_huff_table *pTable; - mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; - used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) - { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) - { - mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; - cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) - { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; - } - if (r->m_type == 2) - { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) - { - mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) - { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); - } - num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; - TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) - { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); - } - } - for ( ; ; ) - { - mz_uint8 *pSrc; - for ( ; ; ) - { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) - { - TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)counter; - } - else - { - int sym2; mz_uint code_len; -#if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } -#else - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) - break; - -#if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - bit_buf >>= code_len; num_bits -= code_len; - - pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) - { - pOut_buf_cur++; - counter = sym2; - break; - } - pOut_buf_cur[1] = (mz_uint8)sym2; - pOut_buf_cur += 2; - } - } - if ((counter &= 511) == 256) break; - - num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } - - TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); - num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } - - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } - - pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) - { - while (counter--) - { - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; - } - continue; - } -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) - { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do - { - ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; - ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) - { - if (counter) - { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - continue; - } - } -#endif - do - { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) - { - pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - } - } - } while (!(r->m_final & 1)); - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - TINFL_CR_FINISH - -common_exit: - r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) - { - const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) - { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) - { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; -} - -// Higher level helper functions. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) break; - new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; - } - return pBuf; -} - -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); - status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; -} - -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) - { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; -} - -#ifndef MINIZ_NO_COMPRESSION -// ------------------- Low-level Compression (independent from all decompression API's) - -// Purposely making these tables static for faster init and thread safety. -static const mz_uint16 s_tdefl_len_sym[256] = { - 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, - 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, - 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, - 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; - -static const mz_uint8 s_tdefl_len_extra[256] = { - 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; - -static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; - -static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7 }; - -static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, - 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; - -static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; - -// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; -static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) -{ - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) - { - const mz_uint32* pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; - { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } - } - return pCur_syms; -} - -// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) -{ - int root, leaf, next, avbl, used, dpth; - if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } - A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next=1; next < n-1; next++) - { - if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; - avbl = 1; used = dpth = 0; root = n-2; next = n-1; - while (avbl>0) - { - while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } - while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } - avbl = 2*used; dpth++; used = 0; - } -} - -// Limits canonical Huffman code table's max code size. -enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) -{ - int i; mz_uint32 total = 0; if (code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) - { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } - total--; - } -} - -static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) -{ - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) - { - for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; - } - else - { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } - - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); - - MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); - } - - next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - - for (i = 0; i < table_len; i++) - { - mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; - code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; - } -} - -#define TDEFL_PUT_BITS(b, l) do { \ - mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ - d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ - while (d->m_bits_in >= 8) { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ - *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ - d->m_bit_buffer >>= 8; \ - d->m_bits_in -= 8; \ - } \ -} MZ_MACRO_END - -#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ - if (rle_repeat_count < 3) { \ - d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ - while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ - } else { \ - d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ -} rle_repeat_count = 0; } } - -#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ - if (rle_z_count < 3) { \ - d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ - } else if (rle_z_count <= 10) { \ - d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ - } else { \ - d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ -} rle_z_count = 0; } } - -static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -static void tdefl_start_dynamic_block(tdefl_compressor *d) -{ - int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; - - d->m_huff_count[0][256] = 1; - - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; - - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; - - memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) - { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } - } - else - { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; - } - else if (++rle_repeat_count == 6) - { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } - - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); - - TDEFL_PUT_BITS(2, 2); - - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); - - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) - { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); - } -} - -static void tdefl_start_static_block(tdefl_compressor *d) -{ - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - - for (i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - - memset(d->m_huff_code_sizes[1], 5, 32); - - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - - TDEFL_PUT_BITS(1, 2); -} - -static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; - -#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - - if (flags & 1) - { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - // This sequence coaxes MSVC into using cmov's vs. jmp's. - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; - - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - } - - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; - - *(mz_uint64*)pOutput_buf = bit_buffer; - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } - -#undef TDEFL_PUT_BITS_FAST - - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; - - while (bits_in) - { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#else -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - if (flags & 1) - { - mz_uint sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - if (match_dist < 512) - { - sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; - } - else - { - sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; - } - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS - -static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) -{ - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); -} - -static int tdefl_flush_block(tdefl_compressor *d, int flush) -{ - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; - - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; - - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) - { - TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); - } - - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - - pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; - - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - - // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. - if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) - { - mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) - { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) - { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); - } - } - // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. - else if (!comp_block_succeeded) - { - d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } - - if (flush) - { - if (flush == TDEFL_FINISH) - { - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } - } - else - { - mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } - } - } - - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; - - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) - { - if (d->m_pPut_buf_func) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) - return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } - else if (pOutput_buf_start == d->m_output_buf) - { - int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) - { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } - else - { - d->m_out_buf_ofs += n; - } - } - - return d->m_output_flush_remaining; -} - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES -#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - if (!probe_len) - { - *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; - } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; - c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); - } - } -} -#else -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint8 *s = d->m_dict + pos, *p, *q; - mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; - if (probe_len > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; - c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; - } - } -} -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static mz_bool tdefl_compress_fast(tdefl_compressor *d) -{ - // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. - mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) - { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; - - while (num_bytes_to_process) - { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } - - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - - while (lookahead_size >= 4) - { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; - mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16)lookahead_pos; - - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) - { - const mz_uint16 *p = (const mz_uint16 *)pCur_dict; - const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); - mz_uint32 probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) - { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - else - { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); - - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); - - cur_match_dist--; - - pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); - *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); - - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; - - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; - } - } - else - { - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - - while (lookahead_size) - { - mz_uint8 lit = d->m_dict[cur_pos]; - - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - d->m_huff_count[0][lit]++; - - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - } - - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - return MZ_TRUE; -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) -{ - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - d->m_huff_count[0][lit]++; -} - -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) -{ - mz_uint32 s0, s1; - - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); - - d->m_total_lz_bytes += match_len; - - d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); - - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; - - *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - - s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - - if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; -} - -static mz_bool tdefl_compress_normal(tdefl_compressor *d) -{ - const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; - - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) - { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) - { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) - { - mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; - } - } - else - { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) - { - mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; - mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; - - // Simple lazy/greedy parsing state machine. - len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) - { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) - { - mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; - } - } - else - { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) - { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) - { - if (cur_match_len > d->m_saved_match_len) - { - tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - } - else - { - tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; - } - } - else if (!cur_match_dist) - tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - // Move the lookahead forward by len_to_move bytes. - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); - // Check if it's time to flush the current LZ codes to the internal output buffer. - if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) - { - int n; - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } - - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - return MZ_TRUE; -} - -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) -{ - if (d->m_pIn_buf_size) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - } - - if (d->m_pOut_buf_size) - { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint)n; - d->m_output_flush_remaining -= (mz_uint)n; - d->m_out_buf_ofs += n; - - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } - - return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) -{ - if (!d) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } - - d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; - - if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); - - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) - { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } - else -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } - - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) - d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); - - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) - { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } - } - - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); -} - -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) -{ - MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); -} - -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; - d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) -{ - return d->m_prev_return_status; -} - -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) -{ - return d->m_adler32; -} - -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; - pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); - MZ_FREE(pComp); return succeeded; -} - -typedef struct -{ - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; -} tdefl_output_buffer; - -static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) -{ - tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) - { - size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; - do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); - pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; - p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; - } - memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; - return MZ_TRUE; -} - -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; - *pOut_len = out_buf.m_size; return out_buf.m_pBuf; -} - -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) return 0; - out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; - return out_buf.m_size; -} - -#ifndef MINIZ_NO_ZLIB_APIS -static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - -// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) -{ - mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - - if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; - - return comp_flags; -} -#endif //MINIZ_NO_ZLIB_APIS - -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) -#endif - -// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at -// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. -// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) -{ - // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. - static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; - if (!pComp) return NULL; - MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } - // write dummy header - for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); - // compress image data - tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - // write real header - *pLen_out = out_buf.m_size-41; - { - static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; - mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, - 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0, - (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; - c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); - memcpy(out_buf.m_pBuf, pnghdr, 41); - } - // write footer (IDAT CRC-32, followed by IEND chunk) - if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); - // compute final size of file, grab compressed data buffer and return - *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; -} -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) -{ - // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) - return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); -} - -#endif // MINIZ_NO_COMPRESSION - -#ifdef _MSC_VER -#pragma warning (pop) -#endif - -// ------------------- .ZIP archive reading - -#ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef MINIZ_NO_STDIO - #define MZ_FILE void * -#else - #include - #include - - #if defined(_MSC_VER) || defined(__MINGW64__) - static FILE *mz_fopen(const char *pFilename, const char *pMode) - { - FILE* pFile = NULL; - fopen_s(&pFile, pFilename, pMode); - return pFile; - } - static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) - { - FILE* pFile = NULL; - if (freopen_s(&pFile, pPath, pMode, pStream)) - return NULL; - return pFile; - } - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 _ftelli64 - #define MZ_FSEEK64 _fseeki64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #elif defined(__MINGW32__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello64 - #define MZ_FSEEK64 fseeko64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #elif defined(__TINYC__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftell - #define MZ_FSEEK64 fseek - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #elif defined(__GNUC__) && _LARGEFILE64_SOURCE - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen64(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello64 - #define MZ_FSEEK64 fseeko64 - #define MZ_FILE_STAT_STRUCT stat64 - #define MZ_FILE_STAT stat64 - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(p, m, s) freopen64(p, m, s) - #define MZ_DELETE_FILE remove - #else - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello - #define MZ_FSEEK64 fseeko - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #endif // #ifdef _MSC_VER -#endif // #ifdef MINIZ_NO_STDIO - -#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) - -// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. -enum -{ - // ZIP archive identifiers and record sizes - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, - // Central directory header record offsets - MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, - MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, - MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, - // Local directory header offsets - MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, - MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, - MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, - // End of central directory offsets - MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, - MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, -}; - -typedef struct -{ - void *m_p; - size_t m_size, m_capacity; - mz_uint m_element_size; -} mz_zip_array; - -struct mz_zip_internal_state_tag -{ - mz_zip_array m_central_dir; - mz_zip_array m_central_dir_offsets; - mz_zip_array m_sorted_central_dir_offsets; - MZ_FILE *m_pFile; - void *m_pMem; - size_t m_mem_size; - size_t m_mem_capacity; -}; - -#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size -#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] - -static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) -{ - pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); - memset(pArray, 0, sizeof(mz_zip_array)); -} - -static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) -{ - void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; - if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } - if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; - pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) -{ - if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) -{ - if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } - pArray->m_size = new_size; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) -{ - return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) -{ - size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; - memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); - return MZ_TRUE; -} - -#ifndef MINIZ_NO_TIME -static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) -{ - struct tm tm; - memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; - tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; - tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; - return mktime(&tm); -} - -static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef _MSC_VER - struct tm tm_struct; - struct tm *tm = &tm_struct; - errno_t err = localtime_s(tm, &time); - if (err) - { - *pDOS_date = 0; *pDOS_time = 0; - return; - } -#else - struct tm *tm = localtime(&time); -#endif - *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); - *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); -} -#endif - -#ifndef MINIZ_NO_STDIO -static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef MINIZ_NO_TIME - (void)pFilename; *pDOS_date = *pDOS_time = 0; -#else - struct MZ_FILE_STAT_STRUCT file_stat; - // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. - if (MZ_FILE_STAT(pFilename, &file_stat) != 0) - return MZ_FALSE; - mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); -#endif // #ifdef MINIZ_NO_TIME - return MZ_TRUE; -} - -#ifndef MINIZ_NO_TIME -static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) -{ - struct utimbuf t; t.actime = access_time; t.modtime = modified_time; - return !utime(pFilename, &t); -} -#endif // #ifndef MINIZ_NO_TIME -#endif // #ifndef MINIZ_NO_STDIO - -static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) -{ - (void)flags; - if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_READING; - pZip->m_archive_size = 0; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (l_len < r_len) : (l < r); -} - -#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END - -// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) -static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - int start = (size - 2) >> 1, end; - while (start >= 0) - { - int child, root = start; - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= size) - break; - child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - start--; - } - - end = size - 1; - while (end > 0) - { - int child, root = 0; - MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= end) - break; - child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - end--; - } -} - -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) -{ - mz_uint cdir_size, num_this_disk, cdir_disk_index; - mz_uint64 cdir_ofs; - mz_int64 cur_file_ofs; - const mz_uint8 *p; - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; - mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); - // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - // Find the end of central directory record by scanning the file from the end towards the beginning. - cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); - for ( ; ; ) - { - int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) - return MZ_FALSE; - for (i = n - 4; i >= 0; --i) - if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - break; - if (i >= 0) - { - cur_file_ofs += i; - break; - } - if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) - return MZ_FALSE; - cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); - } - // Read and verify the end of central directory record. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || - ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) - return MZ_FALSE; - - num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); - cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); - if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) - return MZ_FALSE; - - if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) - return MZ_FALSE; - - pZip->m_central_directory_file_ofs = cdir_ofs; - - if (pZip->m_total_files) - { - mz_uint i, n; - - // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) - return MZ_FALSE; - - if (sort_central_dir) - { - if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) - return MZ_FALSE; - } - - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) - return MZ_FALSE; - - // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). - p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) - { - mz_uint total_header_size, comp_size, decomp_size, disk_index; - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return MZ_FALSE; - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); - if (sort_central_dir) - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) - return MZ_FALSE; - disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index != num_this_disk) && (disk_index != 1)) - return MZ_FALSE; - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) - return MZ_FALSE; - if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return MZ_FALSE; - n -= total_header_size; p += total_header_size; - } - } - - if (sort_central_dir) - mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - - return MZ_TRUE; -} - -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) -{ - if ((!pZip) || (!pZip->m_pRead)) - return MZ_FALSE; - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); - memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); - return s; -} - -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) -{ - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - pZip->m_pRead = mz_zip_mem_read_func; - pZip->m_pIO_opaque = pZip; -#ifdef __cplusplus - pZip->m_pState->m_pMem = const_cast(pMem); -#else - pZip->m_pState->m_pMem = (void *)pMem; -#endif - pZip->m_pState->m_mem_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) -{ - mz_uint64 file_size; - MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) - return MZ_FALSE; - if (MZ_FSEEK64(pFile, 0, SEEK_END)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - file_size = MZ_FTELL64(pFile); - if (!mz_zip_reader_init_internal(pZip, flags)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - pZip->m_pRead = mz_zip_file_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = file_size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) -{ - return pZip ? pZip->m_total_files : 0; -} - -static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) -{ - if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return NULL; - return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); -} - -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint m_bit_flag; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - return (m_bit_flag & 1); -} - -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint filename_len, external_attr; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - - // First see if the filename ends with a '/' character. - filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) - { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') - return MZ_TRUE; - } - - // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. - // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. - // FIXME: Remove this check? Is it necessary - we already check the filename. - external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((external_attr & 0x10) != 0) - return MZ_TRUE; - - return MZ_FALSE; -} - -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if ((!p) || (!pStat)) - return MZ_FALSE; - - // Unpack the central directory record. - pStat->m_file_index = file_index; - pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); - pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); - pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); - pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); -#ifndef MINIZ_NO_TIME - pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); -#endif - pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); - pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - - // Copy as much of the filename and comment as possible. - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); - memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; - - n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); - pStat->m_comment_size = n; - memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; - - return MZ_TRUE; -} - -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) - { - n = MZ_MIN(n, filename_buf_size - 1); - memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pFilename[n] = '\0'; - } - return n + 1; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) -{ - mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) - return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) - return MZ_FALSE; - return MZ_TRUE; -} - -static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (int)(l_len - r_len) : (l - r); -} - -static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - const mz_uint filename_len = (mz_uint)strlen(pFilename); - int l = 0, h = size - 1; - while (l <= h) - { - int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); - if (!comp) - return file_index; - else if (comp < 0) - l = m + 1; - else - h = m - 1; - } - return -1; -} - -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) -{ - mz_uint file_index; size_t name_len, comment_len; - if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return -1; - if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) - return mz_zip_reader_locate_file_binary_search(pZip, pName); - name_len = strlen(pName); if (name_len > 0xFFFF) return -1; - comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; - for (file_index = 0; file_index < pZip->m_total_files; file_index++) - { - const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); - mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); - const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) - continue; - if (comment_len) - { - mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); - const char *pFile_comment = pFilename + filename_len + file_extra_len; - if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) - continue; - } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) - { - int ofs = filename_len - 1; - do - { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) - break; - } while (--ofs >= 0); - ofs++; - pFilename += ofs; filename_len -= ofs; - } - if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) - return file_index; - } - return -1; -} - -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int status = TINFL_STATUS_DONE; - mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - tinfl_decompressor inflator; - - if ((buf_size) && (!pBuf)) - return MZ_FALSE; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Ensure supplied output buffer is large enough. - needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; - if (buf_size < needed_size) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) - return MZ_FALSE; - return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); - } - - // Decompress the file either directly from memory or from a file input buffer. - tinfl_init(&inflator); - - if (pZip->m_pState->m_pMem) - { - // Read directly from the archive in memory. - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else if (pUser_read_buf) - { - // Use a user provided read buffer. - if (!user_read_buf_size) - return MZ_FALSE; - pRead_buf = (mz_uint8 *)pUser_read_buf; - read_buf_size = user_read_buf_size; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - else - { - // Temporarily allocate a read buffer. - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#endif - return MZ_FALSE; - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - do - { - size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); - - if (status == TINFL_STATUS_DONE) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); -} - -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); -} - -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); -} - -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) -{ - mz_uint64 comp_size, uncomp_size, alloc_size; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - void *pBuf; - - if (pSize) - *pSize = 0; - if (!p) - return NULL; - - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - - alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#endif - return NULL; - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) - return NULL; - - if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return NULL; - } - - if (pSize) *pSize = (size_t)alloc_size; - return pBuf; -} - -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - { - if (pSize) *pSize = 0; - return MZ_FALSE; - } - return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); -} - -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; - mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf = NULL; void *pWrite_buf = NULL; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - // Decompress the file either directly from memory or from a file input buffer. - if (pZip->m_pState->m_pMem) - { - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pState->m_pMem) - { -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#endif - return MZ_FALSE; - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) - status = TINFL_STATUS_FAILED; - else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); - cur_file_ofs += file_stat.m_comp_size; - out_buf_ofs += file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - while (comp_remaining) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); - - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - out_buf_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - } - } - } - else - { - tinfl_decompressor inflator; - tinfl_init(&inflator); - - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) - status = TINFL_STATUS_FAILED; - else - { - do - { - mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - - if (out_buf_size) - { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) - { - status = TINFL_STATUS_FAILED; - break; - } - file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); - if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) - { - status = TINFL_STATUS_FAILED; - break; - } - } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); - } - } - - if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if (!pZip->m_pState->m_pMem) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - if (pWrite_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) -{ - (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); -} - -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) -{ - mz_bool status; - mz_zip_archive_file_stat file_stat; - MZ_FILE *pFile; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) - return MZ_FALSE; - status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); - if (MZ_FCLOSE(pFile) == EOF) - return MZ_FALSE; -#ifndef MINIZ_NO_TIME - if (status) - mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); -#endif - return status; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_reader_end(mz_zip_archive *pZip) -{ - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - - if (pZip->m_pState) - { - mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } -#endif // #ifndef MINIZ_NO_STDIO - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - } - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); -} -#endif - -// ------------------- .ZIP archive writing - -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } -static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } -#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) -#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) - -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) -{ - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (pZip->m_file_offset_alignment) - { - // Ensure user specified file offset alignment is a power of 2. - if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) - return MZ_FALSE; - } - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_archive_size = existing_size; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); -#ifdef _MSC_VER - if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#else - if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#endif - return 0; - if (new_size > pState->m_mem_capacity) - { - void *pNew_block; - size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) - return 0; - pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; - } - memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); - pState->m_mem_size = (size_t)new_size; - return n; -} - -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) -{ - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) - { - if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_mem_capacity = initial_allocation_size; - } - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) -{ - MZ_FILE *pFile; - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_pFile = pFile; - if (size_to_reserve_at_beginning) - { - mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); - do - { - size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - cur_ofs += n; size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - // No sense in trying to write to an archive that's already at the support max size - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if (pState->m_pFile) - { -#ifdef MINIZ_NO_STDIO - pFilename; return MZ_FALSE; -#else - // Archive is being read from stdio - try to reopen as writable. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - if (!pFilename) - return MZ_FALSE; - pZip->m_pWrite = mz_zip_file_write_func; - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) - { - // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. - mz_zip_reader_end(pZip); - return MZ_FALSE; - } -#endif // #ifdef MINIZ_NO_STDIO - } - else if (pState->m_pMem) - { - // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - pState->m_mem_capacity = pState->m_mem_size; - pZip->m_pWrite = mz_zip_heap_write_func; - } - // Archive is being read via a user provided read function - make sure the user has specified a write function too. - else if (!pZip->m_pWrite) - return MZ_FALSE; - - // Start writing new files at the archive's current central directory location. - pZip->m_archive_size = pZip->m_central_directory_file_ofs; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_central_directory_file_ofs = 0; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) -{ - return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); -} - -typedef struct -{ - mz_zip_archive *m_pZip; - mz_uint64 m_cur_archive_file_ofs; - mz_uint64 m_comp_size; -} mz_zip_writer_add_state; - -static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) -{ - mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; - if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) - return MZ_FALSE; - pState->m_cur_archive_file_ofs += len; - pState->m_comp_size += len; - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; - size_t orig_central_dir_size = pState->m_central_dir.m_size; - mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - - // No zip64 support yet - if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) - return MZ_FALSE; - - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) - { - // Try to push the central directory array back into its original state. - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) -{ - // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. - if (*pArchive_name == '/') - return MZ_FALSE; - while (*pArchive_name) - { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) - return MZ_FALSE; - pArchive_name++; - } - return MZ_TRUE; -} - -static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) -{ - mz_uint32 n; - if (!pZip->m_file_offset_alignment) - return 0; - n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); -} - -static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) -{ - char buf[4096]; - memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) - { - mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) - return MZ_FALSE; - cur_file_ofs += s; n -= s; - } - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) -{ - mz_uint16 method = 0, dos_time = 0, dos_date = 0; - mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - tdefl_compressor *pComp = NULL; - mz_bool store_data_uncompressed; - mz_zip_internal_state *pState; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) - return MZ_FALSE; - // No zip64 support yet - if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - -#ifndef MINIZ_NO_TIME - { - time_t cur_time; time(&cur_time); - mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); - } -#endif // #ifndef MINIZ_NO_TIME - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) - { - // Set DOS Subdirectory attribute bit. - ext_attributes |= 0x10; - // Subdirectories cannot contain data. - if ((buf_size) || (uncomp_size)) - return MZ_FALSE; - } - - // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) - if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) - return MZ_FALSE; - - if ((!store_data_uncompressed) && (buf_size)) - { - if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) - return MZ_FALSE; - } - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - { - uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) - { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } - - if (store_data_uncompressed) - { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - - cur_archive_file_ofs += buf_size; - comp_size = buf_size; - - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - method = MZ_DEFLATED; - } - else if (buf_size) - { - mz_zip_writer_add_state state; - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || - (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - - method = MZ_DEFLATED; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pComp = NULL; - - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; - - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; - mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - MZ_FILE *pSrc_file = NULL; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) - return MZ_FALSE; - - pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) - return MZ_FALSE; - MZ_FSEEK64(pSrc_file, 0, SEEK_END); - uncomp_size = MZ_FTELL64(pSrc_file); - MZ_FSEEK64(pSrc_file, 0, SEEK_SET); - - if (uncomp_size > 0xFFFFFFFF) - { - // No zip64 support yet - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - if (uncomp_size <= 3) - level = 0; - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (uncomp_size) - { - mz_uint64 uncomp_remaining = uncomp_size; - void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - if (!level) - { - while (uncomp_remaining) - { - mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); - uncomp_remaining -= n; - cur_archive_file_ofs += n; - } - comp_size = uncomp_size; - } - else - { - mz_bool result = MZ_FALSE; - mz_zip_writer_add_state state; - tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - for ( ; ; ) - { - size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); - tdefl_status status; - - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) - break; - - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); - uncomp_remaining -= in_buf_size; - - status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); - if (status == TDEFL_STATUS_DONE) - { - result = MZ_TRUE; - break; - } - else if (status != TDEFL_STATUS_OKAY) - break; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - - if (!result) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - - method = MZ_DEFLATED; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - } - - MZ_FCLOSE(pSrc_file); pSrc_file = NULL; - - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; - - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) -{ - mz_uint n, bit_flags, num_alignment_padding_bytes; - mz_uint64 comp_bytes_remaining, local_dir_header_ofs; - mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - size_t orig_central_dir_size; - mz_zip_internal_state *pState; - void *pBuf; const mz_uint8 *pSrc_central_header; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) - return MZ_FALSE; - pState = pZip->m_pState; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - cur_dst_file_ofs = pZip->m_archive_size; - - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) - return MZ_FALSE; - cur_dst_file_ofs += num_alignment_padding_bytes; - local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) - return MZ_FALSE; - - while (comp_bytes_remaining) - { - n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_src_file_ofs += n; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_dst_file_ofs += n; - - comp_bytes_remaining -= n; - } - - bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) - { - // Copy data descriptor - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - - n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - - cur_src_file_ofs += n; - cur_dst_file_ofs += n; - } - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - - // no zip64 support yet - if (cur_dst_file_ofs > 0xFFFFFFFF) - return MZ_FALSE; - - orig_central_dir_size = pState->m_central_dir.m_size; - - memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) - return MZ_FALSE; - - n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - if (pState->m_central_dir.m_size > 0xFFFFFFFF) - return MZ_FALSE; - n = (mz_uint32)orig_central_dir_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - pZip->m_total_files++; - pZip->m_archive_size = cur_dst_file_ofs; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_uint64 central_dir_ofs, central_dir_size; - mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - - pState = pZip->m_pState; - - // no zip64 support yet - if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - central_dir_ofs = 0; - central_dir_size = 0; - if (pZip->m_total_files) - { - // Write central directory - central_dir_ofs = pZip->m_archive_size; - central_dir_size = pState->m_central_dir.m_size; - pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) - return MZ_FALSE; - pZip->m_archive_size += central_dir_size; - } - - // Write end of central directory record - MZ_CLEAR_OBJ(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) - return MZ_FALSE; -#ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) - return MZ_FALSE; -#endif // #ifndef MINIZ_NO_STDIO - - pZip->m_archive_size += sizeof(hdr); - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) -{ - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) - return MZ_FALSE; - if (pZip->m_pWrite != mz_zip_heap_write_func) - return MZ_FALSE; - if (!mz_zip_writer_finalize_archive(pZip)) - return MZ_FALSE; - - *pBuf = pZip->m_pState->m_pMem; - *pSize = pZip->m_pState->m_mem_size; - pZip->m_pState->m_pMem = NULL; - pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_end(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_bool status = MZ_TRUE; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) - return MZ_FALSE; - - pState = pZip->m_pState; - pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } -#endif // #ifndef MINIZ_NO_STDIO - - if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); - pState->m_pMem = NULL; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return status; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_bool status, created_new_archive = MZ_FALSE; - mz_zip_archive zip_archive; - struct MZ_FILE_STAT_STRUCT file_stat; - MZ_CLEAR_OBJ(zip_archive); - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) - { - // Create a new archive. - if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) - return MZ_FALSE; - created_new_archive = MZ_TRUE; - } - else - { - // Append to an existing archive. - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return MZ_FALSE; - if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) - { - mz_zip_reader_end(&zip_archive); - return MZ_FALSE; - } - } - status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); - // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) - if (!mz_zip_writer_finalize_archive(&zip_archive)) - status = MZ_FALSE; - if (!mz_zip_writer_end(&zip_archive)) - status = MZ_FALSE; - if ((!status) && (created_new_archive)) - { - // It's a new archive and something went wrong, so just delete it. - int ignoredStatus = MZ_DELETE_FILE(pZip_filename); - (void)ignoredStatus; - } - return status; -} - -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) -{ - int file_index; - mz_zip_archive zip_archive; - void *p = NULL; - - if (pSize) - *pSize = 0; - - if ((!pZip_filename) || (!pArchive_name)) - return NULL; - - MZ_CLEAR_OBJ(zip_archive); - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return NULL; - - if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) - p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); - - mz_zip_reader_end(&zip_archive); - return p; -} - -#endif // #ifndef MINIZ_NO_STDIO - -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_FILE_ONLY - -/* - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -*/ diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.h b/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.h deleted file mode 100644 index 971d34e8..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/miniz.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MINIZ_HEADER_FILE_ONLY -#include "miniz.c" diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.c b/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.c deleted file mode 100644 index 0b475494..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.c +++ /dev/null @@ -1,821 +0,0 @@ -/*- - * MIT License - * - * Copyright (c) 2019 kikuchan - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "miniz.h" -#include "pngle.h" - -#define PNGLE_ERROR(s) (pngle->error = (s), pngle->state = PNGLE_STATE_ERROR, -1) -#define PNGLE_CALLOC(a, b, name) static_cast(debug_printf("[pngle] Allocating %zu bytes for %s\n", (size_t)(a) * (size_t)(b), (name)), calloc((size_t)(a), (size_t)(b))) - -#define PNGLE_UNUSED(x) (void)(x) - -// magic -static const uint8_t png_sig[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; -static uint32_t interlace_off_x[8] = { 0, 0, 4, 0, 2, 0, 1, 0 }; -static uint32_t interlace_off_y[8] = { 0, 0, 0, 4, 0, 2, 0, 1 }; -static uint32_t interlace_div_x[8] = { 1, 8, 8, 4, 4, 2, 2, 1 }; -static uint32_t interlace_div_y[8] = { 1, 8, 8, 8, 4, 4, 2, 2 }; - -static inline uint8_t read_uint8(const uint8_t *p) -{ - return *p; -} - -static inline uint32_t read_uint32(const uint8_t *p) -{ - return (p[0] << 24) - | (p[1] << 16) - | (p[2] << 8) - | (p[3] << 0) - ; -} - -static inline uint32_t U32_CLAMP_ADD(uint32_t a, uint32_t b, uint32_t top) -{ - uint32_t v = a + b; - if (v < a) return top; // uint32 overflow - if (v > top) return top; // clamp - return v; -} - - -void pngle_reset(pngle_t *pngle) -{ - if (!pngle) return ; - - pngle->state = PNGLE_STATE_INITIAL; - pngle->error = "No error"; - - if (pngle->scanline_ringbuf) free(pngle->scanline_ringbuf); - if (pngle->palette) free(pngle->palette); - if (pngle->trans_palette) free(pngle->trans_palette); -#ifndef PNGLE_NO_GAMMA_CORRECTION - if (pngle->gamma_table) free(pngle->gamma_table); -#endif - - pngle->scanline_ringbuf = NULL; - pngle->palette = NULL; - pngle->trans_palette = NULL; -#ifndef PNGLE_NO_GAMMA_CORRECTION - pngle->gamma_table = NULL; -#endif - - pngle->channels = 0; // indicates IHDR hasn't been processed yet - pngle->next_out = NULL; // indicates IDAT hasn't been processed yet - - // clear them just in case... - memset(&pngle->hdr, 0, sizeof(pngle->hdr)); - pngle->n_palettes = 0; - pngle->n_trans_palettes = 0; - - tinfl_init(&pngle->inflator); -} - -pngle_t *pngle_new(uint16_t width, uint16_t height) -{ - pngle_t *pngle = (pngle_t *)PNGLE_CALLOC(1, sizeof(pngle_t), "pngle_t"); - if (!pngle) return NULL; - - pngle_reset(pngle); - - pngle->pixels = NULL; - - //Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. - pngle->pixels = static_cast(calloc(height, sizeof(pixel_png *))); - if (pngle->pixels == NULL) { - printf("%s:Error allocating memory for lines\n", __func__); - //ret = ESP_ERR_NO_MEM; - goto err; - } - for (int i = 0; i < height; i++) { - (pngle->pixels)[i] = static_cast(malloc(width * sizeof(pixel_png))); - if ((pngle->pixels)[i] == NULL) { - printf("%s:Error allocating memory for line %d\n", __func__, i); - //ret = ESP_ERR_NO_MEM; - goto err; - } - } - - pngle->screenWidth = width; - pngle->screenHeight = height; - return pngle; - - err: - //Something went wrong! Exit cleanly, de-allocating everything we allocated. - if (pngle->pixels != NULL) { - for (int i = 0; i < height; i++) { - free((pngle->pixels)[i]); - } - free(pngle->pixels); - } - return NULL; -} - -void pngle_destroy(pngle_t *pngle, uint16_t width, uint16_t height) -{ - if (pngle) { - if (pngle->pixels != NULL) { - for (int i = 0; i < height; i++) { - free((pngle->pixels)[i]); - } - free(pngle->pixels); - } - pngle_reset(pngle); - free(pngle); - } -} - -const char *pngle_error(pngle_t *pngle) -{ - if (!pngle) return "Uninitialized"; - return pngle->error; -} - -uint32_t pngle_get_width(pngle_t *pngle) -{ - if (!pngle) return 0; - return pngle->hdr.width; -} - -uint32_t pngle_get_height(pngle_t *pngle) -{ - if (!pngle) return 0; - return pngle->hdr.height; -} - -pngle_ihdr_t *pngle_get_ihdr(pngle_t *pngle) -{ - if (!pngle) return NULL; - if (pngle->channels == 0) return NULL; - return &pngle->hdr; -} - - -static int is_trans_color(pngle_t *pngle, uint16_t *value, size_t n) -{ - if (pngle->n_trans_palettes != 1) return 0; // false (none or indexed) - - for (size_t i = 0; i < n; i++) { - if (value[i] != (pngle->trans_palette[i * 2 + 0] * 0x100 + pngle->trans_palette[i * 2 + 1])) return 0; // false - } - return 1; // true -} - -static inline void scanline_ringbuf_push(pngle_t *pngle, uint8_t value) -{ - pngle->scanline_ringbuf[pngle->scanline_ringbuf_cidx] = value; - pngle->scanline_ringbuf_cidx = (pngle->scanline_ringbuf_cidx + 1) % pngle->scanline_ringbuf_size; -} - -static inline uint16_t get_value(pngle_t *pngle, size_t *ridx, int *bitcount, int depth) -{ - uint16_t v=0; - - switch (depth) { - case 4: - if (*bitcount >= 8) { - *bitcount = 0; - *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; - } - *bitcount += depth; - uint8_t mask = ((1UL << depth) - 1); - uint8_t shift = (8 - *bitcount); - v = (pngle->scanline_ringbuf[*ridx] >> shift) & mask; - break; - case 8: - v = pngle->scanline_ringbuf[*ridx]; - *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; - break; - case 16: - v = pngle->scanline_ringbuf[*ridx]; - *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; - - v = v * 0x100 + pngle->scanline_ringbuf[*ridx]; - *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; - break; - } - - return v; -} - -static int pngle_draw_pixels(pngle_t *pngle, size_t scanline_ringbuf_xidx) -{ - uint16_t v[4]; // MAX_CHANNELS - int bitcount = 0; - uint8_t pixel_depth = (pngle->hdr.color_type & 1) ? 8 : pngle->hdr.depth; - uint16_t maxval = (1UL << pixel_depth) - 1; - - int n_pixels = pngle->hdr.depth == 16 ? 1 : (8 / pngle->hdr.depth); - - for (; n_pixels-- > 0 && pngle->drawing_x < pngle->hdr.width; pngle->drawing_x = U32_CLAMP_ADD(pngle->drawing_x, interlace_div_x[pngle->interlace_pass], pngle->hdr.width)) { - for (uint_fast8_t c = 0; c < pngle->channels; c++) { - v[c] = get_value(pngle, &scanline_ringbuf_xidx, &bitcount, pngle->hdr.depth); - } - - // color type: 0000 0111 - // ^-- indexed color (palette) - // ^--- Color - // ^---- Alpha channel - - if (pngle->hdr.color_type & 2) { - // color - if (pngle->hdr.color_type & 1) { - // indexed color: type 3 - - // lookup palette info - uint16_t pidx = v[0]; - if (pidx >= pngle->n_palettes) return PNGLE_ERROR("Color index is out of range"); - - v[0] = pngle->palette[pidx * 3 + 0]; - v[1] = pngle->palette[pidx * 3 + 1]; - v[2] = pngle->palette[pidx * 3 + 2]; - - // tRNS as an indexed alpha value table (for color type 3) - v[3] = pidx < pngle->n_trans_palettes ? pngle->trans_palette[pidx] : maxval; - } else { - // true color: 2, and 6 - v[3] = (pngle->hdr.color_type & 4) ? v[3] : is_trans_color(pngle, v, 3) ? 0 : maxval; - } - } else { - // alpha, tRNS, or opaque - v[3] = (pngle->hdr.color_type & 4) ? v[1] : is_trans_color(pngle, v, 1) ? 0 : maxval; - - // monochrome - v[1] = v[2] = v[0]; - } - - if (pngle->draw_callback) { - uint8_t rgba[4] = { - (v[0] * 255 + maxval / 2) / maxval, - (v[1] * 255 + maxval / 2) / maxval, - (v[2] * 255 + maxval / 2) / maxval, - (v[3] * 255 + maxval / 2) / maxval - }; - -#ifndef PNGLE_NO_GAMMA_CORRECTION - if (pngle->gamma_table) { - for (int i = 0; i < 3; i++) { - rgba[i] = pngle->gamma_table[v[i]]; - } - } -#endif - - pngle->draw_callback(pngle, pngle->drawing_x, pngle->drawing_y - , MIN(interlace_div_x[pngle->interlace_pass] - interlace_off_x[pngle->interlace_pass], pngle->hdr.width - pngle->drawing_x) - , MIN(interlace_div_y[pngle->interlace_pass] - interlace_off_y[pngle->interlace_pass], pngle->hdr.height - pngle->drawing_y) - , rgba - ); - } - } - - return 0; -} - -static inline int paeth(int a, int b, int c) -{ - int p = a + b - c; - int pa = abs(p - a); - int pb = abs(p - b); - int pc = abs(p - c); - - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; -} - -static int set_interlace_pass(pngle_t *pngle, uint_fast8_t pass) -{ - pngle->interlace_pass = pass; - - uint_fast8_t bytes_per_pixel = (pngle->channels * pngle->hdr.depth + 7) / 8; // 1 if depth <= 8 - size_t scanline_pixels = (pngle->hdr.width - interlace_off_x[pngle->interlace_pass] + interlace_div_x[pngle->interlace_pass] - 1) / interlace_div_x[pngle->interlace_pass]; - size_t scanline_stride = (scanline_pixels * pngle->channels * pngle->hdr.depth + 7) / 8; - - pngle->scanline_ringbuf_size = scanline_stride + bytes_per_pixel * 2; // 2 rooms for c/x and a - - if (pngle->scanline_ringbuf) free(pngle->scanline_ringbuf); - if ((pngle->scanline_ringbuf = PNGLE_CALLOC(pngle->scanline_ringbuf_size, 1, "scanline ringbuf")) == NULL) return PNGLE_ERROR("Insufficient memory"); - - pngle->drawing_x = interlace_off_x[pngle->interlace_pass]; - pngle->drawing_y = interlace_off_y[pngle->interlace_pass]; - pngle->filter_type = -1; - - pngle->scanline_ringbuf_cidx = 0; - pngle->scanline_remain_bytes_to_render = -1; - - return 0; -} - -static int setup_gamma_table(pngle_t *pngle, uint32_t png_gamma) -{ -#ifndef PNGLE_NO_GAMMA_CORRECTION - if (pngle->gamma_table) free(pngle->gamma_table); - - if (pngle->display_gamma <= 0) return 0; // disable gamma correction - if (png_gamma == 0) return 0; - - uint8_t pixel_depth = (pngle->hdr.color_type & 1) ? 8 : pngle->hdr.depth; - uint16_t maxval = (1UL << pixel_depth) - 1; - - pngle->gamma_table = PNGLE_CALLOC(1, maxval + 1, "gamma table"); - if (!pngle->gamma_table) return PNGLE_ERROR("Insufficient memory"); - - for (int i = 0; i < maxval + 1; i++) { - pngle->gamma_table[i] = (uint8_t)floor(pow(i / (double)maxval, 100000.0 / png_gamma / pngle->display_gamma) * 255.0 + 0.5); - } - debug_printf("[pngle] gamma value = %d\n", png_gamma); -#else - PNGLE_UNUSED(pngle); - PNGLE_UNUSED(png_gamma); -#endif - return 0; -} - - -static int pngle_on_data(pngle_t *pngle, const uint8_t *p, int len) -{ - const uint8_t *ep = p + len; - - uint_fast8_t bytes_per_pixel = (pngle->channels * pngle->hdr.depth + 7) / 8; // 1 if depth <= 8 - - while (p < ep) { - if (pngle->drawing_x >= pngle->hdr.width) { - // New row - pngle->drawing_x = interlace_off_x[pngle->interlace_pass]; - pngle->drawing_y = U32_CLAMP_ADD(pngle->drawing_y, interlace_div_y[pngle->interlace_pass], pngle->hdr.height); - pngle->filter_type = -1; // Indicate new line - } - - if (pngle->drawing_x >= pngle->hdr.width || pngle->drawing_y >= pngle->hdr.height) { - if (pngle->interlace_pass == 0 || pngle->interlace_pass >= 7) return len; // Do nothing further - - // Interlace: Next pass - if (set_interlace_pass(pngle, pngle->interlace_pass + 1) < 0) return -1; - debug_printf("[pngle] interlace pass changed to: %d\n", pngle->interlace_pass); - - continue; // This is required because "No filter type bytes are present in an empty pass". - } - - if (pngle->filter_type < 0) { - if (*p > 4) { - debug_printf("[pngle] Invalid filter type is found; 0x%02x\n", *p); - return PNGLE_ERROR("Invalid filter type is found"); - } - - pngle->filter_type = (int_fast8_t)*p++; // 0 - 4 - - // push sentinel bytes for new line - for (uint_fast8_t i = 0; i < bytes_per_pixel; i++) { - scanline_ringbuf_push(pngle, 0); - } - - continue; - } - - size_t cidx = pngle->scanline_ringbuf_cidx; - size_t bidx = (pngle->scanline_ringbuf_cidx + bytes_per_pixel) % pngle->scanline_ringbuf_size; - size_t aidx = (pngle->scanline_ringbuf_cidx + pngle->scanline_ringbuf_size - bytes_per_pixel) % pngle->scanline_ringbuf_size; - // debug_printf("[pngle] cidx = %zd, bidx = %zd, aidx = %zd\n", cidx, bidx, aidx); - - uint8_t c = pngle->scanline_ringbuf[cidx]; // left-up - uint8_t b = pngle->scanline_ringbuf[bidx]; // up - uint8_t a = pngle->scanline_ringbuf[aidx]; // left - uint8_t x = *p++; // target - // debug_printf("[pngle] c = 0x%02x, b = 0x%02x, a = 0x%02x, x = 0x%02x\n", c, b, a, x); - - // Reverse the filter - switch (pngle->filter_type) { - case 0: break; // None - case 1: x += a; break; // Sub - case 2: x += b; break; // Up - case 3: x += (a + b) / 2; break; // Average - case 4: x += paeth(a, b, c); break; // Paeth - } - - scanline_ringbuf_push(pngle, x); // updates scanline_ringbuf_cidx - - if (pngle->scanline_remain_bytes_to_render < 0) pngle->scanline_remain_bytes_to_render = bytes_per_pixel; - if (--pngle->scanline_remain_bytes_to_render == 0) { - size_t xidx = (pngle->scanline_ringbuf_cidx + pngle->scanline_ringbuf_size - bytes_per_pixel) % pngle->scanline_ringbuf_size; - - if (pngle_draw_pixels(pngle, xidx) < 0) return -1; - - pngle->scanline_remain_bytes_to_render = -1; // reset - } - } - - return len; -} - - -static int pngle_handle_chunk(pngle_t *pngle, const uint8_t *buf, size_t len) -{ - size_t consume = 0; - - switch (pngle->chunk_type) { - case PNGLE_CHUNK_IHDR: - // parse IHDR - consume = 13; - if (len < consume) return 0; - - debug_printf("[pngle] Parse IHDR\n"); - - pngle->hdr.width = read_uint32(buf + 0); - pngle->hdr.height = read_uint32(buf + 4); - pngle->hdr.depth = read_uint8 (buf + 8); - pngle->hdr.color_type = read_uint8 (buf + 9); - pngle->hdr.compression = read_uint8 (buf + 10); - pngle->hdr.filter = read_uint8 (buf + 11); - pngle->hdr.interlace = read_uint8 (buf + 12); - - - debug_printf("[pngle] width : %d\n", pngle->hdr.width ); - debug_printf("[pngle] height : %d\n", pngle->hdr.height ); - debug_printf("[pngle] depth : %d\n", pngle->hdr.depth ); - debug_printf("[pngle] color_type : %d\n", pngle->hdr.color_type ); - debug_printf("[pngle] compression: %d\n", pngle->hdr.compression); - debug_printf("[pngle] filter : %d\n", pngle->hdr.filter ); - debug_printf("[pngle] interlace : %d\n", pngle->hdr.interlace ); - - /* - Color Allowed Interpretation channels - Type Bit Depths - - 0 1,2,4,8,16 Each pixel is a grayscale sample. 1 channels (Brightness) - - 2 8,16 Each pixel is an R,G,B triple. 3 channels (R, G, B) - - 3 1,2,4,8 Each pixel is a palette index; 1 channels (palette info) - a PLTE chunk must appear. - - 4 8,16 Each pixel is a grayscale sample, 2 channels (Brightness, Alpha) - followed by an alpha sample. - - 6 8,16 Each pixel is an R,G,B triple, 4 channels (R, G, B, Alpha) - followed by an alpha sample. - */ - // 111 - // ^-- indexed color (palette) - // ^--- Color - // ^---- Alpha channel - - switch (pngle->hdr.color_type) { - case 0: pngle->channels = 1; if (pngle->hdr.depth != 1 && pngle->hdr.depth != 2 && pngle->hdr.depth != 4 && pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // grayscale - case 2: pngle->channels = 3; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // truecolor - case 3: pngle->channels = 1; if (pngle->hdr.depth != 1 && pngle->hdr.depth != 2 && pngle->hdr.depth != 4 && pngle->hdr.depth != 8 ) return PNGLE_ERROR("Invalid bit depth"); break; // indexed color - case 4: pngle->channels = 2; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // grayscale + alpha - case 6: pngle->channels = 4; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // truecolor + alpha - default: - return PNGLE_ERROR("Incorrect IHDR info"); - } - - if (pngle->hdr.compression != 0) return PNGLE_ERROR("Unsupported compression type in IHDR"); - if (pngle->hdr.filter != 0) return PNGLE_ERROR("Unsupported filter type in IHDR"); - - // interlace - if (set_interlace_pass(pngle, pngle->hdr.interlace ? 1 : 0) < 0) return -1; - - // callback - if (pngle->init_callback) pngle->init_callback(pngle, pngle->hdr.width, pngle->hdr.height); - - break; - - case PNGLE_CHUNK_IDAT: - // parse & decode IDAT chunk - if (len < 1) return 0; - - debug_printf("[pngle] Reading IDAT (len %zd / chunk remain %u)\n", len, pngle->chunk_remain); - - size_t in_bytes = len; - size_t out_bytes = pngle->avail_out; - - //debug_printf("[pngle] in_bytes %zd, out_bytes %zd, next_out %p\n", in_bytes, out_bytes, pngle->next_out); - - // XXX: tinfl_decompress always requires (next_out - lz_buf + avail_out) == TINFL_LZ_DICT_SIZE - tinfl_status status = tinfl_decompress(&pngle->inflator, (const mz_uint8 *)buf, &in_bytes, pngle->lz_buf, (mz_uint8 *)pngle->next_out, &out_bytes, TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_PARSE_ZLIB_HEADER); - - //debug_printf("[pngle] tinfl_decompress\n"); - //debug_printf("[pngle] => in_bytes %zd, out_bytes %zd, next_out %p, status %d\n", in_bytes, out_bytes, pngle->next_out, status); - - if (status < TINFL_STATUS_DONE) { - // Decompression failed. - debug_printf("[pngle] tinfl_decompress() failed with status %d!\n", status); - return PNGLE_ERROR("Failed to decompress the IDAT stream"); - } - - pngle->next_out += out_bytes; - pngle->avail_out -= out_bytes; - - // debug_printf("[pngle] => avail_out %zd, next_out %p\n", pngle->avail_out, pngle->next_out); - - if (status == TINFL_STATUS_DONE || pngle->avail_out == 0) { - // Output buffer is full, or decompression is done, so write buffer to output file. - // XXX: This is the only chance to process the buffer. - uint8_t *read_ptr = pngle->lz_buf; - size_t n = TINFL_LZ_DICT_SIZE - (size_t)pngle->avail_out; - - // pngle_on_data() usually returns n, otherwise -1 on error - if (pngle_on_data(pngle, read_ptr, n) < 0) return -1; - - // XXX: tinfl_decompress always requires (next_out - lz_buf + avail_out) == TINFL_LZ_DICT_SIZE - pngle->next_out = pngle->lz_buf; - pngle->avail_out = TINFL_LZ_DICT_SIZE; - } - - consume = in_bytes; - break; - case PNGLE_CHUNK_PLTE: - consume = 3; - if (len < consume) return 0; - - memcpy(pngle->palette + pngle->n_palettes * 3, buf, 3); - - debug_printf("[pngle] PLTE[%zd]: (%d, %d, %d)\n" - , pngle->n_palettes - , pngle->palette[pngle->n_palettes * 3 + 0] - , pngle->palette[pngle->n_palettes * 3 + 1] - , pngle->palette[pngle->n_palettes * 3 + 2] - ); - - pngle->n_palettes++; - - break; - - case PNGLE_CHUNK_IEND: - consume = 0; - break; - - case PNGLE_CHUNK_tRNS: - switch (pngle->hdr.color_type) { - case 3: consume = 1; break; - case 0: consume = 2 * 1; break; - case 2: consume = 2 * 3; break; - default: - return PNGLE_ERROR("tRNS chunk is prohibited on the color type"); - } - if (len < consume) return 0; - - memcpy(pngle->trans_palette + pngle->n_trans_palettes, buf, consume); - - pngle->n_trans_palettes++; - - break; - - case PNGLE_CHUNK_gAMA: - consume = 4; - if (len < consume) return 0; - - if (setup_gamma_table(pngle, read_uint32(buf)) < 0) return -1; - - break; - - default: - // unknown chunk - consume = len; - - debug_printf("[pngle] Unknown chunk; %zd bytes discarded\n", consume); - break; - } - - return consume; -} - -static int pngle_feed_internal(pngle_t *pngle, const uint8_t *buf, size_t len) -{ - if (!pngle) return -1; - - switch (pngle->state) { - case PNGLE_STATE_ERROR: - return -1; - - case PNGLE_STATE_EOF: - return len; - - case PNGLE_STATE_INITIAL: - // find PNG header - if (len < sizeof(png_sig)) return 0; - - if (memcmp(png_sig, buf, sizeof(png_sig))) return PNGLE_ERROR("Incorrect PNG signature"); - - debug_printf("[pngle] PNG signature found\n"); - - pngle->state = PNGLE_STATE_FIND_CHUNK_HEADER; - return sizeof(png_sig); - - case PNGLE_STATE_FIND_CHUNK_HEADER: - if (len < 8) return 0; - - pngle->chunk_remain = read_uint32(buf); - pngle->chunk_type = read_uint32(buf + 4); - - pngle->crc32 = mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)(buf + 4), 4); - - debug_printf("[pngle] Chunk '%.4s' len %u\n", buf + 4, pngle->chunk_remain); - - pngle->state = PNGLE_STATE_HANDLE_CHUNK; - - // initialize & sanity check - switch (pngle->chunk_type) { - case PNGLE_CHUNK_IHDR: - if (pngle->chunk_remain != 13) return PNGLE_ERROR("Invalid IHDR chunk size"); - if (pngle->channels != 0) return PNGLE_ERROR("Multiple IHDR chunks are not allowed"); - break; - - case PNGLE_CHUNK_IDAT: - if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid IDAT chunk size"); - if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); - if (pngle->hdr.color_type == 3 && pngle->palette == NULL) return PNGLE_ERROR("No PLTE chunk is found"); - - if (pngle->next_out == NULL) { - // Very first IDAT - pngle->next_out = pngle->lz_buf; - pngle->avail_out = TINFL_LZ_DICT_SIZE; - } - break; - - case PNGLE_CHUNK_PLTE: - if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid PLTE chunk size"); - if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); - if (pngle->palette) return PNGLE_ERROR("Too many PLTE chunk"); - - switch (pngle->hdr.color_type) { - case 3: // indexed color - break; - case 2: // truecolor - case 6: // truecolor + alpha - // suggested palettes - break; - default: - return PNGLE_ERROR("PLTE chunk is prohibited on the color type"); - } - - if (pngle->chunk_remain % 3) return PNGLE_ERROR("Invalid PLTE chunk size"); - if (pngle->chunk_remain / 3 > MIN(256, (1UL << pngle->hdr.depth))) return PNGLE_ERROR("Too many palettes in PLTE"); - if ((pngle->palette = PNGLE_CALLOC(pngle->chunk_remain / 3, 3, "palette")) == NULL) return PNGLE_ERROR("Insufficient memory"); - pngle->n_palettes = 0; - break; - - case PNGLE_CHUNK_IEND: - if (pngle->next_out == NULL) return PNGLE_ERROR("No IDAT chunk is found"); - if (pngle->chunk_remain > 0) return PNGLE_ERROR("Invalid IEND chunk size"); - break; - - case PNGLE_CHUNK_tRNS: - if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid tRNS chunk size"); - if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); - if (pngle->trans_palette) return PNGLE_ERROR("Too many tRNS chunk"); - - switch (pngle->hdr.color_type) { - case 3: // indexed color - if (pngle->chunk_remain > (1UL << pngle->hdr.depth)) return PNGLE_ERROR("Too many palettes in tRNS"); - break; - case 0: // grayscale - if (pngle->chunk_remain != 2) return PNGLE_ERROR("Invalid tRNS chunk size"); - break; - case 2: // truecolor - if (pngle->chunk_remain != 6) return PNGLE_ERROR("Invalid tRNS chunk size"); - break; - - default: - return PNGLE_ERROR("tRNS chunk is prohibited on the color type"); - } - if ((pngle->trans_palette = PNGLE_CALLOC(pngle->chunk_remain, 1, "trans palette")) == NULL) return PNGLE_ERROR("Insufficient memory"); - pngle->n_trans_palettes = 0; - break; - - default: - break; - } - - return 8; - - case PNGLE_STATE_HANDLE_CHUNK: - len = MIN(len, pngle->chunk_remain); - - int consumed = pngle_handle_chunk(pngle, buf, len); - - if (consumed > 0) { - if (pngle->chunk_remain < (uint32_t)consumed) return PNGLE_ERROR("Chunk data has been consumed too much"); - - pngle->chunk_remain -= consumed; - pngle->crc32 = mz_crc32(pngle->crc32, (const mz_uint8 *)buf, consumed); - } - if (pngle->chunk_remain <= 0) pngle->state = PNGLE_STATE_CRC; - - return consumed; - - case PNGLE_STATE_CRC: - if (len < 4) return 0; - - uint32_t crc32 = read_uint32(buf); - - if (crc32 != pngle->crc32) { - debug_printf("[pngle] CRC: %08x vs %08x => NG\n", crc32, (uint32_t)pngle->crc32); - return PNGLE_ERROR("CRC mismatch"); - } - - debug_printf("[pngle] CRC: %08x vs %08x => OK\n", crc32, (uint32_t)pngle->crc32); - pngle->state = PNGLE_STATE_FIND_CHUNK_HEADER; - - // XXX: - if (pngle->chunk_type == PNGLE_CHUNK_IEND) { - pngle->state = PNGLE_STATE_EOF; - if (pngle->done_callback) pngle->done_callback(pngle); - debug_printf("[pngle] DONE\n"); - } - - return 4; - - default: - break; - } - - return PNGLE_ERROR("Invalid state"); -} - -int pngle_feed(pngle_t *pngle, const void *buf, size_t len) -{ - size_t pos = 0; - pngle_state_t last_state = pngle->state; - - while (pos < len) { - int r = pngle_feed_internal(pngle, (const uint8_t *)buf + pos, len - pos); - if (r < 0) return r; // error - - if (r == 0 && last_state == pngle->state) break; - last_state = pngle->state; - - pos += r; - } - - return pos; -} - -void pngle_set_display_gamma(pngle_t *pngle, double display_gamma) -{ - if (!pngle) return ; -#ifndef PNGLE_NO_GAMMA_CORRECTION - pngle->display_gamma = display_gamma; -#else - PNGLE_UNUSED(display_gamma); -#endif -} - -void pngle_set_init_callback(pngle_t *pngle, pngle_init_callback_t callback) -{ - if (!pngle) return ; - pngle->init_callback = callback; -} - -void pngle_set_draw_callback(pngle_t *pngle, pngle_draw_callback_t callback) -{ - if (!pngle) return ; - pngle->draw_callback = callback; -} - -void pngle_set_done_callback(pngle_t *pngle, pngle_done_callback_t callback) -{ - if (!pngle) return ; - pngle->done_callback = callback; -} - -void pngle_set_user_data(pngle_t *pngle, void *user_data) -{ - if (!pngle) return ; - pngle->user_data = user_data; -} - -void *pngle_get_user_data(pngle_t *pngle) -{ - if (!pngle) return NULL; - return pngle->user_data; -} - -/* vim: set ts=4 sw=4 noexpandtab: */ diff --git a/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.h b/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.h deleted file mode 100644 index 41acf094..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/pngle/pngle.h +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * MIT License - * - * Copyright (c) 2019 kikuchan - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __PNGLE_H__ -#define __PNGLE_H__ - -#include -#include -#include "miniz.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifdef PNGLE_DEBUG -#define debug_printf(...) fprintf(stderr, __VA_ARGS__) -#else -#define debug_printf(...) ((void)0) -#endif - -//#define PNGLE_NO_GAMMA_CORRECTION - -typedef struct __attribute__((__packed__)) { - uint8_t red; - uint8_t green; - uint8_t blue; -} pixel_png; - -typedef enum { - PNGLE_STATE_ERROR = -2, - PNGLE_STATE_EOF = -1, - PNGLE_STATE_INITIAL = 0, - - PNGLE_STATE_FIND_CHUNK_HEADER, - PNGLE_STATE_HANDLE_CHUNK, - PNGLE_STATE_CRC, -} pngle_state_t; - - -typedef enum { -// Supported chunks -// Filter chunk names by following command to (re)generate hex constants; -// % perl -ne 'chomp; s/.*\s*\/\/\s*//; print "\tPNGLE_CHUNK_$_ = 0x" . unpack("H*") . "UL, // $_\n";' - PNGLE_CHUNK_IHDR = 0x49484452UL, // IHDR - PNGLE_CHUNK_PLTE = 0x504c5445UL, // PLTE - PNGLE_CHUNK_IDAT = 0x49444154UL, // IDAT - PNGLE_CHUNK_IEND = 0x49454e44UL, // IEND - PNGLE_CHUNK_tRNS = 0x74524e53UL, // tRNS - PNGLE_CHUNK_gAMA = 0x67414d41UL, // gAMA -} pngle_chunk_t; - -typedef struct _pngle_ihdr_t { - uint32_t width; - uint32_t height; - uint8_t depth; - uint8_t color_type; - uint8_t compression; - uint8_t filter; - uint8_t interlace; -} pngle_ihdr_t; - -typedef unsigned int UINT; - -typedef struct pngle pngle_t; - -typedef void (*pngle_init_callback_t)(pngle_t *pngle, uint32_t w, uint32_t h); -typedef void (*pngle_draw_callback_t)(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); -typedef void (*pngle_done_callback_t)(pngle_t *pngle); - -struct pngle { - pngle_ihdr_t hdr; - - uint_fast8_t channels; // 0 indicates IHDR hasn't been processed yet - - // PLTE chunk - size_t n_palettes; - uint8_t *palette; - - // tRNS chunk - size_t n_trans_palettes; - uint8_t *trans_palette; - - // parser state (reset on every chunk header) - pngle_state_t state; - uint32_t chunk_type; - uint32_t chunk_remain; - mz_ulong crc32; - - // decompression state (reset on IHDR) - tinfl_decompressor inflator; // 11000 bytes - uint8_t lz_buf[TINFL_LZ_DICT_SIZE]; // 32768 bytes - uint8_t *next_out; // NULL indicates IDAT hasn't been processed yet - size_t avail_out; - - // scanline decoder (reset on every set_interlace_pass() call) - uint8_t *scanline_ringbuf; - size_t scanline_ringbuf_size; - size_t scanline_ringbuf_cidx; - int_fast8_t scanline_remain_bytes_to_render; - int_fast8_t filter_type; - uint32_t drawing_x; - uint32_t drawing_y; - - // interlace - uint_fast8_t interlace_pass; - - const char *error; - -#ifndef PNGLE_NO_GAMMA_CORRECTION - uint8_t *gamma_table; - double display_gamma; -#endif - - pngle_init_callback_t init_callback; - pngle_draw_callback_t draw_callback; - pngle_done_callback_t done_callback; - - void *user_data; - uint16_t screenWidth; - uint16_t screenHeight; - uint16_t imageWidth; - uint16_t imageHeight; - pixel_png **pixels; - bool reduction; - double scale_factor; -}; - - -// ---------------- -// Basic interfaces -// ---------------- -pngle_t *pngle_new(uint16_t width, uint16_t height); -void pngle_destroy(pngle_t *pngle, uint16_t width, uint16_t height); -void pngle_reset(pngle_t *pngle); // clear its internal state (not applied to pngle_set_* functions) -const char *pngle_error(pngle_t *pngle); -int pngle_feed(pngle_t *pngle, const void *buf, size_t len); // returns -1: On error, 0: Need more data, n: n bytes eaten - -uint32_t pngle_get_width(pngle_t *pngle); -uint32_t pngle_get_height(pngle_t *pngle); - -void pngle_set_init_callback(pngle_t *png, pngle_init_callback_t callback); -void pngle_set_draw_callback(pngle_t *png, pngle_draw_callback_t callback); -void pngle_set_done_callback(pngle_t *png, pngle_done_callback_t callback); - -void pngle_set_display_gamma(pngle_t *pngle, double display_gamma); // enables gamma correction by specifying display gamma, typically 2.2. No effect when gAMA chunk is missing - -void pngle_set_user_data(pngle_t *pngle, void *user_data); -void *pngle_get_user_data(pngle_t *pngle); - - -// Get IHDR information -pngle_ihdr_t *pngle_get_ihdr(pngle_t *pngle); - - -#ifdef __cplusplus -} -#endif - -#endif /* __PNGLE_H__ */ diff --git a/rootfs/usr/share/d3m0n/src/lib/radiowave_generator.cpp b/rootfs/usr/share/d3m0n/src/lib/radiowave_generator.cpp deleted file mode 100644 index 03ad65a7..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/radiowave_generator.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -#define PIN RPI_GPIO_P1_07 // GPIO pin 4 - -// Function to set the pin high or low -void setPin(bool state) { - if (state) { - bcm2835_gpio_set(PIN); - } else { - bcm2835_gpio_clr(PIN); - } -} - -// Function to modulate the frequency to send binary data -void sendBinaryData(const std::string& data, int frequency, int bitDuration) { - int period = 1000000 / frequency; // Period in microseconds - - for (char bit : data) { - bool state = (bit == '1'); - for (int i = 0; i < bitDuration; ++i) { - setPin(state); - bcm2835_delayMicroseconds(period / 2); - setPin(!state); - bcm2835_delayMicroseconds(period / 2); - } - } -} - -int main() { - if (!bcm2835_init()) { - std::cerr << "bcm2835_init failed. Are you running as root?" << std::endl; - return 1; - } - - if (!bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP)) { - std::cerr << "bcm2835_gpio_fsel failed. Are you running as root?" << std::endl; - return 1; - } - - std::string binaryData = "101010001110"; // Example binary data - int frequency = 100000; // Frequency in Hz (100 kHz) - int bitDuration = 100; // Duration of each bit in microseconds - - sendBinaryData(binaryData, frequency, bitDuration); - - bcm2835_close(); - return 0; -} \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/lib/tft.conf b/rootfs/usr/share/d3m0n/src/lib/tft.conf deleted file mode 100644 index 1ace7262..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tft.conf +++ /dev/null @@ -1,8 +0,0 @@ -#width=128 height=128 -width=240 height=320 -#width=240 height=400 - -#If TFT have GRAM offset -#offsetx=2 -#offsety=1 - diff --git a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.c b/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.c deleted file mode 100644 index 9d0389b8..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - jpeg decoder. - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - - -/* -The image used for the effect on the LCD in the SPI master example is stored in flash -as a jpeg file. This file contains the decode_image routine, which uses the tiny JPEG -decoder library in ROM to decode this JPEG into a format that can be sent to the display. - -Keep in mind that the decoder library cannot handle progressive files (will give -``Image decoder: jd_prepare failed (8)`` as an error) so make sure to save in the correct -format if you want to use a different image file. -*/ - -#include -#include -#include -#include -#include "decode_jpeg.h" -#include "tjpgd.h" - -#define _DEBUG_ 0 - -//Data that is passed from the decoder function to the infunc/outfunc functions. -typedef struct { - pixel_jpeg **outData; // Array of IMAGE_H pointers to arrays of 16-bit pixel values - int screenWidth; // Width of the screen - int screenHeight; // Height of the screen - FILE* fp; // File pointer of jpeg file -} JpegDev; - - -//Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure. -static size_t infunc(JDEC *decoder, uint8_t *buf, size_t len) { - JpegDev *jd = (JpegDev *) decoder->device; - if (_DEBUG_) printf("infunc len=%d fp=%p\n", len, jd->fp); - int rlen; - if (buf != NULL) { /* Read nd bytes from the input strem */ - rlen = fread(buf, 1, len, jd->fp); - if (_DEBUG_) printf("rlen=%d\n",rlen); - } else { /* Skip nd bytes on the input stream */ - if (_DEBUG_) printf("buff is NULL\n"); - fseek(jd->fp, len, SEEK_CUR); - rlen = len; - } - return rlen; -} - -//Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and -//stores it in the outData array of the JpegDev structure. -static int outfunc(JDEC *decoder, void *bitmap, JRECT *rect) { - JpegDev *jd = (JpegDev *) decoder->device; - uint8_t *in = (uint8_t *) bitmap; - if (_DEBUG_) printf("rect->top=%d rect->bottom=%d\n", rect->top, rect->bottom); - if (_DEBUG_) printf("rect->left=%d rect->right=%d\n", rect->left, rect->right); - if (_DEBUG_) printf("jd->screenWidth=%d jd->screenHeight=%d\n", jd->screenWidth, jd->screenHeight); - - for (int y = rect->top; y <= rect->bottom; y++) { - for (int x = rect->left; x <= rect->right; x++) { - - if (y < jd->screenHeight && x < jd->screenWidth) { - jd->outData[y][x] = RGBtoRGB565(in[0], in[1], in[2]); - } - - in += 3; - } - } - return 1; -} - -// Specifies scaling factor N for output. The output image is descaled to 1 / 2 ^ N (N = 0 to 3). -// When scaling feature is disabled (JD_USE_SCALE == 0), it must be 0. -uint8_t getScale(uint16_t screenWidth, uint16_t screenHeight, uint16_t imageWidth, uint16_t imageHeight) { - if (screenWidth >= imageWidth && screenHeight >= imageHeight) return 0; - - if (_DEBUG_) printf("screenWidth=%d imageWidth=%d\n", screenWidth, imageWidth); - if (_DEBUG_) printf("screenHeight=%d imageHeight=%d\n", screenHeight, imageHeight); - double scaleWidth = (double)imageWidth / (double)screenWidth; - double scaleHeight = (double)imageHeight / (double)screenHeight; - if (_DEBUG_) printf("scaleWidth=%f scaleHeight=%f\n", scaleWidth, scaleHeight); - double scale = scaleWidth; - if (scaleWidth < scaleHeight) scale = scaleHeight; - if (_DEBUG_) printf("scale=%f\n", scale); - //if (scale < 2.0) return 1; - //if (scale < 4.0) return 2; - if (scale <= 2.0) return 1; - if (scale <= 4.0) return 2; - return 3; - -} - -//Size of the work space for the jpeg decoder. -#define WORKSZ 3100 - -//Decode the embedded image into pixel lines that can be used with the rest of the logic. -int16_t decode_jpeg(pixel_jpeg ***pixels, char * file, uint16_t width, uint16_t height, uint16_t * imageWidth, uint16_t * imageHeight) { - char *work = NULL; - int r; - JDEC decoder; - JpegDev jd; - *pixels = NULL; - uint16_t ret = JPG_OK; - - - //Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. - *pixels = static_cast(calloc(height, sizeof(pixel_jpeg *))); - if (*pixels == NULL) { - printf("%s:Error allocating memory for lines\n", __func__); - ret = JPG_ERR_NO_MEM; - goto err; - } - for (int i = 0; i < height; i++) { - (*pixels)[i] = static_cast(malloc(width * sizeof(pixel_jpeg))); - if ((*pixels)[i] == NULL) { - printf("%s:Error allocating memory for line %d\n", __func__, i); - ret = JPG_ERR_NO_MEM; - goto err; - } - } - - //Allocate the work space for the jpeg decoder. - work = static_cast(calloc(WORKSZ, 1)); - if (work == NULL) { - printf("%s:Cannot allocate workspace\n", __func__); - ret = JPG_ERR_NO_MEM; - goto err; - } - - - //Populate fields of the JpegDev struct. - jd.outData = *pixels; - jd.screenWidth = width; - jd.screenHeight = height; - jd.fp = fopen(file, "rb"); - if (jd.fp == NULL) { - printf("%s:Image file not found [%s]\n", __func__, file); - ret = JPG_ERR_NOT_FOUND; - goto err; - } - if (_DEBUG_) printf("jd.fp=%p\n", jd.fp); - - //Prepare and decode the jpeg. - r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *) &jd); - if (r != JDR_OK) { - printf("%s:jd_prepare failed (%d)\n", __func__, r); - ret = JPG_ERR_NOT_SUPPORTED; - goto err; - } - if (_DEBUG_) printf("decoder.width=%d decoder.height=%d\n", decoder.width, decoder.height); - - //Calculate Scaling factor - uint8_t scale = getScale(width, height, decoder.width, decoder.height); - if (_DEBUG_) printf("scale=%d\n", scale); - - //Calculate image size - double factor = 1.0; - if (scale == 1) factor = 0.5; - if (scale == 2) factor = 0.25; - if (scale == 3) factor = 0.125; - if (_DEBUG_) printf("factor=%f\n",factor); - *imageWidth = (double)decoder.width * factor; - *imageHeight = (double)decoder.height * factor; - if (_DEBUG_) printf("imageWidth=%d imageHeight=%d\n", *imageWidth, *imageHeight); - - - r = jd_decomp(&decoder, outfunc, scale); - if (r != JDR_OK) { - printf("%s:jd_decomp failed (%d)\n", __func__, r); - ret = JPG_ERR_NOT_SUPPORTED; - goto err; - } - - //All done! Free the work area (as we don't need it anymore) and return victoriously. - free(work); - fclose(jd.fp); - return ret; - - err: - //Something went wrong! Exit cleanly, de-allocating everything we allocated. - if (*pixels != NULL) { - for (int i = 0; i < height; i++) { - free((*pixels)[i]); - } - free(*pixels); - } - free(work); - if (jd.fp != NULL) fclose(jd.fp); - return ret; -} - - -int16_t release_jpeg(pixel_jpeg ***pixels, uint16_t width, uint16_t height) { - if (*pixels != NULL) { - for (int i = 0; i < height; i++) { - free((*pixels)[i]); - } - free(*pixels); - } - return JPG_OK; -} - diff --git a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.h b/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.h deleted file mode 100644 index 52214f24..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/decode_jpeg.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include - -#define JPG_OK 0 -#define JPG_FAIL -1 -#define JPG_ERR_NO_MEM 0x101 -#define JPG_ERR_INVALID_ARG 0x102 -#define JPG_ERR_INVALID_STATE 0x103 -#define JPG_ERR_INVALID_SIZE 0x104 -#define JPG_ERR_NOT_FOUND 0x105 -#define JPG_ERR_NOT_SUPPORTED 0x106 -#define JPG_ERR_TIMEOUT 0x107 -#define JPG_ERR_INVALID_RESPONSE 0x108 -#define JPG_ERR_INVALID_CRC 0x109 -#define JPG_ERR_INVALID_VERSION 0x10A -#define JPG_ERR_INVALID_MAC 0x10B -#define JPG_ERR_WIFI_BASE 0x3000 -#define JPG_ERR_MESH_BASE 0x4000 - -//rgb565 format -typedef uint16_t pixel_jpeg; - -/** - * @brief Decode the jpeg ``image.jpg`` embedded into the program file into pixel data. - * - * @param pixels A pointer to a pointer for an array of rows, which themselves are an array of pixels. - * Effectively, you can get the pixel data by doing ``decode_image(&myPixels); pixelval=myPixels[ypos][xpos];`` - * @return - ESP_ERR_NOT_SUPPORTED if image is malformed or a progressive jpeg file - * - ESP_ERR_NO_MEM if out of memory - * - ESP_OK on succesful decode - */ - -int16_t decode_jpeg(pixel_jpeg ***pixels, char * file, uint16_t width, uint16_t height, uint16_t * imageWidth, uint16_t * imageHeight); - -/** - * @brief Release image memory. - * - */ - -int16_t release_jpeg(pixel_jpeg ***pixels, uint16_t width, uint16_t height); - diff --git a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.c b/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.c deleted file mode 100644 index 3e2b7e60..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.c +++ /dev/null @@ -1,1153 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021 -/-----------------------------------------------------------------------------/ -/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2021, ChaN, all right reserved. -/ -/ * The TJpgDec module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-----------------------------------------------------------------------------/ -/ Oct 04, 2011 R0.01 First release. -/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. -/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. -/ Mar 16, 2019 R0.01c Supprted stdint.h. -/ Jul 01, 2020 R0.01d Fixed wrong integer type usage. -/ May 08, 2021 R0.02 Supprted grayscale image. Separated configuration options. -/ Jun 11, 2021 R0.02a Some performance improvement. -/ Jul 01, 2021 R0.03 Added JD_FASTDECODE option. -/ Some performance improvement. -/----------------------------------------------------------------------------*/ - -#include "tjpgd.h" - - -#if JD_FASTDECODE == 2 -#define HUFF_BIT 10 /* Bit length to apply fast huffman decode */ -#define HUFF_LEN (1 << HUFF_BIT) -#define HUFF_MASK (HUFF_LEN - 1) -#endif - - -/*-----------------------------------------------*/ -/* Zigzag-order to raster-order conversion table */ -/*-----------------------------------------------*/ - -static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - - - -/*-------------------------------------------------*/ -/* Input scale factor of Arai algorithm */ -/* (scaled up 16 bits for fixed point operations) */ -/*-------------------------------------------------*/ - -static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ - (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), - (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), - (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), - (uint16_t)(1.17588*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.38268*8192), (uint16_t)(1.17588*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.32442*8192), - (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), - (uint16_t)(0.78570*8192), (uint16_t)(1.08979*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.61732*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.21677*8192), - (uint16_t)(0.54120*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.29290*8192), (uint16_t)(0.14932*8192), - (uint16_t)(0.27590*8192), (uint16_t)(0.38268*8192), (uint16_t)(0.36048*8192), (uint16_t)(0.32442*8192), (uint16_t)(0.27590*8192), (uint16_t)(0.21678*8192), (uint16_t)(0.14932*8192), (uint16_t)(0.07612*8192) -}; - - - -/*---------------------------------------------*/ -/* Conversion table for fast clipping process */ -/*---------------------------------------------*/ - -#if JD_TBLCLIP - -#define BYTECLIP(v) Clip8[(unsigned int)(v) & 0x3FF] - -static const uint8_t Clip8[1024] = { - /* 0..255 */ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - /* 256..511 */ - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - /* -512..-257 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* -256..-1 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#else /* JD_TBLCLIP */ - -static uint8_t BYTECLIP (int val) -{ - if (val < 0) return 0; - if (val > 255) return 255; - return (uint8_t)val; -} - -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Allocate a memory block from memory pool */ -/*-----------------------------------------------------------------------*/ - -static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ - JDEC* jd, /* Pointer to the decompressor object */ - size_t ndata /* Number of bytes to allocate */ -) -{ - char *rp = 0; - - - ndata = (ndata + 3) & ~3; /* Align block size to the word boundary */ - - if (jd->sz_pool >= ndata) { - jd->sz_pool -= ndata; - rp = (char*)jd->pool; /* Get start of available memory pool */ - jd->pool = (void*)(rp + ndata); /* Allocate requierd bytes */ - } - - return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create de-quantization and prescaling tables with a DQT segment */ -/*-----------------------------------------------------------------------*/ - -static JRESULT create_qt_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const uint8_t* data, /* Pointer to the quantizer tables */ - size_t ndata /* Size of input data */ -) -{ - unsigned int i, zi; - uint8_t d; - int32_t *pb; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ - ndata -= 65; - d = *data++; /* Get table property */ - if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ - i = d & 3; /* Get table ID */ - pb = static_cast(alloc_pool(jd, 64 * sizeof (int32_t)));/* Allocate a memory block for the table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->qttbl[i] = pb; /* Register the table */ - for (i = 0; i < 64; i++) { /* Load the table */ - zi = Zig[i]; /* Zigzag-order to raster-order conversion */ - pb[zi] = (int32_t)((uint32_t)*data++ * Ipsf[zi]); /* Apply scale factor of Arai algorithm to the de-quantizers */ - } - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create huffman code tables with a DHT segment */ -/*-----------------------------------------------------------------------*/ - -static JRESULT create_huffman_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const uint8_t* data, /* Pointer to the packed huffman tables */ - size_t ndata /* Size of input data */ -) -{ - unsigned int i, j, b, cls, num; - size_t np; - uint8_t d, *pb, *pd; - uint16_t hc, *ph; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ - ndata -= 17; - d = *data++; /* Get table number and class */ - if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ - cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ - pb = static_cast(alloc_pool(jd, 16)); /* Allocate a memory block for the bit distribution table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->huffbits[num][cls] = pb; - for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ - np += (pb[i] = *data++); /* Get sum of code words for each code */ - } - ph = static_cast(alloc_pool(jd, np * sizeof (uint16_t)));/* Allocate a memory block for the code word table */ - if (!ph) return JDR_MEM1; /* Err: not enough memory */ - jd->huffcode[num][cls] = ph; - hc = 0; - for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ - b = pb[i]; - while (b--) ph[j++] = hc++; - hc <<= 1; - } - - if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ - ndata -= np; - pd = static_cast(alloc_pool(jd, np)); /* Allocate a memory block for the decoded data */ - if (!pd) return JDR_MEM1; /* Err: not enough memory */ - jd->huffdata[num][cls] = pd; - for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code word */ - d = *data++; - if (!cls && d > 11) return JDR_FMT1; - pd[i] = d; - } -#if JD_FASTDECODE == 2 - { /* Create fast huffman decode table */ - unsigned int span, td, ti; - uint16_t *tbl_ac = 0; - uint8_t *tbl_dc = 0; - - if (cls) { - tbl_ac = alloc_pool(jd, HUFF_LEN * sizeof (uint16_t)); /* LUT for AC elements */ - if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */ - jd->hufflut_ac[num] = tbl_ac; - memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */ - } else { - tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */ - if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */ - jd->hufflut_dc[num] = tbl_dc; - memset(tbl_dc, 0xFF, HUFF_LEN * sizeof (uint8_t)); /* Default value (0xFF: may be long code) */ - } - for (i = b = 0; b < HUFF_BIT; b++) { /* Create LUT */ - for (j = pb[b]; j; j--) { - ti = ph[i] << (HUFF_BIT - 1 - b) & HUFF_MASK; /* Index of input pattern for the code */ - if (cls) { - td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */ - for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ; - } else { - td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */ - for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ; - } - } - } - jd->longofs[num][cls] = i; /* Code table offset for long code */ - } -#endif - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract a huffman decoded data from input stream */ -/*-----------------------------------------------------------------------*/ - -static int huffext ( /* >=0: decoded data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - unsigned int id, /* Table ID (0:Y, 1:C) */ - unsigned int cls /* Table class (0:DC, 1:AC) */ -) -{ - size_t dc = jd->dctr; - uint8_t *dp = jd->dptr; - unsigned int d, flg = 0; - -#if JD_FASTDECODE == 0 - uint8_t bm, nd, bl; - const uint8_t *hb = jd->huffbits[id][cls]; /* Bit distribution table */ - const uint16_t *hc = jd->huffcode[id][cls]; /* Code word table */ - const uint8_t *hd = jd->huffdata[id][cls]; /* Data table */ - - - bm = jd->dbit; /* Bit mask to extract */ - d = 0; bl = 16; /* Max code length */ - do { - if (!bm) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = 0xFF; /* The flag is a data 0xFF */ - } else { - if (*dp == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - bm = 0x80; /* Read from MSB */ - } - d <<= 1; /* Get a bit */ - if (*dp & bm) d++; - bm >>= 1; - - for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */ - if (d == *hc++) { /* Matched? */ - jd->dbit = bm; jd->dctr = dc; jd->dptr = dp; - return *hd; /* Return the decoded data */ - } - hd++; - } - bl--; - } while (bl); - -#else - const uint8_t *hb, *hd; - const uint16_t *hc; - unsigned int nc, bl, wbit = jd->dbit % 32; - uint32_t w = jd->wreg & ((1UL << wbit) - 1); - - - while (wbit < 16) { /* Prepare 16 bits into the working register */ - if (jd->marker) { - d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */ - } else { - if (!dc) { /* Buffer empty, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } - d = *dp++; dc--; - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ - d = 0xFF; - } else { - if (d == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - } - w = w << 8 | d; /* Shift 8 bits in the working register */ - wbit += 8; - } - jd->dctr = dc; jd->dptr = dp; - jd->wreg = w; - -#if JD_FASTDECODE == 2 - /* Table serch for the short codes */ - d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */ - if (cls) { /* AC element */ - d = jd->hufflut_ac[id][d]; /* Table decode */ - if (d != 0xFFFF) { /* It is done if hit in short code */ - jd->dbit = wbit - (d >> 8); /* Snip the code length */ - return d & 0xFF; /* b7..0: zero run and following data bits */ - } - } else { /* DC element */ - d = jd->hufflut_dc[id][d]; /* Table decode */ - if (d != 0xFF) { /* It is done if hit in short code */ - jd->dbit = wbit - (d >> 4); /* Snip the code length */ - return d & 0xF; /* b3..0: following data bits */ - } - } - - /* Incremental serch for the codes longer than HUFF_BIT */ - hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */ - hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */ - hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */ - bl = HUFF_BIT + 1; -#else - /* Incremental serch for all codes */ - hb = jd->huffbits[id][cls]; /* Bit distribution table */ - hc = jd->huffcode[id][cls]; /* Code word table */ - hd = jd->huffdata[id][cls]; /* Data table */ - bl = 1; -#endif - for ( ; bl <= 16; bl++) { /* Incremental search */ - nc = *hb++; - if (nc) { - d = w >> (wbit - bl); - do { /* Search the code word in this bit length */ - if (d == *hc++) { /* Matched? */ - jd->dbit = wbit - bl; /* Snip the huffman code */ - return *hd; /* Return the decoded data */ - } - hd++; - } while (--nc); - } - } -#endif - - return 0 - (int)JDR_FMT1; /* Err: code not found (may be collapted data) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract N bits from input stream */ -/*-----------------------------------------------------------------------*/ - -static int bitext ( /* >=0: extracted data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - unsigned int nbit /* Number of bits to extract (1 to 16) */ -) -{ - size_t dc = jd->dctr; - uint8_t *dp = jd->dptr; - unsigned int d, flg = 0; - -#if JD_FASTDECODE == 0 - uint8_t mbit = jd->dbit; - - d = 0; - do { - if (!mbit) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = 0xFF; /* The flag is a data 0xFF */ - } else { - if (*dp == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence */ - } - } - mbit = 0x80; /* Read from MSB */ - } - d <<= 1; /* Get a bit */ - if (*dp & mbit) d |= 1; - mbit >>= 1; - nbit--; - } while (nbit); - - jd->dbit = mbit; jd->dctr = dc; jd->dptr = dp; - return (int)d; - -#else - unsigned int wbit = jd->dbit % 32; - uint32_t w = jd->wreg & ((1UL << wbit) - 1); - - - while (wbit < nbit) { /* Prepare nbit bits into the working register */ - if (jd->marker) { - d = 0xFF; /* Input stream stalled, generate stuff bits */ - } else { - if (!dc) { /* Buffer empty, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } - d = *dp++; dc--; - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ - d = 0xFF; - } else { - if (d == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - } - w = w << 8 | d; /* Get 8 bits into the working register */ - wbit += 8; - } - jd->wreg = w; jd->dbit = wbit - nbit; - jd->dctr = dc; jd->dptr = dp; - - return (int)(w >> ((wbit - nbit) % 32)); -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Process restart interval */ -/*-----------------------------------------------------------------------*/ - -static JRESULT restart ( - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t rstn /* Expected restert sequense number */ -) -{ - unsigned int i; - uint8_t *dp = jd->dptr; - size_t dc = jd->dctr; - -#if JD_FASTDECODE == 0 - uint16_t d = 0; - - /* Get two bytes from the input stream */ - for (i = 0; i < 2; i++) { - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return JDR_INP; - } else { - dp++; - } - dc--; - d = d << 8 | *dp; /* Get a byte */ - } - jd->dptr = dp; jd->dctr = dc; jd->dbit = 0; - - /* Check the marker */ - if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { - return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ - } - -#else - uint16_t marker; - - - if (jd->marker) { /* Generate a maker if it has been detected */ - marker = 0xFF00 | jd->marker; - jd->marker = 0; - } else { - marker = 0; - for (i = 0; i < 2; i++) { /* Get a restart marker */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return JDR_INP; - } - marker = (marker << 8) | *dp++; /* Get a byte */ - dc--; - } - jd->dptr = dp; jd->dctr = dc; - } - - /* Check the marker */ - if ((marker & 0xFFD8) != 0xFFD0 || (marker & 7) != (rstn & 7)) { - return JDR_FMT1; /* Err: expected RSTn marker was not detected (may be collapted data) */ - } - - jd->dbit = 0; /* Discard stuff bits */ -#endif - - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Reset DC offset */ - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ -/*-----------------------------------------------------------------------*/ - -static void block_idct ( - int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ - jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */ -) -{ - const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); - int32_t v0, v1, v2, v3, v4, v5, v6, v7; - int32_t t10, t11, t12, t13; - int i; - - /* Process columns */ - for (i = 0; i < 8; i++) { - v0 = src[8 * 0]; /* Get even elements */ - v1 = src[8 * 2]; - v2 = src[8 * 4]; - v3 = src[8 * 6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[8 * 7]; /* Get odd elements */ - v5 = src[8 * 1]; - v6 = src[8 * 5]; - v7 = src[8 * 3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - src[8 * 0] = v0 + v7; /* Write-back transformed values */ - src[8 * 7] = v0 - v7; - src[8 * 1] = v1 + v6; - src[8 * 6] = v1 - v6; - src[8 * 2] = v2 + v5; - src[8 * 5] = v2 - v5; - src[8 * 3] = v3 + v4; - src[8 * 4] = v3 - v4; - - src++; /* Next column */ - } - - /* Process rows */ - src -= 8; - for (i = 0; i < 8; i++) { - v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ - v1 = src[2]; - v2 = src[4]; - v3 = src[6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[7]; /* Get odd elements */ - v5 = src[1]; - v6 = src[5]; - v7 = src[3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - /* Descale the transformed values 8 bits and output a row */ -#if JD_FASTDECODE >= 1 - dst[0] = (int16_t)((v0 + v7) >> 8); - dst[7] = (int16_t)((v0 - v7) >> 8); - dst[1] = (int16_t)((v1 + v6) >> 8); - dst[6] = (int16_t)((v1 - v6) >> 8); - dst[2] = (int16_t)((v2 + v5) >> 8); - dst[5] = (int16_t)((v2 - v5) >> 8); - dst[3] = (int16_t)((v3 + v4) >> 8); - dst[4] = (int16_t)((v3 - v4) >> 8); -#else - dst[0] = BYTECLIP((v0 + v7) >> 8); - dst[7] = BYTECLIP((v0 - v7) >> 8); - dst[1] = BYTECLIP((v1 + v6) >> 8); - dst[6] = BYTECLIP((v1 - v6) >> 8); - dst[2] = BYTECLIP((v2 + v5) >> 8); - dst[5] = BYTECLIP((v2 - v5) >> 8); - dst[3] = BYTECLIP((v3 + v4) >> 8); - dst[4] = BYTECLIP((v3 - v4) >> 8); -#endif - - dst += 8; src += 8; /* Next row */ - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load all blocks in an MCU into working buffer */ -/*-----------------------------------------------------------------------*/ - -static JRESULT mcu_load ( - JDEC* jd /* Pointer to the decompressor object */ -) -{ - int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ - int d, e; - unsigned int blk, nby, i, bc, z, id, cmp; - jd_yuv_t *bp; - const int32_t *dqf; - - - nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ - bp = jd->mcubuf; /* Pointer to the first block of MCU */ - - for (blk = 0; blk < nby + 2; blk++) { /* Get nby Y blocks and two C blocks */ - cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ - - if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */ - for (i = 0; i < 64; bp[i++] = 128) ; - - } else { /* Load Y/C blocks from input stream */ - id = cmp ? 1 : 0; /* Huffman table ID of this component */ - - /* Extract a DC element from input stream */ - d = huffext(jd, id, 0); /* Extract a huffman coded data (bit length) */ - if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input */ - bc = (unsigned int)d; - d = jd->dcv[cmp]; /* DC value of previous block */ - if (bc) { /* If there is any difference from previous block */ - e = bitext(jd, bc); /* Extract data bits */ - if (e < 0) return (JRESULT)(0 - e); /* Err: input */ - bc = 1 << (bc - 1); /* MSB position */ - if (!(e & bc)) e -= (bc << 1) - 1; /* Restore negative value if needed */ - d += e; /* Get current value */ - jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */ - } - dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ - tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - - /* Extract following 63 AC elements from input stream */ - memset(&tmp[1], 0, 63 * sizeof (int32_t)); /* Initialize all AC elements */ - z = 1; /* Top of the AC elements (in zigzag-order) */ - do { - d = huffext(jd, id, 1); /* Extract a huffman coded value (zero runs and bit length) */ - if (d == 0) break; /* EOB? */ - if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input error */ - bc = (unsigned int)d; - z += bc >> 4; /* Skip leading zero run */ - if (z >= 64) return JDR_FMT1; /* Too long zero run */ - if (bc &= 0x0F) { /* Bit length? */ - d = bitext(jd, bc); /* Extract data bits */ - if (d < 0) return (JRESULT)(0 - d); /* Err: input device */ - bc = 1 << (bc - 1); /* MSB position */ - if (!(d & bc)) d -= (bc << 1) - 1; /* Restore negative value if needed */ - i = Zig[z]; /* Get raster-order index */ - tmp[i] = d * dqf[i] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - } - } while (++z < 64); /* Next AC element */ - - if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */ - if (z == 1 || (JD_USE_SCALE && jd->scale == 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be ommited and the block is filled with DC value */ - d = (jd_yuv_t)((*tmp / 256) + 128); - if (JD_FASTDECODE >= 1) { - for (i = 0; i < 64; bp[i++] = d) ; - } else { - memset(bp, d, 64); - } - } else { - block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ - } - } - } - - bp += 64; /* Next block */ - } - - return JDR_OK; /* All blocks have been loaded successfully */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ -/*-----------------------------------------------------------------------*/ - -static JRESULT mcu_output ( - JDEC* jd, /* Pointer to the decompressor object */ - int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - unsigned int x, /* MCU location in the image */ - unsigned int y /* MCU location in the image */ -) -{ - const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */ - unsigned int ix, iy, mx, my, rx, ry; - int yy, cb, cr; - jd_yuv_t *py, *pc; - uint8_t *pix; - JRECT rect; - - - mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ - rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end of image) */ - ry = (y + my <= jd->height) ? my : jd->height - y; - if (JD_USE_SCALE) { - rx >>= jd->scale; ry >>= jd->scale; - if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ - x >>= jd->scale; y >>= jd->scale; - } - rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ - rect.top = y; rect.bottom = y + ry - 1; - - - if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ - pix = (uint8_t*)jd->workbuf; - - if (JD_FORMAT != 2) { /* RGB output (build an RGB MCU from Y/C component) */ - for (iy = 0; iy < my; iy++) { - pc = py = jd->mcubuf; - if (my == 16) { /* Double block height? */ - pc += 64 * 4 + (iy >> 1) * 8; - if (iy >= 8) py += 64; - } else { /* Single block height */ - pc += mx * 8 + iy * 8; - } - py += iy * 8; - for (ix = 0; ix < mx; ix++) { - cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */ - cr = pc[64] - 128; - if (mx == 16) { /* Double block width? */ - if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ - pc += ix & 1; /* Step forward chroma pointer every two pixels */ - } else { /* Single block width */ - pc++; /* Step forward chroma pointer every pixel */ - } - yy = *py++; /* Get Y component */ - *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC); - *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); - *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC); - } - } - } else { /* Monochrome output (build a grayscale MCU from Y comopnent) */ - for (iy = 0; iy < my; iy++) { - py = jd->mcubuf + iy * 8; - if (my == 16) { /* Double block height? */ - if (iy >= 8) py += 64; - } - for (ix = 0; ix < mx; ix++) { - if (mx == 16) { /* Double block width? */ - if (ix == 8) py += 64 - 8; /* Jump to next block if double block height */ - } - *pix++ = (uint8_t)*py++; /* Get and store a Y value as grayscale */ - } - } - } - - /* Descale the MCU rectangular if needed */ - if (JD_USE_SCALE && jd->scale) { - unsigned int x, y, r, g, b, s, w, a; - uint8_t *op; - - /* Get averaged RGB value of each square correcponds to a pixel */ - s = jd->scale * 2; /* Number of shifts for averaging */ - w = 1 << jd->scale; /* Width of square */ - a = (mx - w) * (JD_FORMAT != 2 ? 3 : 1); /* Bytes to skip for next line in the square */ - op = (uint8_t*)jd->workbuf; - for (iy = 0; iy < my; iy += w) { - for (ix = 0; ix < mx; ix += w) { - pix = (uint8_t*)jd->workbuf + (iy * mx + ix) * (JD_FORMAT != 2 ? 3 : 1); - r = g = b = 0; - for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ - for (x = 0; x < w; x++) { - r += *pix++; /* Accumulate R or Y (monochrome output) */ - if (JD_FORMAT != 2) { /* RGB output? */ - g += *pix++; /* Accumulate G */ - b += *pix++; /* Accumulate B */ - } - } - pix += a; - } /* Put the averaged pixel value */ - *op++ = (uint8_t)(r >> s); /* Put R or Y (monochrome output) */ - if (JD_FORMAT != 2) { /* RGB output? */ - *op++ = (uint8_t)(g >> s); /* Put G */ - *op++ = (uint8_t)(b >> s); /* Put B */ - } - } - } - } - - } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ - - /* Build a 1/8 descaled RGB MCU from discrete comopnents */ - pix = (uint8_t*)jd->workbuf; - pc = jd->mcubuf + mx * my; - cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ - cr = pc[64] - 128; - for (iy = 0; iy < my; iy += 8) { - py = jd->mcubuf; - if (iy == 8) py += 64 * 2; - for (ix = 0; ix < mx; ix += 8) { - yy = *py; /* Get Y component */ - py += 64; - if (JD_FORMAT != 2) { - *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr / CVACC)); - *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); - *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb / CVACC)); - } else { - *pix++ = yy; - } - } - } - } - - /* Squeeze up pixel table if a part of MCU is to be truncated */ - mx >>= jd->scale; - if (rx < mx) { /* Is the MCU spans rigit edge? */ - uint8_t *s, *d; - unsigned int x, y; - - s = d = (uint8_t*)jd->workbuf; - for (y = 0; y < ry; y++) { - for (x = 0; x < rx; x++) { /* Copy effective pixels */ - *d++ = *s++; - if (JD_FORMAT != 2) { - *d++ = *s++; - *d++ = *s++; - } - } - s += (mx - rx) * (JD_FORMAT != 2 ? 3 : 1); /* Skip truncated pixels */ - } - } - - /* Convert RGB888 to RGB565 if needed */ - if (JD_FORMAT == 1) { - uint8_t *s = (uint8_t*)jd->workbuf; - uint16_t w, *d = (uint16_t*)s; - unsigned int n = rx * ry; - - do { - w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ - w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ - w |= *s++ >> 3; /* -----------BBBBB */ - *d++ = w; - } while (--n); - } - - /* Output the rectangular */ - return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Analyze the JPEG image and Initialize decompressor object */ -/*-----------------------------------------------------------------------*/ - -#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) - - -JRESULT jd_prepare ( - JDEC* jd, /* Blank decompressor object */ - size_t (*infunc)(JDEC*, uint8_t*, size_t), /* JPEG strem input function */ - void* pool, /* Working buffer for the decompression session */ - size_t sz_pool, /* Size of working buffer */ - void* dev /* I/O device identifier for the session */ -) -{ - uint8_t *seg, b; - uint16_t marker; - unsigned int n, i, ofs; - size_t len; - JRESULT rc; - - - memset(jd, 0, sizeof (JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */ - jd->pool = pool; /* Work memroy */ - jd->sz_pool = sz_pool; /* Size of given work memory */ - jd->infunc = infunc; /* Stream input function */ - jd->device = dev; /* I/O device identifier */ - - jd->inbuf = seg = static_cast(alloc_pool(jd, JD_SZBUF)); /* Allocate stream input buffer */ - if (!seg) return JDR_MEM1; - - ofs = marker = 0; /* Find SOI marker */ - do { - if (jd->infunc(jd, seg, 1) != 1) return JDR_INP; /* Err: SOI was not detected */ - ofs++; - marker = marker << 8 | seg[0]; - } while (marker != 0xFFD8); - - for (;;) { /* Parse JPEG segments */ - /* Get a JPEG marker */ - if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; - marker = LDB_WORD(seg); /* Marker */ - len = LDB_WORD(seg + 2); /* Length field */ - if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; - len -= 2; /* Segent content size */ - ofs += 4 + len; /* Number of bytes loaded */ - - switch (marker & 0xFF) { - case 0xC0: /* SOF0 (baseline JPEG) */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - jd->width = LDB_WORD(&seg[3]); /* Image width in unit of pixel */ - jd->height = LDB_WORD(&seg[1]); /* Image height in unit of pixel */ - jd->ncomp = seg[5]; /* Number of color components */ - if (jd->ncomp != 3 && jd->ncomp != 1) return JDR_FMT3; /* Err: Supports only Grayscale and Y/Cb/Cr */ - - /* Check each image component */ - for (i = 0; i < jd->ncomp; i++) { - b = seg[7 + 3 * i]; /* Get sampling factor */ - if (i == 0) { /* Y component */ - if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ - return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ - } - jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ - } else { /* Cb/Cr component */ - if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */ - } - jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ - if (jd->qtid[i] > 3) return JDR_FMT3; /* Err: Invalid ID */ - } - break; - - case 0xDD: /* DRI - Define Restart Interval */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - jd->nrst = LDB_WORD(seg); /* Get restart interval (MCUs) */ - break; - - case 0xC4: /* DHT - Define Huffman Tables */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - rc = create_huffman_tbl(jd, seg, len); /* Create huffman tables */ - if (rc) return rc; - break; - - case 0xDB: /* DQT - Define Quaitizer Tables */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - rc = create_qt_tbl(jd, seg, len); /* Create de-quantizer tables */ - if (rc) return rc; - break; - - case 0xDA: /* SOS - Start of Scan */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ - if (seg[0] != jd->ncomp) return JDR_FMT3; /* Err: Wrong color components */ - - /* Check if all tables corresponding to each components have been loaded */ - for (i = 0; i < jd->ncomp; i++) { - b = seg[2 + 2 * i]; /* Get huffman table ID */ - if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ - n = i ? 1 : 0; /* Component class */ - if (!jd->huffbits[n][0] || !jd->huffbits[n][1]) { /* Check huffman table for this component */ - return JDR_FMT1; /* Err: Nnot loaded */ - } - if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ - return JDR_FMT1; /* Err: Not loaded */ - } - } - - /* Allocate working buffer for MCU and pixel output */ - n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ - if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ - len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ - if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ - jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ - if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ - jd->mcubuf = static_cast(alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t))); /* Allocate MCU working buffer */ - if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ - - /* Align stream read offset to JD_SZBUF */ - if (ofs %= JD_SZBUF) { - jd->dctr = jd->infunc(jd, seg + ofs, (size_t)(JD_SZBUF - ofs)); - } - jd->dptr = seg + ofs - (JD_FASTDECODE ? 0 : 1); - - return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ - - case 0xC1: /* SOF1 */ - case 0xC2: /* SOF2 */ - case 0xC3: /* SOF3 */ - case 0xC5: /* SOF5 */ - case 0xC6: /* SOF6 */ - case 0xC7: /* SOF7 */ - case 0xC9: /* SOF9 */ - case 0xCA: /* SOF10 */ - case 0xCB: /* SOF11 */ - case 0xCD: /* SOF13 */ - case 0xCE: /* SOF14 */ - case 0xCF: /* SOF15 */ - case 0xD9: /* EOI */ - return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ - - default: /* Unknown segment (comment, exif or etc..) */ - /* Skip segment data (null pointer specifies to remove data from the stream) */ - if (jd->infunc(jd, 0, len) != len) return JDR_INP; - } - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Start to decompress the JPEG picture */ -/*-----------------------------------------------------------------------*/ - -JRESULT jd_decomp ( - JDEC* jd, /* Initialized decompression object */ - int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint8_t scale /* Output de-scaling factor (0 to 3) */ -) -{ - unsigned int x, y, mx, my; - uint16_t rst, rsc; - JRESULT rc; - - - if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; - jd->scale = scale; - - mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ - - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ - rst = rsc = 0; - - rc = JDR_OK; - for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ - for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ - if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ - rc = restart(jd, rsc++); - if (rc != JDR_OK) return rc; - rst = 1; - } - rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ - if (rc != JDR_OK) return rc; - rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */ - if (rc != JDR_OK) return rc; - } - } - - return rc; -} diff --git a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.h b/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.h deleted file mode 100644 index 7b4f82f5..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgd.h +++ /dev/null @@ -1,102 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 -/----------------------------------------------------------------------------*/ -#ifndef DEF_TJPGDEC -#define DEF_TJPGDEC - -#ifdef __cplusplus -extern "C" { -#endif - -#include "tjpgdcnf.h" -#include - -#if defined(_WIN32) /* VC++ or some compiler without stdint.h */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef short int16_t; -typedef unsigned long uint32_t; -typedef long int32_t; -#else /* Embedded platform */ -#include -#endif - -#if JD_FASTDECODE >= 1 -typedef int16_t jd_yuv_t; -#else -typedef uint8_t jd_yuv_t; -#endif - - -/* Error code */ -typedef enum { - JDR_OK = 0, /* 0: Succeeded */ - JDR_INTR, /* 1: Interrupted by output function */ - JDR_INP, /* 2: Device error or wrong termination of input stream */ - JDR_MEM1, /* 3: Insufficient memory pool for the image */ - JDR_MEM2, /* 4: Insufficient stream input buffer */ - JDR_PAR, /* 5: Parameter error */ - JDR_FMT1, /* 6: Data format error (may be broken data) */ - JDR_FMT2, /* 7: Right format but not supported */ - JDR_FMT3 /* 8: Not supported JPEG standard */ -} JRESULT; - - - -/* Rectangular region in the output image */ -typedef struct { - uint16_t left; /* Left end */ - uint16_t right; /* Right end */ - uint16_t top; /* Top end */ - uint16_t bottom; /* Bottom end */ -} JRECT; - - - -/* Decompressor object structure */ -typedef struct JDEC JDEC; -struct JDEC { - size_t dctr; /* Number of bytes available in the input buffer */ - uint8_t* dptr; /* Current data read ptr */ - uint8_t* inbuf; /* Bit stream input buffer */ - uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */ - uint8_t scale; /* Output scaling ratio */ - uint8_t msx, msy; /* MCU size in unit of block (width, height) */ - uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */ - uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ - int16_t dcv[3]; /* Previous DC element of each component */ - uint16_t nrst; /* Restart inverval */ - uint16_t width, height; /* Size of the input image (pixel) */ - uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ - uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ - uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ - int32_t* qttbl[4]; /* Dequantizer tables [id] */ -#if JD_FASTDECODE >= 1 - uint32_t wreg; /* Working shift register */ - uint8_t marker; /* Detected marker (0:None) */ -#if JD_FASTDECODE == 2 - uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */ - uint16_t* hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */ - uint8_t* hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */ -#endif -#endif - void* workbuf; /* Working buffer for IDCT and RGB output */ - jd_yuv_t* mcubuf; /* Working buffer for the MCU */ - void* pool; /* Pointer to available memory pool */ - size_t sz_pool; /* Size of momory pool (bytes available) */ - size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */ - void* device; /* Pointer to I/O device identifiler for the session */ -}; - - - -/* TJpgDec API functions */ -JRESULT jd_prepare (JDEC* jd, size_t (*infunc)(JDEC*,uint8_t*,size_t), void* pool, size_t sz_pool, void* dev); -JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TJPGDEC */ diff --git a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgdcnf.h b/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgdcnf.h deleted file mode 100644 index 6d425e6f..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/tjpgd3/tjpgdcnf.h +++ /dev/null @@ -1,33 +0,0 @@ -/*----------------------------------------------*/ -/* TJpgDec System Configurations R0.03 */ -/*----------------------------------------------*/ - -#define JD_SZBUF 512 -/* Specifies size of stream input buffer */ - -#define JD_FORMAT 0 -/* Specifies output pixel format. -/ 0: RGB888 (24-bit/pix) -/ 1: RGB565 (16-bit/pix) -/ 2: Grayscale (8-bit/pix) -*/ - -#define JD_USE_SCALE 1 -/* Switches output descaling feature. -/ 0: Disable -/ 1: Enable -*/ - -#define JD_TBLCLIP 1 -/* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size. -/ 0: Disable -/ 1: Enable -*/ - -#define JD_FASTDECODE 0 -/* Optimization level -/ 0: Basic optimization. Suitable for 8/16-bit MCUs. -/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. -/ 2: + Table conversion for huffman decoding (wants 6 << HUFF_BIT bytes of RAM) -*/ - diff --git a/rootfs/usr/share/d3m0n/src/lib/xpt2046.c b/rootfs/usr/share/d3m0n/src/lib/xpt2046.c deleted file mode 100644 index 7cd4396a..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/xpt2046.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - XPT2046 Touch Screen Controller Library for Raspberry - - I ported from here. - https://github.com/xofc/xpt2uinput -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ili9340.h" -#include "xpt2046.h" - -#define MAX_LEN 3 - -#define XPT_START 0x80 -#define XPT_XPOS 0x50 -#define XPT_YPOS 0x10 -#define XPT_8BIT 0x80 -#define XPT_SER 0x04 -#define XPT_DEF 0x03 - -#define _DEBUG_ 0 - -int xptGetit(int cmd){ - char rbuf[MAX_LEN]; - char wbuf[MAX_LEN]; - - memset(wbuf, 0, sizeof(rbuf)); - memset(rbuf, 0, sizeof(rbuf)); - wbuf[0] = cmd; - bcm2835_spi_transfernb(wbuf, rbuf, sizeof(wbuf)); -if(_DEBUG_)printf("rbuf[0]=%02x rbuf[1]=%02x rbuf[2]=%02x\n", rbuf[0], rbuf[1], rbuf[2]); - //return((rbuf[1]<<8)+rbuf[2]); - return((rbuf[1]<<4) + (rbuf[2]>>4)); -} - -void xptGetxy(int chipSelect, int *xp, int *yp){ - bcm2835_spi_begin(); - - bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); - bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_1024); - //bcm2835_spi_chipSelect(BCM2835_SPI_CS1); - bcm2835_spi_chipSelect(chipSelect); - //bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW); - bcm2835_spi_setChipSelectPolarity(chipSelect, LOW); - -#if 0 - *xp = xptGetit(XPT_START | XPT_XPOS); - *yp = xptGetit(XPT_START | XPT_YPOS); -#endif - *xp = xptGetit(XPT_START | XPT_XPOS | XPT_SER); - *yp = xptGetit(XPT_START | XPT_YPOS | XPT_SER); - - bcm2835_spi_end(); -} - - -void xptInit(TouchInfo *hoge){ - hoge->tpc = 0; - hoge->tpx = MAXTP; - hoge->lsec = 0; - hoge->lusec = 0; -} - -void xptDump(TouchInfo *hoge){ - int i; - if (_DEBUG_ == 0) return; - printf("tpc=%d\n",hoge->tpc); - printf("tpx=%d\n",hoge->tpx); - for(i=0;itpc;i++) { - printf("x1[%02d]=%d",i,hoge->tps[i].x1); - printf(" x2[%02d]=%d",i,hoge->tps[i].x2); - printf(" y1[%02d]=%d",i,hoge->tps[i].y1); - printf(" y2[%02d]=%d",i,hoge->tps[i].y2); - printf(" id[%02d]=%d\n",i,hoge->tps[i].id); - } -} - -void xptSetPoint(TouchInfo *hoge,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t id){ - if (hoge->tpc == hoge->tpx) return; - int index = hoge->tpc; - if (x1 > x2) { - hoge->tps[index].x1 = x2; - hoge->tps[index].x2 = x1; - } else { - hoge->tps[index].x1 = x1; - hoge->tps[index].x2 = x2; - } - if (y1 > y2) { - hoge->tps[index].y1 = y2; - hoge->tps[index].y2 = y1; - } else { - hoge->tps[index].y1 = y1; - hoge->tps[index].y2 = y2; - } - hoge->tps[index].id = id; - hoge->tpc++; -} - -#define DTMAX 800000 // 800m sec - -int xptGetPoint(uint8_t chipSelect, TouchInfo *hoge) { - int i; - struct timeval myTime; - //struct tm *time_st; - suseconds_t dt; - - float _xd = hoge->_max_xp - hoge->_min_xp; - float _yd = hoge->_max_yp - hoge->_min_yp; - float _xs = hoge->_max_xc - hoge->_min_xc; - float _ys = hoge->_max_yc - hoge->_min_yc; - - int _xp; - int _yp; - xptGetxy(chipSelect, &_xp, &_yp); -if(_DEBUG_)printf("touch !! _xp=%5d hoge->_min_xp=%5d hoge->_max_xp=%5d\n", _xp, hoge->_min_xp, hoge->_max_xp); -if(_DEBUG_)printf("touch !! _yp=%5d hoge->_min_yp=%5d hoge->_max_yp=%5d\n", _yp, hoge->_min_yp, hoge->_max_yp); - if (_xp < hoge->_min_xp && _xp > hoge->_max_xp) return -1; - if (_yp < hoge->_min_yp && _yp > hoge->_max_yp) return -1; - int _xpos = ( (float)(_xp - hoge->_min_xp) / _xd * _xs ) + hoge->_min_xc; - int _ypos = ( (float)(_yp - hoge->_min_yp) / _yd * _ys ) + hoge->_min_yc; - - // Disable double touch - gettimeofday(&myTime, NULL); - //time_st = localtime(&myTime.tv_sec); - localtime(&myTime.tv_sec); - if (myTime.tv_sec == hoge->lsec) { - dt = myTime.tv_usec - hoge->lusec; - if (dt < DTMAX) return -1; - } - - // Check range - for(i=0;itpc;i++) { - if(_DEBUG_) { - printf("x1[%02d]=%d",i,hoge->tps[i].x1); - printf(" x2[%02d]=%d",i,hoge->tps[i].x2); - printf(" y1[%02d]=%d",i,hoge->tps[i].y1); - printf(" y2[%02d]=%d",i,hoge->tps[i].y2); - printf(" id[%02d]=%d\n",i,hoge->tps[i].id); - } - if (_xpos > hoge->tps[i].x1 && _xpos < hoge->tps[i].x2) { - if (_ypos > hoge->tps[i].y1 && _ypos < hoge->tps[i].y2) { - gettimeofday(&myTime, NULL); - //time_st = localtime(&myTime.tv_sec); - localtime(&myTime.tv_sec); - hoge->lsec = myTime.tv_sec; - hoge->lusec = myTime.tv_usec; - return hoge->tps[i].id; - } - } - } - return -1; -} diff --git a/rootfs/usr/share/d3m0n/src/lib/xpt2046.h b/rootfs/usr/share/d3m0n/src/lib/xpt2046.h deleted file mode 100644 index 3a9b08b9..00000000 --- a/rootfs/usr/share/d3m0n/src/lib/xpt2046.h +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -typedef struct { - uint32_t x1; - uint32_t x2; - uint32_t y1; - uint32_t y2; - uint32_t id; -} TouchPoint; - -#define MAXTP 20 - -typedef struct { - int _cs; - uint16_t tpc; - uint16_t tpx; - time_t lsec; - suseconds_t lusec; - TouchPoint tps[MAXTP]; - bool _calibration; - int16_t _min_xp; // Minimum xp calibration - int16_t _min_yp; // Minimum yp calibration - int16_t _max_xp; // Maximum xp calibration - int16_t _max_yp; // Maximum yp calibration - int16_t _min_xc; // Minimum x coordinate - int16_t _min_yc; // Minimum y coordinate - int16_t _max_xc; // Maximum x coordinate - int16_t _max_yc; // Maximum y coordinate -} TouchInfo; - -int xptGetit(int cmd); -void xptGetxy(int chipSelect, int *xp, int *yp); -void xptInit(TouchInfo *hoge); -void xptDump(TouchInfo *hoge); -void xptSetPoint(TouchInfo *hoge,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t id); -int xptGetPoint(uint8_t chipSelect, TouchInfo *hoge); diff --git a/rootfs/usr/share/d3m0n/src/settings.cpp b/rootfs/usr/share/d3m0n/src/settings.cpp deleted file mode 100644 index 40262fcf..00000000 --- a/rootfs/usr/share/d3m0n/src/settings.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include -#include -#include "settings.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -string remove_space(string input) { - input.erase(remove(input.begin(), input.end(), ' '), input.end()); - input.erase(remove(input.begin(), input.end(), ' '), input.end()); - return input; -} -string splitintwo(const string& str, char delimiter, bool beforeDelimiter = true) { - size_t pos = str.find(delimiter); - if (pos != string::npos) { - if (beforeDelimiter) { - return str.substr(0, pos); - } else { - return str.substr(pos + 1); - } - } - return str; // Return an empty string if delimiter is not found -} - -char* delete_crlf(const char* input) { - size_t input_length = strlen(input); - char* result = (char*)malloc(input_length + 1); // Allocate memory for the result - if (result == NULL) { - return NULL; // Memory allocation failed - } - - size_t j = 0; // Index for the result buffer - for (size_t i = 0; i < input_length; ++i) { - // Look for "\r\n" and skip them - if (input[i] == '\r' && i + 1 < input_length && input[i + 1] == '\n') { - ++i; // Skip the '\n' too - continue; - } - - // Copy character to the result buffer - result[j++] = input[i]; - } - result[j] = '\0'; // Null-terminate the result string - - return result; -} -string trim(const string& str) { - // Find the first non-space character - size_t start = str.find_first_not_of(" \t\n\r"); - - // If the string is all spaces, return an empty string - if (start == string::npos) return ""; - - // Find the last non-space character - size_t end = str.find_last_not_of(" \t\n\r"); - - // Return the trimmed substring - return str.substr(start, end - start + 1); -} - -char* getSetting(char* name, char* path) -{ - char* output="not found"; - - ifstream file(path); // Open the file - if (!file.is_open()) { - printf("Can't open settings file\n"); - return "not found"; - } - - string line; - string name2; - while (getline(file, line)) { - name2=delete_crlf(splitintwo(line, ':', true).c_str()); // Get setting name - if(remove_space(name2) == (string)name) - { - name2=splitintwo(line, ':', false); - name2=trim(name2); - output=delete_crlf(name2.c_str()); // Get setting value - } - } - - file.close(); // Close the file - return output; -} - -void writeSetting(char* name, char* value, char* path) -{ - FILE* fptr; - - fptr = fopen(path,"w"); - - if(fptr == NULL) - { - printf("[x] Error writting SettingsFile: doesn't exist\n"); - exit(1); - } - - fprintf(fptr,"name2: custom_value"); - fclose(fptr); -} \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/settings.h b/rootfs/usr/share/d3m0n/src/settings.h deleted file mode 100644 index 45d6f251..00000000 --- a/rootfs/usr/share/d3m0n/src/settings.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SETTINGSFILEHANDLER_H -#define SETTINGSFILEHANDLER_H - -char* getSetting(char* name, char* path); -void writeSetting(char* name, char* value, char* path); - -#endif \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/test/build.sh b/rootfs/usr/share/d3m0n/src/test/build.sh deleted file mode 100644 index 9b826eb8..00000000 --- a/rootfs/usr/share/d3m0n/src/test/build.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - - -TEMP=$(pwd) -CURRENT_DIR=$(basename $TEMP) - -echo -e "\e[32m █████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗ - ██╔══██╗██╔══██╗██╔══██╗ ██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗ - ███████║██████╔╝██████╔╝ ██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝ - ██╔══██║██╔═══╝ ██╔═══╝ ██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗ - ██║ ██║██║ ██║ ██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║ - ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝" -echo -e " \e[35md3m0n application builder\e[0m" - -echo -e "\e[33m -Current path: ${CURRENT_DIR}\e[0m" - - -cd source -zip -r ${CURRENT_DIR}.d3m0n * - -cd .. - -cp -rf source/${CURRENT_DIR}.d3m0n ./ -rm -rf source/${CURRENT_DIR}.d3m0n \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/test/com.4re5.d3m0n.test.colors.d3m0n b/rootfs/usr/share/d3m0n/src/test/com.4re5.d3m0n.test.colors.d3m0n deleted file mode 100644 index 43344559..00000000 Binary files a/rootfs/usr/share/d3m0n/src/test/com.4re5.d3m0n.test.colors.d3m0n and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/test/source/app b/rootfs/usr/share/d3m0n/src/test/source/app deleted file mode 100644 index d428fa30..00000000 --- a/rootfs/usr/share/d3m0n/src/test/source/app +++ /dev/null @@ -1,6 +0,0 @@ -name: RADIO MODULE -package: com.4re5.d3m0n.main.radio -icon: radio -perms: none -start_path: /path/to -category: main \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/test/source/layouts/main.layout b/rootfs/usr/share/d3m0n/src/test/source/layouts/main.layout deleted file mode 100644 index 4dc9f811..00000000 --- a/rootfs/usr/share/d3m0n/src/test/source/layouts/main.layout +++ /dev/null @@ -1,27 +0,0 @@ -# d3m0n layout - -Window: - width="100%"; - height="100%"; - name="RADIO MODULE"; - bg_color="white"; - topbar="true"; - -# bug rect white => cause maybe color conv text to color=>utils - -Text: - location="bottom"; - margin_top="100"; - name="text1"; - font_size="16"; - content="RADIO MODULE"; - color="orange"; - -Image: - name="image1"; - src="radio"; - width="90"; - height="90"; - location="top"; - margin_top="10"; - diff --git a/rootfs/usr/share/d3m0n/src/test/source/src/main.src b/rootfs/usr/share/d3m0n/src/test/source/src/main.src deleted file mode 100644 index ba14dee9..00000000 --- a/rootfs/usr/share/d3m0n/src/test/source/src/main.src +++ /dev/null @@ -1,4 +0,0 @@ -# d3m0n source - -Window.OnCreate => - logn([o] RADIO MODULE, lime); \ No newline at end of file diff --git a/rootfs/usr/share/d3m0n/src/test/test.d3m0n b/rootfs/usr/share/d3m0n/src/test/test.d3m0n deleted file mode 100644 index 41b61657..00000000 Binary files a/rootfs/usr/share/d3m0n/src/test/test.d3m0n and /dev/null differ diff --git a/rootfs/usr/share/d3m0n/src/utils.h b/rootfs/usr/share/d3m0n/src/utils.h deleted file mode 100644 index 9884dda5..00000000 --- a/rootfs/usr/share/d3m0n/src/utils.h +++ /dev/null @@ -1,516 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace std; - -// def vars -int SCREEN_WIDTH=240; -int SCREEN_HEIGHT=320; -// debug window name -string window_name = "d3m0n emulator"; - -// debug -#define DEBUG 1 - -bool isTestingMode() { - #ifdef TESTING - return true; - #endif - return false; -} - -bool isDebugMode() { - #ifdef DEBUG - return true; - #endif - return false; -} -string bashColor(int color) { - return "\033[38;5;"+to_string(color)+"m"; -} -void RGB565toRGB(uint16_t rgb565, uint8_t& r, uint8_t& g, uint8_t& b) { - // Extract red, green, and blue components from RGB565 - r = (rgb565 >> 8) & 0xF8; // 5 bits for red - g = (rgb565 >> 3) & 0xFC; // 6 bits for green - b = (rgb565 << 3) & 0xF8; // 5 bits for blue - - // Scale components to 8-bit range (0-255) - // r >>= 3; // Scale 5-bit value to 8-bit range - // g >>= 2; // Scale 6-bit value to 8-bit range - // b >>= 3; // Scale 5-bit value to 8-bit range - - -} -uint16_t RGBtoRGB565(uint8_t r, uint8_t g, uint8_t b) { - return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); -} -bool isNumber(const string& str) { - istringstream iss(str); - double value; - iss >> noskipws >> value; // Skip white spaces and attempt to read a double - - // Check if the entire string was consumed and if the stream is in a good state - return iss.eof() && !iss.fail(); -} -namespace Colors { - // colors used are the sames as those in shell - ushort Red = RGBtoRGB565(255, 0, 0); - ushort DarkRed = RGBtoRGB565(139, 0, 0); - ushort Orange = RGBtoRGB565(255, 165, 0); - ushort DarkOrange = RGBtoRGB565(255, 140, 0); - ushort DarkYellow = RGBtoRGB565(255, 215, 0); - ushort Yellow = RGBtoRGB565(255, 255, 0); - ushort DarkGreen = RGBtoRGB565(0, 100, 0); - ushort Green = RGBtoRGB565(0, 128, 0); - ushort DarkBlue = RGBtoRGB565(0, 0, 139); - ushort Blue = RGBtoRGB565(0, 0, 255); - ushort Cyan = RGBtoRGB565(0, 255, 255); - ushort DarkCyan = RGBtoRGB565(0, 139, 139); - ushort DarkMagenta = RGBtoRGB565(139, 0, 139); - ushort Magenta = RGBtoRGB565(255, 0, 255); - ushort DarkGrey = RGBtoRGB565(169, 169, 169); - ushort Grey = RGBtoRGB565(128, 128, 128); - ushort White = RGBtoRGB565(255, 255, 255); - ushort Reset = RGBtoRGB565(204, 204, 204); - ushort Black = RGBtoRGB565(0, 0, 0); -}; -ushort GetColor(string color) -{ - try { - unsigned long ulongValue = stoul(color); - - if (ulongValue > numeric_limits::max()) { - throw out_of_range("Value exceeds range of unsigned short"); - } - - return static_cast(ulongValue); - } catch (const exception& e) { - if (color == "black") return Colors::Black; - if (color == "dark_grey") return Colors::DarkGrey; - if (color == "grey") return Colors::Grey; - if (color == "white") return Colors::White; - if (color == "reset") return Colors::Reset; - if (color == "red") return Colors::Red; - if (color == "dark_red") return Colors::DarkRed; - if (color == "orange") return Colors::Orange; - if (color == "dark_orange") return Colors::DarkOrange; - if (color == "dark_yellow") return Colors::DarkYellow; - if (color == "yellow") return Colors::Yellow; - if (color == "dark_green") return Colors::DarkGreen; - if (color == "green") return Colors::Green; - if (color == "dark_blue") return Colors::DarkBlue; - if (color == "blue") return Colors::Blue; - if (color == "dark_cyan") return Colors::DarkCyan; - if (color == "cyan") return Colors::Cyan; - if (color == "dark_magenta") return Colors::DarkMagenta; - if (color == "magenta") return Colors::Magenta; - } - return Colors::Red; // default is red. -} - -void replaceAll(string& str, const string& from, const string& to) { - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', advance start_pos to avoid infinite loop - } -} - -bool startsWith(const string& str, const string& prefix) { - return str.compare(0, prefix.size(), prefix) == 0; -} -bool endsWith(const string& str, const string& suffix) { - if (str.length() < suffix.length()) { - return false; - } - return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; -} - -bool contains(const string& str, const string& substr) { - return str.find(substr) != string::npos; -} -string Split(const string& str, char delimiter, bool beforeDelimiter = true) { - size_t pos = str.find(delimiter); - if (pos != string::npos) { - if (beforeDelimiter) { - return str.substr(0, pos); - } else { - return str.substr(pos + 1); - } - } - return str; // Return an empty string if delimiter is not found -} -string delete_space(string input) { - input.erase(remove(input.begin(), input.end(), ' '), input.end()); - input.erase(remove(input.begin(), input.end(), ' '), input.end()); - return input; -} - -namespace ConsoleColor { - const string Reset = "\e[0m"; - const string Black = "\e[0;30m"; - const string Red = "\e[1;31m"; - const string Green = "\e[1;32m"; - const string Yellow = "\e[1;33m"; - const string Blue = "\e[1;34m"; - const string Magenta = "\e[1;35m"; - const string Cyan = "\e[1;36m"; - const string White = "\e[1;37m"; - const string Orange = "\e[38;5;208m"; - const string DarkRed = "\e[0;31m"; - const string DarkOrange = "\e[1;38;5;208m"; - const string DarkYellow = "\e[0;33m"; - const string DarkGreen = "\e[0;32m"; - const string DarkBlue = "\e[0;34m"; - const string DarkCyan = "\e[0;36m"; - const string DarkMagenta = "\e[0;35m"; - const string DarkGrey = "\e[1;30m"; - const string Grey = "\e[0;30m"; - - static string get(string color) { - color = delete_space(color); - if(color == "black") return Black; - if(color == "orange") return Orange; - if(color == "reset") return Reset; - if(color == "red") return Red; - if(color == "green") return Green; - if(color == "yellow") return Yellow; - if(color == "blue") return Blue; - if(color == "white") return White; - if(color == "dark_red") return DarkRed; - if(color == "dark_orange") return DarkOrange; - if(color == "dark_yellow") return DarkYellow; - if(color == "dark_green") return DarkGreen; - if(color == "dark_blue") return DarkBlue; - if(color == "dark_cyan") return DarkCyan; - if(color == "cyan") return Cyan; - if(color == "dark_magenta") return DarkMagenta; - if(color == "magenta") return Magenta; - if(color == "dark_grey") return DarkGrey; - if(color == "grey") return Grey; - return Reset; - } -} - -struct Application -{ - string name; - string description; - string package; - string icon; - string perms; - string start_path; - string category; - string temp_path; - vector windows; - DataTypes::Window* mainWindow; -}; - - -namespace LogStatus { - const int Success = 0; - const int Loading = 1; - const int Info = 2; - const int Warning = 3; - const int Error = -1; - const int Critical = -99; -} - -bool readAllBytes(const string& filePath, vector& data) { - // Open the file in binary mode - ifstream file(filePath, ios::binary | ios::ate); - if (!file.is_open()) { - cerr << "Failed to open file: " << filePath << endl; - return false; - } - - // Get the size of the file - streamsize fileSize = file.tellg(); - if (fileSize < 0) { - cerr << "Failed to get file size." << endl; - return false; - } - - // Resize the vector to hold all bytes - data.resize(fileSize); - - // Seek back to the beginning of the file - file.seekg(0, ios::beg); - if (file.fail()) { - cerr << "Failed to seek to beginning of file." << endl; - return false; - } - - // Read the entire file into the vector - file.read(reinterpret_cast(data.data()), fileSize); - if (file.fail()) { - cerr << "Failed to read data from file." << endl; - return false; - } - - // Close the file - file.close(); - return true; -} - -string logn(string text, string color) -{ - printf((color+text+ConsoleColor::Reset+(string)"\n").c_str()); - return(color+text+ConsoleColor::Reset+(string)"\n"); -} - -string log(string text, int status) -{ - switch (status) - { - case LogStatus::Success: - return logn((string)"[o] "+text, ConsoleColor::Green); - break; - case LogStatus::Loading: - return logn((string)"[~] "+text, ConsoleColor::Yellow); - break; - case LogStatus::Info: - return logn((string)"[^] "+text, ConsoleColor::Magenta); - break; - case LogStatus::Warning: - return logn((string)"[*] "+text, ConsoleColor::Cyan); - break; - case LogStatus::Error: - return logn((string)"[x] "+text, ConsoleColor::Red); - break; - case LogStatus::Critical: - string tmp=""; - int totalLen = 100; - size_t length = (size_t)totalLen-((string)"║ "+text).length(); - - string bar=""; - for (int i = 0; i < totalLen-2; i++) { - bar+="═"; - } - tmp+=logn("╔"+bar+"╗", ConsoleColor::Red); - - - string spaces(length, ' '); - tmp+=logn((string)"║ "+text+spaces+(string)" ║", ConsoleColor::Red); - return tmp+logn((string)"╚"+bar+"╝", ConsoleColor::Red); - break; - } - return ""; -} -string exec(const char* cmd) { - array buffer; - string result; - unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - throw runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; -} -string Trim(string str) { - str.erase(remove(str.begin(), str.end(), '\n'), str.cend()); - str.erase(remove(str.begin(), str.end(), '\r'), str.cend()); - return str; -} - -string removeUnwantedChars(string input) { - // Define regular expression pattern to match unwanted characters - // regex pattern("[^a-zA-Z0-9[:space:][:punct:]]"); // Matches any character that is not a letter, number, space, or punctuation - - string::size_type i = 0; - while (i < input.length()) { - i = input.find('\n', i); - if (i == string::npos) { - break; - } - input.erase(i); - } - return input; - - // Replace unwanted characters with an empty string - // return regex_replace(input, pattern2, ""); - // return regex_replace(input, pattern, ""); -} - -string GetAppPath() { - // added these lines for testing purpose - #ifdef TESTING - return "/home/d3m0n/d3m0n-testing-applications"; - #endif // TESTING - #ifdef DEBUG - return "/home/kali/d3m0n_os_debian/rootfs/usr/share/applications"; - #endif // DEBUG - return "/usr/share/applications"; -} - - -string GetPath() { - // added these lines for testing purpose - #ifdef TESTING - return "/home/d3m0n/d3m0n-testing"; - #endif // TESTING - #ifdef DEBUG - return "/home/kali/d3m0n_os_debian/rootfs/usr/share/d3m0n"; - #endif // DEBUG - return "/usr/share/d3m0n"; -} - -char* GetConfig() { - // added these lines for testing purpose - #ifdef TESTING - return "/home/d3m0n/d3m0n-testing/config"; - #endif // TESTING - - #ifdef DEBUG - return "/home/kali/d3m0n_os_debian/rootfs/usr/share/d3m0n/config"; - #endif // DEBUG - return "/usr/share/d3m0n/config"; -} - -string Split(string s, string delimiter) { - return s.substr(0, s.find(delimiter)); -} - -void removeQuotes(string& str) { - // Check if the string is empty or its length is less than 2 - if (str.empty() || str.length() < 2) { - return; - } - - // Check if the first and last characters are double quotes - if (str.front() == '"' && str.back() == '"') { - // Erase the first and last characters - str.erase(0, 1); // Erase first character - str.pop_back(); // Erase last character - } -} -void deleteLeadingSpaces(string& str) { - // Find the position of the first non-space character - size_t pos = str.find_first_not_of(" \t"); - - // Erase leading spaces - if (pos != string::npos) { - str = str.substr(pos); - } else { - // If string contains only spaces, make it empty - str.clear(); - } -} -string printInfos() { - string to_return=""; - // displays system infos - to_return+=logn("d3m0n OS - system informations", ConsoleColor::Cyan); - to_return+=logn("# CREDITS", ConsoleColor::DarkCyan); - to_return+=logn(" 4re5 group - 2024 @ all rights reserved", ConsoleColor::Cyan); - to_return+="\n"; - to_return+=logn("# DEBUG DATA", ConsoleColor::DarkCyan); - to_return+=logn(" DEBUG ==> '"+(string)(isDebugMode()?"true":"false")+"'", ConsoleColor::Cyan); - to_return+=logn(" TESTING ==> '"+(string)(isTestingMode()?"true":"false")+"'", ConsoleColor::Cyan); - to_return+=logn(" d3m0n path ==> '"+(string)GetPath()+"'", ConsoleColor::Cyan); - to_return+=logn(" d3m0n config path ==> '"+(string)GetConfig()+"'", ConsoleColor::Cyan); - to_return+="\n"; - to_return+=logn("# ONLINE RESSOURCES", ConsoleColor::DarkCyan); - to_return+=logn(" github repository ==> 'https://github.com/d3m0n-project/d3m0n_os'", ConsoleColor::Cyan); - to_return+=logn(" shell documentaion ==> 'https://github.com/d3m0n-project/d3m0n_os/tree/main/rootfs/usr/share/d3m0n/documentation/shell'", ConsoleColor::Cyan); - to_return+=logn(" api documentaion ==> 'https://github.com/d3m0n-project/d3m0n_os/blob/main/rootfs/usr/share/d3m0n/documentation/api.md'", ConsoleColor::Cyan); - to_return+=logn(" forum ==> 'https://forum.ducksploit.com'", ConsoleColor::Cyan); - to_return+=logn(" discord server ==> 'https://discord.com/invite/sTVWespH4M'", ConsoleColor::Cyan); - - - return to_return; -} -u16string to_u16string(const string& str) { - wstring_convert, char16_t> converter; - return converter.from_bytes(str); -} -string bashGradient(int baseColor, string text) { - int i = baseColor; - int a = 1; - string to_return; - - wstring_convert, char32_t> convert; - u32string ustr = convert.from_bytes(text); - - // iterate over each character in the UTF-32 string - for (char32_t c : ustr) { - string s = convert.to_bytes(&c, &c + 1); - string color_code = "\033[38;5;" + to_string(i) + "m"; - to_return += color_code + s; - - if (i == baseColor) { - a = 1; - } - if (i >= baseColor + 5) { - a = -1; - } - i = i + (1 * a); - } - - - return to_return + "\033[0m"; // Reset color at the end of the string -} -vector stringToUtf8(const string& str) { - vector utf8Bytes; - for (char c : str) { - if ((c & 0x80) == 0) { - // ASCII character (0xxxxxxx) - utf8Bytes.push_back(c); - } else if ((c & 0xE0) == 0xC0) { - // 2-byte UTF-8 character (110xxxxx 10xxxxxx) - utf8Bytes.push_back(0xC0 | ((c >> 6) & 0x1F)); - utf8Bytes.push_back(0x80 | (c & 0x3F)); - } else if ((c & 0xF0) == 0xE0) { - // 3-byte UTF-8 character (1110xxxx 10xxxxxx 10xxxxxx) - utf8Bytes.push_back(0xE0 | ((c >> 12) & 0x0F)); - utf8Bytes.push_back(0x80 | ((c >> 6) & 0x3F)); - utf8Bytes.push_back(0x80 | (c & 0x3F)); - } else if ((c & 0xF8) == 0xF0) { - // 4-byte UTF-8 character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx) - utf8Bytes.push_back(0xF0 | ((c >> 18) & 0x07)); - utf8Bytes.push_back(0x80 | ((c >> 12) & 0x3F)); - utf8Bytes.push_back(0x80 | ((c >> 6) & 0x3F)); - utf8Bytes.push_back(0x80 | (c & 0x3F)); - } - } - return utf8Bytes; -} - -class Event -{ - public: - struct Listener { - DataTypes::Rect rect; - std::function callback; - short type; - Application* app; - }; - - static const short OnClick=0; - static const short OnLongClick=1; - static const short OnTouch=2; - static const short OnRelease=3; - static const short OnMove=4; - static const short OnScroll=5; -}; - -#endif // !UTILS_H \ No newline at end of file