diff --git a/Makefile b/Makefile index 70b0024..9af5e2b 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ MAKEFLAGS += --no-print-directory #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lfat -liosuhax -lxml2 +LIBS := -lfat -liosuhax -lfreetype -lpng -lz -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/README.md b/README.md index e3c0069..5d4c2e9 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,19 @@ -# savemii +# savemii (Original by Ryuzaki-MrL, modded by GabyPCgeeK) WiiU/vWii Save Manager -**You need to run iosuhax/mocha cfw first in order for this homebrew to work.** +**You need to run haxchi/iosuhax/mocha cfw first in order for this homebrew to work.** + +**Got it working with CBHC but not extensively tested. Not tested in normal haxchi.** This homebrew allows you to backup your Wii U and vWii savegames to the SD card and also restore them. Up to 256 backups can be made per title. Backups are stored in sd:/wiiu/backups. +For sorting Titles press R to change sorting method and press L to change between descending and ascending. + Use it at your own risk and please report any issues that may occur. -Known issues: -- some games exhibit unexpected behaviour when the savefile is restored +**Needs freetype-2.8 library for compiling.** TODO: - installable package @@ -19,4 +22,4 @@ Credits: - Bruno Vinicius, for the icon - dimok, for libiosuhax and libfat for Wii U - rw-r-r-0644, for lib_easy -- dimok again, because he's awesome :3 \ No newline at end of file +- dimok again, because he's awesome :3 diff --git a/TGAReader_LICENSE b/TGAReader_LICENSE new file mode 100644 index 0000000..aa9072e --- /dev/null +++ b/TGAReader_LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Kenji Sasaki + +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. + diff --git a/libxml2/lib/libxml2.a b/libxml2/lib/libxml2.a index ec8a1cd..ccd0595 100644 Binary files a/libxml2/lib/libxml2.a and b/libxml2/lib/libxml2.a differ diff --git a/meta/meta.xml b/meta/meta.xml index 0299611..2d552ab 100644 --- a/meta/meta.xml +++ b/meta/meta.xml @@ -1,15 +1,15 @@ - SaveMii - Ryuzaki_MrL - 1.2.0 - 20170404000000 + SaveMii Mod + Ryuzaki_MrL original (GabyPCgeeK mod) + 1.2.0.mod5 + 20170812000000 WiiU/vWii Save Manager WiiU/vWii Save Manager -You need to run iosuhax/mocha cfw first in order for this homebrew to work. +You need to run haxchi/iosuhax/mocha cfw first in order for this homebrew to work. -This homebrew allows you to backup your Wii U and vWii savegames to the SD card and also restore them. Up to 256 backups can be made per title. Backups are stored in sd:/wiiu/backups. +This homebrew allows you to backup your Wii U and vWii savegames to the SD card and also restore them. Can also copy saves from NAND<->USB if title is installed to both. Up to 256 backups can be made per title. Backups are stored in sd:/wiiu/backups. tool -https://github.com/Ryuzaki-MrL/savemii/releases - \ No newline at end of file +https://github.com/GabyPCgeeK/savemii/releases + diff --git a/src/common/fs_defs.h b/src/common/fs_defs.h index feda725..37feb3f 100644 --- a/src/common/fs_defs.h +++ b/src/common/fs_defs.h @@ -26,7 +26,6 @@ extern "C" { #define FS_SOURCETYPE_EXTERNAL 0 #define FS_SOURCETYPE_HFIO 1 -#define FS_SOURCETYPE_HFIO 1 #define FS_MOUNT_SOURCE_SIZE 0x300 #define FS_CLIENT_SIZE 0x1700 diff --git a/src/draw.c b/src/draw.c new file mode 100644 index 0000000..a353517 --- /dev/null +++ b/src/draw.c @@ -0,0 +1,519 @@ +#include "draw.h" + +unsigned char *scrBuffer; +int scr_buf0_size = 0; +int scr_buf1_size = 0; +bool cur_buf1; + +u8 *ttfFont; +RGBAColor fcolor = {0xFFFFFFFF}; +FT_Library library; +FT_Face face; + +void initDraw(char* buf, int size0, int size1) { + scrBuffer = buf; + scr_buf0_size = size0; + scr_buf1_size = size1; + + clearBuffers(); + uint32_t *screen2 = scrBuffer + scr_buf0_size; + OSScreenPutPixelEx(1, 0, 0, 0xABCDEFFF); + + if (screen2[0] == 0xABCDEFFF) cur_buf1 = false; + else cur_buf1 = true; +} + +void flipBuffers() { + //Flush the cache + DCFlushRange(scrBuffer + scr_buf0_size, scr_buf1_size); + DCFlushRange(scrBuffer, scr_buf0_size); + //Flip the buffer + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + cur_buf1 = !cur_buf1; +} + +void clearBuffers() { + for(int i = 0; i < 2; i++) { + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + flipBuffers(); + } +} + +void drawString(int x, int line, char* string) { + OSScreenPutFontEx(0, x, line, string); + OSScreenPutFontEx(1, x, line, string); +} + +void fillScreen(u8 r, u8 g, u8 b, u8 a) { + RGBAColor color; + color.r = r; color.g = g; color.b = b; color.a = a; + //uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; + OSScreenClearBufferEx(0, color.c); + OSScreenClearBufferEx(1, color.c); +} + +void drawPixel32(int x, int y, RGBAColor color) { + drawPixel(x, y, color.r, color.g, color.b, color.a); +} + +void drawPixel(int x, int y, u8 r, u8 g, u8 b, u8 a) { + /*uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; + OSScreenPutPixelEx(0, x, y, num); + OSScreenPutPixelEx(1, x, y, num);*/ + + int width = 1280; //height = 1024 720? + char *screen = scrBuffer; + int otherBuff0 = scr_buf0_size / 2; + int otherBuff1 = scr_buf1_size / 2; + float opacity = a / 255.0; + + for (int yy = (y * 1.5); yy < ((y * 1.5) + 1); yy++) { + for (int xx = (x * 1.5); xx < ((x * 1.5) + 1); xx++) { + u32 v = (xx + yy * width) * 4; + if (cur_buf1) v += otherBuff0; + screen[v ] = r * opacity + (1 - opacity) * screen[v]; + screen[v + 1] = g * opacity + (1 - opacity) * screen[v + 1]; + screen[v + 2] = b * opacity + (1 - opacity) * screen[v + 2]; + screen[v + 3] = a; + } + } + /*u32 v = (x + y * width) * 4; + if (cur_buf1) v += otherBuff0; + screen[v ] = r * opacity + (1 - opacity) * screen[v]; + screen[v + 1] = g * opacity + (1 - opacity) * screen[v + 1]; + screen[v + 2] = b * opacity + (1 - opacity) * screen[v + 2]; + screen[v + 3] = a;*/ + + width = 896; //height = 480; + char *screen2 = scrBuffer + scr_buf0_size; + u32 v = (x + y * width) * 4; + if (cur_buf1) v += otherBuff1; + screen2[v ] = r * opacity + (1 - opacity) * screen2[v]; + screen2[v + 1] = g * opacity + (1 - opacity) * screen2[v + 1]; + screen2[v + 2] = b * opacity + (1 - opacity) * screen2[v + 2]; + screen2[v + 3] = a; +} + +void drawLine(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a) { + + int x, y; + if (x1 == x2){ + if (y1 < y2) for (y = y1; y <= y2; y++) drawPixel(x1, y, r, g, b, a); + else for (y = y2; y <= y1; y++) drawPixel(x1, y, r, g, b, a); + } + else { + if (x1 < x2) for (x = x1; x <= x2; x++) drawPixel(x, y1, r, g, b, a); + else for (x = x2; x <= x1; x++) drawPixel(x, y1, r, g, b, a); + } +} + +void drawRect(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a) { + drawLine(x1, y1, x2, y1, r, g, b, a); + drawLine(x2, y1, x2, y2, r, g, b, a); + drawLine(x1, y2, x2, y2, r, g, b, a); + drawLine(x1, y1, x1, y2, r, g, b, a); +} + +void drawFillRect(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a) { + int X1, X2, Y1, Y2, i, j; + + if (x1 < x2){ + X1 = x1; + X2 = x2; + } + else { + X1 = x2; + X2 = x1; + } + + if (y1 < y2){ + Y1 = y1; + Y2 = y2; + } + else { + Y1 = y2; + Y2 = y1; + } + for (i = X1; i <= X2; i++){ + for (j = Y1; j <= Y2; j++){ + drawPixel(i, j, r, g, b, a); + } + } +} + +void drawCircle(int xCen, int yCen, int radius, u8 r, u8 g, u8 b, u8 a) { + int x = 0; + int y = radius; + int p = (5 - radius * 4) / 4; + drawCircleCircum(xCen, yCen, x, y, r, g, b, a); + while (x < y){ + x++; + if (p < 0){ + p += 2 * x + 1; + } + else{ + y--; + p += 2 * (x - y) + 1; + } + drawCircleCircum(xCen, yCen, x, y, r, g, b, a); + } +} + +void drawFillCircle(int xCen, int yCen, int radius, u8 r, u8 g, u8 b, u8 a) { + drawCircle(xCen, yCen, radius, r, g, b, a); + int x, y; + for (y = -radius; y <= radius; y++){ + for (x = -radius; x <= radius; x++) + if (x*x + y*y <= radius*radius + radius * .8f) + drawPixel(xCen + x, yCen + y, r, g, b, a); + } +} + +void drawCircleCircum(int cx, int cy, int x, int y, u8 r, u8 g, u8 b, u8 a) { + + if (x == 0){ + drawPixel(cx, cy + y, r, g, b, a); + drawPixel(cx, cy - y, r, g, b, a); + drawPixel(cx + y, cy, r, g, b, a); + drawPixel(cx - y, cy, r, g, b, a); + } + if (x == y){ + drawPixel(cx + x, cy + y, r, g, b, a); + drawPixel(cx - x, cy + y, r, g, b, a); + drawPixel(cx + x, cy - y, r, g, b, a); + drawPixel(cx - x, cy - y, r, g, b, a); + } + if (x < y){ + drawPixel(cx + x, cy + y, r, g, b, a); + drawPixel(cx - x, cy + y, r, g, b, a); + drawPixel(cx + x, cy - y, r, g, b, a); + drawPixel(cx - x, cy - y, r, g, b, a); + drawPixel(cx + y, cy + x, r, g, b, a); + drawPixel(cx - y, cy + x, r, g, b, a); + drawPixel(cx + y, cy - x, r, g, b, a); + drawPixel(cx - y, cy - x, r, g, b, a); + } +} + +void drawPic(int x, int y, u32 w, u32 h, float scale, u32* pixels) { + u32 nw = w, nh = h; + RGBAColor color; + if (scale <= 0) scale = 1; + nw = w * scale; nh = h * scale; + + + for (u32 j = y; j < (y + nh); j++) { + for (u32 i = x; i < (x + nw); i++) { + color.c = pixels[((i - x) * w / nw) + ((j - y) * h / nh) * w]; + drawPixel32(i, j, color); + } + } +} + +void drawTGA(int x, int y, float scale, u8* fileContent) { + u32 w = tgaGetWidth(fileContent), h = tgaGetHeight(fileContent); + u32 nw = w, nh = h; + u32* out = tgaRead(fileContent, TGA_READER_RGBA); + + if (scale <= 0) scale = 1; + nw = w * scale; nh = h * scale; + + drawPic(x, y, w, h, scale, out); + if (scale > 0.5) { + if ((x > 0) && (y > 0)) drawRect(x - 1, y - 1, x + nw, y + nh, 255, 255, 255, 128); + if ((x > 1) && (y > 1)) drawRect(x - 2, y - 2, x + nw + 1, y + nh + 1, 255, 255, 255, 128); + if ((x > 2) && (y > 2)) drawRect(x - 3, y - 3, x + nw + 2, y + nh + 2, 255, 255, 255, 128); + } + free(out); +} + +void drawRGB5A3(int x, int y, float scale, u8* fileContent) { + u32 w = 192, h = 64, num = 0; + u32 nw = w, nh = h; + + if (scale <= 0) scale = 1; + nw = w * scale; nh = h * scale; + + u32 pos = 0, npos = 0; + RGBAColor color; + u16* pixels = (u16*)fileContent; + + u8 sum = (4 * scale); + for (u32 j = y; j < (y + nh); j += sum) { + for (u32 i = x; i < (x + nw); i += sum) { + for (u32 sj = j; sj < (j + sum); sj++, pos++) { + for (u32 si = i; si < (i + sum); si++) { + npos = ((si - i) / scale) + ((pos / scale) * 4); + if (pixels[npos] & 0x8000) + color.c = ((pixels[npos] & 0x7C00) << 17) | ((pixels[npos] & 0x3E0) << 14) | ((pixels[npos] & 0x1F) << 11) | 0xFF; + else + color.c = (((pixels[npos] & 0xF00) * 0x11) << 16) | (((pixels[npos] & 0xF0) * 0x11) << 12) | (((pixels[npos] & 0xF) * 0x11) << 8) | (((pixels[npos] & 0x7000) >> 12) * 0x24); + drawPixel32(si, sj, color); + } + } + } + } + if (scale > 0.5) { + if ((x > 0) && (y > 0)) drawRect(x - 1, y - 1, x + nw, y + nh, 255, 255, 255, 128); + if ((x > 1) && (y > 1)) drawRect(x - 2, y - 2, x + nw + 1, y + nh + 1, 255, 255, 255, 128); + if ((x > 2) && (y > 2)) drawRect(x - 3, y - 3, x + nw + 2, y + nh + 2, 255, 255, 255, 128); + } +} + +void drawBackgroundDRC(u32 w, u32 h, u8* out) { + uint32_t *screen2 = NULL; + int otherBuff1 = scr_buf1_size / 2; + + if (cur_buf1) screen2 = scrBuffer + scr_buf0_size + otherBuff1; + else screen2 = scrBuffer + scr_buf0_size; + memcpy(screen2, out, w * h * 4); +} + +void drawBackgroundTV(u32 w, u32 h, u8* out) { + uint32_t *screen1 = scrBuffer; + int otherBuff0 = scr_buf0_size / 2; + + if (cur_buf1) screen1 = scrBuffer + otherBuff0; + memcpy(screen1, out, w * h * 4); +} + +bool initFont(void* fontBuf, FT_Long fsize) { + FT_Long size = fsize; + if (fontBuf) { + ttfFont = fontBuf; + } else { + OSGetSharedData(2, 0, &ttfFont, &size); + } + + FT_Error error; + error = FT_Init_FreeType(&library); + if (error) return false; + + error = FT_New_Memory_Face(library, ttfFont, size, 0, &face); + if (error) return false; + + /*error = FT_Set_Char_Size(face, 8*64, 10*64, 158, 158); + if (error) return false;*/ + + error = FT_Set_Pixel_Sizes(face, 0, 22); //pixel width, height + if (error) return false; + + return true; +} + +void freeFont(void* fontBuf) { + FT_Done_Face(face); + FT_Done_FreeType(library); + //if (fontBuf) free(fontBuf); +} + +void draw_bitmap(FT_Bitmap* bitmap, FT_Int x, FT_Int y) { + FT_Int i, j, p, q; + FT_Int x_max; + FT_Int y_max = y + bitmap->rows; + + switch(bitmap->pixel_mode) { + case FT_PIXEL_MODE_GRAY: + x_max = x + bitmap->width; + for (i = x, p = 0; i < x_max; i++, p++) { + for (j = y, q = 0; j < y_max; j++, q++) { + if (i < 0 || j < 0 || i >= 854 || j >= 480) continue; + u8 col = bitmap->buffer[q * bitmap->pitch + p]; + if (col == 0) continue; + float opacity = col / 255.0; + /*u8 cr = fcolor.r * opacity + (1 - opacity) * 0; + u8 cg = fcolor.g * opacity + (1 - opacity) * 0; + u8 cb = fcolor.b * opacity + (1 - opacity) * 0; + drawPixel(i, j, cr, cg, cb, fcolor.a);*/ + drawPixel(i, j, fcolor.r, fcolor.g, fcolor.b, (u8)(fcolor.a * opacity)); + } + } + break; + case FT_PIXEL_MODE_LCD: + x_max = x + bitmap->width / 3; + for (i = x, p = 0; i < x_max; i++, p++) { + for (j = y, q = 0; j < y_max; j++, q++) { + if (i < 0 || j < 0 || i >= 854 || j >= 480) continue; + u8 cr = bitmap->buffer[q * bitmap->pitch + p * 3]; + u8 cg = bitmap->buffer[q * bitmap->pitch + p * 3 + 1]; + u8 cb = bitmap->buffer[q * bitmap->pitch + p * 3 + 2]; + + if ((cr | cg | cb) == 0) continue; + drawPixel(i, j, cr, cg, cb, 255); + } + } + break; + case FT_PIXEL_MODE_BGRA: + x_max = x + bitmap->width/2; + for (i = x, p = 0; i < x_max; i++, p++) { + for (j = y, q = 0; j < y_max; j++, q++) { + if (i < 0 || j < 0 || i >= 854 || j >= 480) continue; + u8 cb = bitmap->buffer[q * bitmap->pitch + p * 4]; + u8 cg = bitmap->buffer[q * bitmap->pitch + p * 4 + 1]; + u8 cr = bitmap->buffer[q * bitmap->pitch + p * 4 + 2]; + u8 ca = bitmap->buffer[q * bitmap->pitch + p * 4 + 3]; + + if ((cr | cg | cb) == 0) continue; + drawPixel(i, j, cr, cg, cb, ca); + } + } + break; + } +} + +bool ttfFontSize(u8 w, u8 h) { + FT_Error error; + + /*error = FT_Set_Char_Size(face, 8*64, 10*64, 158, 158); + if (error) return false;*/ + + error = FT_Set_Pixel_Sizes(face, w, h); //pixel width, height + if (error) return false; + return true; +} + +void ttfFontColor32(u32 color) { + fcolor.c = color; +} + +void ttfFontColor(u8 r, u8 g, u8 b, u8 a) { + RGBAColor color = {.r = r, .g = g, .b = b, .a = a}; + ttfFontColor32(color.c); +} + +int ttfPrintString(int x, int y, char *string, bool wWrap, bool ceroX) { + FT_GlyphSlot slot = face->glyph; + FT_Error error; + int pen_x = x, pen_y = y; + FT_UInt previous_glyph; + + while(*string) { + uint32_t buf = *string++; + int dy = 0; + + if ((buf >> 6) == 3) { + if ((buf & 0xF0) == 0xC0) { + uint8_t b1 = buf & 0xFF, b2 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + buf = ((b1 & 0xF) << 6) | b2; + } else if ((buf & 0xF0) == 0xD0) { + uint8_t b1 = buf & 0xFF, b2 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + buf = 0x400 | ((b1 & 0xF) << 6) | b2; + } else if ((buf & 0xF0) == 0xE0) { + uint8_t b1 = buf & 0xFF, b2 = *string++, b3 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + if ((b3 & 0xC0) == 0x80) b3 &= 0x3F; + buf = ((b1 & 0xF) << 12) | (b2 << 6) | b3; + } + } else if (buf & 0x80) { + string++; + continue; + } + + if (buf == '\n') { + pen_y += (face->size->metrics.height >> 6); + if (ceroX) pen_x = 0; + else pen_x = x; + continue; + } + + //error = FT_Load_Char(face, buf, FT_LOAD_RENDER); + + FT_UInt glyph_index; + glyph_index = FT_Get_Char_Index(face, buf); + + if (FT_HAS_KERNING(face)) { + FT_Vector vector; + FT_Get_Kerning(face, previous_glyph, glyph_index, FT_KERNING_DEFAULT, &vector); + pen_x += (vector.x >> 6); + dy = vector.y >> 6; + } + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);//FT_LOAD_COLOR);// + if (error) + continue; + + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);//FT_RENDER_MODE_LCD);// + if (error) + continue; + + if ((pen_x + (slot->advance.x >> 6)) > 853) { + if (wWrap) { + pen_y += (face->size->metrics.height >> 6); + if (ceroX) pen_x = 0; + else pen_x = x; + } else { + return pen_x; + } + } + + draw_bitmap(&slot->bitmap, pen_x + slot->bitmap_left, (face->height >> 6) + pen_y - slot->bitmap_top); + + pen_x += (slot->advance.x >> 6); + previous_glyph = glyph_index; + } + return pen_x; +} + +int ttfStringWidth(char *string, s8 part) { + FT_GlyphSlot slot = face->glyph; + FT_Error error; + int pen_x = 0, max_x = 0, spart = 1; + FT_UInt previous_glyph; + + while(*string) { + uint32_t buf = *string++; + if ((buf >> 6) == 3) { + if ((buf & 0xF0) == 0xC0) { + uint8_t b1 = buf & 0xFF, b2 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + buf = ((b1 & 0xF) << 6) | b2; + } else if ((buf & 0xF0) == 0xD0) { + uint8_t b1 = buf & 0xFF, b2 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + buf = 0x400 | ((b1 & 0xF) << 6) | b2; + } else if ((buf & 0xF0) == 0xE0) { + uint8_t b1 = buf & 0xFF, b2 = *string++, b3 = *string++; + if ((b2 & 0xC0) == 0x80) b2 &= 0x3F; + if ((b3 & 0xC0) == 0x80) b3 &= 0x3F; + buf = ((b1 & 0xF) << 12) | (b2 << 6) | b3; + } + } else if (buf & 0x80) { + string++; + continue; + } + + //error = FT_Load_Char(face, buf, FT_LOAD_RENDER); + + FT_UInt glyph_index; + glyph_index = FT_Get_Char_Index(face, buf); + + if (FT_HAS_KERNING(face)) { + FT_Vector vector; + FT_Get_Kerning(face, previous_glyph, glyph_index, FT_KERNING_DEFAULT, &vector); + pen_x += (vector.x >> 6); + } + + if (buf == '\n') { + if (part != 0) { + if ((part > 0) && (spart == part)) return pen_x; + if (part == -2) max_x = max(pen_x, max_x); + pen_x = 0; + spart++; + } + continue; + } + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_BITMAP_METRICS_ONLY); + if (error) + continue; + + pen_x += (slot->advance.x >> 6); + previous_glyph = glyph_index; + } + if (spart < part) pen_x = 0; + return max(pen_x, max_x); +} diff --git a/src/draw.h b/src/draw.h new file mode 100644 index 0000000..85f92fe --- /dev/null +++ b/src/draw.h @@ -0,0 +1,53 @@ +#ifndef DRAW_H +#define DRAW_H +#include +//#include +#include "lib_easy.h" +#include "tga_reader.h" +#include +#include FT_FREETYPE_H + +typedef union _RGBAColor { + u32 c; + struct { + u8 r; + u8 g; + u8 b; + u8 a; + }; +} RGBAColor; + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +//Function declarations for my graphics library +void initDraw(char* buf, int size0, int size1); +void flipBuffers(); +void clearBuffers(); +void fillScreen(u8 r, u8 g, u8 b, u8 a); +void drawString(int x, int line, char * string); +void drawPixel32(int x, int y, RGBAColor color); +void drawPixel(int x, int y, u8 r, u8 g, u8 b, u8 a); +void drawLine(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a); +void drawRect(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a); +void drawFillRect(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b, u8 a); +void drawCircle(int xCen, int yCen, int radius, u8 r, u8 g, u8 b, u8 a); +void drawFillCircle(int xCen, int yCen, int radius, u8 r, u8 g, u8 b, u8 a); +void drawCircleCircum(int cx, int cy, int x, int y, u8 r, u8 g, u8 b, u8 a); + +void drawPic(int x, int y, u32 w, u32 h, float scale, u32* pixels); +void drawTGA(int x, int y, float scale, u8* fileContent); +void drawRGB5A3(int x, int y, float scale, u8* pixels); +void drawBackgroundDRC(u32 w, u32 h, u8* out); +void drawBackgroundTV(u32 w, u32 h, u8* out); + +bool initFont(); +void freeFont(); +bool ttfFontSize(u8 w, u8 h); +void ttfFontColor32(u32 color); +void ttfFontColor(u8 r, u8 g, u8 b, u8 a); +int ttfPrintString(int x, int y, char *string, bool wWrap, bool ceroX); +int ttfStringWidth(char *string, s8 part); + +#endif /* DRAW_H */ diff --git a/src/dynamic_libs/acp_functions.c b/src/dynamic_libs/acp_functions.c index eb931f8..beed06a 100644 --- a/src/dynamic_libs/acp_functions.c +++ b/src/dynamic_libs/acp_functions.c @@ -24,7 +24,7 @@ #include "os_functions.h" #include "acp_functions.h" -unsigned int acp_handle __attribute__((section(".data"))) = 0; +u32 acp_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, GetMetaXml, void * _ACPMetaXml); diff --git a/src/dynamic_libs/acp_functions.h b/src/dynamic_libs/acp_functions.h index dc1822d..328b9c3 100644 --- a/src/dynamic_libs/acp_functions.h +++ b/src/dynamic_libs/acp_functions.h @@ -30,7 +30,7 @@ extern "C" { #include -extern unsigned int acp_handle; +extern u32 acp_handle; void InitACPFunctionPointers(void); void InitAcquireACP(void); diff --git a/src/dynamic_libs/aoc_functions.c b/src/dynamic_libs/aoc_functions.c index e74306d..e1adc7a 100644 --- a/src/dynamic_libs/aoc_functions.c +++ b/src/dynamic_libs/aoc_functions.c @@ -24,7 +24,7 @@ #include "os_functions.h" #include "aoc_functions.h" -unsigned int aoc_handle __attribute__((section(".data"))) = 0; +u32 aoc_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(s32, AOC_Initialize, void); EXPORT_DECL(s32, AOC_Finalize, void); diff --git a/src/dynamic_libs/aoc_functions.h b/src/dynamic_libs/aoc_functions.h index efca771..f2e8205 100644 --- a/src/dynamic_libs/aoc_functions.h +++ b/src/dynamic_libs/aoc_functions.h @@ -28,7 +28,9 @@ extern "C" { #endif -extern unsigned int aoc_handle; +#include + +extern u32 aoc_handle; #define AOC_TITLE_SIZE 104 diff --git a/src/dynamic_libs/ax_functions.c b/src/dynamic_libs/ax_functions.c index e517f6d..dc49494 100644 --- a/src/dynamic_libs/ax_functions.c +++ b/src/dynamic_libs/ax_functions.c @@ -25,7 +25,7 @@ #include "os_functions.h" #include "ax_functions.h" -unsigned int sound_handle __attribute__((section(".data"))) = 0; +u32 sound_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, AXInitWithParams, u32 * params); EXPORT_DECL(void, AXInit, void); @@ -51,7 +51,7 @@ EXPORT_DECL(void, AXSetVoiceLoopOffset, void *v, u32 offset); void InitAcquireAX(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; if(OS_FIRMWARE >= 400) { @@ -73,7 +73,7 @@ void InitAcquireAX(void) void InitAXFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireAX(); @@ -102,8 +102,8 @@ void ProperlyEndTransitionAudio(void) void (* AXInit_old)(void); void (* AXQuit_old)(void); - unsigned int *funcPointer = 0; - unsigned int sound_handle; + u32 *funcPointer = 0; + u32 sound_handle; OSDynLoad_Acquire("snd_core.rpl", &sound_handle); OS_FIND_EXPORT_EX(sound_handle, check_os_audio_transition_flag, check_os_audio_transition_flag_old); diff --git a/src/dynamic_libs/ax_functions.h b/src/dynamic_libs/ax_functions.h index 086346f..206d34f 100644 --- a/src/dynamic_libs/ax_functions.h +++ b/src/dynamic_libs/ax_functions.h @@ -30,7 +30,7 @@ extern "C" { #include -extern unsigned int sound_handle; +extern u32 sound_handle; void InitAXFunctionPointers(void); void InitAcquireAX(void); diff --git a/src/dynamic_libs/curl_functions.c b/src/dynamic_libs/curl_functions.c index 0c2988e..459524d 100644 --- a/src/dynamic_libs/curl_functions.c +++ b/src/dynamic_libs/curl_functions.c @@ -41,7 +41,7 @@ void InitAcquireCurl(void) void InitCurlFunctionPointers(void) { InitAcquireCurl(); - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; OS_FIND_EXPORT_EX(libcurl_handle, curl_global_init, n_curl_global_init); OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_init, n_curl_easy_init); diff --git a/src/dynamic_libs/fs_defs.h b/src/dynamic_libs/fs_defs.h index 1b1bc41..bb98595 100644 --- a/src/dynamic_libs/fs_defs.h +++ b/src/dynamic_libs/fs_defs.h @@ -1,5 +1,5 @@ #ifndef FS_DEFS_H -#define FS_DEFS_H +#define FS_DEFS_H #include @@ -17,7 +17,7 @@ extern "C" { #define FS_STATUS_OK 0 #define FS_RET_UNSUPPORTED_CMD 0x0400 #define FS_RET_NO_ERROR 0x0000 -#define FS_RET_ALL_ERROR (unsigned int)(-1) +#define FS_RET_ALL_ERROR (u32)(-1) #define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 @@ -31,6 +31,13 @@ extern "C" { #define FS_CLIENT_SIZE 0x1700 #define FS_CMD_BLOCK_SIZE 0xA80 +#define FSA_STATUS_OK 0 +#define FSA_STATUS_END_OF_DIRECTORY -4 +#define FSA_STATUS_END_OF_FILE -5 +#define FSA_STATUS_ALREADY_EXISTS -22 +#define FSA_STATUS_NOT_FOUND -23 +#define FSA_STATUS_NOT_EMPTY -24 + typedef struct { uint32_t flag; @@ -43,7 +50,7 @@ typedef struct uint32_t ent_id; uint64_t ctime; uint64_t mtime; - uint8_t attributes[48]; + uint8_t attributes[48]; } __attribute__((packed)) FSStat; typedef struct @@ -52,10 +59,17 @@ typedef struct char name[FS_MAX_ENTNAME_SIZE]; } FSDirEntry; +typedef void (*FSAsyncCallback)(void *pClient, void *pCmd, int result, void *context); +typedef struct +{ + FSAsyncCallback userCallback; + void *userContext; + void *ioMsgQueue; +} FSAsyncParams; + #ifdef __cplusplus } #endif -#endif /* FS_DEFS_H */ - +#endif /* FS_DEFS_H */ diff --git a/src/dynamic_libs/fs_functions.c b/src/dynamic_libs/fs_functions.c index 08a4fb6..1da25f3 100644 --- a/src/dynamic_libs/fs_functions.c +++ b/src/dynamic_libs/fs_functions.c @@ -24,65 +24,69 @@ #include "fs_functions.h" #include "os_functions.h" -EXPORT_DECL(int, FSInit, void); -EXPORT_DECL(int, FSShutdown, void); -EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling); -EXPORT_DECL(int, FSDelClient, void *pClient); +EXPORT_DECL(s32, FSInit, void); +EXPORT_DECL(s32, FSShutdown, void); +EXPORT_DECL(s32, FSAddClient, void *pClient, s32 errHandling); +EXPORT_DECL(s32, FSAddClientEx, void *pClient, s32 unk_zero_param, s32 errHandling); +EXPORT_DECL(s32, FSDelClient, void *pClient); EXPORT_DECL(void, FSInitCmdBlock, void *pCmd); -EXPORT_DECL(int, FSGetMountSource, void *pClient, void *pCmd, int type, void *source, int errHandling); +EXPORT_DECL(void *, FSGetCurrentCmdBlock, void *pClient); +EXPORT_DECL(s32, FSGetMountSource, void *pClient, void *pCmd, s32 type, void *source, s32 errHandling); -EXPORT_DECL(int, FSMount, void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); -EXPORT_DECL(int, FSUnmount, void *pClient, void *pCmd, const char *target, int errHandling); +EXPORT_DECL(s32, FSMount, void *pClient, void *pCmd, void *source, char *target, u32 bytes, s32 errHandling); +EXPORT_DECL(s32, FSUnmount, void *pClient, void *pCmd, const char *target, s32 errHandling); -EXPORT_DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); -EXPORT_DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); -EXPORT_DECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); -EXPORT_DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); -EXPORT_DECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error); -EXPORT_DECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -EXPORT_DECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error); -EXPORT_DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -EXPORT_DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); -EXPORT_DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); -EXPORT_DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error); -EXPORT_DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(s32, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, s32 errHandling); +EXPORT_DECL(s32, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error); +EXPORT_DECL(s32, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSRemove, void *pClient, void *pCmd, const char *path, s32 error); +EXPORT_DECL(s32, FSRemoveAsync, void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSFlushQuota, void *pClient, void *pCmd, const char* path, s32 error); +EXPORT_DECL(s32, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, s32 error); +EXPORT_DECL(s32, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSRollbackQuota, void *pClient, void *pCmd, const char *path, s32 error); +EXPORT_DECL(s32, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); -EXPORT_DECL(int, FSOpenDir, void *pClient, void *pCmd, const char *path, int *dh, int errHandling); -EXPORT_DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); -EXPORT_DECL(int, FSReadDir, void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); -EXPORT_DECL(int, FSRewindDir, void *pClient, void *pCmd, int dh, int errHandling); -EXPORT_DECL(int, FSCloseDir, void *pClient, void *pCmd, int dh, int errHandling); -EXPORT_DECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int errHandling); -EXPORT_DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -EXPORT_DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int errHandling); -EXPORT_DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(s32, FSOpenDir, void *pClient, void *pCmd, const char *path, s32 *dh, s32 errHandling); +EXPORT_DECL(s32, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, s32 *handle, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSReadDir, void *pClient, void *pCmd, s32 dh, FSDirEntry *dir_entry, s32 errHandling); +EXPORT_DECL(s32, FSRewindDir, void *pClient, void *pCmd, s32 dh, s32 errHandling); +EXPORT_DECL(s32, FSCloseDir, void *pClient, void *pCmd, s32 dh, s32 errHandling); +EXPORT_DECL(s32, FSChangeDir, void *pClient, void *pCmd, const char *path, s32 errHandling); +EXPORT_DECL(s32, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +EXPORT_DECL(s32, FSMakeDir, void *pClient, void *pCmd, const char *path, s32 errHandling); +EXPORT_DECL(s32, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); -EXPORT_DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); -EXPORT_DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); -EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); -EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling); +EXPORT_DECL(s32, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, s32 *fd, s32 errHandling); +EXPORT_DECL(s32, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, s32 *handle, s32 error, const void *asyncParams); +EXPORT_DECL(s32, FSReadFile, void *pClient, void *pCmd, void *buffer, s32 size, s32 count, s32 fd, s32 flag, s32 errHandling); +EXPORT_DECL(s32, FSCloseFile, void *pClient, void *pCmd, s32 fd, s32 errHandling); -EXPORT_DECL(int, FSFlushFile, void *pClient, void *pCmd, int fd, int error); -EXPORT_DECL(int, FSTruncateFile, void *pClient, void *pCmd, int fd, int error); -EXPORT_DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error); -EXPORT_DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error); -EXPORT_DECL(int, FSWriteFile, void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); +EXPORT_DECL(s32, FSFlushFile, void *pClient, void *pCmd, s32 fd, s32 error); +EXPORT_DECL(s32, FSTruncateFile, void *pClient, void *pCmd, s32 fd, s32 error); +EXPORT_DECL(s32, FSGetStatFile, void *pClient, void *pCmd, s32 fd, void *buffer, s32 error); +EXPORT_DECL(s32, FSSetPosFile, void *pClient, void *pCmd, s32 fd, s32 pos, s32 error); +EXPORT_DECL(s32, FSWriteFile, void *pClient, void *pCmd, const void *source, s32 block_size, s32 block_count, s32 fd, s32 flag, s32 error); -EXPORT_DECL(int, FSBindMount, void *pClient, void *pCmd, char *source, char *target, int error); -EXPORT_DECL(int, FSBindUnmount, void *pClient, void *pCmd, char *target, int error); +EXPORT_DECL(s32, FSBindMount, void *pClient, void *pCmd, char *source, char *target, s32 error); +EXPORT_DECL(s32, FSBindUnmount, void *pClient, void *pCmd, char *target, s32 error); -EXPORT_DECL(int, FSMakeQuota, void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); -EXPORT_DECL(int, FSMakeQuotaAsync ,void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); +EXPORT_DECL(s32, FSMakeQuota, void *pClient, void *pCmd, const char *path,u32 mode, u64 size, s32 errHandling); +EXPORT_DECL(s32, FSMakeQuotaAsync ,void *pClient, void *pCmd, const char *path,u32 mode, u64 size, s32 errHandling,const void *asyncParams); void InitFSFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; OS_FIND_EXPORT(coreinit_handle, FSInit); OS_FIND_EXPORT(coreinit_handle, FSShutdown); + OS_FIND_EXPORT(coreinit_handle, FSAddClient); OS_FIND_EXPORT(coreinit_handle, FSAddClientEx); OS_FIND_EXPORT(coreinit_handle, FSDelClient); OS_FIND_EXPORT(coreinit_handle, FSInitCmdBlock); + OS_FIND_EXPORT(coreinit_handle, FSGetCurrentCmdBlock); OS_FIND_EXPORT(coreinit_handle, FSGetMountSource); OS_FIND_EXPORT(coreinit_handle, FSMount); diff --git a/src/dynamic_libs/fs_functions.h b/src/dynamic_libs/fs_functions.h index d024655..24e7403 100644 --- a/src/dynamic_libs/fs_functions.h +++ b/src/dynamic_libs/fs_functions.h @@ -33,59 +33,61 @@ extern "C" { void InitFSFunctionPointers(void); -extern int (* FSInit)(void); -extern int (* FSShutdown)(void); -extern int (* FSAddClientEx)(void *pClient, int unk_zero_param, int errHandling); -extern int (* FSDelClient)(void *pClient); +extern s32 (* FSInit)(void); +extern s32 (* FSShutdown)(void); +extern s32 (* FSAddClient)(void *pClient, s32 errHandling); +extern s32 (* FSAddClientEx)(void *pClient, s32 unk_zero_param, s32 errHandling); +extern s32 (* FSDelClient)(void *pClient); extern void (* FSInitCmdBlock)(void *pCmd); -extern int (* FSGetMountSource)(void *pClient, void *pCmd, int type, void *source, int errHandling); +extern void *(* FSGetCurrentCmdBlock)(void *pClient); +extern s32 (* FSGetMountSource)(void *pClient, void *pCmd, s32 type, void *source, s32 errHandling); -extern int (* FSMount)(void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); -extern int (* FSUnmount)(void *pClient, void *pCmd, const char *target, int errHandling); -extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); -extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); -extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); -extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern s32 (* FSMount)(void *pClient, void *pCmd, void *source, char *target, u32 bytes, s32 errHandling); +extern s32 (* FSUnmount)(void *pClient, void *pCmd, const char *target, s32 errHandling); +extern s32 (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error); +extern s32 (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error, void *asyncParams); +extern s32 (* FSRemove)(void *pClient, void *pCmd, const char *path, s32 error); +extern s32 (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); -extern int (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); -extern int (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); -extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); -extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); -extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); -extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -extern int (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, int error); -extern int (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -extern int (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); -extern int (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); -extern int (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, int error); -extern int (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern s32 (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, s32 errHandling); +extern s32 (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, s32 error, void *asyncParams); +extern s32 (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error); +extern s32 (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, s32 error, void *asyncParams); +extern s32 (* FSRemove)(void *pClient, void *pCmd, const char *path, s32 error); +extern s32 (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +extern s32 (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, s32 error); +extern s32 (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +extern s32 (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, s32 error); +extern s32 (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, s32 error, void *asyncParams); +extern s32 (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, s32 error); +extern s32 (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); -extern int (* FSOpenDir)(void *pClient, void *pCmd, const char *path, int *dh, int errHandling); -extern int (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); -extern int (* FSReadDir)(void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); -extern int (* FSRewindDir)(void *pClient, void *pCmd, int dh, int errHandling); -extern int (* FSCloseDir)(void *pClient, void *pCmd, int dh, int errHandling); -extern int (* FSChangeDir)(void *pClient, void *pCmd, const char *path, int errHandling); -extern int (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); -extern int (* FSMakeDir)(void *pClient, void *pCmd, const char *path, int errHandling); -extern int (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern s32 (* FSOpenDir)(void *pClient, void *pCmd, const char *path, s32 *dh, s32 errHandling); +extern s32 (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, s32 *handle, s32 error, void *asyncParams); +extern s32 (* FSReadDir)(void *pClient, void *pCmd, s32 dh, FSDirEntry *dir_entry, s32 errHandling); +extern s32 (* FSRewindDir)(void *pClient, void *pCmd, s32 dh, s32 errHandling); +extern s32 (* FSCloseDir)(void *pClient, void *pCmd, s32 dh, s32 errHandling); +extern s32 (* FSChangeDir)(void *pClient, void *pCmd, const char *path, s32 errHandling); +extern s32 (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); +extern s32 (* FSMakeDir)(void *pClient, void *pCmd, const char *path, s32 errHandling); +extern s32 (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, s32 error, void *asyncParams); -extern int (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); -extern int (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); -extern int (* FSReadFile)(void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); -extern int (* FSCloseFile)(void *pClient, void *pCmd, int fd, int errHandling); +extern s32 (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, s32 *fd, s32 errHandling); +extern s32 (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, s32 *handle, s32 error, const void *asyncParams); +extern s32 (* FSReadFile)(void *pClient, void *pCmd, void *buffer, s32 size, s32 count, s32 fd, s32 flag, s32 errHandling); +extern s32 (* FSCloseFile)(void *pClient, void *pCmd, s32 fd, s32 errHandling); -extern int (* FSFlushFile)(void *pClient, void *pCmd, int fd, int error); -extern int (* FSTruncateFile)(void *pClient, void *pCmd, int fd, int error); -extern int (* FSGetStatFile)(void *pClient, void *pCmd, int fd, void *buffer, int error); -extern int (* FSSetPosFile)(void *pClient, void *pCmd, int fd, int pos, int error); -extern int (* FSWriteFile)(void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); +extern s32 (* FSFlushFile)(void *pClient, void *pCmd, s32 fd, s32 error); +extern s32 (* FSTruncateFile)(void *pClient, void *pCmd, s32 fd, s32 error); +extern s32 (* FSGetStatFile)(void *pClient, void *pCmd, s32 fd, void *buffer, s32 error); +extern s32 (* FSSetPosFile)(void *pClient, void *pCmd, s32 fd, s32 pos, s32 error); +extern s32 (* FSWriteFile)(void *pClient, void *pCmd, const void *source, s32 block_size, s32 block_count, s32 fd, s32 flag, s32 error); -extern int (* FSBindMount)(void *pClient, void *pCmd, char *source, char *target, int error); -extern int (* FSBindUnmount)(void *pClient, void *pCmd, char *target, int error); +extern s32 (* FSBindMount)(void *pClient, void *pCmd, char *source, char *target, s32 error); +extern s32 (* FSBindUnmount)(void *pClient, void *pCmd, char *target, s32 error); -extern int (* FSMakeQuota)( void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); -extern int (* FSMakeQuotaAsync)(void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); +extern s32 (* FSMakeQuota)( void *pClient, void *pCmd, const char *path,u32 mode, u64 size, s32 errHandling); +extern s32 (* FSMakeQuotaAsync)(void *pClient, void *pCmd, const char *path,u32 mode, u64 size, s32 errHandling,const void *asyncParams); #ifdef __cplusplus diff --git a/src/dynamic_libs/gx2_functions.c b/src/dynamic_libs/gx2_functions.c index a34807e..501c4d7 100644 --- a/src/dynamic_libs/gx2_functions.c +++ b/src/dynamic_libs/gx2_functions.c @@ -24,7 +24,7 @@ #include "os_functions.h" #include "gx2_types.h" -unsigned int gx2_handle __attribute__((section(".data"))) = 0; +u32 gx2_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, GX2Init, u32 * init_attribs); EXPORT_DECL(void, GX2Shutdown, void); @@ -93,7 +93,7 @@ EXPORT_DECL(s32, GX2GetSystemDRCScanMode, void); EXPORT_DECL(void, GX2RSetAllocator, void * (* allocFunc)(u32, u32, u32), void (* freeFunc)(u32, void*)); EXPORT_DECL(void, GX2CopySurface, GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); -EXPORT_DECL(void, GX2ClearBuffersEx, GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); +EXPORT_DECL(void, GX2ClearBuffersEx, GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,s32 clearFlags); void InitAcquireGX2(void) { @@ -102,7 +102,7 @@ void InitAcquireGX2(void) void InitGX2FunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireGX2(); OS_FIND_EXPORT(gx2_handle, GX2Init); diff --git a/src/dynamic_libs/gx2_functions.h b/src/dynamic_libs/gx2_functions.h index 0b06826..9133fcc 100644 --- a/src/dynamic_libs/gx2_functions.h +++ b/src/dynamic_libs/gx2_functions.h @@ -28,9 +28,10 @@ extern "C" { #endif +#include #include "gx2_types.h" -extern unsigned int gx2_handle; +extern u32 gx2_handle; void InitGX2FunctionPointers(void); void InitAcquireGX2(void); @@ -101,7 +102,7 @@ extern s32 (* GX2GetSystemTVScanMode)(void); extern s32 (* GX2GetSystemDRCScanMode)(void); extern void (* GX2RSetAllocator)(void * (*allocFunc)(u32, u32, u32), void (*freeFunc)(u32, void*)); extern void (* GX2CopySurface)(GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); -extern void (* GX2ClearBuffersEx)(GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); +extern void (* GX2ClearBuffersEx)(GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,s32 clearFlags); static inline void GX2InitDepthBuffer(GX2DepthBuffer *depthBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) { diff --git a/src/dynamic_libs/os_functions.c b/src/dynamic_libs/os_functions.c index 2923bcd..7999c63 100644 --- a/src/dynamic_libs/os_functions.c +++ b/src/dynamic_libs/os_functions.c @@ -24,50 +24,55 @@ #include "common/common.h" #include "os_functions.h" -unsigned int coreinit_handle __attribute__((section(".data"))) = 0; +u32 coreinit_handle __attribute__((section(".data"))) = 0; //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Lib handle functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle); -EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address); +EXPORT_DECL(s32, OSDynLoad_Acquire, const char* rpl, u32 *handle); +EXPORT_DECL(s32, OSDynLoad_FindExport, u32 handle, s32 isdata, const char *symbol, void *address); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Security functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(int, OSGetSecurityLevel, void); -EXPORT_DECL(int, OSForceFullRelaunch, void); +EXPORT_DECL(s32, OSGetSecurityLevel, void); +EXPORT_DECL(s32, OSForceFullRelaunch, void); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Thread functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(int, OSCreateThread, void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); -EXPORT_DECL(int, OSResumeThread, void *thread); -EXPORT_DECL(int, OSSuspendThread, void *thread); -EXPORT_DECL(int, OSIsThreadTerminated, void *thread); -EXPORT_DECL(int, OSIsThreadSuspended, void *thread); -EXPORT_DECL(int, OSSetThreadPriority, void * thread, int priority); -EXPORT_DECL(int, OSJoinThread, void * thread, int * ret_val); +EXPORT_DECL(s32, OSCreateThread, void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +EXPORT_DECL(s32, OSResumeThread, void *thread); +EXPORT_DECL(s32, OSSuspendThread, void *thread); +EXPORT_DECL(void, OSExitThread, u32 result); +EXPORT_DECL(s32, OSIsThreadTerminated, void *thread); +EXPORT_DECL(s32, OSIsThreadSuspended, void *thread); +EXPORT_DECL(s32, OSSetThreadPriority, void * thread, s32 priority); +EXPORT_DECL(s32, OSJoinThread, void * thread, s32 * ret_val); EXPORT_DECL(void, OSDetachThread, void * thread); EXPORT_DECL(void, OSSleepTicks, u64 ticks); EXPORT_DECL(u64, OSGetTick, void); EXPORT_DECL(u64, OSGetTime, void); EXPORT_DECL(void, OSTicksToCalendarTime, u64 time, OSCalendarTime * calendarTime); - //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Mutex functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- EXPORT_DECL(void, OSInitMutex, void* mutex); EXPORT_DECL(void, OSLockMutex, void* mutex); EXPORT_DECL(void, OSUnlockMutex, void* mutex); -EXPORT_DECL(int, OSTryLockMutex, void* mutex); +EXPORT_DECL(s32, OSTryLockMutex, void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Shared Data functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(bool, OSGetSharedData, u32 type, u32 unk_r4, u8 *addr, u32 *size); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! System functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- EXPORT_DECL(u64, OSGetTitleID, void); -EXPORT_DECL(void, OSGetArgcArgv, int* argc, char*** argv); +EXPORT_DECL(void, OSGetArgcArgv, s32* argc, char*** argv); EXPORT_DECL(void, __Exit, void); EXPORT_DECL(void, OSFatal, const char* msg); EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback newCallback); @@ -75,47 +80,51 @@ EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length); EXPORT_DECL(void, DCStoreRange, const void *addr, u32 length); EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length); EXPORT_DECL(void*, OSEffectiveToPhysical, const void*); -EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...); -EXPORT_DECL(int *, __gh_errno_ptr, void); +EXPORT_DECL(s32, __os_snprintf, char* s, s32 n, const char * format, ...); +EXPORT_DECL(s32 *, __gh_errno_ptr, void); EXPORT_DECL(void, OSScreenInit, void); -EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx, unsigned int bufferNum); -EXPORT_DECL(int, OSScreenSetBufferEx, unsigned int bufferNum, void * addr); -EXPORT_DECL(int, OSScreenClearBufferEx, unsigned int bufferNum, unsigned int temp); -EXPORT_DECL(int, OSScreenFlipBuffersEx, unsigned int bufferNum); -EXPORT_DECL(int, OSScreenPutFontEx, unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); -EXPORT_DECL(int, OSScreenEnableEx, unsigned int bufferNum, int enable); +EXPORT_DECL(u32, OSScreenGetBufferSizeEx, u32 bufferNum); +EXPORT_DECL(s32, OSScreenSetBufferEx, u32 bufferNum, void * addr); +EXPORT_DECL(s32, OSScreenClearBufferEx, u32 bufferNum, u32 temp); +EXPORT_DECL(s32, OSScreenFlipBuffersEx, u32 bufferNum); +EXPORT_DECL(s32, OSScreenPutFontEx, u32 bufferNum, u32 posX, u32 posY, const char * buffer); +EXPORT_DECL(s32, OSScreenEnableEx, u32 bufferNum, s32 enable); +EXPORT_DECL(u32, OSScreenPutPixelEx, u32 bufferNum, u32 posX, u32 posY, u32 color); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Memory functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeapEx); -EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeap); -EXPORT_VAR(unsigned int *, pMEMFreeToDefaultHeap); +EXPORT_VAR(u32 *, pMEMAllocFromDefaultHeapEx); +EXPORT_VAR(u32 *, pMEMAllocFromDefaultHeap); +EXPORT_VAR(u32 *, pMEMFreeToDefaultHeap); -EXPORT_DECL(int, MEMGetBaseHeapHandle, int mem_arena); -EXPORT_DECL(unsigned int, MEMGetAllocatableSizeForFrmHeapEx, int heap, int align); -EXPORT_DECL(void *, MEMAllocFromFrmHeapEx, int heap, unsigned int size, int align); -EXPORT_DECL(void, MEMFreeToFrmHeap, int heap, int mode); -EXPORT_DECL(void *, MEMAllocFromExpHeapEx, int heap, unsigned int size, int align); -EXPORT_DECL(int , MEMCreateExpHeapEx, void* address, unsigned int size, unsigned short flags); -EXPORT_DECL(void *, MEMDestroyExpHeap, int heap); -EXPORT_DECL(void, MEMFreeToExpHeap, int heap, void* ptr); +EXPORT_DECL(s32, MEMGetBaseHeapHandle, s32 mem_arena); +EXPORT_DECL(u32, MEMGetAllocatableSizeForFrmHeapEx, s32 heap, s32 align); +EXPORT_DECL(void *, MEMAllocFromFrmHeapEx, s32 heap, u32 size, s32 align); +EXPORT_DECL(void, MEMFreeToFrmHeap, s32 heap, s32 mode); +EXPORT_DECL(void *, MEMAllocFromExpHeapEx, s32 heap, u32 size, s32 align); +EXPORT_DECL(s32 , MEMCreateExpHeapEx, void* address, u32 size, unsigned short flags); +EXPORT_DECL(void *, MEMDestroyExpHeap, s32 heap); +EXPORT_DECL(void, MEMFreeToExpHeap, s32 heap, void* ptr); +EXPORT_DECL(void *, OSAllocFromSystem, int size, int alignment); +EXPORT_DECL(void, OSFreeToSystem, void *addr); +EXPORT_DECL(int, OSIsAddressValid, void *ptr); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! MCP functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(int, MCP_Open, void); -EXPORT_DECL(int, MCP_Close, int handle); -EXPORT_DECL(int, MCP_TitleCount, int handle); -EXPORT_DECL(int, MCP_TitleList, int handle, int *res, void *data, int count); -EXPORT_DECL(int, MCP_GetOwnTitleInfo, int handle, void * data); +EXPORT_DECL(s32, MCP_Open, void); +EXPORT_DECL(s32, MCP_Close, s32 handle); +EXPORT_DECL(s32, MCP_TitleCount, s32 handle); +EXPORT_DECL(s32, MCP_TitleList, s32 handle, s32 *res, void *data, s32 count); +EXPORT_DECL(s32, MCP_GetOwnTitleInfo, s32 handle, void * data); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Loader functions (not real rpl) //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(int, LiWaitIopComplete, int unknown_syscall_arg_r3, int * remaining_bytes); -EXPORT_DECL(int, LiWaitIopCompleteWithInterrupts, int unknown_syscall_arg_r3, int * remaining_bytes); +EXPORT_DECL(s32, LiWaitIopComplete, s32 unknown_syscall_arg_r3, s32 * remaining_bytes); +EXPORT_DECL(s32, LiWaitIopCompleteWithInterrupts, s32 unknown_syscall_arg_r3, s32 * remaining_bytes); EXPORT_DECL(void, addr_LiWaitOneChunk, void); EXPORT_DECL(void, addr_sgIsLoadingBuffer, void); EXPORT_DECL(void, addr_gDynloadInitialized, void); @@ -128,40 +137,77 @@ EXPORT_DECL(void, addr_PrepareTitle_hook, void); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Other function addresses //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -EXPORT_DECL(void, DCInvalidateRange, void *buffer, uint32_t length); +EXPORT_DECL(void, DCInvalidateRange, void *buffer, u32 length); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Energy Saver functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //Burn-in Reduction -EXPORT_DECL(int, IMEnableDim,void); -EXPORT_DECL(int, IMDisableDim,void); -EXPORT_DECL(int, IMIsDimEnabled,int * result); +EXPORT_DECL(s32, IMEnableDim,void); +EXPORT_DECL(s32, IMDisableDim,void); +EXPORT_DECL(s32, IMIsDimEnabled,s32 * result); //Auto power down -EXPORT_DECL(int, IMEnableAPD,void); -EXPORT_DECL(int, IMDisableAPD,void); -EXPORT_DECL(int, IMIsAPDEnabled,int * result); -EXPORT_DECL(int, IMIsAPDEnabledBySysSettings,int * result); +EXPORT_DECL(s32, IMEnableAPD,void); +EXPORT_DECL(s32, IMDisableAPD,void); +EXPORT_DECL(s32, IMIsAPDEnabled,s32 * result); +EXPORT_DECL(s32, IMIsAPDEnabledBySysSettings,s32 * result); +EXPORT_DECL(s32, OSSendAppSwitchRequest,s32 param,void* unknown1,void* unknown2); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! IOS functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +EXPORT_DECL(s32, IOS_Ioctl,s32 fd, u32 request, void *input_buffer,u32 input_buffer_len, void *output_buffer, u32 output_buffer_len); +EXPORT_DECL(s32, IOS_IoctlAsync,s32 fd, u32 request, void *input_buffer,u32 input_buffer_len, void *output_buffer, u32 output_buffer_len, void *cb, void *cbarg); +EXPORT_DECL(s32, IOS_Open,char *path, u32 mode); +EXPORT_DECL(s32, IOS_Close,s32 fd); + +void _os_find_export(u32 handle, const char *funcName, void *funcPointer) +{ + OSDynLoad_FindExport(handle, 0, funcName, funcPointer); + + if(!*(u32 *)funcPointer) { + /* + * This is effectively OSFatal("Function %s is NULL", funcName), + * but we can't rely on any library functions like snprintf or + * strcpy at this point. + * + * Buffer bounds are not checked. Beware! + */ + char buf[256], *bufp = buf; + const char a[] = "Function ", b[] = " is NULL", *p; + unsigned int i; + + for (i = 0; i < sizeof(a) - 1; i++) + *bufp++ = a[i]; + + for (p = funcName; *p; p++) + *bufp++ = *p; + + for (i = 0; i < sizeof(b) - 1; i++) + *bufp++ = b[i]; + + *bufp++ = '\0'; + + OSFatal(buf); + } +} -EXPORT_DECL(int, IOS_Ioctl,int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); -EXPORT_DECL(int, IOS_IoctlAsync,int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len, void *cb, void *cbarg); -EXPORT_DECL(int, IOS_Open,char *path, unsigned int mode); -EXPORT_DECL(int, IOS_Close,int fd); void InitAcquireOS(void) { - //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Lib handle functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - EXPORT_FUNC_WRITE(OSDynLoad_Acquire, (int (*)(const char*, unsigned *))OS_SPECIFICS->addr_OSDynLoad_Acquire); - EXPORT_FUNC_WRITE(OSDynLoad_FindExport, (int (*)(u32, int, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport); + EXPORT_FUNC_WRITE(OSDynLoad_Acquire, (s32 (*)(const char*, unsigned *))OS_SPECIFICS->addr_OSDynLoad_Acquire); + EXPORT_FUNC_WRITE(OSDynLoad_FindExport, (s32 (*)(u32, s32, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport); OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); } void InitOSFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireOS(); @@ -171,6 +217,10 @@ void InitOSFunctionPointers(void) OS_FIND_EXPORT(coreinit_handle, OSGetSecurityLevel); OS_FIND_EXPORT(coreinit_handle, OSForceFullRelaunch); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Shared Data functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSGetSharedData); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! System functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OS_FIND_EXPORT(coreinit_handle, OSFatal); @@ -193,12 +243,14 @@ void InitOSFunctionPointers(void) OS_FIND_EXPORT(coreinit_handle, OSScreenFlipBuffersEx); OS_FIND_EXPORT(coreinit_handle, OSScreenPutFontEx); OS_FIND_EXPORT(coreinit_handle, OSScreenEnableEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenPutPixelEx); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Thread functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OS_FIND_EXPORT(coreinit_handle, OSCreateThread); OS_FIND_EXPORT(coreinit_handle, OSResumeThread); OS_FIND_EXPORT(coreinit_handle, OSSuspendThread); + OS_FIND_EXPORT(coreinit_handle, OSExitThread); OS_FIND_EXPORT(coreinit_handle, OSIsThreadTerminated); OS_FIND_EXPORT(coreinit_handle, OSIsThreadSuspended); OS_FIND_EXPORT(coreinit_handle, OSJoinThread); @@ -240,6 +292,9 @@ void InitOSFunctionPointers(void) OS_FIND_EXPORT(coreinit_handle, MEMCreateExpHeapEx); OS_FIND_EXPORT(coreinit_handle, MEMDestroyExpHeap); OS_FIND_EXPORT(coreinit_handle, MEMFreeToExpHeap); + OS_FIND_EXPORT(coreinit_handle, OSAllocFromSystem); + OS_FIND_EXPORT(coreinit_handle, OSFreeToSystem); + OS_FIND_EXPORT(coreinit_handle, OSIsAddressValid); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Other function addresses @@ -259,6 +314,11 @@ void InitOSFunctionPointers(void) OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabled); OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabledBySysSettings); + OS_FIND_EXPORT(coreinit_handle, OSSendAppSwitchRequest); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! IOS functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OS_FIND_EXPORT(coreinit_handle, IOS_Ioctl); OS_FIND_EXPORT(coreinit_handle, IOS_IoctlAsync); OS_FIND_EXPORT(coreinit_handle, IOS_Open); @@ -267,75 +327,75 @@ void InitOSFunctionPointers(void) //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Special non library functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - if(OS_FIRMWARE == 532 || OS_FIRMWARE == 540) + if(OS_FIRMWARE == 550) { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FFA4); // loader.elf - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FE90); // loader.elf - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); // loader.elf - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18558); // kernel.elf + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x01010180); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0101006C); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x0100080C); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF184E4); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); // loader.elf - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); // loader.elf + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19E80); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE13DBC); + } + else if(OS_FIRMWARE == 532 || OS_FIRMWARE == 540) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100FFA4); // loader.elf + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100FE90); // loader.elf + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010007EC); // loader.elf + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF18558); // kernel.elf + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19D00); // loader.elf + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE13C3C); // loader.elf } else if(OS_FIRMWARE == 500 || OS_FIRMWARE == 510) { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FBC4); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FAB0); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18534); + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100FBC4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100FAB0); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010007EC); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF18534); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19D00); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE13C3C); } else if(OS_FIRMWARE == 410) { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF166DC); + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100F78C); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100F678); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010007F8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF166DC); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19CC0); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE13BFC); } else if(OS_FIRMWARE == 400) //same for 402 and 403 { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15E70); + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100F78C); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100F678); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010007F8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF15E70); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); - } - else if(OS_FIRMWARE == 550) - { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x01010180); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0101006C); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x0100080C); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF184E4); - - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19E80); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13DBC); + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19CC0); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE13BFC); } else if(OS_FIRMWARE == 310) { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15A0C); + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100C4E4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100C3D4); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010004D8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF15A0C); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19340); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE1329C); } else if(OS_FIRMWARE == 300) { - EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); - EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); - EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); - EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15974); + EXPORT_FUNC_WRITE(LiWaitIopComplete, (s32 (*)(s32, s32 *))0x0100C4E4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (s32 (*)(s32, s32 *))0x0100C3D4); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (s32 (*)(s32, s32 *))0x010004D8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (s32 (*)(s32, s32 *))0xFFF15974); - EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); - EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (s32 (*)(s32, s32 *))0xEFE19340); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (s32 (*)(s32, s32 *))0xEFE1329C); } else { diff --git a/src/dynamic_libs/os_functions.h b/src/dynamic_libs/os_functions.h index 3d58932..23ff4a3 100644 --- a/src/dynamic_libs/os_functions.h +++ b/src/dynamic_libs/os_functions.h @@ -37,8 +37,9 @@ extern "C" { #define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000) #define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000) -#define usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) -#define sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) +//To avoid conflicts with the unistd.h +#define os_usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) +#define os_sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) #define FLUSH_DATA_BLOCK(addr) asm volatile("dcbf 0, %0; sync" : : "r"(((addr) & ~31))) #define INVAL_DATA_BLOCK(addr) asm volatile("dcbi 0, %0; sync" : : "r"(((addr) & ~31))) @@ -49,48 +50,44 @@ extern "C" { #define EXPORT_FUNC_WRITE(func, val) *(u32*)(((u32)&func) + 0) = (u32)val -#define OS_FIND_EXPORT(handle, func) funcPointer = 0; \ - OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ - if(!funcPointer) \ - OSFatal("Function " # func " is NULL"); \ +#define OS_FIND_EXPORT(handle, func) _os_find_export(handle, # func, &funcPointer); \ EXPORT_FUNC_WRITE(func, funcPointer); #define OS_FIND_EXPORT_EX(handle, func, func_p) \ - funcPointer = 0; \ - OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ - if(!funcPointer) \ - OSFatal("Function " # func " is NULL"); \ + _os_find_export(handle, # func, &funcPointer); \ EXPORT_FUNC_WRITE(func_p, funcPointer); #define OS_MUTEX_SIZE 44 /* Handle for coreinit */ -extern unsigned int coreinit_handle; -void InitOSFunctionPointers(void); -void InitAcquireOS(void); +extern u32 coreinit_handle; +extern void _os_find_export(u32 handle, const char *funcName, void *funcPointer); +extern void InitAcquireOS(void); +extern void InitOSFunctionPointers(void); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Lib handle functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); -extern int (* OSDynLoad_FindExport)(u32 handle, int isdata, const char *symbol, void *address); +extern s32 (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); +extern s32 (* OSDynLoad_FindExport)(u32 handle, s32 isdata, const char *symbol, void *address); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Security functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (* OSGetSecurityLevel)(void); -extern int (* OSForceFullRelaunch)(void); +extern s32 (* OSGetSecurityLevel)(void); +extern s32 (* OSForceFullRelaunch)(void); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Thread functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); -extern int (* OSResumeThread)(void *thread); -extern int (* OSSuspendThread)(void *thread); -extern int (* OSIsThreadTerminated)(void *thread); -extern int (* OSIsThreadSuspended)(void *thread); -extern int (* OSJoinThread)(void * thread, int * ret_val); -extern int (* OSSetThreadPriority)(void * thread, int priority); +extern s32 (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +extern s32 (* OSResumeThread)(void *thread); +extern s32 (* OSSuspendThread)(void *thread); +extern void (*OSExitThread)(u32 result); +extern s32 (* OSIsThreadTerminated)(void *thread); +extern s32 (* OSIsThreadSuspended)(void *thread); +extern s32 (* OSJoinThread)(void * thread, s32 * ret_val); +extern s32 (* OSSetThreadPriority)(void * thread, s32 priority); extern void (* OSDetachThread)(void * thread); extern void (* OSSleepTicks)(u64 ticks); extern u64 (* OSGetTick)(void); @@ -103,47 +100,72 @@ extern void (*OSTicksToCalendarTime)(u64 time, OSCalendarTime *calendarTime); extern void (* OSInitMutex)(void* mutex); extern void (* OSLockMutex)(void* mutex); extern void (* OSUnlockMutex)(void* mutex); -extern int (* OSTryLockMutex)(void* mutex); +extern s32 (* OSTryLockMutex)(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Shared Data functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern bool (* OSGetSharedData)(u32 type, u32 unk_r4, u8 *addr, u32 *size); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! System functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- extern u64 (* OSGetTitleID)(void); -extern void (* OSGetArgcArgv)(int* argc, char*** argv); +extern void (* OSGetArgcArgv)(s32* argc, char*** argv); extern void (* __Exit)(void); extern void (* OSFatal)(const char* msg); extern void (* DCFlushRange)(const void *addr, u32 length); extern void (* DCStoreRange)(const void *addr, u32 length); extern void (* ICInvalidateRange)(const void *addr, u32 length); extern void* (* OSEffectiveToPhysical)(const void*); -extern int (* __os_snprintf)(char* s, int n, const char * format, ...); -extern int * (* __gh_errno_ptr)(void); +extern s32 (* __os_snprintf)(char* s, s32 n, const char * format, ...); +extern s32 * (* __gh_errno_ptr)(void); extern void (*OSScreenInit)(void); -extern unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum); -extern int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); -extern int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); -extern int (*OSScreenFlipBuffersEx)(unsigned int bufferNum); -extern int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); -extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); +extern u32 (*OSScreenGetBufferSizeEx)(u32 bufferNum); +extern s32 (*OSScreenSetBufferEx)(u32 bufferNum, void * addr); +extern s32 (*OSScreenClearBufferEx)(u32 bufferNum, u32 temp); +extern s32 (*OSScreenFlipBuffersEx)(u32 bufferNum); +extern s32 (*OSScreenPutFontEx)(u32 bufferNum, u32 posX, u32 posY, const char * buffer); +extern s32 (*OSScreenEnableEx)(u32 bufferNum, s32 enable); +extern u32 (*OSScreenPutPixelEx)(u32 bufferNum, u32 posX, u32 posY, u32 color); typedef unsigned char (*exception_callback)(void * interruptedContext); extern void (* OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern u32 *pMEMAllocFromDefaultHeapEx; +extern u32 *pMEMAllocFromDefaultHeap; +extern u32 *pMEMFreeToDefaultHeap; + +extern s32 (* MEMGetBaseHeapHandle)(s32 mem_arena); +extern u32 (* MEMGetAllocatableSizeForFrmHeapEx)(s32 heap, s32 align); +extern void* (* MEMAllocFromFrmHeapEx)(s32 heap, u32 size, s32 align); +extern void (* MEMFreeToFrmHeap)(s32 heap, s32 mode); +extern void *(* MEMAllocFromExpHeapEx)(s32 heap, u32 size, s32 align); +extern s32 (* MEMCreateExpHeapEx)(void* address, u32 size, unsigned short flags); +extern void *(* MEMDestroyExpHeap)(s32 heap); +extern void (* MEMFreeToExpHeap)(s32 heap, void* ptr); +extern void* (* OSAllocFromSystem)(int size, int alignment); +extern void (* OSFreeToSystem)(void *addr); +extern int (* OSIsAddressValid)(void *ptr); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! MCP functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (* MCP_Open)(void); -extern int (* MCP_Close)(int handle); -extern int (* MCP_TitleCount)(int handle); -extern int (* MCP_TitleList)(int handle, int *res, void *data, int count); -extern int (* MCP_GetOwnTitleInfo)(int handle, void * data); +extern s32 (* MCP_Open)(void); +extern s32 (* MCP_Close)(s32 handle); +extern s32 (* MCP_TitleCount)(s32 handle); +extern s32 (* MCP_TitleList)(s32 handle, s32 *res, void *data, s32 count); +extern s32 (* MCP_GetOwnTitleInfo)(s32 handle, void * data); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! LOADER functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (* LiWaitIopComplete)(int unknown_syscall_arg_r3, int * remaining_bytes); -extern int (* LiWaitIopCompleteWithInterrupts)(int unknown_syscall_arg_r3, int * remaining_bytes); +extern s32 (* LiWaitIopComplete)(s32 unknown_syscall_arg_r3, s32 * remaining_bytes); +extern s32 (* LiWaitIopCompleteWithInterrupts)(s32 unknown_syscall_arg_r3, s32 * remaining_bytes); extern void (* addr_LiWaitOneChunk)(void); extern void (* addr_sgIsLoadingBuffer)(void); extern void (* addr_gDynloadInitialized)(void); @@ -156,25 +178,32 @@ extern void (* addr_PrepareTitle_hook)(void); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Other function addresses //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern void (*DCInvalidateRange)(void *buffer, uint32_t length); +extern void (*DCInvalidateRange)(void *buffer, u32 length); //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Energy Saver functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ////Burn-in Reduction -extern int (*IMEnableDim)(void); -extern int (*IMDisableDim)(void); -extern int (*IMIsDimEnabled)(int * result); +extern s32 (*IMEnableDim)(void); +extern s32 (*IMDisableDim)(void); +extern s32 (*IMIsDimEnabled)(s32 * result); //Auto power down -extern int (*IMEnableAPD)(void); -extern int (*IMDisableAPD)(void); -extern int (*IMIsAPDEnabled)(int * result); -extern int (*IMIsAPDEnabledBySysSettings)(int * result); +extern s32 (*IMEnableAPD)(void); +extern s32 (*IMDisableAPD)(void); +extern s32 (*IMIsAPDEnabled)(s32 * result); +extern s32 (*IMIsAPDEnabledBySysSettings)(s32 * result); + +extern s32 (*OSSendAppSwitchRequest)(s32 param,void* unknown1,void* unknown2); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! IOS functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +extern s32 (*IOS_Ioctl)(s32 fd, u32 request, void *input_buffer,u32 input_buffer_len, void *output_buffer, u32 output_buffer_len); +extern s32 (*IOS_IoctlAsync)(s32 fd, u32 request, void *input_buffer,u32 input_buffer_len, void *output_buffer, u32 output_buffer_len, void *cb, void *cbarg); +extern s32 (*IOS_Open)(char *path, u32 mode); +extern s32 (*IOS_Close)(s32 fd); -extern int (*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); -extern int (*IOS_IoctlAsync)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len, void *cb, void *cbarg); -extern int (*IOS_Open)(char *path, unsigned int mode); -extern int (*IOS_Close)(int fd); #ifdef __cplusplus } #endif diff --git a/src/dynamic_libs/padscore_functions.c b/src/dynamic_libs/padscore_functions.c index f7ca8e9..8f774dc 100644 --- a/src/dynamic_libs/padscore_functions.c +++ b/src/dynamic_libs/padscore_functions.c @@ -24,7 +24,7 @@ #include "os_functions.h" #include "padscore_functions.h" -unsigned int padscore_handle __attribute__((section(".data"))) = 0; +u32 padscore_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, KPADInit, void); EXPORT_DECL(void, WPADInit, void); @@ -43,7 +43,7 @@ void InitAcquirePadScore(void) void InitPadScoreFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquirePadScore(); OS_FIND_EXPORT(padscore_handle, WPADInit); diff --git a/src/dynamic_libs/padscore_functions.h b/src/dynamic_libs/padscore_functions.h index 5b000b1..f7f07dc 100644 --- a/src/dynamic_libs/padscore_functions.h +++ b/src/dynamic_libs/padscore_functions.h @@ -30,10 +30,20 @@ extern "C" { #include "dynamic_libs/vpad_functions.h" -extern unsigned int padscore_handle; +extern u32 padscore_handle; #include +#define WPAD_EXT_CORE 0 +#define WPAD_EXT_NUNCHUK 1 +#define WPAD_EXT_CLASSIC 2 +#define WPAD_EXT_MPLUS 5 +#define WPAD_EXT_MPLUS_NUNCHUK 6 +#define WPAD_EXT_MPLUS_CLASSIC 7 +#define WPAD_EXT_PRO_CONTROLLER 31 + +#define WPAD_FMT_PRO_CONTROLLER 22 + #define WPAD_BUTTON_LEFT 0x0001 #define WPAD_BUTTON_RIGHT 0x0002 #define WPAD_BUTTON_DOWN 0x0004 @@ -140,17 +150,36 @@ typedef struct _KPADData f32 lstick_y; f32 rstick_x; f32 rstick_y; - int charging; - int wired; + s32 charging; + s32 wired; } pro; u32 unused_6[20]; }; u32 unused_7[16]; } KPADData; + +typedef struct WPADReadData_ { + u8 unknown[40]; + u8 dev; + u8 err; + u8 unknown1[2]; + u32 buttons; + s16 l_stick_x; + s16 l_stick_y; + s16 r_stick_x; + s16 r_stick_y; + u8 unknown2[8]; + u8 fmt; +}WPADReadData; + +typedef WPADReadData KPADUnifiedWpadData; + void InitPadScoreFunctionPointers(void); void InitAcquirePadScore(void); +typedef void (* wpad_sampling_callback_t)(s32 chan); +typedef void (* wpad_extension_callback_t)(s32 chan, s32 status); typedef void (* wpad_connect_callback_t)(s32 chan, s32 status); extern void (* KPADInit)(void); diff --git a/src/dynamic_libs/socket_functions.c b/src/dynamic_libs/socket_functions.c index de2c31f..06aa769 100644 --- a/src/dynamic_libs/socket_functions.c +++ b/src/dynamic_libs/socket_functions.c @@ -26,26 +26,26 @@ u32 hostIpAddress = 0; -unsigned int nsysnet_handle __attribute__((section(".data"))) = 0; +u32 nsysnet_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, socket_lib_init, void); -EXPORT_DECL(int, socket, int domain, int type, int protocol); -EXPORT_DECL(int, socketclose, int s); -EXPORT_DECL(int, connect, int s, void *addr, int addrlen); -EXPORT_DECL(int, bind, s32 s,struct sockaddr *name,s32 namelen); -EXPORT_DECL(int, listen, s32 s,u32 backlog); -EXPORT_DECL(int, accept, s32 s,struct sockaddr *addr,s32 *addrlen); -EXPORT_DECL(int, send, int s, const void *buffer, int size, int flags); -EXPORT_DECL(int, recv, int s, void *buffer, int size, int flags); -EXPORT_DECL(int, recvfrom,int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); -EXPORT_DECL(int, sendto, int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); -EXPORT_DECL(int, setsockopt, int s, int level, int optname, void *optval, int optlen); +EXPORT_DECL(s32, socket, s32 domain, s32 type, s32 protocol); +EXPORT_DECL(s32, socketclose, s32 s); +EXPORT_DECL(s32, connect, s32 s, void *addr, s32 addrlen); +EXPORT_DECL(s32, bind, s32 s,struct sockaddr *name,s32 namelen); +EXPORT_DECL(s32, listen, s32 s,u32 backlog); +EXPORT_DECL(s32, accept, s32 s,struct sockaddr *addr,s32 *addrlen); +EXPORT_DECL(s32, send, s32 s, const void *buffer, s32 size, s32 flags); +EXPORT_DECL(s32, recv, s32 s, void *buffer, s32 size, s32 flags); +EXPORT_DECL(s32, recvfrom,s32 sockfd, void *buf, s32 len, s32 flags,struct sockaddr *src_addr, s32 *addrlen); +EXPORT_DECL(s32, sendto, s32 s, const void *buffer, s32 size, s32 flags, const struct sockaddr *dest, s32 dest_len); +EXPORT_DECL(s32, setsockopt, s32 s, s32 level, s32 optname, void *optval, s32 optlen); EXPORT_DECL(char *, inet_ntoa, struct in_addr in); -EXPORT_DECL(int, inet_aton, const char *cp, struct in_addr *inp); +EXPORT_DECL(s32, inet_aton, const char *cp, struct in_addr *inp); -EXPORT_DECL(int, NSSLWrite, int connection, const void* buf, int len,int * written); -EXPORT_DECL(int, NSSLRead, int connection, const void* buf, int len,int * read); -EXPORT_DECL(int, NSSLCreateConnection, int context, const char* host, int hotlen,int options,int sock,int block); +EXPORT_DECL(s32, NSSLWrite, s32 connection, const void* buf, s32 len,s32 * written); +EXPORT_DECL(s32, NSSLRead, s32 connection, const void* buf, s32 len,s32 * read); +EXPORT_DECL(s32, NSSLCreateConnection, s32 context, const char* host, s32 hotlen,s32 options,s32 sock,s32 block); void InitAcquireSocket(void) { @@ -54,10 +54,21 @@ void InitAcquireSocket(void) void InitSocketFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireSocket(); + u32 nn_ac_handle; + s32(*ACInitialize)(); + s32(*ACGetStartupId) (u32 *id); + s32(*ACConnectWithConfigId) (u32 id); + s32(*ACGetAssignedAddress) (u32 * ip); + OSDynLoad_Acquire("nn_ac.rpl", &nn_ac_handle); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACInitialize", &ACInitialize); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetStartupId", &ACGetStartupId); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACConnectWithConfigId",&ACConnectWithConfigId); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetAssignedAddress",&ACGetAssignedAddress); + OS_FIND_EXPORT(nsysnet_handle, socket_lib_init); OS_FIND_EXPORT(nsysnet_handle, socket); OS_FIND_EXPORT(nsysnet_handle, socketclose); @@ -77,5 +88,11 @@ void InitSocketFunctionPointers(void) OS_FIND_EXPORT(nsysnet_handle, NSSLRead); OS_FIND_EXPORT(nsysnet_handle, NSSLCreateConnection); + u32 nn_startupid; + ACInitialize(); + ACGetStartupId(&nn_startupid); + ACConnectWithConfigId(nn_startupid); + ACGetAssignedAddress(&hostIpAddress); + socket_lib_init(); } diff --git a/src/dynamic_libs/socket_functions.h b/src/dynamic_libs/socket_functions.h index 1e4df1a..0ab78f7 100644 --- a/src/dynamic_libs/socket_functions.h +++ b/src/dynamic_libs/socket_functions.h @@ -28,7 +28,7 @@ extern "C" { #endif -extern unsigned int nsysnet_handle; +extern u32 nsysnet_handle; #include @@ -61,7 +61,7 @@ extern unsigned int nsysnet_handle; struct in_addr { - unsigned int s_addr; + u32 s_addr; }; struct sockaddr_in { short sin_family; @@ -81,25 +81,25 @@ void InitSocketFunctionPointers(void); void InitAcquireSocket(void); extern void (*socket_lib_init)(void); -extern int (*socket)(int domain, int type, int protocol); -extern int (*socketclose)(int s); -extern int (*connect)(int s, void *addr, int addrlen); -extern int (*bind)(s32 s,struct sockaddr *name,s32 namelen); -extern int (*listen)(s32 s,u32 backlog); -extern int (*accept)(s32 s,struct sockaddr *addr,s32 *addrlen); -extern int (*send)(int s, const void *buffer, int size, int flags); -extern int (*recv)(int s, void *buffer, int size, int flags); -extern int (*recvfrom)(int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); +extern s32 (*socket)(s32 domain, s32 type, s32 protocol); +extern s32 (*socketclose)(s32 s); +extern s32 (*connect)(s32 s, void *addr, s32 addrlen); +extern s32 (*bind)(s32 s,struct sockaddr *name,s32 namelen); +extern s32 (*listen)(s32 s,u32 backlog); +extern s32 (*accept)(s32 s,struct sockaddr *addr,s32 *addrlen); +extern s32 (*send)(s32 s, const void *buffer, s32 size, s32 flags); +extern s32 (*recv)(s32 s, void *buffer, s32 size, s32 flags); +extern s32 (*recvfrom)(s32 sockfd, void *buf, s32 len, s32 flags,struct sockaddr *src_addr, s32 *addrlen); -extern int (*sendto)(int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); -extern int (*setsockopt)(int s, int level, int optname, void *optval, int optlen); +extern s32 (*sendto)(s32 s, const void *buffer, s32 size, s32 flags, const struct sockaddr *dest, s32 dest_len); +extern s32 (*setsockopt)(s32 s, s32 level, s32 optname, void *optval, s32 optlen); -extern int (* NSSLWrite)(int connection, const void* buf, int len,int * written); -extern int (* NSSLRead)(int connection, const void* buf, int len,int * read); -extern int (* NSSLCreateConnection)(int context, const char* host, int hotlen,int options,int sock,int block); +extern s32 (* NSSLWrite)(s32 connection, const void* buf, s32 len,s32 * written); +extern s32 (* NSSLRead)(s32 connection, const void* buf, s32 len,s32 * read); +extern s32 (* NSSLCreateConnection)(s32 context, const char* host, s32 hotlen,s32 options,s32 sock,s32 block); extern char * (*inet_ntoa)(struct in_addr in); -extern int (*inet_aton)(const char *cp, struct in_addr *inp); +extern s32 (*inet_aton)(const char *cp, struct in_addr *inp); #ifdef __cplusplus } diff --git a/src/dynamic_libs/sys_functions.c b/src/dynamic_libs/sys_functions.c index 2cd44b8..25720c5 100644 --- a/src/dynamic_libs/sys_functions.c +++ b/src/dynamic_libs/sys_functions.c @@ -23,14 +23,14 @@ ***************************************************************************/ #include "os_functions.h" - unsigned int sysapp_handle __attribute__((section(".data"))) = 0; +u32 sysapp_handle __attribute__((section(".data"))) = 0; -EXPORT_DECL(int, _SYSLaunchTitleByPathFromLauncher, const char* path, int len, int zero); -EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv); -EXPORT_DECL(int, SYSLaunchMenu, void); -EXPORT_DECL(int, SYSCheckTitleExists, u64 titleId); -EXPORT_DECL(int, SYSLaunchTitle, u64 titleId); -EXPORT_DECL(int, SYSLaunchSettings, int unk); +EXPORT_DECL(s32, _SYSLaunchTitleByPathFromLauncher, const char* path, s32 len, s32 zero); +EXPORT_DECL(s32, SYSRelaunchTitle, s32 argc, char** argv); +EXPORT_DECL(s32, SYSLaunchMenu, void); +EXPORT_DECL(s32, SYSCheckTitleExists, u64 titleId); +EXPORT_DECL(s32, SYSLaunchTitle, u64 titleId); +EXPORT_DECL(s32, SYSLaunchSettings, s32 unk); void InitAcquireSys(void) { @@ -39,7 +39,7 @@ void InitAcquireSys(void) void InitSysFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireSys(); OS_FIND_EXPORT(sysapp_handle, _SYSLaunchTitleByPathFromLauncher); diff --git a/src/dynamic_libs/sys_functions.h b/src/dynamic_libs/sys_functions.h index 64fc2c7..8c66e78 100644 --- a/src/dynamic_libs/sys_functions.h +++ b/src/dynamic_libs/sys_functions.h @@ -28,17 +28,19 @@ extern "C" { #endif -extern unsigned int sysapp_handle; +#include + +extern u32 sysapp_handle; void InitSysFunctionPointers(void); void InitAcquireSys(void); -extern int(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); -extern int (* SYSRelaunchTitle)(int argc, char** argv); +extern int(*_SYSLaunchTitleByPathFromLauncher)(const char* path, s32 len, s32 zero); +extern int (* SYSRelaunchTitle)(s32 argc, char** argv); extern int (* SYSLaunchMenu)(void); extern int (* SYSCheckTitleExists)(u64 titleId); extern int (* SYSLaunchTitle)(u64 titleId); -extern int (* SYSLaunchSettings)(int unk); +extern int (* SYSLaunchSettings)(s32 unk); #ifdef __cplusplus diff --git a/src/dynamic_libs/syshid_functions.c b/src/dynamic_libs/syshid_functions.c index 996d39d..b5dbca4 100644 --- a/src/dynamic_libs/syshid_functions.c +++ b/src/dynamic_libs/syshid_functions.c @@ -24,27 +24,27 @@ #include "os_functions.h" #include "syshid_functions.h" -unsigned int syshid_handle __attribute__((section(".data"))) = 0; +u32 syshid_handle __attribute__((section(".data"))) = 0; -EXPORT_DECL(int, HIDSetup,void); -EXPORT_DECL(int, HIDTeardown,void); +EXPORT_DECL(s32, HIDSetup,void); +EXPORT_DECL(s32, HIDTeardown,void); -EXPORT_DECL(int, HIDAddClient,HIDClient *p_client, HIDAttachCallback attach_callback); -EXPORT_DECL(int, HIDDelClient,HIDClient *p_client); +EXPORT_DECL(s32, HIDAddClient,HIDClient *p_client, HIDAttachCallback attach_callback); +EXPORT_DECL(s32, HIDDelClient,HIDClient *p_client); -EXPORT_DECL(int, HIDGetDescriptor,unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDSetDescriptor,unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDGetDescriptor,u32 handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDSetDescriptor,u32 handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDSetProtocol,unsigned int handle,u8 interface_index,u8 protocol, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDGetProtocol,unsigned int handle,u8 interface_index,u8 * protocol, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDSetProtocol,u32 handle,u8 s32erface_index,u8 protocol, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDGetProtocol,u32 handle,u8 s32erface_index,u8 * protocol, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDGetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDSetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDGetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDSetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDSetIdle,unsigned int handle, u8 interface_index,u8 duration, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDSetIdle,u32 handle, u8 s32erface_index,u8 duration, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDRead,unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); -EXPORT_DECL(int, HIDWrite,unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDRead,u32 handle, unsigned char *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(s32, HIDWrite,u32 handle, unsigned char *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); void InitAcquireSysHID(void) { @@ -59,7 +59,7 @@ void InitSysHIDFunctionPointers(void) return; } - unsigned int funcPointer = 0; + u32 funcPointer = 0; //! assigning those is not mandatory and it does not always work to load them OS_FIND_EXPORT(syshid_handle, HIDSetup); diff --git a/src/dynamic_libs/syshid_functions.h b/src/dynamic_libs/syshid_functions.h index 08213b4..9e29133 100644 --- a/src/dynamic_libs/syshid_functions.h +++ b/src/dynamic_libs/syshid_functions.h @@ -28,60 +28,62 @@ extern "C" { #endif -extern unsigned int syshid_handle; +#include + +extern u32 syshid_handle; typedef struct { - unsigned int handle; - unsigned int physical_device_inst; - unsigned short vid; - unsigned short pid; - unsigned char interface_index; - unsigned char sub_class; - unsigned char protocol; + u32 handle; + u32 physical_device_inst; + u16 vid; + u16 pid; + u8 interface_index; + u8 sub_class; + u8 protocol; - unsigned short max_packet_size_rx; - unsigned short max_packet_size_tx; + u16 max_packet_size_rx; + u16 max_packet_size_tx; } HIDDevice; typedef struct _HIDClient HIDClient; -#define HID_DEVICE_DETACH 0 -#define HID_DEVICE_ATTACH 1 +#define HID_DEVICE_DETACH 0 +#define HID_DEVICE_ATTACH 1 -typedef int (*HIDAttachCallback)(HIDClient *p_hc,HIDDevice *p_hd,unsigned int attach); +typedef s32 (*HIDAttachCallback)(HIDClient *p_hc,HIDDevice *p_hd,u32 attach); struct _HIDClient { - HIDClient *next; - HIDAttachCallback attach_cb; + HIDClient *next; + HIDAttachCallback attach_cb; }; -typedef void (*HIDCallback)(unsigned int handle,int error,unsigned char *p_buffer,unsigned int bytes_transferred,void *p_user); +typedef void (*HIDCallback)(u32 handle,s32 error,u8 *p_buffer,u32 bytes_transferred,void *p_user); void InitSysHIDFunctionPointers(void); void InitAcquireSysHID(void); -extern int(*HIDSetup)(void); -extern int(*HIDTeardown)(void); +extern s32(*HIDSetup)(void); +extern s32(*HIDTeardown)(void); -extern int(*HIDAddClient)(HIDClient *p_client, HIDAttachCallback attach_callback); -extern int(*HIDDelClient)(HIDClient *p_client); +extern s32(*HIDAddClient)(HIDClient *p_client, HIDAttachCallback attach_callback); +extern s32(*HIDDelClient)(HIDClient *p_client); -extern int(*HIDGetDescriptor)(unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); -extern int(*HIDSetDescriptor)(unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDGetDescriptor)(u32 handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDSetDescriptor)(u32 handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -extern int(*HIDGetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -extern int(*HIDSetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDGetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDSetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); -extern int(*HIDSetIdle)(unsigned int handle, u8 interface_index,u8 duration, HIDCallback hc, void *p_user); +extern s32(*HIDSetIdle)(u32 handle, u8 s32erface_index,u8 duration, HIDCallback hc, void *p_user); -extern int(* HIDSetProtocol)(unsigned int handle,u8 interface_index,u8 protocol, HIDCallback hc, void *p_user); -extern int(* HIDGetProtocol)(unsigned int handle,u8 interface_index,u8 * protocol, HIDCallback hc, void *p_user); +extern s32(* HIDSetProtocol)(u32 handle,u8 s32erface_index,u8 protocol, HIDCallback hc, void *p_user); +extern s32(* HIDGetProtocol)(u32 handle,u8 s32erface_index,u8 * protocol, HIDCallback hc, void *p_user); -extern int(*HIDRead)(unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); -extern int(*HIDWrite)(unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDRead)(u32 handle, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +extern s32(*HIDWrite)(u32 handle, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); #ifdef __cplusplus } diff --git a/src/dynamic_libs/vpad_functions.c b/src/dynamic_libs/vpad_functions.c index 201cf34..4af3b49 100644 --- a/src/dynamic_libs/vpad_functions.c +++ b/src/dynamic_libs/vpad_functions.c @@ -24,15 +24,15 @@ #include "os_functions.h" #include "vpad_functions.h" -unsigned int vpad_handle __attribute__((section(".data"))) = 0; -unsigned int vpadbase_handle __attribute__((section(".data"))) = 0; +u32 vpad_handle __attribute__((section(".data"))) = 0; +u32 vpadbase_handle __attribute__((section(".data"))) = 0; EXPORT_DECL(void, VPADInit, void); -EXPORT_DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error); -EXPORT_DECL(int, VPADGetLcdMode, int padnum, int *lcdmode); -EXPORT_DECL(int, VPADSetLcdMode, int padnum, int lcdmode); -EXPORT_DECL(int, VPADBASEGetMotorOnRemainingCount, int padnum); -EXPORT_DECL(int, VPADBASESetMotorOnRemainingCount, int padnum, int counter); +EXPORT_DECL(s32, VPADRead, s32 chan, VPADData *buffer, u32 buffer_size, s32 *error); +EXPORT_DECL(s32, VPADGetLcdMode, s32 padnum, s32 *lcdmode); +EXPORT_DECL(s32, VPADSetLcdMode, s32 padnum, s32 lcdmode); +EXPORT_DECL(s32, VPADBASEGetMotorOnRemainingCount, s32 padnum); +EXPORT_DECL(s32, VPADBASESetMotorOnRemainingCount, s32 padnum, s32 counter); void InitAcquireVPad(void) { @@ -42,7 +42,7 @@ void InitAcquireVPad(void) void InitVPadFunctionPointers(void) { - unsigned int *funcPointer = 0; + u32 *funcPointer = 0; InitAcquireVPad(); diff --git a/src/dynamic_libs/vpad_functions.h b/src/dynamic_libs/vpad_functions.h index 4fafda2..483ccbd 100644 --- a/src/dynamic_libs/vpad_functions.h +++ b/src/dynamic_libs/vpad_functions.h @@ -28,11 +28,11 @@ extern "C" { #endif -extern unsigned int vpad_handle; -extern unsigned int vpadbase_handle; - #include +extern u32 vpad_handle; +extern u32 vpadbase_handle; + #define VPAD_BUTTON_A 0x8000 #define VPAD_BUTTON_B 0x4000 #define VPAD_BUTTON_X 0x2000 @@ -73,6 +73,11 @@ typedef struct f32 x,y; } Vec2D; +typedef struct +{ + f32 x,y,z; +} Vec3D; + typedef struct { u16 x, y; /* Touch coordinates */ @@ -86,26 +91,29 @@ typedef struct u32 btns_d; /* Buttons that are pressed at that instant */ u32 btns_r; /* Released buttons */ Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */ - char unknown1c[0x52 - 0x1c]; /* Contains accelerometer and gyroscope data somewhere */ + char unknown1c[0x38 - 0x1c]; /* Contains accelerometer data somewhere */ + Vec3D gyro; /* Gyro data */ + Vec3D angle; /* Angle data */ + char unknown50[0x52 - 0x50]; /* Two bytes of unknown data */ VPADTPData tpdata; /* Normal touchscreen data */ VPADTPData tpdata1; /* Modified touchscreen data 1 */ VPADTPData tpdata2; /* Modified touchscreen data 2 */ char unknown6a[0xa0 - 0x6a]; - uint8_t volume; - uint8_t battery; /* 0 to 6 */ - uint8_t unk_volume; /* One less than volume */ + u8 volume; + u8 battery; /* 0 to 6 */ + u8 unk_volume; /* One less than volume */ char unknowna4[0xac - 0xa4]; } VPADData; void InitVPadFunctionPointers(void); void InitAcquireVPad(void); -extern int (* VPADRead)(int chan, VPADData *buffer, u32 buffer_size, s32 *error); -extern int (* VPADGetLcdMode)(int padnum, int *lcdmode); -extern int (* VPADSetLcdMode)(int padnum, int lcdmode); +extern s32 (* VPADRead)(s32 chan, VPADData *buffer, u32 buffer_size, s32 *error); +extern s32 (* VPADGetLcdMode)(s32 padnum, s32 *lcdmode); +extern s32 (* VPADSetLcdMode)(s32 padnum, s32 lcdmode); extern void (* VPADInit)(void); -extern int (* VPADBASEGetMotorOnRemainingCount)(int lcdmode); -extern int (* VPADBASESetMotorOnRemainingCount)(int lcdmode,int counter); +extern s32 (* VPADBASEGetMotorOnRemainingCount)(s32 lcdmode); +extern s32 (* VPADBASESetMotorOnRemainingCount)(s32 lcdmode,s32 counter); #ifdef __cplusplus } diff --git a/src/entry.c b/src/entry.c index ef317ff..aad6777 100644 --- a/src/entry.c +++ b/src/entry.c @@ -5,6 +5,7 @@ #include "utils/utils.h" #include "main.h" #include "lib_easy.h" +#include "draw.h" int __entry_menu(int argc, char **argv) { diff --git a/src/fs/fs_utils.c b/src/fs/fs_utils.c index 613cec6..a748029 100644 --- a/src/fs/fs_utils.c +++ b/src/fs/fs_utils.c @@ -173,7 +173,7 @@ int CreateSubfolder(const char * fullpath) if(!result) return 0; - if (mkdir(dirnoslash, 0777) == -1) + if (mkdir(dirnoslash, 0x777) == -1) { return 0; } diff --git a/src/icon.h b/src/icon.h new file mode 100644 index 0000000..439bda3 --- /dev/null +++ b/src/icon.h @@ -0,0 +1,640 @@ +#ifndef _ICON_H_ +#define _ICON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned char icon_tga[] = { + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x60, 0x00, 0x20, 0x08, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, + 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, + 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xbb, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xb7, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xb7, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xb7, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xbb, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xb7, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x9b, 0x7f, + 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xb3, + 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x9b, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xb3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x9b, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xb3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x9b, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xb3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xd3, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x93, 0xd8, + 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xd3, + 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x93, 0xd8, 0xd8, + 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xd8, + 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x93, 0xd8, 0xd8, 0xd8, + 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xd8, 0xd8, + 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x93, 0xd8, 0xd8, 0xd8, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, + 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, + 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, + 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, + 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x7f, 0x7f, 0x7f, 0xff, 0x87, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x7f, 0x7f, 0x7f, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xd8, 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0xa3, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x87, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, + 0x56, 0x4d, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0xa3, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xbb, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xbb, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xbb, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xbb, 0xce, 0x56, + 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, + 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0xbb, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xbb, + 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xbb, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0xbb, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0x17, + 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x83, 0x17, 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0xab, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0x17, 0xdd, 0x8e, + 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xce, 0x56, 0x4d, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, + 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x8b, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, + 0xff, 0x83, 0x17, 0xdd, 0x8e, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, + 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, + 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, + 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, + 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, + 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, + 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, + 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0xa3, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, + 0x4d, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, + 0x97, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, + 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0xc3, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xa3, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xd8, 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, + 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8f, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, + 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0xcf, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, + 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8f, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8f, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, + 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x87, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, + 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, + 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, + 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, + 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x83, + 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x83, 0xb0, 0xe4, + 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x83, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x8b, + 0x17, 0xdd, 0x8e, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xd8, 0xd8, + 0xd8, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, + 0x87, 0x00, 0x00, 0x00, 0xff, 0x8f, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xd3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, + 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, + 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, + 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xd8, 0xd8, 0xd8, 0xff, + 0x8b, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, + 0x00, 0x00, 0xff, 0xb7, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xd3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xd8, 0xd8, 0xd8, + 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, + 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, + 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, + 0x83, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, + 0x00, 0x00, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0x00, 0x00, 0x00, + 0xff, 0xb7, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x87, 0x00, 0x00, + 0x00, 0xff, 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, + 0x83, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, + 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, + 0x56, 0x4d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0xa3, 0xb0, 0xe4, 0xef, + 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x87, 0xce, 0x56, 0x4d, 0xff, 0x83, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, + 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xc3, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, + 0xd8, 0xff, 0x8b, 0xd8, 0xd8, 0xd8, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xaf, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, + 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, + 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, + 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, + 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, + 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xff, 0xd8, 0xd8, + 0xd8, 0xff +}; +unsigned int icon_tga_len = 7478; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib_easy.c b/src/lib_easy.c index 52b794e..d7a6bbe 100644 --- a/src/lib_easy.c +++ b/src/lib_easy.c @@ -6,34 +6,18 @@ VPADData vpad; int screen_buf0_size = 0; int screen_buf1_size = 0; -void flipBuffers() { - // Flush the cache - DCFlushRange(screenBuffer, screen_buf0_size); - DCFlushRange((screenBuffer + screen_buf0_size), screen_buf1_size); - // Flip buffers - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); -} - -void ucls() { - for(int i=0;i<2;i++) { - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - flipBuffers(); - } -} - void ScreenInit() { - //Init screen and screen buffers - OSScreenInit(); - screen_buf0_size = OSScreenGetBufferSizeEx(0); - screen_buf1_size = OSScreenGetBufferSizeEx(1); - screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x40); - OSScreenSetBufferEx(0, screenBuffer); - OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); - OSScreenEnableEx(0, 1); - OSScreenEnableEx(1, 1); - ucls(); //Clear screens + //Init screen and screen buffers + OSScreenInit(); + screen_buf0_size = OSScreenGetBufferSizeEx(0); + screen_buf1_size = OSScreenGetBufferSizeEx(1); + screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x100); + OSScreenSetBufferEx(0, screenBuffer); + OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); + OSScreenEnableEx(0, 1); + OSScreenEnableEx(1, 1); + clearBuffers(); //Clear screens + initDraw(screenBuffer, screen_buf0_size, screen_buf1_size); } void updatePressedButtons() { @@ -51,6 +35,27 @@ void updateReleasedButtons() { buttons_released = vpad.btns_r; } +bool stickPos(u8 stick, f32 value) { + switch(stick) { + case 0 : + return (value > 0) ? (vpad.lstick.x > value): (vpad.lstick.x < value); + case 1 : + return (value > 0) ? (vpad.lstick.y > value): (vpad.lstick.y < value); + case 2 : + return (value > 0) ? (vpad.rstick.x > value): (vpad.rstick.x < value); + case 3 : + return (value > 0) ? (vpad.rstick.y > value): (vpad.rstick.y < value); + case 4 : + return ((vpad.lstick.x > value) || (vpad.lstick.x < -value)) || \ + ((vpad.lstick.y > value) || (vpad.lstick.y < -value)) || \ + ((vpad.rstick.x > value) || (vpad.rstick.x < -value)) || \ + ((vpad.rstick.y > value) || (vpad.rstick.y < -value)); + + default : + return 0; + } +} + int isPressed(int button) { return (buttons_pressed&button); } @@ -64,27 +69,27 @@ int isReleased(int button) { } void uInit() { - //--Initialize every function pointer-- (byebye FindExport :D) - InitOSFunctionPointers(); - InitSocketFunctionPointers(); - InitACPFunctionPointers(); - InitAocFunctionPointers(); - InitAXFunctionPointers(); - InitCurlFunctionPointers(); - InitFSFunctionPointers(); - InitGX2FunctionPointers(); - InitPadScoreFunctionPointers(); - InitSysFunctionPointers(); - InitSysHIDFunctionPointers(); - InitVPadFunctionPointers(); + //--Initialize every function pointer-- (byebye FindExport :D) + InitOSFunctionPointers(); + InitSocketFunctionPointers(); + InitACPFunctionPointers(); + InitAocFunctionPointers(); + InitAXFunctionPointers(); + InitCurlFunctionPointers(); + InitFSFunctionPointers(); + InitGX2FunctionPointers(); + InitPadScoreFunctionPointers(); + InitSysFunctionPointers(); + InitSysHIDFunctionPointers(); + InitVPadFunctionPointers(); - memoryInitialize(); //You probably shouldn't care about this for now :P - VPADInit(); //Init GamePad input library (needed for getting gamepad input) - ScreenInit(); //Init OSScreen (all the complex stuff is in easyfunctions.h :P ) + memoryInitialize(); //You probably shouldn't care about this for now :P + VPADInit(); //Init GamePad input library (needed for getting gamepad input) + ScreenInit(); //Init OSScreen (all the complex stuff is in easyfunctions.h :P ) } void uDeInit() { - MEM1_free(screenBuffer); - screenBuffer = NULL; - memoryRelease(); + MEM1_free(screenBuffer); + screenBuffer = NULL; + memoryRelease(); } diff --git a/src/lib_easy.h b/src/lib_easy.h index 27d1867..e8f46ab 100644 --- a/src/lib_easy.h +++ b/src/lib_easy.h @@ -43,12 +43,11 @@ uint32_t buttons_hold; //Held buttons uint32_t buttons_pressed; //Pressed buttons uint32_t buttons_released; //Released buttons -void ucls(); void ScreenInit(); -void flipBuffers(); void updatePressedButtons(); void updateHeldButtons(); void updateReleasedButtons(); +bool stickPos(u8 stick, f32 value); int isPressed(int button); int isHeld(int button); int isReleased(int button); diff --git a/src/main.c b/src/main.c index f5b4b1d..520d962 100644 --- a/src/main.c +++ b/src/main.c @@ -2,22 +2,25 @@ #include #include #include -#include -#include -#include #include "main.h" #include "savemng.h" +#include "icon.h" #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_MICRO 0 +#define VERSION_MOD "mod5" +#define M_OFF 3 u8 slot = 0; -bool allusers = 0, common = 1; -int menu = 0, mode = 0, task = 0, targ = 0; +s8 allusers = -1, allusers_d = -1, sdusers = -1; +bool common = 1; +int menu = 0, mode = 0, task = 0, targ = 0, tsort = 1, sorta = 1; int cursor = 0, scroll = 0; +int cursorb = 0, cursort = 0, scrollb = 0; int titleswiiu = 0, titlesvwii = 0; +const char *sortn[4] = {"None", "Name", "Storage", "Storage+Name"}; //just to be able to call async void someFunc(void *arg) { @@ -28,10 +31,10 @@ static int mcp_hook_fd = -1; int MCPHookOpen() { //take over mcp thread mcp_hook_fd = MCP_Open(); - if(mcp_hook_fd < 0) return -1; + if (mcp_hook_fd < 0) return -1; IOS_IoctlAsync(mcp_hook_fd, 0x62, (void*)0, 0, (void*)0, 0, someFunc, (void*)0); //let wupserver start up - sleep(1); + os_sleep(1); if (IOSUHAX_Open("/dev/mcp") < 0) { MCP_Close(mcp_hook_fd); mcp_hook_fd = -1; @@ -41,159 +44,374 @@ int MCPHookOpen() { } void MCPHookClose() { - if(mcp_hook_fd < 0) return; + if (mcp_hook_fd < 0) return; //close down wupserver, return control to mcp IOSUHAX_Close(); //wait for mcp to return - sleep(1); + os_sleep(1); MCP_Close(mcp_hook_fd); mcp_hook_fd = -1; } -Title* loadWiiUTitles() { +int titleSort(const void *c1, const void *c2) +{ + if (tsort == 0) { + return ((Title*)c1)->listID - ((Title*)c2)->listID; + } else if (tsort == 1) { + return strcmp(((Title*)c1)->shortName,((Title*)c2)->shortName) * sorta; + } else if (tsort == 2) { + if (((Title*)c1)->isTitleOnUSB == ((Title*)c2)->isTitleOnUSB) + return 0; + if (((Title*)c1)->isTitleOnUSB) + return -1 * sorta; + if (((Title*)c2)->isTitleOnUSB) + return 1 * sorta; + return 0; + } else if (tsort == 3) { + if (((Title*)c1)->isTitleOnUSB && !((Title*)c2)->isTitleOnUSB) + return -1 * sorta; + if (!((Title*)c1)->isTitleOnUSB && ((Title*)c2)->isTitleOnUSB) + return 1 * sorta; + return strcmp(((Title*)c1)->shortName,((Title*)c2)->shortName) * sorta; + } +} + +Title* loadWiiUTitles(int run, int fsaFd) { + static char *tList; + static int receivedCount; // Source: haxchi installer - int mcp_handle = MCP_Open(); - int count = MCP_TitleCount(mcp_handle); - int listSize = count*0x61; - char *tList = memalign(32, listSize); - memset(tList, 0, listSize); - int receivedCount = count; - MCP_TitleList(mcp_handle, &receivedCount, tList, listSize); - MCP_Close(mcp_handle); + if (run == 0) { + int mcp_handle = MCP_Open(); + int count = MCP_TitleCount(mcp_handle); + int listSize = count*0x61; + tList = memalign(32, listSize); + memset(tList, 0, listSize); + receivedCount = count; + MCP_TitleList(mcp_handle, &receivedCount, tList, listSize); + MCP_Close(mcp_handle); + return NULL; + } - Title* titles = malloc(receivedCount*sizeof(Title)); + int usable = receivedCount, j = 0; + Saves* savesl = malloc(receivedCount*sizeof(Saves)); + if (!savesl) { + promptError("Out of memory."); + return NULL; + } + for (int i = 0; i < receivedCount; i++) { + char* element = tList+(i*0x61); + savesl[j].highID = *(u32*)(element); + if (savesl[j].highID != 0x00050000) { + usable--; + continue; + } + savesl[j].lowID = *(u32*)(element+4); + savesl[j].dev = !(memcmp(element+0x56, "usb", 4) == 0); + savesl[j].found = false; + j++; + } + savesl = realloc(savesl, usable * sizeof(Saves)); + + int dirUH, dirNH, foundCount = 0, pos = 0, tNoSave = usable; + for (int i = 0; i <= 1; i++) { + char path[255]; + sprintf(path, "/vol/storage_%s01/usr/save/00050000", (i == 0) ? "usb" : "mlc"); + if (IOSUHAX_FSA_OpenDir(fsaFd, path, &dirUH) >= 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirUH, &data); + if (ret != 0) + break; + + sprintf(path, "/vol/storage_%s01/usr/save/00050000/%s/user", (i == 0) ? "usb" : "mlc", data.name); + if (checkEntry(path) == 2) { + sprintf(path, "/vol/storage_%s01/usr/save/00050000/%s/meta/meta.xml", (i == 0) ? "usb" : "mlc", data.name); + if (checkEntry(path) == 1) { + for (int i = 0; i < usable; i++) { + if ((savesl[i].highID == 0x00050000) && (strtoul(data.name, NULL, 16) == savesl[i].lowID)) { + savesl[i].found = true; + tNoSave--; + break; + } + } + foundCount++; + } + } + } + IOSUHAX_FSA_CloseDir(fsaFd, dirUH); + } + } + + foundCount += tNoSave; + Saves* saves = malloc((foundCount + tNoSave)*sizeof(Saves)); + if (!saves) { + promptError("Out of memory."); + return NULL; + } + + for (int i = 0; i <= 1; i++) { + char path[255]; + sprintf(path, "/vol/storage_%s01/usr/save/00050000", (i == 0) ? "usb" : "mlc"); + if (IOSUHAX_FSA_OpenDir(fsaFd, path, &dirUH) >= 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirUH, &data); + if (ret != 0) + break; + + sprintf(path, "/vol/storage_%s01/usr/save/00050000/%s/meta/meta.xml", (i == 0) ? "usb" : "mlc", data.name); + if (checkEntry(path) == 1) { + saves[pos].highID = 0x00050000; + saves[pos].lowID = strtoul(data.name, NULL, 16); + saves[pos].dev = i; + saves[pos].found = false; + pos++; + } + } + IOSUHAX_FSA_CloseDir(fsaFd, dirUH); + } + } + + for (int i = 0; i < usable; i++) { + if (!savesl[i].found) { + saves[pos].highID = savesl[i].highID; + saves[pos].lowID = savesl[i].lowID; + saves[pos].dev = savesl[i].dev; + saves[pos].found = true; + pos++; + } + } + + Title* titles = malloc(foundCount*sizeof(Title)); if (!titles) { promptError("Out of memory."); return NULL; } - for (int i = 0; i < receivedCount; i++) { + for (int i = 0; i < foundCount; i++) { + int srcFd = -1; + u32 highID = saves[i].highID, lowID = saves[i].lowID; + bool isTitleOnUSB = !saves[i].dev; - char* element = tList+(i*0x61); - u32 highID = *(u32*)(element), lowID = *(u32*)(element+4); - if (highID!=0x00050000) continue; - bool isTitleOnUSB = (memcmp(element+0x56,"usb",4)==0); char path[255]; memset(path, 0, 255); - if (memcmp(element+0x56,"odd",4)==0) strcpy(path, "storage_odd:/meta/meta.xml"); - else sprintf(path, "storage_%s:/usr/title/%08x/%08x/meta/meta.xml", element+0x56, highID, lowID); + if (saves[i].found) + sprintf(path, "/vol/storage_%s01/usr/title/%08x/%08x/meta/meta.xml", isTitleOnUSB ? "usb" : "mlc", highID, lowID); + else + sprintf(path, "/vol/storage_%s01/usr/save/%08x/%08x/meta/meta.xml", isTitleOnUSB ? "usb" : "mlc", highID, lowID); + titles[titleswiiu].saveInit = !saves[i].found; - FILE* xmlFile = fopen(path, "rb"); - if (xmlFile) { - fseek(xmlFile, 0, SEEK_END); - size_t xmlSize = ftell(xmlFile); - fseek(xmlFile, 0, SEEK_SET); - char* xmlBuf = malloc(xmlSize+1); - if (xmlBuf) { - memset(xmlBuf, 0, xmlSize+1); - fread(xmlBuf, 1, xmlSize, xmlFile); - fclose(xmlFile); + char* xmlBuf = NULL; + if (loadFile(path, &xmlBuf) > 0) { + char *cptr = strchr(strstr(xmlBuf, "product_code"), '>') + 7; + memset(titles[titleswiiu].productCode, 0, sizeof(titles[titleswiiu].productCode)); + strncpy(titles[titleswiiu].productCode, cptr, strcspn(cptr, "<")); - xmlDocPtr tmp = xmlReadMemory(xmlBuf, xmlSize, "meta.xml", "utf-8", 0); - xmlNode* root_element = xmlDocGetRootElement(tmp); - xmlNode* cur_node = NULL; - for (cur_node = root_element->children; cur_node; cur_node = cur_node->next) { - if ( - (cur_node->type != XML_ELEMENT_NODE) || - (xmlNodeGetContent(cur_node) == NULL) || - (!strlen((char*)xmlNodeGetContent(cur_node))) - ) continue; + cptr = strchr(strstr(xmlBuf, "shortname_en"), '>') + 1; + memset(titles[titleswiiu].shortName, 0, sizeof(titles[titleswiiu].shortName)); + if (strcspn(cptr, "<") == 0) + cptr = strchr(strstr(xmlBuf, "shortname_ja"), '>') + 1; + strncpy(titles[titleswiiu].shortName, cptr, strcspn(cptr, "<")); - if (!memcmp(cur_node->name, "shortname_en", 13)) - strcpy(titles[titleswiiu].shortName, (char*)xmlNodeGetContent(cur_node)); - if (!memcmp(cur_node->name, "product_code", 13)) - strcpy(titles[titleswiiu].productCode, (char*)(xmlNodeGetContent(cur_node)+6)); - } + cptr = strchr(strstr(xmlBuf, "longname_en"), '>') + 1; + memset(titles[i].longName, 0, sizeof(titles[i].longName)); + if (strcspn(cptr, "<") == 0) + cptr = strchr(strstr(xmlBuf, "longname_ja"), '>') + 1; + strncpy(titles[titleswiiu].longName, cptr, strcspn(cptr, "<")); - xmlFreeDoc(tmp); - free(xmlBuf); - } + free(xmlBuf); } + titles[titleswiiu].isTitleDupe = false; + for (int i = 0; i < titleswiiu; i++) { + if ((titles[i].highID == highID) && (titles[i].lowID == lowID)) { + titles[titleswiiu].isTitleDupe = true; + titles[titleswiiu].dupeID = i; + titles[i].isTitleDupe = true; + titles[i].dupeID = titleswiiu; + } + } + titles[titleswiiu].highID = highID; titles[titleswiiu].lowID = lowID; titles[titleswiiu].isTitleOnUSB = isTitleOnUSB; + titles[titleswiiu].listID = titleswiiu; + if (loadTitleIcon(&titles[titleswiiu]) < 0) titles[titleswiiu].iconBuf = NULL; titleswiiu++; OSScreenClearBufferEx(0, 0); OSScreenClearBufferEx(1, 0); - console_print_pos(0, 0, "Loaded %i Wii U titles.", titleswiiu); - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); + drawTGA(298, 144, 1, icon_tga); + console_print_pos_aligned(10, 0, 1, "Loaded %i Wii U titles.", titleswiiu); + flipBuffers(); } + free(savesl); + free(saves); free(tList); return titles; } -Title* loadWiiTitles() { +Title* loadWiiTitles(int fsaFd) { + int dirH; + char* highIDs[3] = {"00010000", "00010001", "00010004"}; + bool found = false; + u32* blacklist[7][2] = {{0x00010000, 0x00555044}, {0x00010000, 0x00555045}, \ + {0x00010000, 0x0055504A}, {0x00010000, 0x524F4E45}, \ + {0x00010000, 0x52543445}, {0x00010001, 0x48424344}, + {0x00010001, 0x554E454F}}; - struct dirent* dirent = NULL; - DIR* dir = NULL; + char pathW[256]; + for (int k = 0; k < 3; k++) { + sprintf(pathW, "/vol/storage_slccmpt01/title/%s", highIDs[k]); + if (IOSUHAX_FSA_OpenDir(fsaFd, pathW, &dirH) >= 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) break; + for (int ii = 0; ii < 7; ii++) { + if (blacklist[ii][0] == strtoul(highIDs[k], NULL, 16)) { + if (blacklist[ii][1] == strtoul(data.name, NULL, 16)) {found = true; break;} + } + } if (found) {found = false; continue;} - dir = opendir("slccmpt01:/title/00010000"); - if (dir == NULL) return NULL; + titlesvwii++; + } IOSUHAX_FSA_CloseDir(fsaFd, dirH); + } + } + if (titlesvwii == 0) return NULL; - while ((dirent = readdir(dir)) != 0) { - if(strcmp(dirent->d_name, "..")==0 || strcmp(dirent->d_name, ".")==0) continue; - titlesvwii++; - } rewinddir(dir); - - Title* titles = malloc(titlesvwii*sizeof(Title)); + Title* titles = malloc(titlesvwii * sizeof(Title)); if (!titles) { promptError("Out of memory."); return NULL; } int i = 0; - while ((dirent = readdir(dir)) != 0) { + for (int k = 0; k < 3; k++) { + sprintf(pathW, "/vol/storage_slccmpt01/title/%s", highIDs[k]); + if (IOSUHAX_FSA_OpenDir(fsaFd, pathW, &dirH) >= 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) break; + for (int ii = 0; ii < 7; ii++) { + if (blacklist[ii][0] == strtoul(highIDs[k], NULL, 16)) { + if (blacklist[ii][1] == strtoul(data.name, NULL, 16)) {found = true; break;} + } + } if (found) {found = false; continue;} - if(strcmp(dirent->d_name, "..")==0 || strcmp(dirent->d_name, ".")==0) continue; + int srcFd = -1; + char path[256]; + sprintf(path, "/vol/storage_slccmpt01/title/%s/%s/data/banner.bin", highIDs[k], data.name); + ret = IOSUHAX_FSA_OpenFile(fsaFd, path, "rb", &srcFd); + if (ret >= 0) { + IOSUHAX_FSA_SetFilePos(fsaFd, srcFd, 0x20); + u16* bnrBuf = (u16*)malloc(0x80); + if (bnrBuf) { + IOSUHAX_FSA_ReadFile(fsaFd, bnrBuf, 0x02, 0x40, srcFd, 0); + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); - char path[256]; - sprintf(path, "slccmpt01:/title/00010000/%s/data/banner.bin", dirent->d_name); - FILE* bnrFile = fopen(path, "rb"); - if (bnrFile) { - fseek(bnrFile, 0x20, SEEK_SET); - u16* bnrBuf = (u16*)malloc(0x40); - if (bnrBuf) { - fread(bnrBuf, 0x02, 0x20, bnrFile); - fclose(bnrFile); - for (int j = 0, k = 0; j < 0x20; j++) { - titles[i].shortName[k++] = (char)bnrBuf[j]; + memset(titles[i].shortName, 0, sizeof(titles[i].shortName)); + for (int j = 0, k = 0; j < 0x20; j++) { + if (bnrBuf[j] < 0x80) + titles[i].shortName[k++] = (char)bnrBuf[j]; + else if ((bnrBuf[j] & 0xF000) > 0) { + titles[i].shortName[k++] = 0xE0 | ((bnrBuf[j] & 0xF000) >> 12); + titles[i].shortName[k++] = 0x80 | ((bnrBuf[j] & 0xFC0) >> 6); + titles[i].shortName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } else if (bnrBuf[j] < 0x400) { + titles[i].shortName[k++] = 0xC0 | ((bnrBuf[j] & 0x3C0) >> 6); + titles[i].shortName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } else { + titles[i].shortName[k++] = 0xD0 | ((bnrBuf[j] & 0x3C0) >> 6); + titles[i].shortName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } + } + + memset(titles[i].longName, 0, sizeof(titles[i].longName)); + for (int j = 0x20, k = 0; j < 0x40; j++) { + if (bnrBuf[j] < 0x80) + titles[i].longName[k++] = (char)bnrBuf[j]; + else if ((bnrBuf[j] & 0xF000) > 0) { + titles[i].longName[k++] = 0xE0 | ((bnrBuf[j] & 0xF000) >> 12); + titles[i].longName[k++] = 0x80 | ((bnrBuf[j] & 0xFC0) >> 6); + titles[i].longName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } else if (bnrBuf[j] < 0x400) { + titles[i].longName[k++] = 0xC0 | ((bnrBuf[j] & 0x3C0) >> 6); + titles[i].longName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } else { + titles[i].longName[k++] = 0xD0 | ((bnrBuf[j] & 0x3C0) >> 6); + titles[i].longName[k++] = 0x80 | (bnrBuf[j] & 0x3F); + } + } + + free(bnrBuf); + titles[i].saveInit = true; + } + } else { + sprintf(titles[i].shortName, "%s%s (No banner.bin)", highIDs[k], data.name); + memset(titles[i].longName, 0, sizeof(titles[i].longName)); + titles[i].saveInit = false; } - free(bnrBuf); + + titles[i].highID = strtoul(highIDs[k], NULL, 16); + titles[i].lowID = strtoul(data.name, NULL, 16); + + titles[i].listID = i; + memcpy(titles[i].productCode, &titles[i].lowID, 4); + for (int ii = 0; ii < 4; ii++) { + if (titles[i].productCode[ii] == 0) titles[i].productCode[ii] = '.'; + } + titles[i].productCode[4] = 0; + titles[i].isTitleOnUSB = false; + titles[i].isTitleDupe = false; + titles[i].dupeID = 0; + if (!titles[i].saveInit || (loadTitleIcon(&titles[i]) < 0)) titles[i].iconBuf = NULL; + i++; + + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + drawTGA(298, 144, 1, icon_tga); + console_print_pos_aligned(10, 0, 1, "Loaded %i Wii U titles.", titleswiiu); + console_print_pos_aligned(11, 0, 1, "Loaded %i Wii titles.", i); + flipBuffers(); } + IOSUHAX_FSA_CloseDir(fsaFd, dirH); } - - titles[i].highID = 0x00010000; - titles[i].lowID = strtoul(dirent->d_name, NULL, 16); - i++; - - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - console_print_pos(0, 1, "Loaded %i Wii titles.", i); - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); - } - closedir(dir); return titles; - } -void unloadTitles(Title* titles) { +void unloadTitles(Title* titles, int count) { + for (int i = 0; i < count; i++) { + if (titles[i].iconBuf) free(titles[i].iconBuf); + } if (titles) free(titles); } +void disclaimer() { + fillScreen(0, 0, 0, 0); + console_print_pos_aligned(3, 0, 1, "Savemii Mod"); + //drawTGA(298, 36, 1, icon_tga); + console_print_pos_aligned(6, 0, 1, "Created by: Ryuzaki-MrL"); + console_print_pos_aligned(7, 0, 1, "Modded by: GabyPCgeeK"); + console_print_pos_aligned(11, 0, 1, "Disclaimer:"); + console_print_pos_aligned(12, 0, 1, "There is always the potential for a brick."); + console_print_pos_aligned(13, 0, 1, "Everything you do with this software is your own responsibility"); + flipBuffers(); + os_sleep(4); +} + /* Entry point */ int Menu_Main(void) { - mount_sd_fat("sd"); + //mount_sd_fat("sd"); + loadWiiUTitles(0, -1); int res = IOSUHAX_Open(NULL); if (res < 0) { @@ -201,7 +419,7 @@ int Menu_Main(void) { } if (res < 0) { promptError("IOSUHAX_Open failed."); - unmount_sd_fat("sd"); + //unmount_sd_fat("sd"); return EXIT_SUCCESS; } @@ -210,29 +428,72 @@ int Menu_Main(void) { int fsaFd = IOSUHAX_FSA_Open(); if (fsaFd < 0) { promptError("IOSUHAX_FSA_Open failed."); - unmount_sd_fat("sd"); + //unmount_sd_fat("sd"); if (mcp_hook_fd >= 0) MCPHookClose(); else IOSUHAX_Close(); return EXIT_SUCCESS; } + setFSAFD(fsaFd); + IOSUHAX_FSA_Mount(fsaFd, "/dev/sdcard01", "/vol/storage_sdcard", 2, (void*)0, 0); + mount_fs("sd", fsaFd, NULL, "/vol/storage_sdcard"); mount_fs("slccmpt01", fsaFd, "/dev/slccmpt01", "/vol/storage_slccmpt01"); mount_fs("storage_mlc", fsaFd, NULL, "/vol/storage_mlc01"); mount_fs("storage_usb", fsaFd, NULL, "/vol/storage_usb01"); mount_fs("storage_odd", fsaFd, "/dev/odd03", "/vol/storage_odd_content"); - ucls(); - Title* wiiutitles = loadWiiUTitles(); - Title* wiititles = loadWiiTitles(); - int* versionList = (int*)malloc(0x100*sizeof(int)); + u8* fontBuf = NULL; + s32 fsize = loadFile("/vol/storage_sdcard/wiiu/apps/savemii_mod/font.ttf", &fontBuf); + if (fsize > 0) { + initFont(fontBuf, fsize); + } else initFont(NULL, 0); + + disclaimer(); + clearBuffers(); + Title* wiiutitles = loadWiiUTitles(1, fsaFd); + Title* wiititles = loadWiiTitles(fsaFd); + int* versionList = (int*)malloc(0x100 * sizeof(int)); + os_sleep(1); + getAccountsWiiU(); + + qsort(wiiutitles, titleswiiu, sizeof(Title), titleSort); + qsort(wiititles, titlesvwii, sizeof(Title), titleSort); + + u8* tgaBufDRC = NULL; + u8* tgaBufTV = NULL; + u8* fileContent = NULL; + u32 wDRC = 0, hDRC = 0, wTV = 0, hTV = 0; + + if (loadFile("/vol/storage_sdcard/wiiu/apps/savemii_mod/backgroundDRC.tga", &fileContent) > 0) { + wDRC = tgaGetWidth(fileContent); hDRC = tgaGetHeight(fileContent); + tgaBufDRC = tgaRead(fileContent, TGA_READER_RGBA); + free(fileContent); + fileContent = NULL; + } + + if (loadFile("/vol/storage_sdcard/wiiu/apps/savemii_mod/backgroundTV.tga", &fileContent) > 0) { + wTV = tgaGetWidth(fileContent); hTV = tgaGetHeight(fileContent); + tgaBufTV = tgaRead(fileContent, TGA_READER_RGBA); + free(fileContent); + fileContent = NULL; + } while(1) { + //u64 startTime = OSGetTime(); - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); + if (tgaBufDRC) { + drawBackgroundDRC(wDRC, hDRC, tgaBufDRC); + } else { + OSScreenClearBufferEx(1, 0x00006F00); + } + if (tgaBufTV) { + drawBackgroundTV(wTV, hTV, tgaBufTV); + } else { + OSScreenClearBufferEx(0, 0x00006F00); + } - console_print_pos(0, 0, "SaveMii v%u.%u.%u", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO); - console_print_pos(0, 1, "--------------------------------------------------"); + console_print_pos(0, 0, "SaveMii v%u.%u.%u.%s", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, VERSION_MOD); + console_print_pos(0, 1, "----------------------------------------------------------------------------"); Title* titles = mode ? wiititles : wiiutitles; int count = mode ? titlesvwii : titleswiiu; @@ -240,117 +501,413 @@ int Menu_Main(void) { switch(menu) { case 0: { // Main Menu - entrycount = 2; - console_print_pos(0, 2, " Wii U Save Management"); - console_print_pos(0, 3, " vWii Save Management"); - console_print_pos(0, 2 + cursor, "->"); + entrycount = 3; + console_print_pos(M_OFF, 2, " Wii U Save Management (%u Title%s)", titleswiiu, (titleswiiu > 1) ? "s": ""); + console_print_pos(M_OFF, 3, " vWii Save Management (%u Title%s)", titlesvwii, (titlesvwii > 1) ? "s": ""); + console_print_pos(M_OFF, 4, " Batch Backup"); + console_print_pos(M_OFF, 2 + cursor, "\u2192"); + console_print_pos_aligned(17, 4, 2, "\ue000: Select Mode"); } break; case 1: { // Select Title - entrycount = count; - for (int i = 0; i < 14; i++) { - if (i+scroll<0 || i+scroll>=count) break; - if (strlen(titles[i+scroll].shortName)) console_print_pos(0, i+2, " %s", titles[i+scroll].shortName); - else console_print_pos(0, i+2, " %08lx%08lx", titles[i+scroll].highID, titles[i+scroll].lowID); - } console_print_pos(0, 2 + cursor, "->"); + if (mode == 2) { + entrycount = 3; + console_print_pos(M_OFF, 2, " Backup All (%u Title%s)", titleswiiu + titlesvwii, ((titleswiiu + titlesvwii) > 1) ? "s": ""); + console_print_pos(M_OFF, 3, " Backup Wii U (%u Title%s)", titleswiiu, (titleswiiu > 1) ? "s": ""); + console_print_pos(M_OFF, 4, " Backup vWii (%u Title%s)", titlesvwii, (titlesvwii > 1) ? "s": ""); + console_print_pos(M_OFF, 2 + cursor, "\u2192"); + console_print_pos_aligned(17, 4, 2, "\ue000: Backup \ue001: Back"); + } else { + console_print_pos(40, 0, "\ue084 Sort: %s %s", sortn[tsort], (tsort > 0) ? ((sorta == 1) ? "\u2193 \ue083": "\u2191 \ue083"): ""); + entrycount = count; + for (int i = 0; i < 14; i++) { + if (i + scroll < 0 || i + scroll >= count) break; + ttfFontColor32(0x00FF00FF); + if (!titles[i + scroll].saveInit) ttfFontColor32(0xFFFF00FF); + if (strcmp(titles[i + scroll].shortName, "DONT TOUCH ME") == 0) ttfFontColor32(0xFF0000FF); + if (strlen(titles[i + scroll].shortName)) console_print_pos(M_OFF, i+2, " %s %s%s%s", titles[i + scroll].shortName, titles[i + scroll].isTitleOnUSB ? "(USB)" : ((mode == 0) ? "(NAND)" : ""), titles[i + scroll].isTitleDupe ? " [D]" : "", titles[i + scroll].saveInit ? "" : " [Not Init]"); + else console_print_pos(M_OFF, i+2, " %08lx%08lx", titles[i + scroll].highID, titles[i + scroll].lowID); + ttfFontColor32(0xFFFFFFFF); + if (mode == 0) { + if (titles[i + scroll].iconBuf) drawTGA((M_OFF + 4) * 12 - 2, (i + 3) * 24, 0.18, titles[i + scroll].iconBuf); + } else if (mode == 1) { + if (titles[i + scroll].iconBuf) drawRGB5A3((M_OFF + 2) * 12 - 2, (i + 3) * 24 + 3, 0.25, titles[i + scroll].iconBuf); + } + } + if (mode == 0) { + console_print_pos(0, 2 + cursor, "\u2192"); + } else if (mode == 1) { + console_print_pos(-1, 2 + cursor, "\u2192"); + } + console_print_pos_aligned(17, 4, 2, "\ue000: Select Game \ue001: Back"); + } } break; case 2: { // Select Task - entrycount = 3 + 2*(mode==0); - console_print_pos(0, 2, " Backup savedata"); - console_print_pos(0, 3, " Restore savedata"); - console_print_pos(0, 4, " Wipe savedata"); - if (mode==0) { - console_print_pos(0, 5, " Import from loadiine"); - console_print_pos(0, 6, " Export to loadiine"); + entrycount = 3 + 2 * (mode == 0) + 1 * ((mode == 0) && (titles[targ].isTitleDupe)); + console_print_pos(M_OFF, 2, " [%08X-%08X] [%s]", titles[targ].highID, titles[targ].lowID, titles[targ].productCode); + console_print_pos(M_OFF, 3, " %s", titles[targ].shortName); + //console_print_pos(M_OFF, 4, " %s", titles[targ].longName); + console_print_pos(M_OFF, 5, " Backup savedata"); + console_print_pos(M_OFF, 6, " Restore savedata"); + console_print_pos(M_OFF, 7, " Wipe savedata"); + if (mode == 0) { + console_print_pos(M_OFF, 8, " Import from loadiine"); + console_print_pos(M_OFF, 9, " Export to loadiine"); + if (titles[targ].isTitleDupe) { + console_print_pos(M_OFF, 10, " Copy Savedata to Title in %s", titles[targ].isTitleOnUSB ? "NAND" : "USB"); + } + if (titles[targ].iconBuf) drawTGA(660, 80, 1, titles[targ].iconBuf); + } else if (mode == 1) { + if (titles[targ].iconBuf) drawRGB5A3(650, 80, 1, titles[targ].iconBuf); } - console_print_pos(0, 2 + cursor, "->"); + console_print_pos(M_OFF, 2 + 3 + cursor, "\u2192"); + console_print_pos_aligned(17, 4, 2, "\ue000: Select Task \ue001: Back"); } break; case 3: { // Select Options - entrycount = 1 + 2*(mode==0); - console_print_pos(0, 2, "Select %s:", task>2 ? "version" : "slot"); - if (task > 2) console_print_pos(0, 3, " < v%u >", versionList ? versionList[slot] : 0); - else console_print_pos(0, 3, " < %03u >", slot); - if (mode==0) { - console_print_pos(0, 5, "Select user:"); - console_print_pos(0, 6, " < %s >", (allusers&&(task<3)) ? "all users" : "this user"); - console_print_pos(0, 8, "Include 'common' save?"); - console_print_pos(0, 9, " < %s >", common ? "yes" : "no "); - console_print_pos(0, 3 + cursor*3, "->"); + entrycount = 3; + console_print_pos(M_OFF, 2, "[%08X-%08X] %s", titles[targ].highID, titles[targ].lowID, titles[targ].shortName); + + if (task == 5) { + console_print_pos(M_OFF, 4, "Destination:"); + console_print_pos(M_OFF, 5, " (%s)", titles[targ].isTitleOnUSB ? "NAND" : "USB"); + } else if (task > 2) { + entrycount = 2; + console_print_pos(M_OFF, 4, "Select %s:", "version"); + console_print_pos(M_OFF, 5, " < v%u >", versionList ? versionList[slot] : 0); + } else if (task == 2) { + console_print_pos(M_OFF, 4, "Delete from:"); + console_print_pos(M_OFF, 5, " (%s)", titles[targ].isTitleOnUSB ? "USB" : "NAND"); + } else { + console_print_pos(M_OFF, 4, "Select %s:", "slot"); + + if (((titles[targ].highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) { + console_print_pos(M_OFF, 5, " < SaveGame Manager GX > (%s)", isSlotEmpty(titles[targ].highID, titles[targ].lowID, slot) ? "Empty" : "Used"); + } else { + console_print_pos(M_OFF, 5, " < %03u > (%s)", slot, isSlotEmpty(titles[targ].highID, titles[targ].lowID, slot) ? "Empty" : "Used"); + } + } + + if (mode == 0) { + if (task == 1) { + if (!isSlotEmpty(titles[targ].highID, titles[targ].lowID, slot)) { + entrycount++; + console_print_pos(M_OFF, 7, "Select SD user to copy from:"); + if (sdusers == -1) + console_print_pos(M_OFF, 8, " < %s >", "all users"); + else + console_print_pos(M_OFF, 8, " < %s > (%s)", sdacc[sdusers].persistentID, hasAccountSave(&titles[targ], true, false, sdacc[sdusers].pID, slot, 0) ? "Has Save" : "Empty"); + } + } + + if (task == 2) { + console_print_pos(M_OFF, 7, "Select Wii U user to delete from:"); + if (allusers == -1) + console_print_pos(M_OFF, 8, " < %s >", "all users"); + else + console_print_pos(M_OFF, 8, " < %s (%s) > (%s)", wiiuacc[allusers].miiName, wiiuacc[allusers].persistentID, hasAccountSave(&titles[targ], false, false, wiiuacc[allusers].pID, slot, 0) ? "Has Save" : "Empty"); + } + + if ((task == 0) || (task == 1) || (task == 5)) { + if ((task == 1) && isSlotEmpty(titles[targ].highID, titles[targ].lowID, slot)) { + entrycount--; + } else { + console_print_pos(M_OFF, (task == 1) ? 10 : 7, "Select Wii U user%s:", (task == 5) ? " to copy from" : ((task == 1) ? " to copy to" : "")); + if (allusers == -1) + console_print_pos(M_OFF, (task == 1) ? 11 : 8, " < %s >", "all users"); + else + console_print_pos(M_OFF, (task == 1) ? 11 : 8, " < %s (%s) > (%s)", wiiuacc[allusers].miiName, wiiuacc[allusers].persistentID, hasAccountSave(&titles[targ], ((task == 0) || (task == 1) || (task == 5) ? false : true), ((task < 3) || (task == 5) ? false : true), wiiuacc[allusers].pID, slot, versionList ? versionList[slot] : 0) ? "Has Save" : "Empty"); + } + } + + if (task == 5) { + entrycount++; + console_print_pos(M_OFF, 10, "Select Wii U user%s:", (task == 5) ? " to copy to" : ""); + if (allusers_d == -1) + console_print_pos(M_OFF, 11, " < %s >", "all users"); + else + console_print_pos(M_OFF, 11, " < %s (%s) > (%s)", wiiuacc[allusers_d].miiName, wiiuacc[allusers_d].persistentID, hasAccountSave(&titles[titles[targ].dupeID], false, false, wiiuacc[allusers_d].pID, 0, 0) ? "Has Save" : "Empty"); + } + + if ((task != 3) && (task != 4)) { + if (allusers > -1) { + if (hasCommonSave(&titles[targ], ((task == 0) || (task == 2) || (task == 5) ? false : true), ((task < 3) || (task == 5) ? false : true), slot, versionList ? versionList[slot] : 0)) { + console_print_pos(M_OFF, (task == 1) || (task == 5) ? 13 : 10, "Include 'common' save?"); + console_print_pos(M_OFF, (task == 1) || (task == 5) ? 14 : 11, " < %s >", common ? "yes" : "no "); + } else { + common = false; + console_print_pos(M_OFF, (task == 1) || (task == 5) ? 13 : 10, "No 'common' save found."); + entrycount--; + } + } else { + common = false; + entrycount--; + } + } else { + if (hasCommonSave(&titles[targ], true, true, slot, versionList ? versionList[slot] : 0)) { + console_print_pos(M_OFF, 7, "Include 'common' save?"); + console_print_pos(M_OFF, 8, " < %s >", common ? "yes" : "no "); + } else { + common = false; + console_print_pos(M_OFF, 7, "No 'common' save found."); + entrycount--; + } + } + + console_print_pos(M_OFF, 5 + cursor * 3, "\u2192"); + if (titles[targ].iconBuf) drawTGA(660, 100, 1, titles[targ].iconBuf); + } else if (mode == 1) { + entrycount = 1; + if (titles[targ].iconBuf) drawRGB5A3(650, 100, 1, titles[targ].iconBuf); + } + + switch(task) { + case 0: console_print_pos_aligned(17, 4, 2, "\ue000: Backup \ue001: Back"); break; + case 1: console_print_pos_aligned(17, 4, 2, "\ue000: Restore \ue001: Back"); break; + case 2: console_print_pos_aligned(17, 4, 2, "\ue000: Wipe \ue001: Back"); break; + case 3: console_print_pos_aligned(17, 4, 2, "\ue000: Import \ue001: Back"); break; + case 4: console_print_pos_aligned(17, 4, 2, "\ue000: Export \ue001: Back"); break; + case 5: console_print_pos_aligned(17, 4, 2, "\ue000: Copy \ue001: Back"); break; } } break; } + console_print_pos(0,16, "----------------------------------------------------------------------------"); + console_print_pos(0,17, "Press \ue044 to exit."); - console_print_pos(0,16, "--------------------------------------------------"); - console_print_pos(0,17, "Press HOME to exit."); - - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); + /*u32 passedMs = (OSGetTime() - startTime) * 4000ULL / BUS_SPEED; + console_print_pos(-4, -1, "%d", passedMs);*/ + flipBuffers(); + while(1) { + updatePressedButtons(); + updateHeldButtons(); + if (isPressed(0xFFFF) || isHeld(0xFFFF) || stickPos(4, 0.7)) break; + } updatePressedButtons(); updateHeldButtons(); - if (isPressed(VPAD_BUTTON_DOWN) || isHeld(VPAD_BUTTON_DOWN)) { - if (entrycount<=14) cursor = (cursor + 1) % entrycount; + if (isPressed(VPAD_BUTTON_DOWN) || isHeld(VPAD_BUTTON_DOWN) || stickPos(1, -0.7) || stickPos(3, -0.7)) { + if (entrycount <= 14) cursor = (cursor + 1) % entrycount; else if (cursor < 6) cursor++; - else if ((cursor+scroll+1) % entrycount) scroll++; + else if ((cursor + scroll + 1) % entrycount) scroll++; else cursor = scroll = 0; - usleep(100000); - } else if (isPressed(VPAD_BUTTON_UP) || isHeld(VPAD_BUTTON_UP)) { - if (scroll > 0) cursor -= (cursor>6) ? 1 : 0*(scroll--); + os_usleep(100000); + } else if (isPressed(VPAD_BUTTON_UP) || isHeld(VPAD_BUTTON_UP) || stickPos(1, 0.7) || stickPos(3, 0.7)) { + if (scroll > 0) cursor -= (cursor>6) ? 1 : 0 * (scroll--); else if (cursor > 0) cursor--; - else if (entrycount>14) scroll = entrycount - (cursor = 6) - 1; + else if (entrycount > 14) scroll = entrycount - (cursor = 6) - 1; else cursor = entrycount - 1; - usleep(100000); + os_usleep(100000); } - if (isPressed(VPAD_BUTTON_LEFT) || isHeld(VPAD_BUTTON_LEFT)) { + if (isPressed(VPAD_BUTTON_LEFT) || isHeld(VPAD_BUTTON_LEFT) || stickPos(0, -0.7) || stickPos(2, -0.7)) { if (menu==3) { - switch(cursor) { - case 0: slot--; break; - case 1: allusers^=1; break; - case 2: common^=1; break; + if (task == 5) { + switch(cursor) { + case 0: break; + case 1: + allusers = ((allusers == -1) ? -1 : (allusers - 1)); + allusers_d = allusers; + break; + case 2: + allusers_d = (((allusers == -1) || (allusers_d == -1)) ? -1 : (allusers_d - 1)); + allusers_d = ((allusers > -1) && (allusers_d == -1)) ? 0 : allusers_d; + break; + case 3: common ^= 1; break; + } + } else if (task == 1) { + switch(cursor) { + case 0: slot--; getAccountsSD(&titles[targ], slot); break; + case 1: + sdusers = ((sdusers == -1) ? -1 : (sdusers - 1)); + allusers = ((sdusers == -1) ? -1 : allusers); + break; + case 2: + allusers = (((allusers == -1) || (sdusers == -1)) ? -1 : (allusers - 1)); + allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + break; + case 3: common ^= 1; break; + } + } else if (task == 2) { + switch(cursor) { + case 0: break; + case 1: allusers = ((allusers == -1) ? -1 : (allusers - 1)); break; + case 2: common ^= 1; break; + } + } else if ((task == 3) || (task == 4)) { + switch(cursor) { + case 0: slot--; break; + case 1: common ^= 1; break; + } + } else { + switch(cursor) { + case 0: slot--; break; + case 1: allusers = ((allusers == -1) ? -1 : (allusers - 1)); break; + case 2: common ^= 1; break; + } } } - usleep(100000); - } else if (isPressed(VPAD_BUTTON_RIGHT) || isHeld(VPAD_BUTTON_RIGHT)) { - if (menu==3) { - switch(cursor) { - case 0: slot++; break; - case 1: allusers^=1; break; - case 2: common^=1; break; + os_usleep(100000); + } else if (isPressed(VPAD_BUTTON_RIGHT) || isHeld(VPAD_BUTTON_RIGHT) || stickPos(0, 0.7) || stickPos(2, 0.7)) { + if (menu == 3) { + if (task == 5) { + switch(cursor) { + case 0: break; + case 1: + allusers = ((allusers == (wiiuaccn - 1)) ? (wiiuaccn - 1) : (allusers + 1)); + allusers_d = allusers; + break; + case 2: + allusers_d = ((allusers_d == (wiiuaccn - 1)) ? (wiiuaccn - 1) : (allusers_d + 1)); + allusers_d = (allusers == -1) ? -1 : allusers_d; + break; + case 3: common ^= 1; break; + } + } else if (task == 1) { + switch(cursor) { + case 0: slot++; getAccountsSD(&titles[targ], slot); break; + case 1: + sdusers = ((sdusers == (sdaccn - 1)) ? (sdaccn - 1) : (sdusers + 1)); + allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + break; + case 2: + allusers = ((allusers == (wiiuaccn - 1)) ? (wiiuaccn - 1) : (allusers + 1)); + allusers = (sdusers == -1) ? -1 : allusers; + break; + case 3: common ^= 1; break; + } + } else if (task == 2) { + switch(cursor) { + case 0: break; + case 1: allusers = ((allusers == (wiiuaccn - 1)) ? (wiiuaccn - 1) : (allusers + 1)); break; + case 2: common ^= 1; break; + } + } else if ((task == 3) || (task == 4)) { + switch(cursor) { + case 0: slot++; break; + case 1: common ^= 1; break; + } + } else { + switch(cursor) { + case 0: slot++; break; + case 1: allusers = ((allusers == (wiiuaccn - 1)) ? (wiiuaccn - 1) : (allusers + 1)); break; + case 2: common ^= 1; break; + } } } - usleep(100000); + os_usleep(100000); + } + + if (isPressed(VPAD_BUTTON_R)) { + if (menu == 1) { + tsort = (tsort + 1) % 4; + qsort(titles, count, sizeof(Title), titleSort); + } else if (menu == 2) { + + targ = ++targ % count; + } + } + + if (isPressed(VPAD_BUTTON_L)) { + if ((menu==1) && (tsort > 0)) { + sorta *= -1; + qsort(titles, count, sizeof(Title), titleSort); + } else if (menu == 2) { + targ--; + if (targ < 0) targ = count -1; + } } if (isPressed(VPAD_BUTTON_A)) { - ucls(); - if (menu<3) { - if (menu==0) { + clearBuffers(); + if (menu < 3) { + if (menu == 0) { mode = cursor; - if (mode==0 && (!wiiutitles || !titleswiiu)) { + if (mode == 0 && (!wiiutitles || !titleswiiu)) { promptError("No Wii U titles found."); continue; } - if (mode==1 && (!wiititles || !titlesvwii)) { + + if (mode == 1 && (!wiititles || !titlesvwii)) { promptError("No vWii saves found."); continue; } } - if (menu==1) { - targ = cursor+scroll; - if (titles[targ].highID==0 || titles[targ].lowID==0) continue; - } - if (menu==2) { - task = cursor; - if (task==2) { - wipeSavedata(&titles[targ], allusers, common); + + if (menu == 1) { + targ = cursor + scroll; + cursorb = cursor; + scrollb = scroll; + if (mode == 2) { + OSCalendarTime dateTime; + switch(cursor) { + case 0: + dateTime.year = 0; + backupAllSave(wiiutitles, titleswiiu, &dateTime); + backupAllSave(wiititles, titlesvwii, &dateTime); + break; + case 1: backupAllSave(wiiutitles, titleswiiu, NULL); break; + case 2: backupAllSave(wiititles, titlesvwii, NULL); break; + } continue; } - if (task > 2) { + if (titles[targ].highID==0 || titles[targ].lowID==0) continue; + if ((mode == 0) && (strcmp(titles[targ].shortName, "DONT TOUCH ME") == 0)) { + if (!promptConfirm(ST_ERROR, "CBHC save. Could be dangerous to modify. Continue?") || !promptConfirm(ST_WARNING, "Are you REALLY sure?")) { + cursor = cursorb; + scroll = scrollb; + continue; + } + } + if ((mode == 0) && (!titles[targ].saveInit)) { + if (!promptConfirm(ST_WARNING, "Recommended to run Game at least one time. Continue?") || !promptConfirm(ST_WARNING, "Are you REALLY sure?")) { + cursor = cursorb; + scroll = scrollb; + continue; + } + } + } + + if (menu == 2) { + task = cursor; + cursort = cursor; + + if (task == 0) { + if (!titles[targ].saveInit) { + promptError("No save to Backup."); + continue; + } + } + + if (task == 1) { + getAccountsSD(&titles[targ], slot); + allusers = ((sdusers == -1) ? -1 : allusers); + sdusers = ((allusers == -1) ? -1 : sdusers); + } + + if (task == 2) { + if (!titles[targ].saveInit) { + promptError("No save to Wipe."); + continue; + } + } + + if ((task == 3) || (task == 4)) { char gamePath[PATH_SIZE]; - memset(versionList, 0, 0x100*sizeof(int)); - if (getLoadiineGameSaveDir(gamePath, titles[targ].productCode)!=0) continue; + memset(versionList, 0, 0x100 * sizeof(int)); + if (getLoadiineGameSaveDir(gamePath, titles[targ].productCode) != 0) continue; getLoadiineSaveVersionList(versionList, gamePath); + if (task == 4) { + if (!titles[targ].saveInit) { + promptError("No save to Export."); + continue; + } + } + } + + if (task == 5) { + if (!titles[targ].saveInit) { + promptError("No save to Copy."); + continue; + } } } menu++; @@ -358,24 +915,37 @@ int Menu_Main(void) { } else { switch(task) { case 0: backupSavedata(&titles[targ], slot, allusers, common); break; - case 1: restoreSavedata(&titles[targ], slot, allusers, common); break; + case 1: restoreSavedata(&titles[targ], slot, sdusers, allusers, common); break; case 2: wipeSavedata(&titles[targ], allusers, common); break; case 3: importFromLoadiine(&titles[targ], common, versionList ? versionList[slot] : 0); break; case 4: exportToLoadiine(&titles[targ], common, versionList ? versionList[slot] : 0); break; + case 5: + for (int i = 0; i < count; i++) { + if (titles[i].listID == titles[targ].dupeID) { + copySavedata(&titles[targ], &titles[i], allusers, allusers_d, common); + break; + } + } break; } } - } else if (isPressed(VPAD_BUTTON_B) && menu>0) { - ucls(); + } else if (isPressed(VPAD_BUTTON_B) && menu > 0) { + clearBuffers(); menu--; cursor = scroll = 0; + if (menu == 1) { + cursor = cursorb; + scroll = scrollb; + } + if (menu == 2) cursor = cursort; } - if (isPressed(VPAD_BUTTON_HOME)) break; - } - unloadTitles(wiiutitles); - unloadTitles(wiititles); + if (tgaBufDRC) free(tgaBufDRC); + if (tgaBufTV) free(tgaBufTV); + freeFont(fontBuf); + unloadTitles(wiiutitles, titleswiiu); + unloadTitles(wiititles, titlesvwii); free(versionList); fatUnmount("sd"); @@ -384,11 +954,12 @@ int Menu_Main(void) { IOSUHAX_usb_disc_interface.shutdown(); unmount_fs("slccmpt01"); + //unmount_fs("sd"); unmount_fs("storage_mlc"); unmount_fs("storage_usb"); unmount_fs("storage_odd"); - unmount_sd_fat("sd"); + //unmount_sd_fat("sd"); IOSUHAX_FSA_Close(fsaFd); diff --git a/src/savemng.c b/src/savemng.c index f2bc663..2d31355 100644 --- a/src/savemng.c +++ b/src/savemng.c @@ -1,38 +1,304 @@ #include "savemng.h" -#define BUFFER_SIZE 0x80000 +#define BUFFER_SIZE 0x8020 +#define BUFFER_SIZE_STEPS 0x20 + +int fsaFd = -1; +char * p1; +Account* wiiuacc; +Account* sdacc; +u8 wiiuaccn = 0, sdaccn = 5; + + +void setFSAFD(int fd) { + fsaFd = fd; +} + +void replace_str(char *str, char *orig, char *rep, int start, char *out) { + static char temp[PATH_SIZE]; + static char buffer[PATH_SIZE]; + char *p; + + strcpy(temp, str + start); + + if (!(p = strstr(temp, orig))) // Is 'orig' even in 'temp'? + return temp; + + strncpy(buffer, temp, p-temp); // Copy characters from 'temp' start to 'orig' str + buffer[p-temp] = '\0'; + + sprintf(buffer + (p - temp), "%s%s", rep, p + strlen(orig)); + sprintf(out, "%s", buffer); +} + +void show_file_operation(char* file_name, char* file_src, char* file_dest) { + char* dev_s[10], dev_d[10]; + + if (strncmp(strchr(file_src, '_'), "_usb", 4) == 0) { + sprintf(dev_s, " (USB)"); + } else if (strncmp(strchr(file_src, '_'), "_mlc", 4) == 0) { + sprintf(dev_s, " (NAND WiiU)"); + } else if (strncmp(strchr(file_src, '_'), "_slccmpt", 8) == 0) { + sprintf(dev_s, " (NAND vWii)"); + } else if (strncmp(strchr(file_src, '_'), "_sdcard", 7) == 0) { + sprintf(dev_s, " (SD)"); + } + + if (strncmp(strchr(file_dest, '_'), "_usb", 4) == 0) { + sprintf(dev_d, " (USB)"); + } else if (strncmp(strchr(file_dest, '_'), "_mlc", 4) == 0) { + sprintf(dev_d, " (NAND WiiU)"); + } else if (strncmp(strchr(file_dest, '_'), "_slccmpt", 8) == 0) { + sprintf(dev_d, " (NAND vWii)"); + } else if (strncmp(strchr(file_dest, '_'), "_sdcard", 7) == 0) { + sprintf(dev_d, " (SD)"); + } + + console_print_pos(-2, 0, "Copying file: %s", file_name); + console_print_pos_multiline(-2, 2, '/', "From%s: \n%s", dev_s, strstr(strstr(strstr(file_src, "/") + 1,"/") + 1,"/")); + console_print_pos_multiline(-2, 8, '/', "To%s: \n%s", dev_d, strstr(strstr(strstr(file_dest, "/") + 1,"/") + 1,"/")); +} + +int FSAR(int result) { + if ((result & 0xFFFF0000) == 0xFFFC0000) + return (result & 0xFFFF) | 0xFFFF0000; + else + return result; +} + +s32 loadFile(const char * fPath, u8 **buf) { + int srcFd = -1; + int ret = IOSUHAX_FSA_OpenFile(fsaFd, fPath, "rb", &srcFd); + if (ret >= 0) { + fileStat_s fStat; + IOSUHAX_FSA_StatFile(fsaFd, srcFd, &fStat); + size_t size = fStat.size; + + *buf = malloc(size); + if (*buf) { + memset(*buf, 0, size); + ret = IOSUHAX_FSA_ReadFile(fsaFd, *buf, 0x01, size, srcFd, 0); + } + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + } + return ret; +} + +s32 loadFilePart(const char * fPath, u32 start, u32 size, u8 **buf) { + int srcFd = -1; + int ret = IOSUHAX_FSA_OpenFile(fsaFd, fPath, "rb", &srcFd); + if (ret >= 0) { + fileStat_s fStat; + IOSUHAX_FSA_StatFile(fsaFd, srcFd, &fStat); + if ((start + size) > fStat.size) { + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + return -43; + } + IOSUHAX_FSA_SetFilePos(fsaFd, srcFd, start); + + *buf = malloc(size); + if (*buf) { + memset(*buf, 0, size); + ret = IOSUHAX_FSA_ReadFile(fsaFd, *buf, 0x01, size, srcFd, 0); + } + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + } + return ret; +} + +s32 loadTitleIcon(Title* title) { + u32 highID = title->highID, lowID = title->lowID; + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + char path[255]; + memset(path, 0, 255); + + if (isWii) { + if (title->saveInit) { + sprintf(path, "/vol/storage_slccmpt01/title/%08x/%08x/data/banner.bin", highID, lowID); + return loadFilePart(path, 0xA0, 24576, &title->iconBuf); + } + } else { + if (title->saveInit) + sprintf(path, "/vol/storage_%s01/usr/save/%08x/%08x/meta/iconTex.tga", isUSB ? "usb" : "mlc", highID, lowID); + else + sprintf(path, "/vol/storage_%s01/usr/title/%08x/%08x/meta/iconTex.tga", isUSB ? "usb" : "mlc", highID, lowID); + + return loadFile(path, &title->iconBuf); + } + return -23; +} + +int checkEntry(const char * fPath) { + fileStat_s fStat; + int ret = FSAR(IOSUHAX_FSA_GetStat(fsaFd, fPath, &fStat)); + + if (ret == FSA_STATUS_NOT_FOUND) return 0; + else if (ret < 0) return -1; + + if (fStat.flag & DIR_ENTRY_IS_DIRECTORY) return 2; + return 1; +} + +int folderEmpty(const char * fPath) { + int dirH; + + if (IOSUHAX_FSA_OpenDir(fsaFd, fPath, &dirH) >= 0) { + directoryEntry_s data; + int ret = FSAR(IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data)); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); + if (ret == FSA_STATUS_END_OF_DIRECTORY) + return 1; + } else return -1; + return 0; +} + +int createFolder(const char * fPath) { //Adapted from mkdir_p made by JonathonReinhart + const size_t len = strlen(fPath); + char _path[FS_MAX_FULLPATH_SIZE]; + char *p; + int ret, found = 0; + + if (len > sizeof(_path)-1) { + return -1; + } + strcpy(_path, fPath); + + for (p = _path + 1; *p; p++) { + if (*p == '/') { + found++; + if (found > 2) { + *p = '\0'; + if (checkEntry(_path) == 0) { + if ((ret = FSAR(IOSUHAX_FSA_MakeDir(fsaFd, _path, 0x666))) < 0) return -1; + } + *p = '/'; + } + } + } + + if (checkEntry(_path) == 0) { + if ((ret = FSAR(IOSUHAX_FSA_MakeDir(fsaFd, _path, 0x666))) < 0) return -1; + } + + return 0; +} + +void console_print_pos_aligned(int y, u16 offset, u8 align, const char* format, ...) { + char* tmp = NULL; + int x = 0; + + va_list va; + va_start(va, format); + if ((vasprintf(&tmp, format, va) >= 0) && tmp) { + switch(align) { + case 0: x = (offset * 12); break; + case 1: x = (853 - ttfStringWidth(tmp, -2)) / 2; break; + case 2: x = 853 - (offset * 12) - ttfStringWidth(tmp, 0); break; + default: x = (853 - ttfStringWidth(tmp, -2)) / 2; break; + } + ttfPrintString(x, (y + 1) * 24, tmp, false, false); + } + va_end(va); + if (tmp) free(tmp); +} void console_print_pos(int x, int y, const char* format, ...) { // Source: ftpiiu - char* tmp = NULL; va_list va; va_start(va, format); if ((vasprintf(&tmp, format, va) >= 0) && tmp) { - - if (strlen(tmp) > 79) tmp[79] = 0; - - OSScreenPutFontEx(0, x, y, tmp); - OSScreenPutFontEx(1, x, y, tmp); - + ttfPrintString((x + 4) * 12, (y + 1) * 24, tmp, false, true); + //OSScreenPutFontEx(0, x, y, tmp); + //OSScreenPutFontEx(1, x, y, tmp); } - va_end(va); if (tmp) free(tmp); - } -bool promptConfirm(const char* question) { - ucls(); - const char* msg = "(A) Confirm - (B) Cancel"; - int ret = 0; - while(1) { - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - console_print_pos(25 - (strlen(question)>>1), 8, question); - console_print_pos(25 - (strlen(msg)>>1), 10, msg); - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); +void console_print_pos_multiline(int x, int y, char cdiv, const char* format, ...) { // Source: ftpiiu + char* tmp = NULL; + u32 len = (66 - x); + + va_list va; + va_start(va, format); + if ((vasprintf(&tmp, format, va) >= 0) && tmp) { + + if ((ttfStringWidth(tmp, -1) / 12) > len) { + char* p = tmp; + if (strrchr(p, '\n') != NULL) p = strrchr(p, '\n') + 1; + while((ttfStringWidth(p, -1) / 12) > len) { + char* q = p; + int l1 = strlen(q); + for(int i = l1; i > 0; i--) { + char o = q[l1]; + q[l1] = '\0'; + if ((ttfStringWidth(p, -1) / 12) <= len) { + if (strrchr(p, cdiv) != NULL) p = strrchr(p, cdiv) + 1; + else p = q + l1; + q[l1] = o; + break; + } + q[l1] = o; + l1--; + } + char* buf[255]; + memset(buf, 0, 255); + strcpy(buf, p); + sprintf(p, "\n%s", buf); + p++; + len = 69; + } + } + ttfPrintString((x + 4) * 12, (y + 1) * 24, tmp, true, true); + //OSScreenPutFontEx(0, x, y, tmp); + //OSScreenPutFontEx(1, x, y, tmp); + } + va_end(va); + if (tmp) free(tmp); +} + +void console_print_pos_va(int x, int y, const char* format, va_list va) { // Source: ftpiiu + char* tmp = NULL; + + if ((vasprintf(&tmp, format, va) >= 0) && tmp) { + ttfPrintString((x + 4) * 12, (y + 1) * 24, tmp, false, true); + //OSScreenPutFontEx(0, x, y, tmp); + //OSScreenPutFontEx(1, x, y, tmp); + } + if (tmp) free(tmp); +} + +bool promptConfirm(Style st, const char* question) { + clearBuffers(); + const char* msg1 = "\ue000 Yes - \ue001 No"; + const char* msg2 = "\ue000 Confirm - \ue001 Cancel"; + const char* msg; + switch(st & 0x0F) { + case ST_YES_NO: msg = msg1; break; + case ST_CONFIRM_CANCEL: msg = msg2; break; + default: msg = msg2; + } + if (st & ST_WARNING) { + OSScreenClearBufferEx(0, 0x7F7F0000); + OSScreenClearBufferEx(1, 0x7F7F0000); + } else if (st & ST_ERROR) { + OSScreenClearBufferEx(0, 0x7F000000); + OSScreenClearBufferEx(1, 0x7F000000); + } else { + OSScreenClearBufferEx(0, 0x007F0000); + OSScreenClearBufferEx(1, 0x007F0000); + } + if (st & ST_MULTILINE) { + + } else { + console_print_pos(31 - (ttfStringWidth(question, 0) / 24), 7, question); + console_print_pos(31 - (ttfStringWidth(msg, -1) / 24), 9, msg); + } + flipBuffers(); + + int ret = 0; + while(1) { updatePressedButtons(); if (isPressed(VPAD_BUTTON_A | VPAD_BUTTON_B | VPAD_BUTTON_HOME)) { ret = isPressed(VPAD_BUTTON_A); @@ -42,167 +308,290 @@ bool promptConfirm(const char* question) { return ret; } -void promptError(const char* message) { - ucls(); - while(1) { - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - console_print_pos(25 - (strlen(message)>>1), 9, message); - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); +void promptError(const char* message, ...) { + clearBuffers(); + va_list va; + va_start(va, message); + OSScreenClearBufferEx(0, 0x7F000000); + OSScreenClearBufferEx(1, 0x7F000000); + + char* tmp = NULL; + if ((vasprintf(&tmp, message, va) >= 0) && tmp) { + //int x = 31 - (strlen(tmp)>>1), y = 9; + int x = 31 - (ttfStringWidth(tmp, -2) / 24), y = 8; + x = (x < -4 ? -4 : x); + ttfPrintString((x + 4) * 12, (y + 1) * 24, tmp, true, false); + //OSScreenPutFontEx(0, x, y, tmp); + //OSScreenPutFontEx(1, x, y, tmp); + } + if (tmp) free(tmp); + + flipBuffers(); + va_end(va); + while(1) { updatePressedButtons(); if (isPressed(0xFFFF)) break; } } -int DumpFile(char* pPath, const char* output_path) { // Source: ft2sd +void getAccountsWiiU() { + /* get persistent ID - thanks to Maschell */ + unsigned int nn_act_handle; + u32 (*GetPersistentIdEx)(unsigned char); + bool (*IsSlotOccupied)(unsigned char); + int (*GetSlotNo)(void); + int (*GetNumOfAccounts)(void); + int (*GetMiiNameEx)(uint16_t*, unsigned char); + void (*nn_Initialize)(void); + void (*nn_Finalize)(void); + OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle); + OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", &GetPersistentIdEx); + OSDynLoad_FindExport(nn_act_handle, 0, "IsSlotOccupied__Q2_2nn3actFUc", &IsSlotOccupied); + OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", &GetSlotNo); + OSDynLoad_FindExport(nn_act_handle, 0, "GetNumOfAccounts__Q2_2nn3actFv", &GetNumOfAccounts); + OSDynLoad_FindExport(nn_act_handle, 0, "GetMiiNameEx__Q2_2nn3actFPwUc", &GetMiiNameEx); + OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", &nn_Initialize); + OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", &nn_Finalize); - unsigned char* dataBuf = (unsigned char*)memalign(0x40, BUFFER_SIZE); - if (!dataBuf) { - promptError("Out of memory."); - return -1; - } - - FILE* pReadFile = fopen(pPath, "rb"); - if (!pReadFile) { - promptError("Failed to open file."); - free(dataBuf); - return -2; - } - - FILE* pWriteFile = fopen(output_path, "wb"); - if (!pWriteFile) { - promptError("Failed to create file."); - fclose(pReadFile); - free(dataBuf); - return -3; - } - - u32 rsize; - while ((rsize = fread(dataBuf, 0x1, BUFFER_SIZE, pReadFile)) > 0) { - u32 wsize = fwrite(dataBuf, 0x01, rsize, pWriteFile); - if (wsize!=rsize) { - promptError("Failed to write to file."); - fclose(pWriteFile); - fclose(pReadFile); - free(dataBuf); - return -4; - } - } - - fclose(pWriteFile); - fclose(pReadFile); - free(dataBuf); - - return 0; + nn_Initialize(); // To be sure that it is really Initialized + int i = 0, accn = 0; + wiiuaccn = GetNumOfAccounts(); + wiiuacc = malloc(wiiuaccn * sizeof(Account)); + uint16_t out[11]; + while ((accn < wiiuaccn) && (i <= 12)) { + if (IsSlotOccupied(i)) { + unsigned int persistentID = GetPersistentIdEx(i); + wiiuacc[accn].pID = persistentID; + sprintf(wiiuacc[accn].persistentID, "%08X", persistentID); + GetMiiNameEx(out, i); + //convert_to_ascii(out, wiiuacc[accn].miiName); + memset(wiiuacc[accn].miiName, 0, sizeof(wiiuacc[accn].miiName)); + for (int j = 0, k = 0; j < 10; j++) { + if (out[j] < 0x80) + wiiuacc[accn].miiName[k++] = (char)out[j]; + else if ((out[j] & 0xF000) > 0) { + wiiuacc[accn].miiName[k++] = 0xE0 | ((out[j] & 0xF000) >> 12); + wiiuacc[accn].miiName[k++] = 0x80 | ((out[j] & 0xFC0) >> 6); + wiiuacc[accn].miiName[k++] = 0x80 | (out[j] & 0x3F); + } else if (out[j] < 0x400) { + wiiuacc[accn].miiName[k++] = 0xC0 | ((out[j] & 0x3C0) >> 6); + wiiuacc[accn].miiName[k++] = 0x80 | (out[j] & 0x3F); + } else { + wiiuacc[accn].miiName[k++] = 0xD0 | ((out[j] & 0x3C0) >> 6); + wiiuacc[accn].miiName[k++] = 0x80 | (out[j] & 0x3F); + } + } + wiiuacc[accn].slot = i; + accn++; + } + i++; + } + nn_Finalize(); //must be called an equal number of times to nn_Initialize } -int DumpDir(char* pPath, const char* target_path) { // Source: ft2sd +void getAccountsSD(Title* title, u8 slot) { + u32 highID = title->highID, lowID = title->lowID; + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + int dirH; + sdaccn = 0; + if (sdacc) free(sdacc); - struct dirent* dirent = NULL; - DIR* dir = NULL; + char path[255]; + sprintf(path, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + if (IOSUHAX_FSA_OpenDir(fsaFd, path, &dirH) >= 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) break; - dir = opendir(pPath); - if (dir == NULL) return -1; + if (strncmp(data.name, "common", 6) == 0) continue; + sdaccn++; + } + IOSUHAX_FSA_CloseDir(fsaFd, dirH); + } - CreateSubfolder(target_path); + sdacc = malloc(sdaccn * sizeof(Account)); + if (IOSUHAX_FSA_OpenDir(fsaFd, path, &dirH) >= 0) { + for(int i = 0; i < sdaccn; i++) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) break; - while ((dirent = readdir(dir)) != 0) { + if (strncmp(data.name, "common", 6) == 0) continue; + sprintf(sdacc[i].persistentID, "%s", data.name); + sdacc[i].pID = strtoul(data.name, NULL, 16); + sdacc[i].slot = i; + } + IOSUHAX_FSA_CloseDir(fsaFd, dirH); + } +} + +int DumpFile(char* pPath, const char* oPath) { + int srcFd = -1, destFd = -1; + int ret = 0; + int buf_size = BUFFER_SIZE; + uint8_t * pBuffer; + + do{ + buf_size -= BUFFER_SIZE_STEPS; + if (buf_size < 0) { + promptError("Error allocating Buffer."); + return; + } + pBuffer = (uint8_t *)memalign(0x40, buf_size); + if (pBuffer) memset(pBuffer, 0x00, buf_size); + }while(!pBuffer); + + ret = IOSUHAX_FSA_OpenFile(fsaFd, pPath, "rb", &srcFd); + if (ret >= 0) { + fileStat_s fStat; + IOSUHAX_FSA_StatFile(fsaFd, srcFd, &fStat); + if ((ret = IOSUHAX_FSA_OpenFile(fsaFd, oPath, "wb", &destFd)) >= 0) { + int result, sizew = 0, sizef = fStat.size; + int fwrite = 0; + u32 passedMs = 1; + u64 startTime = OSGetTime(); + + while ((result = IOSUHAX_FSA_ReadFile(fsaFd, pBuffer, 0x01, buf_size, srcFd, 0)) > 0) { + if ((fwrite = IOSUHAX_FSA_WriteFile(fsaFd, pBuffer, 0x01, result, destFd, 0)) < 0) { + promptError("Write %d,%s", fwrite, oPath); + IOSUHAX_FSA_CloseFile(fsaFd, destFd); + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + free(pBuffer); + return -1; + } + sizew += fwrite; + passedMs = (OSGetTime() - startTime) * 4000ULL / BUS_SPEED; + if(passedMs == 0) + passedMs = 1; + + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + show_file_operation(p1, pPath, oPath); + console_print_pos(-2, 15, "Bytes Copied: %d of %d (%i kB/s)", sizew, sizef, (u32)(((u64)sizew * 1000) / ((u64)1024 * passedMs))); + flipBuffers(); + } + } else { + promptError("Open File W %d,%s", ret, oPath); + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + free(pBuffer); + return -1; + } + IOSUHAX_FSA_CloseFile(fsaFd, destFd); + IOSUHAX_FSA_CloseFile(fsaFd, srcFd); + IOSUHAX_FSA_ChangeMode(fsaFd, oPath, 0x666); + free(pBuffer); + } else { + promptError("Open File R %d,%s", ret, pPath); + free(pBuffer); + return -1; + } + return 0; +} + +int DumpDir(char* pPath, const char* tPath) { // Source: ft2sd + int dirH; + + if (IOSUHAX_FSA_OpenDir(fsaFd, pPath, &dirH) < 0) return -1; + IOSUHAX_FSA_MakeDir(fsaFd, tPath, 0x666); + + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) + break; OSScreenClearBufferEx(0, 0); OSScreenClearBufferEx(1, 0); - if (strcmp(dirent->d_name, "..") == 0 || strcmp(dirent->d_name, ".") == 0) continue; + if (strcmp(data.name, "..") == 0 || strcmp(data.name, ".") == 0) continue; int len = strlen(pPath); - snprintf(pPath + len, FS_MAX_FULLPATH_SIZE - len, "/%s", dirent->d_name); - - if (dirent->d_type & DT_DIR) { + snprintf(pPath + len, FS_MAX_FULLPATH_SIZE - len, "/%s", data.name); + if (data.stat.flag & DIR_ENTRY_IS_DIRECTORY) { char* targetPath = (char*)malloc(FS_MAX_FULLPATH_SIZE); - snprintf(targetPath, FS_MAX_FULLPATH_SIZE, "%s/%s", target_path, dirent->d_name); + snprintf(targetPath, FS_MAX_FULLPATH_SIZE, "%s/%s", tPath, data.name); - CreateSubfolder(targetPath); - if (DumpDir(pPath, targetPath)!=0) { - closedir(dir); + IOSUHAX_FSA_MakeDir(fsaFd, targetPath, 0x666); + if (DumpDir(pPath, targetPath) != 0) { + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return -2; } free(targetPath); - } else { - char* targetPath = (char*)malloc(FS_MAX_FULLPATH_SIZE); - snprintf(targetPath, FS_MAX_FULLPATH_SIZE, "%s/%s", target_path, dirent->d_name); + snprintf(targetPath, FS_MAX_FULLPATH_SIZE, "%s/%s", tPath, data.name); - console_print_pos(0, 0, "Copying file %s", dirent->d_name); - console_print_pos(0, 1, "From: %s", pPath); - console_print_pos(0, 2, "To: %s", targetPath); + p1 = data.name; + ttfFontSize(0, 20); + show_file_operation(data.name, pPath, targetPath); - if (DumpFile(pPath, targetPath)!=0) { - closedir(dir); + if (DumpFile(pPath, targetPath) != 0) { + ttfFontSize(0, 22); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return -3; } + ttfFontSize(0, 22); free(targetPath); - } - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); - pPath[len] = 0; - } - closedir(dir); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; - } int DeleteDir(char* pPath) { + int dirH; - struct dirent* dirent = NULL; - DIR* dir = NULL; + if (IOSUHAX_FSA_OpenDir(fsaFd, pPath, &dirH) < 0) return -1; - dir = opendir(pPath); - if (dir == NULL) return -1; - - while ((dirent = readdir(dir)) != 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) + break; OSScreenClearBufferEx(0, 0); OSScreenClearBufferEx(1, 0); - if (strcmp(dirent->d_name, "..") == 0 || strcmp(dirent->d_name, ".") == 0) continue; + if (strcmp(data.name, "..") == 0 || strcmp(data.name, ".") == 0) continue; int len = strlen(pPath); - snprintf(pPath + len, FS_MAX_FULLPATH_SIZE - len, "/%s", dirent->d_name); + snprintf(pPath + len, FS_MAX_FULLPATH_SIZE - len, "/%s", data.name); - if (dirent->d_type & DT_DIR) { + if (data.stat.flag & DIR_ENTRY_IS_DIRECTORY) { + char origPath[PATH_SIZE]; + sprintf(origPath, "%s", pPath); DeleteDir(pPath); + + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + console_print_pos(-2, 0, "Deleting folder %s", data.name); + console_print_pos_multiline(-2, 2, '/', "From: \n%s", origPath); + if (IOSUHAX_FSA_Remove(fsaFd, origPath) != 0) promptError("Failed to delete folder."); } else { - console_print_pos(0, 0, "Deleting file %s", dirent->d_name); - console_print_pos(0, 1, "From: %s", pPath); - if (remove(pPath)!=0) promptError("Failed to delete file."); + console_print_pos(-2, 0, "Deleting file %s", data.name); + console_print_pos_multiline(-2, 2, '/', "From: \n%s", pPath); + if (IOSUHAX_FSA_Remove(fsaFd, pPath) != 0) promptError("Failed to delete file."); } - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); - + flipBuffers(); pPath[len] = 0; - } - closedir(dir); - + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; - } void getUserID(char* out) { // Source: loadiine_gx2 - /* get persistent ID - thanks to Maschell */ unsigned int nn_act_handle; unsigned long (*GetPersistentIdEx)(unsigned char); @@ -226,90 +615,106 @@ void getUserID(char* out) { // Source: loadiine_gx2 } int getLoadiineGameSaveDir(char* out, const char* productCode) { + int dirH; - struct dirent* dirent = NULL; - DIR* dir = NULL; + if (IOSUHAX_FSA_OpenDir(fsaFd, "/vol/storage_sdcard/wiiu/saves", &dirH) < 0) return -1; - dir = opendir("sd:/wiiu/saves"); - if (dir == NULL) { - promptError("Failed to open directory."); - return -1; - } + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) + break; - while ((dirent = readdir(dir)) != 0) { - - if ((dirent->d_type & DT_DIR) && (strstr(dirent->d_name, productCode)!=NULL)) { - sprintf(out, "sd:/wiiu/saves/%s", dirent->d_name); - closedir(dir); + if ((data.stat.flag & DIR_ENTRY_IS_DIRECTORY) && (strstr(data.name, productCode) != NULL)) { + sprintf(out, "/vol/storage_sdcard/wiiu/saves/%s", data.name); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; } - } promptError("Loadiine game folder not found."); - closedir(dir); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return -2; - } int getLoadiineSaveVersionList(int* out, const char* gamePath) { + int dirH; - struct dirent* dirent = NULL; - DIR* dir = NULL; - - dir = opendir(gamePath); - if (dir == NULL) { - promptError("Loadiine game folder not found."); - return -1; - } + if (IOSUHAX_FSA_OpenDir(fsaFd, gamePath, &dirH) < 0) { + promptError("Loadiine game folder not found."); + return -1; + } int i = 0; - while ((i < 255) && ((dirent = readdir(dir)) != 0)) { + while (i < 255) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) + break; - if ((dirent->d_type & DT_DIR) && (strchr(dirent->d_name, 'v')!=NULL)) { - out[++i] = strtol((dirent->d_name)+1, NULL, 10); + if ((data.stat.flag & DIR_ENTRY_IS_DIRECTORY) && (strchr(data.name, 'v') != NULL)) { + out[++i] = strtol((data.name)+1, NULL, 10); } } - closedir(dir); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; - } int getLoadiineUserDir(char* out, const char* fullSavePath, const char* userID) { + int dirH; - struct dirent* dirent = NULL; - DIR* dir = NULL; - - dir = opendir(fullSavePath); - if (dir == NULL) { - promptError("Failed to open directory."); + if (IOSUHAX_FSA_OpenDir(fsaFd, fullSavePath, &dirH) < 0) { + promptError("Failed to open Loadiine game save directory."); return -1; } - while ((dirent = readdir(dir)) != 0) { + while (1) { + directoryEntry_s data; + int ret = IOSUHAX_FSA_ReadDir(fsaFd, dirH, &data); + if (ret != 0) + break; - if ((dirent->d_type & DT_DIR) && (strstr(dirent->d_name, userID))) { - sprintf(out, "%s/%s", fullSavePath, dirent->d_name); - closedir(dir); + if ((data.stat.flag & DIR_ENTRY_IS_DIRECTORY) && (strstr(data.name, userID))) { + sprintf(out, "%s/%s", fullSavePath, data.name); + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; } - } sprintf(out, "%s/u", fullSavePath); - closedir(dir); + if (checkEntry(out) <= 0) return -1; + IOSUHAX_FSA_CloseDir(fsaFd, dirH); return 0; +} +u64 getSlotDate(u32 highID, u32 lowID, u8 slot) { + char path[PATH_SIZE]; + if (((highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) { + sprintf(path, "/vol/storage_sdcard/savegames/%08x%08x", highID, lowID); + } else { + sprintf(path, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + } + int ret = checkEntry(path); + if (ret <= 0) return 0; + else { + fileStat_s fStat; + int ret = FSAR(IOSUHAX_FSA_GetStat(fsaFd, path, &fStat)); + return fStat.ctime; + } } bool isSlotEmpty(u32 highID, u32 lowID, u8 slot) { char path[PATH_SIZE]; - sprintf(path, "sd:/wiiu/backups/%08x%08x/%u", highID, lowID, slot); - DIR* dir = opendir(path); - if (dir==NULL) return 1; - else return closedir(dir); + if (((highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) { + sprintf(path, "/vol/storage_sdcard/savegames/%08x%08x", highID, lowID); + } else { + sprintf(path, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + } + int ret = checkEntry(path); + if (ret <= 0) return 1; + else return 0; } int getEmptySlot(u32 highID, u32 lowID) { @@ -319,118 +724,318 @@ int getEmptySlot(u32 highID, u32 lowID) { return -1; } -void backupSavedata(Title* title, u8 slot, bool allusers, bool common) { +bool hasAccountSave(Title* title, bool inSD, bool iine, u32 user, u8 slot, int version) { + u32 highID = title->highID, lowID = title->lowID; + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + if (highID == 0 || lowID == 0) return false; - if (!isSlotEmpty(title->highID, title->lowID, slot) && !promptConfirm("Backup found on this slot. Overwrite it?")) return; + char srcPath[PATH_SIZE]; + if (!isWii) { + if (!inSD) { + const char* path = (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save"); + if (user == 0) + sprintf(srcPath, "%s/%08x/%08x/%s/common", path, highID, lowID, "user"); + else if (user == 0xFFFFFFFF) + sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, "user"); + else + sprintf(srcPath, "%s/%08x/%08x/%s/%08X", path, highID, lowID, "user", user); + } else { + if (!iine) + sprintf(srcPath, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u/%08X", highID, lowID, slot, user); + else { + if (getLoadiineGameSaveDir(srcPath, title->productCode) != 0) return false; + if (version) sprintf(srcPath + strlen(srcPath), "/v%u", version); + if (user == 0) { + u32 srcOffset = strlen(srcPath); + strcpy(srcPath + srcOffset, "/c\0"); + } else { + char usrPath[16]; + sprintf(usrPath, "%08X", user); + getLoadiineUserDir(srcPath, srcPath, usrPath); + } + + } + } + } else { + if (!inSD) { + sprintf(srcPath, "/vol/storage_slccmpt01/title/%08x/%08x/data", highID, lowID); + } else { + sprintf(srcPath, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + } + } + if (checkEntry(srcPath) == 2) + if (folderEmpty(srcPath) == 0) + return true; + return false; +} + +bool hasCommonSave(Title* title, bool inSD, bool iine, u8 slot, int version) { u32 highID = title->highID, lowID = title->lowID; - bool isUSB = title->isTitleOnUSB, isWii = (highID==0x00010000); + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + if (isWii) return false; + + char srcPath[PATH_SIZE]; + if (!inSD) { + const char* path = (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save"); + sprintf(srcPath, "%s/%08x/%08x/%s/common", path, highID, lowID, "user"); + } else { + if (!iine) + sprintf(srcPath, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u/common", highID, lowID, slot); + else { + if (getLoadiineGameSaveDir(srcPath, title->productCode) != 0) return false; + if (version) sprintf(srcPath + strlen(srcPath), "/v%u", version); + u32 srcOffset = strlen(srcPath); + strcpy(srcPath + srcOffset, "/c\0"); + } + } + if (checkEntry(srcPath) == 2) + if (folderEmpty(srcPath) == 0) return true; + return false; +} + +void copySavedata(Title* title, Title* titleb, s8 allusers, s8 allusers_d, bool common) { + + u32 highID = title->highID, lowID = title->lowID; + bool isUSB = title->isTitleOnUSB; + u32 highIDb = titleb->highID, lowIDb = titleb->lowID; + bool isUSBb = titleb->isTitleOnUSB; + + if (!promptConfirm(ST_WARNING, "Are you sure?")) return; + int slotb = getEmptySlot(titleb->highID, titleb->lowID); + if ((slotb >= 0) && promptConfirm(ST_YES_NO, "Backup current savedata first to next empty slot?")) { + backupSavedata(titleb, slotb, allusers, common); + promptError("Backup done. Now copying Savedata."); + } + char srcPath[PATH_SIZE]; char dstPath[PATH_SIZE]; - const char* path = (isWii ? "slccmpt01:/title" : (isUSB ? "storage_usb:/usr/save" : "storage_mlc:/usr/save")); - sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); - sprintf(dstPath, "sd:/wiiu/backups/%08x%08x/%u", highID, lowID, slot); - if (!allusers && !isWii) { - char usrPath[16]; - getUserID(usrPath); + const char* path = (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save"); + const char* pathb = (isUSBb ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save"); + sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, "user"); + sprintf(dstPath, "%s/%08x/%08x/%s", pathb, highIDb, lowIDb, "user"); + createFolder(dstPath); + + if (allusers > -1) { u32 srcOffset = strlen(srcPath); u32 dstOffset = strlen(dstPath); if (common) { strcpy(srcPath + srcOffset, "/common"); strcpy(dstPath + dstOffset, "/common"); - if (DumpDir(srcPath, dstPath)!=0) promptError("Common save not found."); + if (DumpDir(srcPath, dstPath) != 0) promptError("Common save not found."); } - sprintf(srcPath + srcOffset, "/%s", usrPath); - sprintf(dstPath + dstOffset, "/%s", usrPath); + sprintf(srcPath + srcOffset, "/%s", wiiuacc[allusers].persistentID); + sprintf(dstPath + dstOffset, "/%s", wiiuacc[allusers_d].persistentID); } - if (DumpDir(srcPath, dstPath)!=0) promptError("Backup failed. DO NOT restore from this slot."); + if (DumpDir(srcPath, dstPath) != 0) promptError("Copy failed."); + + if (strncmp(strchr(dstPath, '_'), "_usb", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_usb01"); + } else if (strncmp(strchr(dstPath, '_'), "_mlc", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01"); + } else if (strncmp(strchr(dstPath, '_'), "_slccmpt", 8) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_slccmpt01"); + } else if (strncmp(strchr(dstPath, '_'), "_sdcard", 7) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_sdcard"); + } } -void restoreSavedata(Title* title, u8 slot, bool allusers, bool common) { +void backupAllSave(Title* titles, int count, OSCalendarTime* date) { + OSCalendarTime dateTime; + if (date) { + if (date->year == 0) { + OSTicksToCalendarTime(OSGetTime(), date); + date->mon++; + } dateTime = (*date); + } else { + OSTicksToCalendarTime(OSGetTime(), &dateTime); + dateTime.mon++; + } + + char datetime[24]; + sprintf(datetime, "%04d-%02d-%02dT%02d%02d%02d", dateTime.year, dateTime.mon, dateTime.mday, dateTime.hour, dateTime.min, dateTime.sec); + for (int i = 0; i < count; i++) { + if (titles[i].highID == 0 || titles[i].lowID == 0 || !titles[i].saveInit) continue; + + u32 highID = titles[i].highID, lowID = titles[i].lowID; + bool isUSB = titles[i].isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + char srcPath[PATH_SIZE]; + char dstPath[PATH_SIZE]; + const char* path = (isWii ? "/vol/storage_slccmpt01/title" : (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save")); + sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); + sprintf(dstPath, "/vol/storage_sdcard/wiiu/backups/batch/%s/%08x%08x", datetime, highID, lowID); + + createFolder(dstPath); + if (DumpDir(srcPath, dstPath) != 0) promptError("Backup failed."); + } + return dateTime; +} + +void backupSavedata(Title* title, u8 slot, s8 allusers, bool common) { + + if (!isSlotEmpty(title->highID, title->lowID, slot) && !promptConfirm(ST_WARNING, "Backup found on this slot. Overwrite it?")) return; + u32 highID = title->highID, lowID = title->lowID; + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + char srcPath[PATH_SIZE]; + char dstPath[PATH_SIZE]; + const char* path = (isWii ? "/vol/storage_slccmpt01/title" : (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save")); + sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); + if (isWii && (slot == 255)) { + sprintf(dstPath, "/vol/storage_sdcard/savegames/%08x%08x", highID, lowID); + } else { + sprintf(dstPath, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + } + createFolder(dstPath); + + if ((allusers > -1) && !isWii) { + u32 srcOffset = strlen(srcPath); + u32 dstOffset = strlen(dstPath); + if (common) { + strcpy(srcPath + srcOffset, "/common"); + strcpy(dstPath + dstOffset, "/common"); + if (DumpDir(srcPath, dstPath) != 0) promptError("Common save not found."); + } + sprintf(srcPath + srcOffset, "/%s", wiiuacc[allusers].persistentID); + sprintf(dstPath + dstOffset, "/%s", wiiuacc[allusers].persistentID); + if (checkEntry(srcPath) == 0) { + promptError("No save found for this user."); + return; + } + } + + if (DumpDir(srcPath, dstPath) != 0) promptError("Backup failed. DO NOT restore from this slot."); + + if (strncmp(strchr(dstPath, '_'), "_usb", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_usb01"); + } else if (strncmp(strchr(dstPath, '_'), "_mlc", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01"); + } else if (strncmp(strchr(dstPath, '_'), "_slccmpt", 8) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_slccmpt01"); + } else if (strncmp(strchr(dstPath, '_'), "_sdcard", 7) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_sdcard"); + } +} + +void restoreSavedata(Title* title, u8 slot, s8 sdusers, s8 allusers, bool common) { if (isSlotEmpty(title->highID, title->lowID, slot)) { promptError("No backup found on selected slot."); return; } - if (!promptConfirm("Are you sure?")) return; + if (!promptConfirm(ST_WARNING, "Are you sure?")) return; int slotb = getEmptySlot(title->highID, title->lowID); - if (slotb>=0 && promptConfirm("Backup current savedata first?")) backupSavedata(title, slotb, allusers, common); + if ((slotb >= 0) && promptConfirm(ST_YES_NO, "Backup current savedata first to next empty slot?")) backupSavedata(title, slotb, allusers, common); u32 highID = title->highID, lowID = title->lowID; - bool isUSB = title->isTitleOnUSB, isWii = (highID==0x00010000); + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); char srcPath[PATH_SIZE]; char dstPath[PATH_SIZE]; - const char* path = (isWii ? "slccmpt01:/title" : (isUSB ? "storage_usb:/usr/save" : "storage_mlc:/usr/save")); - sprintf(srcPath, "sd:/wiiu/backups/%08x%08x/%u", highID, lowID, slot); - sprintf(dstPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); - if (!allusers && !isWii) { - char usrPath[16]; - getUserID(usrPath); + const char* path = (isWii ? "/vol/storage_slccmpt01/title" : (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save")); + if (isWii && (slot == 255)) { + sprintf(srcPath, "/vol/storage_sdcard/savegames/%08x%08x", highID, lowID); + } else { + sprintf(srcPath, "/vol/storage_sdcard/wiiu/backups/%08x%08x/%u", highID, lowID, slot); + } + sprintf(dstPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); + createFolder(dstPath); + + if ((sdusers > -1) && !isWii) { u32 srcOffset = strlen(srcPath); u32 dstOffset = strlen(dstPath); if (common) { strcpy(srcPath + srcOffset, "/common"); strcpy(dstPath + dstOffset, "/common"); - if (DumpDir(srcPath, dstPath)!=0) promptError("Common save not found."); + if (DumpDir(srcPath, dstPath) != 0) promptError("Common save not found."); } - sprintf(srcPath + srcOffset, "/%s", usrPath); - sprintf(dstPath + dstOffset, "/%s", usrPath); + sprintf(srcPath + srcOffset, "/%s", sdacc[sdusers].persistentID); + sprintf(dstPath + dstOffset, "/%s", wiiuacc[allusers].persistentID); } - if (DumpDir(srcPath, dstPath)!=0) promptError("Restore failed."); + if (DumpDir(srcPath, dstPath) != 0) promptError("Restore failed."); + + if (strncmp(strchr(dstPath, '_'), "_usb", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_usb01"); + } else if (strncmp(strchr(dstPath, '_'), "_mlc", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01"); + } else if (strncmp(strchr(dstPath, '_'), "_slccmpt", 8) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_slccmpt01"); + } else if (strncmp(strchr(dstPath, '_'), "_sdcard", 7) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_sdcard"); + } } -void wipeSavedata(Title* title, bool allusers, bool common) { +void wipeSavedata(Title* title, s8 allusers, bool common) { - if (!promptConfirm("Are you sure?") || !promptConfirm("Hm, are you REALLY sure?")) return; + if (!promptConfirm(ST_WARNING, "Are you sure?") || !promptConfirm(ST_WARNING, "Hm, are you REALLY sure?")) return; int slotb = getEmptySlot(title->highID, title->lowID); - if (slotb>=0 && promptConfirm("Backup current savedata first?")) backupSavedata(title, slotb, allusers, common); + if ((slotb >= 0) && promptConfirm(ST_YES_NO, "Backup current savedata first?")) backupSavedata(title, slotb, allusers, common); u32 highID = title->highID, lowID = title->lowID; - bool isUSB = title->isTitleOnUSB, isWii = (highID==0x00010000); + bool isUSB = title->isTitleOnUSB, isWii = ((highID & 0xFFFFFFF0) == 0x00010000); char srcPath[PATH_SIZE]; - const char* path = (isWii ? "slccmpt01:/title" : (isUSB ? "storage_usb:/usr/save" : "storage_mlc:/usr/save")); + char origPath[PATH_SIZE]; + const char* path = (isWii ? "/vol/storage_slccmpt01/title" : (isUSB ? "/vol/storage_usb01/usr/save" : "/vol/storage_mlc01/usr/save")); sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, isWii ? "data" : "user"); - if (!allusers && !isWii) { + if ((allusers > -1) && !isWii) { u32 offset = strlen(srcPath); if (common) { strcpy(srcPath + offset, "/common"); - if (DeleteDir(srcPath)!=0) promptError("Common save not found."); + sprintf(origPath, "%s", srcPath); + if (DeleteDir(srcPath) != 0) promptError("Common save not found."); + if (IOSUHAX_FSA_Remove(fsaFd, origPath) != 0) promptError("Failed to delete common folder."); } - char usrPath[16]; - getUserID(usrPath); - sprintf(srcPath + offset, "/%s", usrPath); + sprintf(srcPath + offset, "/%s", wiiuacc[allusers].persistentID); + sprintf(origPath, "%s", srcPath); } - if (DeleteDir(srcPath)!=0) promptError("Failed to delete savefile."); + if (DeleteDir(srcPath)!=0) promptError("Failed to delete savefile."); + if ((allusers > -1) && !isWii) { + if (IOSUHAX_FSA_Remove(fsaFd, origPath) != 0) promptError("Failed to delete user folder."); + } + + if (strncmp(strchr(srcPath, '_'), "_usb", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_usb01"); + } else if (strncmp(strchr(srcPath, '_'), "_mlc", 4) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01"); + } else if (strncmp(strchr(srcPath, '_'), "_slccmpt", 8) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_slccmpt01"); + } else if (strncmp(strchr(srcPath, '_'), "_sdcard", 7) == 0) { + IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_sdcard"); + } } void importFromLoadiine(Title* title, bool common, int version) { - if (!promptConfirm("Are you sure?")) return; + if (!promptConfirm(ST_WARNING, "Are you sure?")) return; int slotb = getEmptySlot(title->highID, title->lowID); - if (slotb>=0 && promptConfirm("Backup current savedata first?")) backupSavedata(title, slotb, 0, common); + if (slotb>=0 && promptConfirm(ST_YES_NO, "Backup current savedata first?")) backupSavedata(title, slotb, 0, common); u32 highID = title->highID, lowID = title->lowID; bool isUSB = title->isTitleOnUSB; char srcPath[PATH_SIZE]; char dstPath[PATH_SIZE]; - if (getLoadiineGameSaveDir(srcPath, title->productCode)!=0) return; + if (getLoadiineGameSaveDir(srcPath, title->productCode) !=0 ) return; if (version) sprintf(srcPath + strlen(srcPath), "/v%i", version); char usrPath[16]; getUserID(usrPath); u32 srcOffset = strlen(srcPath); getLoadiineUserDir(srcPath, srcPath, usrPath); - sprintf(dstPath, "storage_%s:/usr/save/%08x/%08x/user", isUSB ? "usb" : "mlc", highID, lowID); + sprintf(dstPath, "/vol/storage_%s01/usr/save/%08x/%08x/user", isUSB ? "usb" : "mlc", highID, lowID); + createFolder(dstPath); u32 dstOffset = strlen(dstPath); sprintf(dstPath + dstOffset, "/%s", usrPath); - if (DumpDir(srcPath, dstPath)!=0) promptError("Failed to import savedata from loadiine."); - strcpy(srcPath + srcOffset, "/c\0"); - strcpy(dstPath + dstOffset, "/common\0"); - if (DumpDir(srcPath, dstPath)!=0) promptError("Common save not found."); - + promptError(srcPath); + promptError(dstPath); + if (DumpDir(srcPath, dstPath) != 0) promptError("Failed to import savedata from loadiine."); + if (common) { + strcpy(srcPath + srcOffset, "/c\0"); + strcpy(dstPath + dstOffset, "/common\0"); + promptError(srcPath); + promptError(dstPath); + if (DumpDir(srcPath, dstPath) != 0) promptError("Common save not found."); + } } void exportToLoadiine(Title* title, bool common, int version) { - if (!promptConfirm("Are you sure?")) return; + if (!promptConfirm(ST_WARNING, "Are you sure?")) return; u32 highID = title->highID, lowID = title->lowID; bool isUSB = title->isTitleOnUSB; char srcPath[PATH_SIZE]; @@ -441,12 +1046,18 @@ void exportToLoadiine(Title* title, bool common, int version) { getUserID(usrPath); u32 dstOffset = strlen(dstPath); getLoadiineUserDir(dstPath, dstPath, usrPath); - sprintf(srcPath, "storage_%s:/usr/save/%08x/%08x/user", isUSB ? "usb" : "mlc", highID, lowID); + sprintf(srcPath, "/vol/storage_%s01/usr/save/%08x/%08x/user", isUSB ? "usb" : "mlc", highID, lowID); u32 srcOffset = strlen(srcPath); sprintf(srcPath + srcOffset, "/%s", usrPath); - if (DumpDir(srcPath, dstPath)!=0) promptError("Failed to export savedata to loadiine."); - strcpy(dstPath + dstOffset, "/c\0"); - strcpy(srcPath + srcOffset, "/common\0"); - if (DumpDir(srcPath, dstPath)!=0) promptError("Common save not found."); - + createFolder(dstPath); + promptError(srcPath); + promptError(dstPath); + if (DumpDir(srcPath, dstPath) != 0) promptError("Failed to export savedata to loadiine."); + if (common) { + strcpy(dstPath + dstOffset, "/c\0"); + strcpy(srcPath + srcOffset, "/common\0"); + promptError(srcPath); + promptError(dstPath); + if (DumpDir(srcPath, dstPath) != 0) promptError("Common save not found."); + } } diff --git a/src/savemng.h b/src/savemng.h index 47a8962..acaab93 100644 --- a/src/savemng.h +++ b/src/savemng.h @@ -9,6 +9,7 @@ #include #include "lib_easy.h" +#include "draw.h" #define PATH_SIZE 0x200 @@ -19,27 +20,77 @@ extern "C" { typedef struct { u32 highID; u32 lowID; + u16 listID; char shortName[256]; - char productCode[32]; + char longName[512]; + char productCode[5]; + bool saveInit; bool isTitleOnUSB; + bool isTitleDupe; + u16 dupeID; + u8* iconBuf; } Title; +typedef struct { + u32 highID; + u32 lowID; + u8 dev; + bool found; +} Saves; + +typedef struct { + char persistentID[9]; + u32 pID; + char miiName[50]; + u8 slot; +} Account; + +typedef enum { + ST_YES_NO = 1, + ST_CONFIRM_CANCEL = 2, + ST_MULTILINE = 16, + ST_WARNING = 32, + ST_ERROR = 64 +} Style; + +extern Account* wiiuacc; +extern Account* sdacc; +extern u8 wiiuaccn, sdaccn; + void console_print_pos(int x, int y, const char* format, ...); -bool promptConfirm(const char* question); -void promptError(const char* message); +bool promptConfirm(Style st, const char* question); +void promptError(const char* message, ...); +void getUserID(char* out); +void getAccountsWiiU(); int getLoadiineGameSaveDir(char* out, const char* productCode); int getLoadiineSaveVersionList(int* out, const char* gamePath); int getLoadiineUserDir(char* out, const char* fullSavePath, const char* userID); -void backupSavedata(Title* title, u8 slot, bool allusers, bool common); -void restoreSavedata(Title* title, u8 slot, bool allusers, bool common); -void wipeSavedata(Title* title, bool allusers, bool common); +u64 getSlotDate(u32 highID, u32 lowID, u8 slot); +bool isSlotEmpty(u32 highID, u32 lowID, u8 slot); +bool hasCommonSave(Title* title, bool inSD, bool iine, u8 slot, int version); + +void copySavedata(Title* title, Title* titled, s8 allusers, s8 allusers_d, bool common); +void backupAllSave(Title* titles, int count, OSCalendarTime* date); +void backupSavedata(Title* title, u8 slot, s8 allusers, bool common); +void restoreSavedata(Title* title, u8 slot, s8 sdusers, s8 allusers, bool common); +void wipeSavedata(Title* title, s8 allusers, bool common); void importFromLoadiine(Title* title, bool common, int version); void exportToLoadiine(Title* title, bool common, int version); +void setFSAFD(int fd); +int checkEntry(const char * fPath); +int folderEmpty(const char * fPath); +s32 loadFile(const char * fPath, u8 **buf); +s32 loadFilePart(const char * fPath, u32 start, u32 size, u8 **buf); +s32 loadTitleIcon(Title* title); + +void show_file_operation(char* file_name, char* file_src, char* file_dest); +void console_print_pos_multiline(int x, int y, char cdiv,const char* format, ...); + #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/src/system/memory.c b/src/system/memory.c index 91f5392..00f62a3 100644 --- a/src/system/memory.c +++ b/src/system/memory.c @@ -34,18 +34,18 @@ //! Memory functions //! This is the only place where those are needed so lets keep them more or less private //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern unsigned int * pMEMAllocFromDefaultHeapEx; -extern unsigned int * pMEMAllocFromDefaultHeap; -extern unsigned int * pMEMFreeToDefaultHeap; +extern u32 * pMEMAllocFromDefaultHeapEx; +extern u32 * pMEMAllocFromDefaultHeap; +extern u32 * pMEMFreeToDefaultHeap; -extern int (* MEMGetBaseHeapHandle)(int mem_arena); -extern unsigned int (* MEMGetAllocatableSizeForFrmHeapEx)(int heap, int align); -extern void *(* MEMAllocFromFrmHeapEx)(int heap, unsigned int size, int align); -extern void (* MEMFreeToFrmHeap)(int heap, int mode); -extern void *(* MEMAllocFromExpHeapEx)(int heap, unsigned int size, int align); -extern int (* MEMCreateExpHeapEx)(void* address, unsigned int size, unsigned short flags); -extern void *(* MEMDestroyExpHeap)(int heap); -extern void (* MEMFreeToExpHeap)(int heap, void* ptr); +extern s32 (* MEMGetBaseHeapHandle)(s32 mem_arena); +extern u32 (* MEMGetAllocatableSizeForFrmHeapEx)(s32 heap, s32 align); +extern void *(* MEMAllocFromFrmHeapEx)(s32 heap, u32 size, s32 align); +extern void (* MEMFreeToFrmHeap)(s32 heap, s32 mode); +extern void *(* MEMAllocFromExpHeapEx)(s32 heap, u32 size, s32 align); +extern s32 (* MEMCreateExpHeapEx)(void* address, u32 size, unsigned short flags); +extern void *(* MEMDestroyExpHeap)(s32 heap); +extern void (* MEMFreeToExpHeap)(s32 heap, void* ptr); static int mem1_heap = -1; static int bucket_heap = -1; diff --git a/src/tga_reader.c b/src/tga_reader.c new file mode 100644 index 0000000..4c519fb --- /dev/null +++ b/src/tga_reader.c @@ -0,0 +1,576 @@ +/** + * tga_reader.c + * + * Copyright (c) 2014 Kenji Sasaki + * Released under the MIT license. + * https://github.com/npedotnet/TGAReader/blob/master/LICENSE + * + * English document + * https://github.com/npedotnet/TGAReader/blob/master/README.md + * + * Japanese document + * http://3dtech.jp/wiki/index.php?TGAReader + * + */ + +#include "tga_reader.h" + +static const TGA_ORDER _TGA_READER_ARGB = {16, 8, 0, 24}; +const TGA_ORDER *TGA_READER_ARGB = &_TGA_READER_ARGB; + +static const TGA_ORDER _TGA_READER_ABGR = {0, 8, 16, 24}; +const TGA_ORDER *TGA_READER_ABGR = &_TGA_READER_ABGR; + +static const TGA_ORDER _TGA_READER_RGBA = {24, 16, 8, 0}; +const TGA_ORDER *TGA_READER_RGBA = &_TGA_READER_RGBA; + +void *tgaMalloc(size_t size) { + return malloc(size); +} + +void tgaFree(void *memory) { + free(memory); +} + +int tgaGetWidth(const unsigned char *buffer) { + return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8; +} + +int tgaGetHeight(const unsigned char *buffer) { + return (buffer[14] & 0xFF) | (buffer[15] & 0xFF) << 8; +} + +#define COLORMAP 1 +#define RGB 2 +#define GRAYSCALE 3 +#define COLORMAP_RLE 9 +#define RGB_RLE 10 +#define GRAYSCALE_RLE 11 +#define RIGHT_ORIGIN 0x10 +#define UPPER_ORIGIN 0x20 + +static unsigned char *decodeRLE(int width, int height, int depth, const unsigned char *buffer, int offset); + +static int *createPixelsFromColormap(int width, int height, int depth, const unsigned char *bytes, int offset, const unsigned char *palette, int colormapOrigin, int descriptor, const TGA_ORDER *order); +static int *createPixelsFromRGB(int width, int height, int depth, const unsigned char *bytes, int offset, int descriptor, const TGA_ORDER *order); +static int *createPixelsFromGrayscale(int width, int height, int depth, const unsigned char *bytes, int offset, int descriptor, const TGA_ORDER *order); + +int *tgaRead(const unsigned char *buffer, const TGA_ORDER *order) { + + // header +// int idFieldLength = buffer[0] & 0xFF; +// int colormapType = buffer[1] & 0xFF; + int type = buffer[2] & 0xFF; + int colormapOrigin = (buffer[3] & 0xFF) | (buffer[4] & 0xFF) << 8; + int colormapLength = (buffer[5] & 0xFF) | (buffer[6] & 0xFF) << 8; + int colormapDepth = buffer[7] & 0xFF; +// int originX = (buffer[8] & 0xFF) | (buffer[9] & 0xFF) << 8; // unsupported +// int originY = (buffer[10] & 0xFF) | (buffer[11] & 0xFF) << 8; // unsupported + int width = tgaGetWidth(buffer); + int height = tgaGetHeight(buffer); + int depth = buffer[16] & 0xFF; + int descriptor = buffer[17] & 0xFF; + + int *pixels = NULL; + + // data + switch(type) { + case COLORMAP: { + int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength; + pixels = createPixelsFromColormap(width, height, colormapDepth, buffer, imageDataOffset, buffer, colormapOrigin, descriptor, order); + } break; + case RGB: + pixels = createPixelsFromRGB(width, height, depth, buffer, 18, descriptor, order); + break; + case GRAYSCALE: + pixels = createPixelsFromGrayscale(width, height, depth, buffer, 18, descriptor, order); + break; + case COLORMAP_RLE: { + int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength; + unsigned char *decodeBuffer = decodeRLE(width, height, depth, buffer, imageDataOffset); + pixels = createPixelsFromColormap(width, height, colormapDepth, decodeBuffer, 0, buffer, colormapOrigin, descriptor, order); + tgaFree(decodeBuffer); + } break; + case RGB_RLE: { + unsigned char *decodeBuffer = decodeRLE(width, height, depth, buffer, 18); + pixels = createPixelsFromRGB(width, height, depth, decodeBuffer, 0, descriptor, order); + tgaFree(decodeBuffer); + } break; + case GRAYSCALE_RLE: { + unsigned char *decodeBuffer = decodeRLE(width, height, depth, buffer, 18); + pixels = createPixelsFromGrayscale(width, height, depth, decodeBuffer, 0, descriptor, order); + tgaFree(decodeBuffer); + } break; + default: + break; + } + + return pixels; + +} + +static unsigned char *decodeRLE(int width, int height, int depth, const unsigned char *buffer, int offset) { + int elementCount = depth/8; + unsigned char elements[4]; + int decodeBufferLength = elementCount * width * height; + unsigned char *decodeBuffer = (unsigned char *)tgaMalloc(decodeBufferLength); + int decoded = 0; + while(decoded < decodeBufferLength) { + int packet = buffer[offset++] & 0xFF; + if((packet & 0x80) != 0) { // RLE + int i, j, count; + for(i=0; iredShift; + int gs = order->greenShift; + int bs = order->blueShift; + int as = order->alphaShift; + switch(depth) { + case 24: + pixels = (int *)tgaMalloc(4*width*height); + if((descriptor & RIGHT_ORIGIN) != 0) { + if((descriptor & UPPER_ORIGIN) != 0) { + // UpperRight + int i, j; + for(i=0; i= 0) { + int index = 3*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = 0xFF; + color = (r<= 0) { + int index = 3*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = 0xFF; + color = (r<= 0) { + int index = 3*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = 0xFF; + color = (r<= 0) { + int index = 3*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = 0xFF; + color = (r<= 0) { + int index = 4*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = palette[index+3] & 0xFF; + color = (r<= 0) { + int index = 4*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = palette[index+3] & 0xFF; + color = (r<= 0) { + int index = 4*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = palette[index+3] & 0xFF; + color = (r<= 0) { + int index = 4*colormapIndex+18; + int b = palette[index+0] & 0xFF; + int g = palette[index+1] & 0xFF; + int r = palette[index+2] & 0xFF; + int a = palette[index+3] & 0xFF; + color = (r<redShift; + int gs = order->greenShift; + int bs = order->blueShift; + int as = order->alphaShift; + switch(depth) { + case 24: + pixels = (int *)tgaMalloc(4*width*height); + if((descriptor & RIGHT_ORIGIN) != 0) { + if((descriptor & UPPER_ORIGIN) != 0) { + // UpperRight + int i, j; + for(i=0; iredShift; + int gs = order->greenShift; + int bs = order->blueShift; + int as = order->alphaShift; + switch(depth) { + case 8: + pixels = (int *)tgaMalloc(4*width*height); + if((descriptor & RIGHT_ORIGIN) != 0) { + if((descriptor & UPPER_ORIGIN) != 0) { + // UpperRight + int i, j; + for(i=0; i +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _TGA_ORDER { + int redShift; + int greenShift; + int blueShift; + int alphaShift; +} TGA_ORDER; + +const TGA_ORDER *TGA_READER_ARGB; +const TGA_ORDER *TGA_READER_ABGR; +const TGA_ORDER *TGA_READER_RGBA; + +void *tgaMalloc(size_t size); +void tgaFree(void *memory); + +int tgaGetWidth(const unsigned char *buffer); +int tgaGetHeight(const unsigned char *buffer); +int *tgaRead(const unsigned char *buffer, const TGA_ORDER *order); + +#ifdef __cplusplus +} +#endif + +#endif /* __TGA_READER_H__ */