From da85d8c671808a39f99f37ad1c6cd4ec9102a8d0 Mon Sep 17 00:00:00 2001 From: Pellegrino Prevete Date: Mon, 1 Nov 2021 08:44:25 +0100 Subject: [PATCH 1/2] Update to 0.987 --- Makefile | 89 +++-- ReqSpaceCalc.c | 0 ReqSpaceCalc.h | 0 UI.c | 467 +++++++++++++++++++-------- UI.h | 32 +- font.c | 315 ++++++++++++------ font.h | 4 + graphics.c | 176 +++++++--- graphics.h | 52 ++- irx/compiled/mctools.irx | Bin 11613 -> 11685 bytes irx/compiled/secrsif.irx | Bin 4685 -> 4685 bytes irx/source/mctools/Makefile | 12 +- irx/source/secrman/Makefile | 30 +- irx/source/secrman/include/secrman.h | 0 irx/source/secrman/src/CardAuth.c | 2 +- irx/source/secrman/src/CardAuth.h | 0 irx/source/secrman/src/MechaAuth.c | 0 irx/source/secrman/src/MechaAuth.h | 0 irx/source/secrman/src/exports.tab | 0 irx/source/secrman/src/imports.lst | 0 irx/source/secrman/src/irx_imports.h | 0 irx/source/secrman/src/keyman.c | 0 irx/source/secrman/src/keyman.h | 0 irx/source/secrman/src/main.h | 0 irx/source/secrman/src/secrman.c | 10 +- irx/source/secrsif/Makefile | 26 +- irx/source/secrsif/src/exports.tab | 0 irx/source/secrsif/src/imports.lst | 0 irx/source/secrsif/src/irx_imports.h | 7 - irx/source/secrsif/src/secrsif.c | 228 ++++++------- irx/source/secrsif/src/secrsif.h | 44 +-- lang.c | 10 +- lang.h | 8 + libsecr.c | 0 libsecr.h | 0 linkfile | 16 +- main.c | 193 +++-------- main.h | 2 +- mctools_rpc.c | 50 ++- mctools_rpc.h | 0 menu.c | 63 +++- menu.h | 0 pad.c | 21 +- pad.h | 3 + resources/background.png | Bin system.c | 326 +++++++++++++++---- system.h | 7 +- 47 files changed, 1420 insertions(+), 773 deletions(-) mode change 100755 => 100644 Makefile mode change 100755 => 100644 ReqSpaceCalc.c mode change 100755 => 100644 ReqSpaceCalc.h mode change 100755 => 100644 UI.c mode change 100755 => 100644 UI.h mode change 100755 => 100644 font.c mode change 100755 => 100644 font.h mode change 100755 => 100644 irx/compiled/mctools.irx mode change 100755 => 100644 irx/source/mctools/Makefile mode change 100755 => 100644 irx/source/secrman/Makefile mode change 100755 => 100644 irx/source/secrman/include/secrman.h mode change 100755 => 100644 irx/source/secrman/src/CardAuth.c mode change 100755 => 100644 irx/source/secrman/src/CardAuth.h mode change 100755 => 100644 irx/source/secrman/src/MechaAuth.c mode change 100755 => 100644 irx/source/secrman/src/MechaAuth.h mode change 100755 => 100644 irx/source/secrman/src/exports.tab mode change 100755 => 100644 irx/source/secrman/src/imports.lst mode change 100755 => 100644 irx/source/secrman/src/irx_imports.h mode change 100755 => 100644 irx/source/secrman/src/keyman.c mode change 100755 => 100644 irx/source/secrman/src/keyman.h mode change 100755 => 100644 irx/source/secrman/src/main.h mode change 100755 => 100644 irx/source/secrman/src/secrman.c mode change 100755 => 100644 irx/source/secrsif/Makefile mode change 100755 => 100644 irx/source/secrsif/src/exports.tab mode change 100755 => 100644 irx/source/secrsif/src/imports.lst mode change 100755 => 100644 irx/source/secrsif/src/irx_imports.h mode change 100755 => 100644 irx/source/secrsif/src/secrsif.c mode change 100755 => 100644 irx/source/secrsif/src/secrsif.h mode change 100755 => 100644 libsecr.c mode change 100755 => 100644 libsecr.h mode change 100755 => 100644 linkfile mode change 100755 => 100644 main.c mode change 100755 => 100644 main.h mode change 100755 => 100644 mctools_rpc.c mode change 100755 => 100644 mctools_rpc.h mode change 100755 => 100644 menu.c mode change 100755 => 100644 menu.h mode change 100755 => 100644 pad.c mode change 100755 => 100644 pad.h mode change 100755 => 100644 resources/background.png mode change 100755 => 100644 system.c mode change 100755 => 100644 system.h diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 index cc6d777..f63098a --- a/Makefile +++ b/Makefile @@ -1,15 +1,15 @@ EE_BIN = FMCBInstaller.elf #IOP modules -EE_IOP_OBJS = UDNL_irx.o IOMANX_irx.o FILEXIO_irx.o SIO2MAN_irx.o PADMAN_irx.o MCMAN_irx.o MCSERV_irx.o SECRSIF_irx.o MCTOOLS_irx.o USBD_irx.o USBHDFSD_irx.o POWEROFF_irx.o DEV9_irx.o ATAD_irx.o HDD_irx.o PFS_irx.o #UDPTTY_irx.o +EE_IOP_OBJS = IOPRP_img.o IOMANX_irx.o FILEXIO_irx.o SIO2MAN_irx.o PADMAN_irx.o MCMAN_irx.o MCSERV_irx.o SECRSIF_irx.o MCTOOLS_irx.o USBD_irx.o USBHDFSD_irx.o POWEROFF_irx.o DEV9_irx.o ATAD_irx.o HDD_irx.o PFS_irx.o IRX_DIR = irx/compiled -EE_RES_OBJS = background.o pad_layout.o -EE_OBJS = main.o ioprstctrl.o modutils.o UI.o menu.o libsecr.o pad.o system.o graphics.o ReqSpaceCalc.o font.o $(EE_RES_OBJS) $(EE_IOP_OBJS) mctools_rpc.o +EE_RES_OBJS = background.o buttons.o +EE_OBJS = main.o iop.o UI.o menu.o libsecr.o pad.o system.o graphics.o ReqSpaceCalc.o font.o $(EE_RES_OBJS) $(EE_IOP_OBJS) mctools_rpc.o -EE_INCS := -I$(PS2SDK)/ports/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -I./irx/source/secrsif/src -I./irx/source/mctools +EE_INCS := -I$(PS2SDK)/ports/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -I./irx/source/secrsif/src -I./irx/source/mctools/src/ EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(PS2SDK)/ee/lib -L$(PS2DEV)/ee/ee/lib -Tlinkfile -s -EE_LIBS = -lgs -lpng -lz -lm -lfreetype -lcdvd -lmc -lpadx -lhdd -lfileXio -lpatches -lc -lkernel +EE_LIBS = -lgs -lpng -lz -lm -lfreetype -lpoweroff -lcdvd -lmc -lpadx -lhdd -lfileXio -lpatches -liopreboot -lc -lkernel EE_GPVAL = -G8192 EE_CFLAGS += -Os -mgpopt $(EE_GPVAL) @@ -29,63 +29,60 @@ all: $(MAKE) $(EE_BIN) clean: - rm -f $(EE_BIN) $(EE_BIN_REL) $(EE_OBJS) + rm -f $(EE_BIN) $(EE_BIN_REL) $(EE_OBJS) *_irx.c background.c buttons.c IOPRP_img.c -background.o: - bin2o $(EE_GPVAL) resources/background.png background.o background +background.c: resources/background.png + bin2c resources/background.png background.c background -pad_layout.o: - bin2o $(EE_GPVAL) resources/pad_layout.png pad_layout.o pad_layout +buttons.c: resources/buttons.png + bin2c resources/buttons.png buttons.c buttons -POWEROFF_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/poweroff.irx POWEROFF_irx.o POWEROFF_irx +POWEROFF_irx.c: $(PS2SDK)/iop/irx/poweroff.irx + bin2c $(PS2SDK)/iop/irx/poweroff.irx POWEROFF_irx.c POWEROFF_irx -DEV9_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/ps2dev9.irx DEV9_irx.o DEV9_irx +DEV9_irx.c: $(PS2SDK)/iop/irx/ps2dev9.irx + bin2c $(PS2SDK)/iop/irx/ps2dev9.irx DEV9_irx.c DEV9_irx -UDPTTY_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/udptty.irx UDPTTY_irx.o UDPTTY_irx +IOMANX_irx.c: $(PS2SDK)/iop/irx/iomanX.irx + bin2c $(PS2SDK)/iop/irx/iomanX.irx IOMANX_irx.c IOMANX_irx -IOMANX_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/iomanX.irx IOMANX_irx.o IOMANX_irx +FILEXIO_irx.c: $(PS2SDK)/iop/irx/fileXio.irx + bin2c $(PS2SDK)/iop/irx/fileXio.irx FILEXIO_irx.c FILEXIO_irx -FILEXIO_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/fileXio.irx FILEXIO_irx.o FILEXIO_irx +SIO2MAN_irx.c: $(PS2SDK)/iop/irx/freesio2.irx + bin2c $(PS2SDK)/iop/irx/freesio2.irx SIO2MAN_irx.c SIO2MAN_irx -SIO2MAN_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/freesio2.irx SIO2MAN_irx.o SIO2MAN_irx +PADMAN_irx.c: $(PS2SDK)/iop/irx/freepad.irx + bin2c $(PS2SDK)/iop/irx/freepad.irx PADMAN_irx.c PADMAN_irx -PADMAN_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/freepad.irx PADMAN_irx.o PADMAN_irx +MCMAN_irx.c: $(PS2SDK)/iop/irx/mcman.irx + bin2c $(PS2SDK)/iop/irx/mcman.irx MCMAN_irx.c MCMAN_irx -MCMAN_irx.o: - bin2o $(EE_GPVAL) $(IRX_DIR)/mcman.irx MCMAN_irx.o MCMAN_irx +MCSERV_irx.c: $(PS2SDK)/iop/irx/mcserv.irx + bin2c $(PS2SDK)/iop/irx/mcserv.irx MCSERV_irx.c MCSERV_irx -MCSERV_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/mcserv.irx MCSERV_irx.o MCSERV_irx +SECRSIF_irx.c: $(IRX_DIR)/secrsif.irx + bin2c $(IRX_DIR)/secrsif.irx SECRSIF_irx.c SECRSIF_irx -SECRSIF_irx.o: - bin2o $(EE_GPVAL) $(IRX_DIR)/secrsif.irx SECRSIF_irx.o SECRSIF_irx +MCTOOLS_irx.c: $(IRX_DIR)/mctools.irx + bin2c $(IRX_DIR)/mctools.irx MCTOOLS_irx.c MCTOOLS_irx -MCTOOLS_irx.o: - bin2o $(EE_GPVAL) $(IRX_DIR)/mctools.irx MCTOOLS_irx.o MCTOOLS_irx +USBD_irx.c: $(PS2SDK)/iop/irx/usbd.irx + bin2c $(PS2SDK)/iop/irx/usbd.irx USBD_irx.c USBD_irx -USBD_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/usbd.irx USBD_irx.o USBD_irx +USBHDFSD_irx.c: $(PS2SDK)/iop/irx/usbhdfsd.irx + bin2c $(PS2SDK)/iop/irx/usbhdfsd.irx USBHDFSD_irx.c USBHDFSD_irx -USBHDFSD_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/usbhdfsd.irx USBHDFSD_irx.o USBHDFSD_irx +IOPRP_img.c: $(IRX_DIR)/IOPRP.img + bin2c $(IRX_DIR)/IOPRP.img IOPRP_img.c IOPRP_img -UDNL_irx.o: - bin2o $(EE_GPVAL) $(IRX_DIR)/udnl.irx UDNL_irx.o UDNL_irx +ATAD_irx.c: $(PS2SDK)/iop/irx/ps2atad.irx + bin2c $(PS2SDK)/iop/irx/ps2atad.irx ATAD_irx.c ATAD_irx -ATAD_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/ps2atad.irx ATAD_irx.o ATAD_irx +HDD_irx.c: $(PS2SDK)/iop/irx/ps2hdd-osd.irx + bin2c $(PS2SDK)/iop/irx/ps2hdd-osd.irx HDD_irx.c HDD_irx -HDD_irx.o: - bin2o $(EE_GPVAL) $(IRX_DIR)/ps2hdd.irx HDD_irx.o HDD_irx +PFS_irx.c: $(PS2SDK)/iop/irx/ps2fs.irx + bin2c $(PS2SDK)/iop/irx/ps2fs.irx PFS_irx.c PFS_irx -PFS_irx.o: - bin2o $(EE_GPVAL) $(PS2SDK)/iop/irx/ps2fs.irx PFS_irx.o PFS_irx - -include $(PS2SDK)/samples/Makefile.pref +include $(PS2SDK)/Defs.make diff --git a/ReqSpaceCalc.c b/ReqSpaceCalc.c old mode 100755 new mode 100644 diff --git a/ReqSpaceCalc.h b/ReqSpaceCalc.h old mode 100755 new mode 100644 diff --git a/UI.c b/UI.c old mode 100755 new mode 100644 index 35a65ae..5fce927 --- a/UI.c +++ b/UI.c @@ -21,12 +21,10 @@ extern int errno __attribute__((section("data"))); struct UIDrawGlobal UIDrawGlobal; GS_IMAGE BackgroundTexture; -GS_IMAGE PadLayoutTexture; +struct ClutImage PadLayoutTexture; -#ifdef UI_FONT_MEM static void *gFontBuffer = NULL; static int gFontBufferSize; -#endif unsigned short int SelectButton, CancelButton; #define NUM_SUPPORTED_LANGUAGES 8 @@ -37,25 +35,33 @@ static int language=LANGUAGE_ENGLISH; static char *LangStringTable[SYS_UI_MSG_COUNT]; static char *LangLblStringTable[SYS_UI_LBL_COUNT]; +static u8 LangStringWrapTable[(SYS_UI_MSG_COUNT + 7) / 8]; static void UnloadLanguage(void); +static void WaitForDevice(void) +{ + nopdelay(); + nopdelay(); + nopdelay(); + nopdelay(); + nopdelay(); + nopdelay(); + nopdelay(); + nopdelay(); +} + static int FormatLanguageString(const char *in, int len, char *out) { wchar_t wchar1, wchar2; - int ActualLength, CharLen1, CharLen2, ScreenLineLen; - char *LastWhitespaceOut; - const char *LastSplit; + int ActualLength, CharLen1, CharLen2; - // Line lengths are counted from the last newline character (either discovered or inserted). ActualLength = 0; - ScreenLineLen = 0; CharLen1 = mbtowc(&wchar1, in, len); - LastWhitespaceOut = NULL; - LastSplit = in; while(CharLen1 > 0 && wchar1 != '\0') { - if(((CharLen2 = mbtowc(&wchar2, in + CharLen1, len - CharLen1)) > 0) && (wchar1 == '\\' && wchar2 != '\0')) + CharLen2 = mbtowc(&wchar2, in + CharLen1, len - CharLen1); + if((CharLen2 > 0) && (wchar1 == '\\' && wchar2 != '\0')) { switch(wchar2) { //When a translation file is used, escape characters appear like "\n" in the file. @@ -63,8 +69,6 @@ static int FormatLanguageString(const char *in, int len, char *out) *out = '\n'; out++; ActualLength++; - ScreenLineLen = 0; - LastWhitespaceOut = NULL; break; } @@ -72,48 +76,75 @@ static int FormatLanguageString(const char *in, int len, char *out) len -= (CharLen1 + CharLen2); CharLen2 = mbtowc(&wchar2, in, len); } else { - switch(wchar1) - { //Record where the latest whitespace is. - case ' ': - LastWhitespaceOut = out; - break; - } - memcpy(out, in, CharLen1); out += CharLen1; ActualLength += CharLen1; in += CharLen1; len -= CharLen1; + } - switch(wchar1) - { //If the lines are built-in, escape characters are used. - case '\n': - ScreenLineLen = 0; - LastWhitespaceOut = NULL; - break; - default: - ScreenLineLen++; - } + CharLen1 = CharLen2; + wchar1 = wchar2; + } + *out = '\0'; + + return(ActualLength + 1); +} + +static void BreakLongLanguageString(char *str) +{ + wchar_t wchar; + int CharLen, ScreenLineLenPx, LineMaxPx, PxSinceLastSpace, len, width; + char *LastWhitespaceOut; + + LineMaxPx = UIDrawGlobal.width - 2*UI_OFFSET_X; + + // Line lengths are counted from the last newline character (either discovered or inserted). + ScreenLineLenPx = 0; + PxSinceLastSpace = 0; + len = strlen(str) + 1; + CharLen = mbtowc(&wchar, str, len); + LastWhitespaceOut = NULL; + while(CharLen > 0 && wchar != '\0') + { + switch(wchar) + { + case '\n': + ScreenLineLenPx = 0; + LastWhitespaceOut = NULL; + PxSinceLastSpace = 0; + break; + case ' ': //Record where the latest whitespace is. + LastWhitespaceOut = str; + PxSinceLastSpace = 0; + break; + } + + if (wchar != '\n') + { + width = FontGetGlyphWidth(&UIDrawGlobal, wchar); // To wrap long lines, replace the last whitespace with a newline character - if(ScreenLineLen >= UI_LINE_MAX) + if(ScreenLineLenPx + width >= LineMaxPx) { if(LastWhitespaceOut != NULL) { - ScreenLineLen = (int)(out - LastWhitespaceOut) - 1; + ScreenLineLenPx = PxSinceLastSpace; *LastWhitespaceOut = '\n'; - LastSplit = LastWhitespaceOut + 1; LastWhitespaceOut = NULL; } } + + ScreenLineLenPx += width; + if(wchar != ' ') + PxSinceLastSpace += width; } - CharLen1 = CharLen2; - wchar1 = wchar2; - } - *out = '\0'; + str += CharLen; + len -= CharLen; - return(ActualLength + 1); + CharLen = mbtowc(&wchar, str, len); + } } static int ParseLanguageFile(char **array, FILE *file, unsigned int ExpectedNumLines) @@ -140,7 +171,8 @@ static int ParseLanguageFile(char **array, FILE *file, unsigned int ExpectedNumL if((array[LinesLoaded] = malloc(len + 1)) != NULL) { - array[LinesLoaded] = realloc(array[LinesLoaded], FormatLanguageString(line, len + 1, array[LinesLoaded])); + len = FormatLanguageString(line, len + 1, array[LinesLoaded]); + array[LinesLoaded] = realloc(array[LinesLoaded], len); } else { result=-ENOMEM; break; @@ -151,7 +183,7 @@ static int ParseLanguageFile(char **array, FILE *file, unsigned int ExpectedNumL { if(LinesLoaded != ExpectedNumLines) { - DEBUG_PRINTF("ParseLanguageFile: Mismatched number of lines (%u/%d)\n", LinesLoaded, ExpectedNumLines); + printf("ParseLanguageFile: Mismatched number of lines (%u/%d)\n", LinesLoaded, ExpectedNumLines); result = -1; } } @@ -179,7 +211,8 @@ static int ParseFontListFile(char **array, FILE *file, unsigned int ExpectedNumL { if((array[LinesLoaded] = malloc(len + 1)) != NULL) { - strcpy(array[LinesLoaded], line); + len = FormatLanguageString(line, len + 1, array[LinesLoaded]); + array[LinesLoaded] = realloc(array[LinesLoaded], len); } else { result = -ENOMEM; break; @@ -191,7 +224,7 @@ static int ParseFontListFile(char **array, FILE *file, unsigned int ExpectedNumL { if(LinesLoaded!=ExpectedNumLines) { - DEBUG_PRINTF("ParseFontListFile: Mismatched number of lines (%u/%d)\n", LinesLoaded, ExpectedNumLines); + printf("ParseFontListFile: Mismatched number of lines (%u/%d)\n", LinesLoaded, ExpectedNumLines); result = -1; } } @@ -220,7 +253,15 @@ static char *GetFontFilePath(unsigned int language) result=NULL; memset(FontFileArray, 0, sizeof(FontFileArray)); - if((file = fopen("lang/fonts.txt", "r")) != NULL) + while((file = fopen("lang/fonts.txt", "r")) == NULL) + { + if(errno != ENODEV) + break; + + WaitForDevice(); + } + + if(file != NULL) { if(ParseFontListFile(FontFileArray, file, NUM_SUPPORTED_LANGUAGES)==0) { @@ -300,7 +341,8 @@ static int LoadDefaultLanguageStrings(void) if((LangStringTable[LinesLoaded] = malloc(len + 1)) != NULL) { - LangStringTable[LinesLoaded] = realloc(LangStringTable[LinesLoaded], FormatLanguageString(DefaultLanguageStringTable[LinesLoaded], len + 1, LangStringTable[LinesLoaded])); + len = FormatLanguageString(DefaultLanguageStringTable[LinesLoaded], len + 1, LangStringTable[LinesLoaded]); + LangStringTable[LinesLoaded] = realloc(LangStringTable[LinesLoaded], len); } else { result=-ENOMEM; break; @@ -316,7 +358,8 @@ static int LoadDefaultLanguageStrings(void) if((LangLblStringTable[LinesLoaded] = malloc(len + 1)) != NULL) { - LangLblStringTable[LinesLoaded] = realloc(LangLblStringTable[LinesLoaded], FormatLanguageString(DefaultLanguageLabelStringTable[LinesLoaded], len + 1, LangLblStringTable[LinesLoaded])); + len = FormatLanguageString(DefaultLanguageLabelStringTable[LinesLoaded], len + 1, LangLblStringTable[LinesLoaded]); + LangLblStringTable[LinesLoaded] = realloc(LangLblStringTable[LinesLoaded], len); } else { result=-ENOMEM; break; @@ -353,25 +396,20 @@ static void UnloadLanguage(void) } } -const char *GetUIString(unsigned int StringID) +const char *GetUIString(unsigned int id) { - return(LangStringTable[StringID]); -} + if(!(LangStringWrapTable[id / 8] & (1 << (id % 8)))) + { + BreakLongLanguageString(LangStringTable[id]); + LangStringWrapTable[id / 8] |= (1 << (id % 8)); + } -const char *GetUILabel(unsigned int LabelID) -{ - return(LangLblStringTable[LabelID]); + return(LangStringTable[id]); } -static void WaitForDevice(void) + +const char *GetUILabel(unsigned int id) { - nopdelay(); - nopdelay(); - nopdelay(); - nopdelay(); - nopdelay(); - nopdelay(); - nopdelay(); - nopdelay(); + return(LangLblStringTable[id]); } static void InitGraphics(void) @@ -436,8 +474,6 @@ static void InitGraphics(void) GsEnableAlphaBlending2(GS_ENABLE); } -#ifdef UI_FONT_MEM -#define UI_LOAD_FONT_FUNC(DrawGlobal, path) LoadFontIntoBuffer(DrawGlobal, path) static int LoadFontIntoBuffer(struct UIDrawGlobal *gsGlobal, const char *path) { @@ -451,11 +487,11 @@ static int LoadFontIntoBuffer(struct UIDrawGlobal *gsGlobal, const char *path) size = ftell(file); rewind(file); - if((buffer = malloc(size)) != NULL) + if((buffer = memalign(64, size)) != NULL) { if(fread(buffer, 1, size, file) == size) { - if((result = FontInitWithBuffer(gsGlobal, buffer, size)) != 0) + if((result = FontInitWithBuffer(&UIDrawGlobal, buffer, size)) != 0) free(buffer); else { gFontBuffer = buffer; @@ -473,17 +509,90 @@ static int LoadFontIntoBuffer(struct UIDrawGlobal *gsGlobal, const char *path) return result; } -#else -#define UI_LOAD_FONT_FUNC(DrawGlobal, path) FontInit(DrawGlobal, path) -#endif -int InitializeUI(void) +static int InitFont(void) { + int result; char *pFontFilePath; + + if((pFontFilePath=GetFontFilePath(language))!=NULL) + { + DEBUG_PRINTF("GetFontFilePath(%d): %s\n", language, pFontFilePath); + } + else{ + printf("Can't get font file path from GetFontFilePath(%d).\n", language); + return -1; + } + + if((result=FontInit(&UIDrawGlobal, pFontFilePath))!=0) + { + DEBUG_PRINTF("InitFont(%s) result: %d. Using default font.\n", pFontFilePath, result); + free(pFontFilePath); + pFontFilePath=GetDefaultFontFilePath(); + + result=FontInit(&UIDrawGlobal, pFontFilePath); + } + if(result != 0) + printf("InitFont(%s) error: %d\n", pFontFilePath, result); + free(pFontFilePath); + + return result; +} + +static int InitFontWithBuffer(void) +{ + int result; + char *pFontFilePath; + + if(gFontBuffer == NULL) + { + if((pFontFilePath=GetFontFilePath(language))!=NULL) + { + DEBUG_PRINTF("GetFontFilePath(%d): %s\n", language, pFontFilePath); + } + else{ + printf("Can't get font file path from GetFontFilePath(%d).\n", language); + return -1; + } + + if((result=LoadFontIntoBuffer(&UIDrawGlobal, pFontFilePath))!=0) + { + DEBUG_PRINTF("InitFont(%s) result: %d. Using default font.\n", pFontFilePath, result); + free(pFontFilePath); + pFontFilePath=GetDefaultFontFilePath(); + + result=LoadFontIntoBuffer(&UIDrawGlobal, pFontFilePath); + } + if(result != 0) + printf("InitFont(%s) error: %d\n", pFontFilePath, result); + free(pFontFilePath); + } else + result = 0; + + return result; +} + +int ReinitializeUI(void) +{ + if(gFontBuffer == NULL) + { + FontDeinit(); + return InitFont(); + } + else + { + //No need to reinitialize font when it is loaded into memory. + return 0; + } +} + +int InitializeUI(int BufferFont) +{ int result; result=0; if((language=configGetLanguage())>=NUM_SUPPORTED_LANGUAGES) language=LANGUAGE_ENGLISH; + memset(LangStringWrapTable, 0, sizeof(LangStringWrapTable)); DEBUG_PRINTF("InitializeUI: language is: %u\n", language); @@ -498,13 +607,12 @@ int InitializeUI(void) InitGraphics(); - DEBUG_PRINTF("InitGraphics()\n"); - - while((result=LoadLanguageStrings(language))==-ENODEV) + while((result = LoadLanguageStrings(language)) == -ENODEV) { DEBUG_PRINTF("LoadLanguageStrings(%u): %d\n", language, result); WaitForDevice(); } + DEBUG_PRINTF("LoadLanguageStrings(%u) result: %d\n", language, result); if(result != 0) { @@ -515,30 +623,9 @@ int InitializeUI(void) } } - if((pFontFilePath=GetFontFilePath(language))!=NULL) - { - DEBUG_PRINTF("GetFontFilePath(%d): %s\n", language, pFontFilePath); - } - else{ - DEBUG_PRINTF("Can't get font file path from GetFontFilePath(%d).\n", language); - return -1; - } - - if((result=UI_LOAD_FONT_FUNC(&UIDrawGlobal, pFontFilePath))!=0) - { - DEBUG_PRINTF("FontInit(%s) result: %d. Using default font.\n", pFontFilePath, result); - free(pFontFilePath); - pFontFilePath=GetDefaultFontFilePath(); - - if((result=UI_LOAD_FONT_FUNC(&UIDrawGlobal, pFontFilePath))!=0) - { - DEBUG_PRINTF("FontInit(%s) result: %d\n", pFontFilePath, result); - } - } - DEBUG_PRINTF("FontInit(%s) result: %d\n", pFontFilePath, result); - free(pFontFilePath); + result = BufferFont ? InitFontWithBuffer() : InitFont(); - if(result==0) + if(result == 0) { LoadBackground(&UIDrawGlobal, &BackgroundTexture); LoadPadGraphics(&UIDrawGlobal, &PadLayoutTexture); @@ -554,14 +641,12 @@ void DeinitializeUI(void) UnloadLanguage(); FontDeinit(); -#ifdef UI_FONT_MEM if(gFontBuffer != NULL) { free(gFontBuffer); gFontBuffer = NULL; gFontBufferSize = 0; } -#endif } enum MBOX_SCREEN_ID{ @@ -741,13 +826,25 @@ void UISetValue(struct UIMenu *menu, unsigned char id, int value) } } +int UIGetValue(struct UIMenu *menu, unsigned char id) +{ + struct UIMenuItem *item; + + if((item = UIGetItem(menu, id)) != NULL) + { + return item->value.value; + } + + return -1; +} + void UISetLabel(struct UIMenu *menu, unsigned char id, int label) { struct UIMenuItem *item; if((item = UIGetItem(menu, id)) != NULL) { - item->value.value = label; + item->label.id = label; } } @@ -782,6 +879,40 @@ void UISetFormat(struct UIMenu *menu, unsigned char id, unsigned char format, un } } +void UISetEnum(struct UIMenu *menu, unsigned char id, const int *labels, int count) +{ + struct UIMenuItem *item; + + if((item = UIGetItem(menu, id)) != NULL) + { + item->enumeration.labels = labels; + item->enumeration.count = count; + item->enumeration.selectedIndex = 0; + } +} + +void UISetEnumSelectedIndex(struct UIMenu *menu, unsigned char id, int selectedIndex) +{ + struct UIMenuItem *item; + + if((item = UIGetItem(menu, id)) != NULL) + { + item->enumeration.selectedIndex = selectedIndex; + } +} + +int UIGetEnumSelectedIndex(struct UIMenu *menu, unsigned char id) +{ + struct UIMenuItem *item; + + if((item = UIGetItem(menu, id)) != NULL) + { + return item->enumeration.selectedIndex; + } + + return -1; +} + void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, short int StartY, short int selection) { const char *pLabel; @@ -789,7 +920,6 @@ void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, struct UIMenuItem *item, *SelectedItem; short int x, y, width, height, xRel, yRel, button, i; GS_RGBAQ colour; - int LabelLen; DrawBackground(&UIDrawGlobal, &BackgroundTexture); @@ -836,10 +966,8 @@ void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, } break; case MITEM_BUTTON: - if((pLabel = GetUILabel(item->value.value)) != NULL) + if((pLabel = GetUILabel(item->label.id)) != NULL) { - LabelLen = mbslen(pLabel); - width = item->width * UI_FONT_WIDTH; height = UI_FONT_HEIGHT + UI_FONT_HEIGHT / 2; if(item == SelectedItem) @@ -855,7 +983,8 @@ void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, colour = (item->flags & MITEM_FLAG_DISABLED) ? GS_GREY_FONT : (item == SelectedItem ? GS_YELLOW_FONT : GS_WHITE_FONT); - FontPrintfWithFeedback(&UIDrawGlobal, x + (width - LabelLen * UI_FONT_WIDTH) / 2, y, 1, 1.0f, colour, pLabel, &xRel, &yRel); + FontPrintfWithFeedback(&UIDrawGlobal, x + (width - item->label.TextWidth) / 2, y, 1, 1.0f, colour, pLabel, &xRel, &yRel); + item->label.TextWidth = xRel; x += xRel; y += yRel + UI_FONT_HEIGHT; } @@ -863,28 +992,26 @@ void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, case MITEM_LABEL: if((pLabel = GetUILabel(item->value.value)) != NULL) { - if(item->flags & MITEM_FLAG_POS_MID) - x = (UIDrawGlobal.width - mbslen(pLabel) * UI_FONT_WIDTH) / 2; FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, pLabel, &xRel, &yRel); x += xRel; y += yRel; } break; case MITEM_COLON: - FontPrintf(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, ":"); - x += UI_FONT_WIDTH; + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, ":", &xRel, NULL); + x += xRel; break; case MITEM_DASH: - FontPrintf(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, "-"); - x += UI_FONT_WIDTH; + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, "-", &xRel, NULL); + x += xRel; break; case MITEM_DOT: - FontPrintf(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, "."); - x += UI_FONT_WIDTH; + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, ".", &xRel, NULL); + x += xRel; break; case MITEM_SLASH: - FontPrintf(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, "/"); - x += UI_FONT_WIDTH; + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, GS_WHITE_FONT, "/", &xRel, NULL); + x += xRel; break; case MITEM_VALUE: pFormatString = FormatString; @@ -943,13 +1070,20 @@ void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, DrawProgressBar(&UIDrawGlobal, item->value.value / 100.0f, x + 20, y, 4, UIDrawGlobal.width - (x + 20) - 20, GS_BLUE); y += UI_FONT_HEIGHT; break; -#ifdef UI_EN_MITEM_TOGGLE case MITEM_TOGGLE: colour = (item->flags & MITEM_FLAG_DISABLED) ? GS_GREY_FONT : ((item->flags & MITEM_FLAG_READONLY) ? GS_WHITE_FONT : (item == SelectedItem ? GS_YELLOW_FONT : GS_BLUE_FONT)); - FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, colour, UIGetLabel(item->value.value == 0 ? : SYS_UI_LBL_DISABLED : SYS_UI_LBL_ENABLED), &xRel, &yRel); + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, colour, GetUILabel(item->value.value == 0 ? SYS_UI_LBL_DISABLED : SYS_UI_LBL_ENABLED), &xRel, &yRel); x += xRel; y += yRel; -#endif + break; + case MITEM_ENUM: + if((pLabel = GetUILabel(item->enumeration.labels[item->enumeration.selectedIndex])) != NULL) + { + colour = (item->flags & MITEM_FLAG_DISABLED) ? GS_GREY_FONT : ((item->flags & MITEM_FLAG_READONLY) ? GS_WHITE_FONT : (item == SelectedItem ? GS_YELLOW_FONT : GS_BLUE_FONT)); + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 1, 1.0f, colour, pLabel, &xRel, &yRel); + x += xRel; + y += yRel; + } } } @@ -1170,7 +1304,7 @@ static short int UIGetPrevSelectableItem(struct UIMenu *menu, short int index) return result; } -int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu **CurrentMenu, int (*callback)(struct UIMenu *menu, unsigned short int frame, int selection, int padstatus)) +int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu **CurrentMenu, int (*callback)(struct UIMenu *menu, unsigned short int frame, int selection, u32 padstatus)) { struct UIMenu *menu; int result; @@ -1178,8 +1312,13 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * struct UIMenuItem *item; short int selection, NextSel; unsigned short int frame; + u32 PadRepeatStatus, PadRepeatStatusOld, PadStatusTemp; + unsigned short int PadRepeatDelayTicks, PadRepeatRateTicks; PadStatus = 0; + PadRepeatStatusOld = 0; + PadRepeatDelayTicks = UI_PAD_REPEAT_START_DELAY; + PadRepeatRateTicks = UI_PAD_REPEAT_DELAY; frame = 0; menu = FirstMenu; @@ -1192,7 +1331,7 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * if(callback != NULL) { - if((result = callback(menu, frame, selection, -1)) != 0) + if((result = callback(menu, frame, selection, 0)) != 0) goto exit_menu; } @@ -1200,7 +1339,46 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * { PadStatus=ReadCombinedPadStatus(); - if(PadStatus&PAD_UP) + //For the pad repeat delay effect. + PadRepeatStatus = ReadCombinedPadStatus_raw(); + if(PadRepeatStatus == 0 || ((PadRepeatStatusOld != 0) && (PadRepeatStatus != PadRepeatStatusOld))) + { + PadRepeatDelayTicks = UI_PAD_REPEAT_START_DELAY; + PadRepeatRateTicks = UI_PAD_REPEAT_DELAY; + + PadStatusTemp = PadRepeatStatus & ~PadRepeatStatusOld; + PadRepeatStatusOld = PadRepeatStatus; + PadRepeatStatus = PadStatusTemp; + } + else + { + if(PadRepeatDelayTicks == 0) + { + //Allow the pad presses to repeat, but only after the pad repeat delay expires. + if(PadRepeatRateTicks == 0) + { + PadRepeatRateTicks = UI_PAD_REPEAT_DELAY; + } + else + { + PadStatusTemp = PadRepeatStatus & ~PadRepeatStatusOld; + PadRepeatStatusOld = PadRepeatStatus; + PadRepeatStatus = PadStatusTemp; + } + + PadRepeatRateTicks--; + } + else + { + PadStatusTemp = PadRepeatStatus & ~PadRepeatStatusOld; + PadRepeatStatusOld = PadRepeatStatus; + PadRepeatStatus = PadStatusTemp; + + PadRepeatDelayTicks--; + } + } + + if(PadRepeatStatus&PAD_UP) { //Try to find the previous selectable option. if((NextSel = UIGetPrevSelectableItem(menu, selection)) >= 0) @@ -1208,44 +1386,71 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * selection = NextSel; item = &menu->items[selection]; } - } else if(PadStatus&PAD_DOWN) { + } else if(PadRepeatStatus&PAD_DOWN) { //Try to find the next selectable option. if((NextSel = UIGetNextSelectableItem(menu, selection)) >= 0) { selection = NextSel; item = &menu->items[selection]; } - } else if(PadStatus&PAD_LEFT) { - if(item != NULL && !(item->flags & MITEM_FLAG_READONLY)) + } else if(PadRepeatStatus&PAD_LEFT) { + if(item != NULL && !(item->flags & MITEM_FLAG_READONLY) && !(item->flags & MITEM_FLAG_DISABLED)) { switch(item->type) { case MITEM_VALUE: - if(item->value.value - 1 > item->value.min) + if(item->value.value - 1 >= item->value.min) item->value.value--; + else + item->value.value = item->value.max; + break; + case MITEM_TOGGLE: + item->value.value = !item->value.value; + break; + case MITEM_ENUM: + if(item->enumeration.selectedIndex > 0) + item->enumeration.selectedIndex--; + else + item->enumeration.selectedIndex = item->enumeration.count - 1; + break; } } - } else if(PadStatus&PAD_RIGHT) { - if(item != NULL && !(item->flags & MITEM_FLAG_READONLY)) + } else if(PadRepeatStatus&PAD_RIGHT) { + if(item != NULL && !(item->flags & MITEM_FLAG_READONLY) && !(item->flags & MITEM_FLAG_DISABLED)) { switch(item->type) { case MITEM_VALUE: - if(item->value.value + 1 < item->value.max) + if(item->value.value + 1 <= item->value.max) item->value.value++; + else + item->value.value = item->value.min; + break; + case MITEM_TOGGLE: + item->value.value = !item->value.value; + break; + case MITEM_ENUM: + if(item->enumeration.selectedIndex + 1 < item->enumeration.count) + item->enumeration.selectedIndex++; + else + item->enumeration.selectedIndex = 0; + break; } } } if(PadStatus&SelectButton) { - if(item != NULL && !(item->flags & MITEM_FLAG_DISABLED)) + if(item != NULL && !(item->flags & MITEM_FLAG_READONLY) && !(item->flags & MITEM_FLAG_DISABLED)) { switch(item->type) { case MITEM_BUTTON: result = item->id; goto exit_menu; + case MITEM_TOGGLE: + item->value.value = !item->value.value; + break; } } } else if(PadStatus&CancelButton) { @@ -1264,12 +1469,6 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * item = ((selection = UIGetNextSelectableItem(menu, -1)) >= 0) ? &menu->items[selection] : NULL; UITransition(menu, UIMT_LEFT_IN, selection); - - if(callback != NULL) - { - if((result = callback(menu, frame, selection, -1)) != 0) - break; - } } } else if(PadStatus&PAD_L1) { if(menu->prev != NULL) @@ -1281,12 +1480,6 @@ int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu * item = ((selection = UIGetNextSelectableItem(menu, -1)) >= 0) ? &menu->items[selection] : NULL; UITransition(menu, UIMT_RIGHT_IN, selection); - - if(callback != NULL) - { - if((result = callback(menu, frame, selection, -1)) != 0) - break; - } } } diff --git a/UI.h b/UI.h old mode 100755 new mode 100644 index 5b10c27..36e5b88 --- a/UI.h +++ b/UI.h @@ -2,13 +2,13 @@ #define UI_OFFSET_X 8 #define UI_OFFSET_Y 8 -#define UI_LINE_MAX 38 //Maximum line length for messages. #define UI_FONT_WIDTH FNT_CHAR_WIDTH #define UI_FONT_HEIGHT FNT_CHAR_HEIGHT #define UI_TAB_STOPS FNT_TAB_STOPS -//#define UI_FONT_MEM 1 //Uncomment to initialize FreeType and store the font in memory (useful when the IOP must be reset during runtime). -//#define UI_EN_MITEM_TOGGLE 1 //Uncomment to make the toggle control available (Enable/disable strings must be available). +//In VSYNC ticks +#define UI_PAD_REPEAT_START_DELAY 20 +#define UI_PAD_REPEAT_DELAY 5 enum MENU_ITEM{ MITEM_SEPERATOR, @@ -26,6 +26,7 @@ enum MENU_ITEM{ MITEM_VALUE, MITEM_BUTTON, MITEM_TOGGLE, + MITEM_ENUM, MITEM_TERMINATOR, @@ -47,7 +48,7 @@ enum MENU_ITEM_FORMAT{ #define MITEM_FLAG_DISABLED 0x04 #define MITEM_FLAG_UNIT_PREFIX 0x08 //For formats with a unit prefix, show it. #define MITEM_FLAG_POS_ABS 0x10 //Coordinates are absolute. -#define MITEM_FLAG_POS_MID 0x20 //Aligned to the middle. Only for labels. +#define MITEM_FLAG_POS_MID 0x20 //Aligned to the middle. Only for buttons. struct UIMenuItem{ unsigned char type; @@ -66,6 +67,15 @@ struct UIMenuItem{ const char *buffer; int maxlen; }string; + struct{ + const int *labels; + int count; + int selectedIndex; + }enumeration; + struct{ + int id; + int TextWidth; + }label; }; }; @@ -89,25 +99,31 @@ enum UI_MENU_TRANSITION{ UIMT_FADE_OUT, }; -const char *GetUIString(unsigned int StringID); -const char *GetUILabel(unsigned int LabelID); -int InitializeUI(void); +const char *GetUIString(unsigned int id); +const char *GetUILabel(unsigned int id); +int InitializeUI(int BufferFont); +int ReinitializeUI(void); void DeinitializeUI(void); int ShowMessageBox(int Option1Label, int Option2Label, int Option3Label, int Option4Label, const char *message, int title); void DisplayWarningMessage(unsigned int message); void DisplayErrorMessage(unsigned int message); void DisplayInfoMessage(unsigned int message); int DisplayPromptMessage(unsigned int message, unsigned char Button1Label, unsigned char Button2Label); +void DisplayFlashStatusUpdate(unsigned int message); struct UIMenuItem *UIGetItem(struct UIMenu *menu, unsigned char id); void UISetVisible(struct UIMenu *menu, unsigned char id, int visible); void UISetReadonly(struct UIMenu *menu, unsigned char id, int readonly); void UISetEnabled(struct UIMenu *menu, unsigned char id, int enabled); void UISetValue(struct UIMenu *menu, unsigned char id, int value); +int UIGetValue(struct UIMenu *menu, unsigned char id); void UISetLabel(struct UIMenu *menu, unsigned char id, int label); void UISetString(struct UIMenu *menu, unsigned char id, const char *string); void UISetType(struct UIMenu *menu, unsigned char id, unsigned char type); void UISetFormat(struct UIMenu *menu, unsigned char id, unsigned char format, unsigned char width); +void UISetEnum(struct UIMenu *menu, unsigned char id, const int *labels, int count); +void UISetEnumSelectedIndex(struct UIMenu *menu, unsigned char id, int selectedIndex); +int UIGetEnumSelectedIndex(struct UIMenu *menu, unsigned char id); void UIDrawMenu(struct UIMenu *menu, unsigned short int frame, short int StartX, short int StartY, short int selection); void UITransition(struct UIMenu *menu, int type, int SelectedOption); -int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu **CurrentMenu, int (*callback)(struct UIMenu *menu, unsigned short int frame, int selection, int padstatus)); +int UIExecMenu(struct UIMenu *FirstMenu, short int SelectedItem, struct UIMenu **CurrentMenu, int (*callback)(struct UIMenu *menu, unsigned short int frame, int selection, u32 padstatus)); diff --git a/font.c b/font.c old mode 100755 new mode 100644 index 0a895dc..2706a86 --- a/font.c +++ b/font.c @@ -1,6 +1,6 @@ /* Font-drawing engine - Version: 1.00 - Last updated: 2016/09/16 */ + Version: 1.23 + Last updated: 2019/01/11 */ #include #include @@ -13,6 +13,7 @@ #include #include FT_FREETYPE_H +#include FT_ADVANCES_H #include "graphics.h" #include "font.h" @@ -60,6 +61,11 @@ YXXX YXXX */ +struct FontGlyphSlotInfo { + struct FontGlyphSlot *slot; + u32 vram; //Address of the atlas buffer in VRAM +}; + struct FontGlyphSlot{ wint_t character; unsigned short int VramPageX, VramPageY; @@ -87,34 +93,40 @@ typedef struct Font{ GS_IMAGE Texture; GS_IMAGE Clut; void *ClutMem; - unsigned int IsLoaded; + unsigned short int IsLoaded; + unsigned short int IsInit; struct FontAtlas atlas[FNT_MAX_ATLASES]; } Font_t; +static FT_Library FTLibrary; static Font_t GS_FTFont; +static Font_t GS_sub_FTFont; -int FontReset(struct UIDrawGlobal *gsGlobal) +static int ResetThisFont(struct UIDrawGlobal *gsGlobal, Font_t *font) { struct FontAtlas *atlas; unsigned short int i; - int result; + int result, vram; - if(GS_FTFont.IsLoaded) - { - result=0; + result=0; + + font->Clut.x = 0; + font->Clut.y = 0; + font->Clut.width = 16; + font->Clut.height = 16; + font->Clut.vram_width = 1; //width (16) / 64 = 1 - GS_FTFont.Clut.x = 0; - GS_FTFont.Clut.y = 0; - GS_FTFont.Clut.width = 16; - GS_FTFont.Clut.height = 16; - GS_FTFont.Clut.vram_width = 1; //width (16) / 64 = 1 + vram = GsVramAllocTextureBuffer(font->Clut.width, font->Clut.height, font->Clut.psm); - GS_FTFont.Clut.vram_addr = GsVramAllocTextureBuffer(GS_FTFont.Clut.width, GS_FTFont.Clut.height, GS_FTFont.Clut.psm); - UploadClut(gsGlobal, &GS_FTFont.Clut, GS_FTFont.ClutMem); + if (vram >= 0) + { + font->Clut.vram_addr = (u16)vram; + + UploadClut(gsGlobal, &font->Clut, font->ClutMem); - GS_FTFont.Texture.x = 0; - GS_FTFont.Texture.y = 0; - for(i=0,atlas=GS_FTFont.atlas; iTexture.x = 0; + font->Texture.y = 0; + for(i=0,atlas=font->atlas; ifrontier[0].width = 0; atlas->frontier[0].height = 0; @@ -133,32 +145,46 @@ int FontReset(struct UIDrawGlobal *gsGlobal) } atlas->NumGlyphs = 0; } + } else { + printf("Font: error - unable to allocate VRAM for CLUT.\n"); + result = -1; } - else result=-1; return result; } -static int InitFontSupportCommon(struct UIDrawGlobal *gsGlobal, Font_t *GS_FTFont) +int FontReset(struct UIDrawGlobal *gsGlobal) +{ + int result; + + if((result = ResetThisFont(gsGlobal, &GS_FTFont)) == 0) + result = ResetThisFont(gsGlobal, &GS_sub_FTFont); + + return 0; +} + +static int InitFontSupportCommon(struct UIDrawGlobal *gsGlobal, Font_t *font) { int result; unsigned short int i; - if((result=FT_Set_Pixel_Sizes(GS_FTFont->FTFace, FNT_CHAR_WIDTH, FNT_CHAR_HEIGHT))==0) + if((result=FT_Set_Pixel_Sizes(font->FTFace, FNT_CHAR_WIDTH, FNT_CHAR_HEIGHT))==0) { - GS_FTFont->Texture.width = FNT_ATLAS_WIDTH; - GS_FTFont->Texture.height = FNT_ATLAS_HEIGHT; - GS_FTFont->Texture.psm = GS_TEX_8; - GS_FTFont->Clut.psm = GS_CLUT_32; + font->Texture.width = FNT_ATLAS_WIDTH; + font->Texture.height = FNT_ATLAS_HEIGHT; + font->Texture.psm = GS_TEX_8; + font->Clut.psm = GS_CLUT_32; // generate the clut table u32 *clut = memalign(64, 256 * 4); - GS_FTFont->ClutMem=clut; + font->ClutMem=clut; for (i = 0; i < 256; ++i) clut[i] = (i > 0x80 ? 0x80 : i) << 24 | i << 16 | i << 8 | i; SyncDCache(clut, (void*)((unsigned int)clut+256*4)); - GS_FTFont->IsLoaded=1; - FontReset(gsGlobal); + if(!font->IsInit) + ResetThisFont(gsGlobal, font); + font->IsLoaded=1; + font->IsInit=1; } return result; @@ -166,11 +192,8 @@ static int InitFontSupportCommon(struct UIDrawGlobal *gsGlobal, Font_t *GS_FTFon int FontInit(struct UIDrawGlobal *gsGlobal, const char *FontFile) { - FT_Library FTLibrary; int result; - memset(&GS_FTFont, 0, sizeof(Font_t)); - if((result=FT_Init_FreeType(&FTLibrary))==0) { if((result=FT_New_Face(FTLibrary, FontFile, 0, &GS_FTFont.FTFace))==0) @@ -185,11 +208,8 @@ int FontInit(struct UIDrawGlobal *gsGlobal, const char *FontFile) int FontInitWithBuffer(struct UIDrawGlobal *gsGlobal, void *buffer, unsigned int size) { - FT_Library FTLibrary; int result; - memset(&GS_FTFont, 0, sizeof(Font_t)); - if((result=FT_Init_FreeType(&FTLibrary))==0) { if((result=FT_New_Memory_Face(FTLibrary, buffer, size, 0, &GS_FTFont.FTFace))==0) @@ -202,25 +222,68 @@ int FontInitWithBuffer(struct UIDrawGlobal *gsGlobal, void *buffer, unsigned int return result; } -void FontDeinit(void) +static void UnloadFont(Font_t *font) { struct FontAtlas *atlas; unsigned int i; - FT_Done_Face(GS_FTFont.FTFace); + if(font->IsLoaded) + FT_Done_Face(font->FTFace); - for(i=0,atlas=GS_FTFont.atlas; iatlas; ibuffer!=NULL) + { free(atlas->buffer); + atlas->buffer = NULL; + } if(atlas->GlyphSlot!=NULL) + { free(atlas->GlyphSlot); + atlas->GlyphSlot = NULL; + } } + font->atlas->NumGlyphs = 0; - if(GS_FTFont.ClutMem!=NULL) - free(GS_FTFont.ClutMem); + if(font->ClutMem != NULL) + { + free(font->ClutMem); + font->ClutMem = NULL; + } + + font->IsLoaded = 0; +} + +int AddSubFont(struct UIDrawGlobal *gsGlobal, const char *FontFile) +{ + int result; + + if((result = FT_New_Face(FTLibrary, FontFile, 0, &GS_sub_FTFont.FTFace)) == 0) + result = InitFontSupportCommon(gsGlobal, &GS_sub_FTFont); + + if(result != 0) + UnloadFont(&GS_sub_FTFont); - memset(&GS_FTFont, 0, sizeof(Font_t)); + return result; +} + +int AddSubFontWithBuffer(struct UIDrawGlobal *gsGlobal, void *buffer, unsigned int size) +{ + int result; + + if((result = FT_New_Memory_Face(FTLibrary, buffer, size, 0, &GS_sub_FTFont.FTFace)) == 0) + result = InitFontSupportCommon(gsGlobal, &GS_sub_FTFont); + + if(result != 0) + UnloadFont(&GS_sub_FTFont); + + return result; +} + +//VRAM stays allocated. +void FontDeinit(void) +{ + UnloadFont(&GS_sub_FTFont); } static int AtlasInit(Font_t *font, struct FontAtlas *atlas) @@ -263,14 +326,15 @@ static struct FontGlyphSlot *AtlasAlloc(Font_t *font, struct FontAtlas *atlas, s if(AtlasInit(font, atlas) != 0) return NULL; - atlas->frontier[0].width = FNT_ATLAS_WIDTH - width; + //Give the glyph 1px more, for texel rendering. + atlas->frontier[0].width = FNT_ATLAS_WIDTH - (width + 1); atlas->frontier[0].height = FNT_ATLAS_HEIGHT; - atlas->frontier[0].x = width; + atlas->frontier[0].x = width + 1; atlas->frontier[0].y = 0; atlas->frontier[1].width = FNT_ATLAS_WIDTH; - atlas->frontier[1].height = FNT_ATLAS_HEIGHT - height; + atlas->frontier[1].height = FNT_ATLAS_HEIGHT - (height + 1); atlas->frontier[1].x = 0; - atlas->frontier[1].y = height; + atlas->frontier[1].y = height + 1; atlas->NumGlyphs++; @@ -288,8 +352,8 @@ static struct FontGlyphSlot *AtlasAlloc(Font_t *font, struct FontAtlas *atlas, s return GlyphSlot; } else { //We have the frontiers //Try to allocate from the horizontal frontier first. - if((atlas->frontier[0].width >= width) - && (atlas->frontier[0].height >= height)) + if((atlas->frontier[0].width >= width + 1) + && (atlas->frontier[0].height >= height + 1)) { atlas->NumGlyphs++; @@ -300,21 +364,24 @@ static struct FontGlyphSlot *AtlasAlloc(Font_t *font, struct FontAtlas *atlas, s GlyphSlot->VramPageX = atlas->frontier[0].x; GlyphSlot->VramPageY = atlas->frontier[0].y; + //Give the glyph 1px more, for texel rendering. //Update frontier. - atlas->frontier[0].width -= width; - atlas->frontier[0].x += width; - //atlas->frontier[1].width += width; //Not required, but this is how the logic works. + atlas->frontier[0].width -= width + 1; + atlas->frontier[0].x += width + 1; //If the new glyph is a little taller than the glyphs under the horizontal frontier, move the vertical frontier. - if(atlas->frontier[0].y + height > atlas->frontier[1].y) - atlas->frontier[1].y = atlas->frontier[0].y + height; + if(atlas->frontier[0].y + height + 1 > atlas->frontier[1].y) + { + atlas->frontier[1].y = atlas->frontier[0].y + height + 1; + atlas->frontier[1].height = FNT_ATLAS_HEIGHT - atlas->frontier[1].y; + } } else { printf("Font: error - unable to allocate a new glyph slot.\n"); atlas->NumGlyphs = 0; } //Now try the vertical frontier. - } else if((atlas->frontier[1].width >= width) - && (atlas->frontier[1].height >= height)) + } else if((atlas->frontier[1].width >= width + 1) + && (atlas->frontier[1].height >= height + 1)) { atlas->NumGlyphs++; @@ -325,6 +392,7 @@ static struct FontGlyphSlot *AtlasAlloc(Font_t *font, struct FontAtlas *atlas, s GlyphSlot->VramPageX = atlas->frontier[1].x; GlyphSlot->VramPageY = atlas->frontier[1].y; + //Give the glyph 1px more, for texel rendering. /* Update frontier. If we got here, it means that the horizontal frontier is very close the edge of VRAM. Give a large portion of the space recorded under this frontier to the horizontal frontier. @@ -334,12 +402,12 @@ static struct FontGlyphSlot *AtlasAlloc(Font_t *font, struct FontAtlas *atlas, s YYYY CXXX YYYY YXXX YYYY YXXX */ - atlas->frontier[0].x = width; + atlas->frontier[0].x = width + 1; atlas->frontier[0].y = atlas->frontier[1].y; - atlas->frontier[0].width = FNT_ATLAS_WIDTH - width; + atlas->frontier[0].width = FNT_ATLAS_WIDTH - (width + 1); atlas->frontier[0].height = atlas->frontier[1].height; - atlas->frontier[1].height -= height; - atlas->frontier[1].y += height; + atlas->frontier[1].height -= height + 1; + atlas->frontier[1].y += height + 1; } else { printf("Font: error - unable to allocate a new glyph slot.\n"); atlas->NumGlyphs = 0; @@ -400,60 +468,84 @@ static struct FontGlyphSlot *UploadGlyph(struct UIDrawGlobal *gsGlobal, Font_t * return GlyphSlot; } -static void DrawGlyph(struct UIDrawGlobal *gsGlobal, Font_t *font, wint_t character, short int x, short int y, short int z, float scale, GS_RGBAQ colour) +static int GetGlyph(struct UIDrawGlobal *gsGlobal, Font_t *font, wint_t character, int DrawMissingGlyph, struct FontGlyphSlotInfo *glyphInfo) { - FT_GlyphSlot FT_GlyphSlot = font->FTFace->glyph; - struct FontGlyphSlot *GlyphSlot; + int i, slot; struct FontAtlas *atlas; - unsigned short int i, slot; - short int XCoordinates, YCoordinates; + struct FontGlyphSlot *glyphSlot; + FT_UInt glyphIndex; - if(font->IsLoaded) + //Scan through all uploaded glyph slots. + for(i=0,atlas=font->atlas; iatlas,GlyphSlot=NULL; iNumGlyphs; slot++) { - for(slot=0; slot < atlas->NumGlyphs; slot++) + if(atlas->GlyphSlot[slot].character==character) { - if(atlas->GlyphSlot[slot].character==character) - { - GlyphSlot=&atlas->GlyphSlot[slot]; - goto atlas_selected; - } + glyphInfo->slot = &atlas->GlyphSlot[slot]; + glyphInfo->vram = atlas->vram; + return 0; } } + } - if(GlyphSlot == NULL) - { //Not in VRAM? Upload it. - if(FT_Load_Char(font->FTFace, character, FT_LOAD_RENDER)) - return; - if((GlyphSlot = UploadGlyph(gsGlobal, font, character, FT_GlyphSlot, &atlas)) == NULL) - return; - // printf("Uploading %c, %u, %u\n", character, GlyphSlot->VramPageX, GlyphSlot->VramPageY); - } + //Not in VRAM? Upload it. + if((glyphIndex = FT_Get_Char_Index(font->FTFace, character)) != 0 || DrawMissingGlyph) + { + if(FT_Load_Glyph(font->FTFace, glyphIndex, FT_LOAD_RENDER)) + return -1; + + if((glyphSlot = UploadGlyph(gsGlobal, font, character, font->FTFace->glyph, &atlas)) == NULL) + return -1; + +// printf("Uploading %c, %u, %u\n", character, GlyphSlot->VramPageX, GlyphSlot->VramPageY); + + glyphInfo->slot = glyphSlot; + glyphInfo->vram = atlas->vram; + return 0; + } else //Otherwise, the glyph is missing from font + return 1; + + return -1; +} + +static int DrawGlyph(struct UIDrawGlobal *gsGlobal, Font_t *font, wint_t character, short int x, short int y, short int z, float scale, GS_RGBAQ colour, int DrawMissingGlyph, short int *width) +{ + struct FontGlyphSlot *glyphSlot; + struct FontGlyphSlotInfo glyphInfo; + struct FontAtlas *atlas; + unsigned short int i, slot; + short int XCoordinates, YCoordinates; + int result; + + if(font->IsLoaded) + { + if ((result = GetGlyph(gsGlobal, font, character, DrawMissingGlyph, &glyphInfo)) != 0) + return result; -atlas_selected: - font->Texture.vram_addr=atlas->vram; + glyphSlot = glyphInfo.slot; + font->Texture.vram_addr = glyphInfo.vram; - YCoordinates=y+FNT_CHAR_HEIGHT*scale-GlyphSlot->top*scale; - XCoordinates=x+GlyphSlot->left*scale; + YCoordinates=y+FNT_CHAR_HEIGHT*scale-glyphSlot->top*scale; + XCoordinates=x+glyphSlot->left*scale; DrawSpriteTexturedClut(gsGlobal, &font->Texture, &font->Clut, XCoordinates, YCoordinates, //x1, y1 - GlyphSlot->VramPageX, GlyphSlot->VramPageY, //u1, v1 - XCoordinates+GlyphSlot->width*scale, YCoordinates+GlyphSlot->height*scale, //x2, y2 - GlyphSlot->VramPageX+GlyphSlot->width, GlyphSlot->VramPageY+GlyphSlot->height, //u2, v2 + glyphSlot->VramPageX, glyphSlot->VramPageY, //u1, v1 + XCoordinates+glyphSlot->width*scale, YCoordinates+glyphSlot->height*scale, //x2, y2 + glyphSlot->VramPageX+glyphSlot->width, glyphSlot->VramPageY+glyphSlot->height, //u2, v2 z, colour); - /* Advancement of the cursor should have been done like this, - but I found the spacing to be too narrow for a TV. - *x_out = x + GlyphSlot->advance_x * scale; */ - } + *width = glyphSlot->advance_x * scale; + } else //Not loaded + return -1; + + return 0; } void FontPrintfWithFeedback(struct UIDrawGlobal *gsGlobal, short x, short int y, short int z, float scale, GS_RGBAQ colour, const char *string, short int *xRel, short int *yRel) { wchar_t wchar; - short int StartX, StartY; + short int StartX, StartY, width; int charsize, bufmax; StartX = x; @@ -477,8 +569,16 @@ void FontPrintfWithFeedback(struct UIDrawGlobal *gsGlobal, short x, short int y, x+=(short int)(FNT_TAB_STOPS*FNT_CHAR_WIDTH*scale)-(unsigned int)x%(unsigned int)(FNT_TAB_STOPS*FNT_CHAR_WIDTH*scale); break; default: - DrawGlyph(gsGlobal, &GS_FTFont, wchar, x, y, z, scale, colour); - x+=(short int)(FNT_CHAR_WIDTH*scale); + width = 0; + if(DrawGlyph(gsGlobal, &GS_FTFont, wchar, x, y, z, scale, colour, 0, &width) != 0) + { + if(DrawGlyph(gsGlobal, &GS_sub_FTFont, wchar, x, y, z, scale, colour, 0, &width) != 0) + { //Cannot locate the glyph, so draw the missing glyph character. + DrawGlyph(gsGlobal, &GS_FTFont, wchar, x, y, z, scale, colour, 1, &width); + } + } + + x += width; } } @@ -492,3 +592,32 @@ void FontPrintf(struct UIDrawGlobal *gsGlobal, short int x, short int y, short i { return FontPrintfWithFeedback(gsGlobal, x, y, z, scale, colour, string, NULL, NULL); } + +static int GetGlyphWidth(struct UIDrawGlobal *gsGlobal, Font_t *font, wint_t character, int DrawMissingGlyph) +{ + struct FontGlyphSlotInfo glyphInfo; + int result; + + if(font->IsLoaded) + { //Calling FT_Get_Advance is slow when I/O is slow, hence a cache is required. Here, the atlas is used as a cache. + if ((result = GetGlyph(gsGlobal, font, character, DrawMissingGlyph, &glyphInfo)) != 0) + return result; + + return glyphInfo.slot->advance_x; + } + + return 0; +} + +int FontGetGlyphWidth(struct UIDrawGlobal *gsGlobal, wint_t character) +{ + int width; + + if((width = GetGlyphWidth(gsGlobal, &GS_FTFont, character, 0)) == 0) + { + if((width = GetGlyphWidth(gsGlobal, &GS_sub_FTFont, character, 0)) == 0) + { + width = GetGlyphWidth(gsGlobal, &GS_FTFont, character, 1); + } + } +} diff --git a/font.h b/font.h old mode 100755 new mode 100644 index f41ac4b..005a859 --- a/font.h +++ b/font.h @@ -7,7 +7,11 @@ int FontInit(struct UIDrawGlobal *gsGlobal, const char *FontFile); int FontInitWithBuffer(struct UIDrawGlobal *gsGlobal, void *buffer, unsigned int size); +int AddSubFont(struct UIDrawGlobal *gsGlobal, const char *FontFile); +int AddSubFontWithBuffer(struct UIDrawGlobal *gsGlobal, void *buffer, unsigned int size); void FontDeinit(void); int FontReset(struct UIDrawGlobal *gsGlobal); //Performs a partial re-initialization of the Font library and re-allocates VRAM. Used when VRAM has been cleared. void FontPrintfWithFeedback(struct UIDrawGlobal *gsGlobal, short int x, short int y, short int z, float scale, GS_RGBAQ colour, const char *string, short int *xRel, short int *yRel); void FontPrintf(struct UIDrawGlobal *gsGlobal, short int x, short int y, short int z, float scale, GS_RGBAQ colour, const char *string); +int FontGetGlyphWidth(struct UIDrawGlobal *gsGlobal, wint_t character); + diff --git a/graphics.c b/graphics.c index ff788b8..f440348 100644 --- a/graphics.c +++ b/graphics.c @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -29,19 +30,22 @@ static char twh(short int val) } static void PNGReadMem(png_structp pngPtr, png_bytep data, png_size_t length){ - void **PngBufferPtr=png_get_io_ptr(pngPtr); + u8 **PngBufferPtr=(u8**)png_get_io_ptr(pngPtr); memcpy(data, *PngBufferPtr, length); - (unsigned int)*PngBufferPtr+=length; + *PngBufferPtr += length; } -static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const void* buffer, unsigned int size){ - static void **PngFileBufferPtr; +static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, GS_IMAGE *Clut, const void* buffer, unsigned int size){ + static u8 **PngFileBufferPtr; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; png_bytep *row_pointers; - void *mem; + void *mem, *clut_mem; + png_colorp palette; + int num_palette; + png_byte color_type_new; unsigned int sig_read = 0; int row, i, k=0, j, bit_depth, color_type, interlace_type; @@ -50,7 +54,6 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const if(!png_ptr) { - //printf("PNG Read Struct Init Failed\n"); return -1; } @@ -58,14 +61,12 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const if(!info_ptr) { - //printf("PNG Info Struct Init Failed\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return -1; } if(setjmp(png_jmpbuf(png_ptr))) { - //printf("Got PNG Error!\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return -1; } @@ -79,7 +80,18 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); + { + if(Clut == NULL) + png_set_expand(png_ptr); + else { + Clut->x = 0; + Clut->y = 0; + Clut->width = 16; + Clut->height = 16; + Clut->psm = GS_CLUT_32; + Clut->vram_width = ((Clut->width + 63) & ~63) / 64; + } + } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); @@ -96,11 +108,12 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const Texture->width = width; Texture->height = height; - if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA) + color_type_new = png_get_color_type(png_ptr, info_ptr); + if(color_type_new == PNG_COLOR_TYPE_RGB_ALPHA) { int row_bytes = png_get_rowbytes(png_ptr, info_ptr); Texture->psm = GS_TEX_32; - mem = memalign(128, Texture->width * Texture->height * 4); + mem = memalign(64, Texture->width * Texture->height * 4); row_pointers = calloc(height, sizeof(png_bytep)); @@ -109,7 +122,7 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const png_read_image(png_ptr, row_pointers); struct pixel { unsigned char r,g,b,a; }; - struct pixel *Pixels = (struct pixel *) UNCACHED_SEG(mem); + struct pixel *Pixels = (struct pixel *) UCAB_SEG(mem); for (i=0;ipsm = GS_TEX_24; - mem = memalign(128, Texture->width * Texture->height * 4); + mem = memalign(64, Texture->width * Texture->height * 4); row_pointers = calloc(height, sizeof(png_bytep)); @@ -137,7 +150,7 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const png_read_image(png_ptr, row_pointers); struct pixel3 { unsigned char r,g,b; }; - struct pixel3 *Pixels = (struct pixel3 *) UNCACHED_SEG(mem); + struct pixel3 *Pixels = (struct pixel3 *) UCAB_SEG(mem); for (i=0;ipsm = GS_TEX_24; + mem = memalign(64, Texture->width * Texture->height); + clut_mem = memalign(64, Clut->width * Clut->height * 4); + + png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); + + struct pixel4 { unsigned char r,g,b,a; }; + struct pixel4 *clut_mem4 = (struct pixel4*)UCAB_SEG(clut_mem); + for(i = 0; i < num_palette; i++) + { + clut_mem4->r = palette[i].red; + clut_mem4->g = palette[i].green; + clut_mem4->b = palette[i].blue; + clut_mem4->a = 0x80; + } + + row_pointers = calloc(height, sizeof(png_bytep)); + + for(row = 0; row < height; row++) row_pointers[row] = malloc(row_bytes); + + png_read_image(png_ptr, row_pointers); + + u8 *Pixels = (u8 *) UCAB_SEG(mem); + + for (i=0;ivram_addr = GsVramAllocTextureBuffer(Clut->width, Clut->height, Clut->psm); + GsLoadImage(clut_mem, Clut); + free(clut_mem); + } else { - //printf("This texture depth is not supported yet!\n"); + printf("This texture depth is not supported yet!\n"); + png_read_end(png_ptr, NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return -1; } png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - Texture->vram_addr = GsVramAllocTextureBuffer(Texture->width, Texture->height + 64, Texture->psm); + Texture->vram_addr = GsVramAllocTextureBuffer(Texture->width, Texture->height, Texture->psm); Texture->vram_width = ((Texture->width + 63) & ~63) / 64; + //Upload texture. GsLoadImage(mem, Texture); GsTextureFlush(); free(mem); @@ -171,6 +229,7 @@ static int LoadPNGImage(struct UIDrawGlobal *gsGlobal, GS_IMAGE *Texture, const } void DrawBackground(struct UIDrawGlobal *gsGlobal, GS_IMAGE *background){ +#ifdef CENTRE_BACKGROUND short int x, y; x=(gsGlobal->width-background->width)/2; @@ -181,21 +240,29 @@ void DrawBackground(struct UIDrawGlobal *gsGlobal, GS_IMAGE *background){ 0, 0, x+background->width, y+background->height, background->width, background->height, - 8, (GS_RGBAQ){0xFF,0xFF,0xFF,0x80,0x00}); + 8, (GS_RGBAQ){0x80,0x80,0x80,0x80,0x00}); +#else + DrawSprite(gsGlobal, 0, 0, gsGlobal->width, gsGlobal->height, 9, (GS_RGBAQ){0x00,0x00,0x00,0x80,0x00}); + DrawSpriteTextured(gsGlobal, background, 0, 0, + 0, 0, + gsGlobal->width, gsGlobal->height, + background->width, background->height, + 8, (GS_RGBAQ){0x80,0x80,0x80,0x80,0x00}); +#endif } -extern unsigned char pad_layout_start[]; -extern unsigned int pad_layout_size; +extern unsigned char buttons[]; +extern unsigned int size_buttons; -extern unsigned char background_start[]; -extern unsigned int background_size; +extern unsigned char background[]; +extern unsigned int size_background; int LoadBackground(struct UIDrawGlobal *gsGlobal, GS_IMAGE* Texture){ - return LoadPNGImage(gsGlobal, Texture, background_start, background_size); + return LoadPNGImage(gsGlobal, Texture, NULL, background, size_background); } -int LoadPadGraphics(struct UIDrawGlobal *gsGlobal, GS_IMAGE* Texture){ - return LoadPNGImage(gsGlobal, Texture, pad_layout_start, pad_layout_size); +int LoadPadGraphics(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphics){ + return LoadPNGImage(gsGlobal, &PadGraphics->texture, &PadGraphics->clut, buttons, size_buttons); } void DrawSetFilterMode(struct UIDrawGlobal *gsGlobal, int mode) @@ -296,47 +363,58 @@ void UploadClut(struct UIDrawGlobal *gsGlobal, GS_IMAGE *clut, const void *buffe gs_setR_TEXFLUSH((GS_R_TEXFLUSH *)&p[1]); } -struct ButtonLayoutParameters{ +struct IconLayout{ unsigned short int u, v; unsigned short int length, width; }; -static const struct ButtonLayoutParameters ButtonLayoutParameters[]= +static const struct IconLayout ButtonLayoutParameters[BUTTON_TYPE_COUNT]= { - /* Triggers */ - {60, 0, 20, 16}, - {40, 0, 20, 16}, - {20, 0, 20, 16}, - {0, 0, 20, 16}, - /* D-pad buttons */ - {0, 16, 16, 16}, - {48, 16, 16, 16}, - {16, 16, 16, 16}, - {32, 16, 16, 16}, - /* CIRCLE, CROSS, SQUARE and TRIANGLE */ - {0, 32, 18, 17}, - {18, 32, 18, 17}, - {36, 32, 18, 17}, - {54, 32, 18, 17}, - /* START and SELECT */ - {80, 18, 38, 18}, - {80, 0, 38, 18} + {22, 0, 22, 22}, //Circle + {0, 0, 22, 22}, //Cross + {44, 0, 22, 22}, //Square + {66, 0, 22, 22}, //Triangle + {0, 22, 28, 20}, //L1 + {56, 22, 28, 20}, //R1 + {28, 22, 28, 20}, //L2 + {84, 22, 28, 20}, //R2 + {150, 42, 30, 30}, //L3 + {150, 72, 30, 30}, //R3 + {140, 22, 29, 19}, //START + {112, 22, 28, 19}, //SELECT + {120, 72, 30, 30}, //RSTICK + {0, 72, 30, 30}, //UP RSTICK + {30, 72, 30, 30}, //DOWN RSTICK + {60, 72, 30, 30}, //LEFT RSTICK + {90, 72, 30, 30}, //RIGHT RSTICK + {120, 42, 30, 30}, //LSTICK + {0, 42, 30, 30}, //UP LSTICK + {30, 42, 30, 30}, //DOWN LSTICK + {60, 42, 30, 30}, //LEFT LSTICK + {90, 42, 30, 30}, //RIGHT LSTICK + {104, 102, 26, 26}, //DPAD + {130, 102, 26, 26}, //LR-DPAD + {156, 102, 26, 26}, //UD-DPAD + {0, 102, 26, 26}, //UP DPAD + {26, 102, 26, 26}, //DOWN DPAD + {52, 102, 26, 26}, //LEFT DPAD + {78, 102, 26, 26}, //RIGHT DPAD }; -void DrawButtonLegendWithFeedback(struct UIDrawGlobal *gsGlobal, GS_IMAGE* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z, short int *xRel) +void DrawButtonLegendWithFeedback(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z, short int *xRel) { - DrawSpriteTextured(gsGlobal, PadGraphicsTexture, + DrawSpriteTexturedClut(gsGlobal, &PadGraphicsTexture->texture, &PadGraphicsTexture->clut, x, y, ButtonLayoutParameters[ButtonType].u, ButtonLayoutParameters[ButtonType].v, x+ButtonLayoutParameters[ButtonType].length, y+ButtonLayoutParameters[ButtonType].width, ButtonLayoutParameters[ButtonType].u+ButtonLayoutParameters[ButtonType].length, ButtonLayoutParameters[ButtonType].v+ButtonLayoutParameters[ButtonType].width, - z, (GS_RGBAQ){0xFF,0xFF,0xFF,0x80,0x00}); + z, (GS_RGBAQ){0x80,0x80,0x80,0x80,0x00}); if(xRel != NULL) *xRel = ButtonLayoutParameters[ButtonType].length; } -void DrawButtonLegend(struct UIDrawGlobal *gsGlobal, GS_IMAGE* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z) +void DrawButtonLegend(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z) { DrawButtonLegendWithFeedback(gsGlobal, PadGraphicsTexture, ButtonType, x, y, z, NULL); } diff --git a/graphics.h b/graphics.h index c21169e..1ae255d 100644 --- a/graphics.h +++ b/graphics.h @@ -1,6 +1,6 @@ #define GS_SETREG_RGBAQ(r, g, b, a, q) (GS_RGBAQ){(r), (g), (b), (a), (q)} -#define GS_WHITE GS_SETREG_RGBAQ(0xFF,0xFF,0xFF,0x80,0x00) +#define GS_WHITE GS_SETREG_RGBAQ(0x80,0x80,0x80,0x80,0x00) #define GS_BLACK GS_SETREG_RGBAQ(0x00,0x00,0x00,0x80,0x00) #define GS_GREY GS_SETREG_RGBAQ(0x30,0x30,0x30,0x80,0x00) #define GS_LGREY GS_SETREG_RGBAQ(0x50,0x50,0x50,0x80,0x00) @@ -17,21 +17,38 @@ #define GS_BLUE_FONT GS_SETREG_RGBAQ(0x30,0x30,0x80,0x80,0x00) /* Button types, for use with DrawButtonLegend() */ -enum ui_button_types{ - BUTTON_TYPE_R1=0, - BUTTON_TYPE_R2, - BUTTON_TYPE_L1, - BUTTON_TYPE_L2, - BUTTON_TYPE_UP, - BUTTON_TYPE_DOWN, - BUTTON_TYPE_LEFT, - BUTTON_TYPE_RIGHT, - BUTTON_TYPE_CIRCLE, +enum BUTTON_TYPE{ + BUTTON_TYPE_CIRCLE=0, BUTTON_TYPE_CROSS, BUTTON_TYPE_SQUARE, BUTTON_TYPE_TRIANGLE, + BUTTON_TYPE_L1, + BUTTON_TYPE_R1, + BUTTON_TYPE_L2, + BUTTON_TYPE_R2, + BUTTON_TYPE_L3, + BUTTON_TYPE_R3, BUTTON_TYPE_START, - BUTTON_TYPE_SELECT + BUTTON_TYPE_SELECT, + BUTTON_TYPE_RSTICK, + BUTTON_TYPE_UP_RSTICK, + BUTTON_TYPE_DOWN_RSTICK, + BUTTON_TYPE_LEFT_RSTICK, + BUTTON_TYPE_RIGHT_RSTICK, + BUTTON_TYPE_LSTICK, + BUTTON_TYPE_UP_LSTICK, + BUTTON_TYPE_DOWN_LSTICK, + BUTTON_TYPE_LEFT_LSTICK, + BUTTON_TYPE_RIGHT_LSTICK, + BUTTON_TYPE_DPAD, + BUTTON_TYPE_LR_DPAD, + BUTTON_TYPE_UD_DPAD, + BUTTON_TYPE_UP_DPAD, + BUTTON_TYPE_DOWN_DPAD, + BUTTON_TYPE_LEFT_DPAD, + BUTTON_TYPE_RIGHT_DPAD, + + BUTTON_TYPE_COUNT }; //Special button types @@ -49,8 +66,13 @@ struct UIDrawGlobal{ GS_PACKET_TABLE giftable; }; +struct ClutImage{ + GS_IMAGE texture; + GS_IMAGE clut; +}; + int LoadBackground(struct UIDrawGlobal *gsGlobal, GS_IMAGE* Texture); -int LoadPadGraphics(struct UIDrawGlobal *gsGlobal, GS_IMAGE* Texture); +int LoadPadGraphics(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphics); void DrawSetFilterMode(struct UIDrawGlobal *gsGlobal, int mode); void DrawLine(struct UIDrawGlobal *gsGlobal, short int x1, short int y1, short int x2, short int y2, short int z, GS_RGBAQ rgbaq); void DrawSprite(struct UIDrawGlobal *gsGlobal, short int x1, short int y1, short int x2, short int y2, short int z, GS_RGBAQ rgbaq); @@ -58,8 +80,8 @@ void DrawSpriteTextured(struct UIDrawGlobal *gsGlobal, GS_IMAGE *texture, short void DrawSpriteTexturedClut(struct UIDrawGlobal *gsGlobal, GS_IMAGE *texture, GS_IMAGE *clut, short int x1, short int y1, short int u1, short int v1, short int x2, short int y2, short int u2, short int v2, short int z, GS_RGBAQ rgbaq); void UploadClut(struct UIDrawGlobal *gsGlobal, GS_IMAGE *clut, const void *buffer); void DrawBackground(struct UIDrawGlobal *gsGlobal, GS_IMAGE *background); -void DrawButtonLegendWithFeedback(struct UIDrawGlobal *gsGlobal, GS_IMAGE* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z, short int *xRel); -void DrawButtonLegend(struct UIDrawGlobal *gsGlobal, GS_IMAGE* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z); +void DrawButtonLegendWithFeedback(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z, short int *xRel); +void DrawButtonLegend(struct UIDrawGlobal *gsGlobal, struct ClutImage* PadGraphicsTexture, unsigned char ButtonType, short int x, short int y, short int z); void DrawProgressBar(struct UIDrawGlobal *gsGlobal, float percentage, short int x, short int y, short int z, short int len, GS_RGBAQ colour); void SyncFlipFB(struct UIDrawGlobal *gsGlobal); void ExecSyncClear(struct UIDrawGlobal *gsGlobal); diff --git a/irx/compiled/mctools.irx b/irx/compiled/mctools.irx old mode 100755 new mode 100644 index 64f85b722117ee4d1b08f81ef6ee3dab7d157ec9..6e93dedcccd091a6172232b7a89725bd3ba454b9 GIT binary patch delta 4327 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 diff --git a/irx/compiled/secrsif.irx b/irx/compiled/secrsif.irx index 5560489d8b3dcfdf1e020023ac065591a367cc46..ed27a14d2c06ea0e75d50c927ab5ba230adc1fbd 100755 GIT binary patch delta 19 acmX@Ba#m%-T~4+F1=XAsuFa1*vp4`wi3cA5 delta 19 acmX@Ba#m%-T~4+X1=SQThRu&Tvp4`t69%UM diff --git a/irx/source/mctools/Makefile b/irx/source/mctools/Makefile old mode 100755 new mode 100644 index bd50266..3c8eefc --- a/irx/source/mctools/Makefile +++ b/irx/source/mctools/Makefile @@ -1,14 +1,8 @@ IOP_BIN = mctools.irx IOP_OBJS = mctools.o MCIO.o cache.o imports.o -IOP_CFLAGS += -Wall -fno-builtin -mgpopt -G8192 -O2 -mno-check-zero-division -IOP_LDFLAGS += -s -IOP_INCS += -I$(PS2SDK)/iop/include -I$(PS2SDK)/common/include - -all: $(IOP_BIN) - -clean: - rm -f $(IOP_BIN) $(IOP_OBJS) +IOP_CFLAGS += -mgpopt -G8192 include $(PS2SDK)/Defs.make -include Rules.make +include ../Rules.bin.make +include ../Rules.make diff --git a/irx/source/secrman/Makefile b/irx/source/secrman/Makefile old mode 100755 new mode 100644 index 4d87892..b7cb8a5 --- a/irx/source/secrman/Makefile +++ b/irx/source/secrman/Makefile @@ -6,27 +6,17 @@ # Licenced under Academic Free License version 2.0 # Review ps2sdk README & LICENSE files for further details. # -# $Id$ -IOP_OBJS_DIR = obj/ -IOP_BIN_DIR = bin/ -IOP_SRC_DIR = src/ -IOP_INC_DIR = include/ +IOP_BIN = secrman.irx +IOP_OBJS = secrman.o MechaAuth.o CardAuth.o keyman.o imports.o exports.o -IOP_BIN = bin/secrman.irx -IOP_OBJS = obj/secrman.o obj/MechaAuth.o obj/CardAuth.o obj/keyman.o obj/imports.o obj/exports.o +# Define to 1, to enable runtime support for both CEX and DEX units. +DEX_SUPPORT ?= 1 -IOP_INCS += -I$(IOP_INC_DIR) -I$(PS2SDKSRC)/iop/kernel/include -I$(PS2SDKSRC)/iop/system/sio2log/include -I$(PS2SDKSRC)/common/include -I$(IOP_SRC_DIR)/include -IOP_CFLAGS += -Wall -fno-builtin -O2 -G0 -mno-check-zero-division -IOP_LDFLAGS += -s +ifeq ($(DEX_SUPPORT),1) + IOP_CFLAGS += -DDEX_SUPPORT=1 +endif -IOP_CFLAGS += -DDEX_SUPPORT=1 #Uncomment to enable unofficial support for the DEX - -all: $(IOP_OBJS_DIR) $(IOP_BIN_DIR) $(IOP_BIN) - -clean: - rm -f -r $(IOP_OBJS_DIR) $(IOP_BIN_DIR) - -include $(PS2SDKSRC)/Defs.make -include $(PS2SDKSRC)/iop/Rules.make -include $(PS2SDKSRC)/iop/Rules.release +include $(PS2SDK)/Defs.make +include ../Rules.bin.make +include ../Rules.make diff --git a/irx/source/secrman/include/secrman.h b/irx/source/secrman/include/secrman.h old mode 100755 new mode 100644 diff --git a/irx/source/secrman/src/CardAuth.c b/irx/source/secrman/src/CardAuth.c old mode 100755 new mode 100644 index 799b6cc..cc00d7f --- a/irx/source/secrman/src/CardAuth.c +++ b/irx/source/secrman/src/CardAuth.c @@ -65,7 +65,7 @@ unsigned char calculate_sio2_buffer_checksum(const void *buffer, unsigned int le for(checksum=0,i=0; iresult=SecrDownloadHeader(((struct SecrSifDownloadHeaderParams*)buffer)->port, ((struct SecrSifDownloadHeaderParams*)buffer)->slot, ((struct SecrSifDownloadHeaderParams*)buffer)->buffer, &((struct SecrSifDownloadHeaderParams*)buffer)->BitTable, &((struct SecrSifDownloadHeaderParams*)buffer)->size); return buffer; } -//0x000000e0 -static void *SifRpcA02_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDownloadBlockHandler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDownloadBlockParams*)buffer)->result=SecrDownloadBlock(((struct SecrSifDownloadBlockParams*)buffer)->buffer, ((struct SecrSifDownloadBlockParams*)buffer)->size); return buffer; } -//0x000001b0 -static void *SifRpcA03_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDownloadGetKbitHandler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDownloadGetKbitParams*)buffer)->result=SecrDownloadGetKbit(((struct SecrSifDownloadGetKbitParams*)buffer)->port, ((struct SecrSifDownloadGetKbitParams*)buffer)->slot, ((struct SecrSifDownloadGetKbitParams*)buffer)->kbit); return buffer; } -//0x00000284 -static void *SifRpcA04_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDownloadGetKcHandler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDownloadGetKcParams*)buffer)->result=SecrDownloadGetKc(((struct SecrSifDownloadGetKcParams*)buffer)->port, ((struct SecrSifDownloadGetKcParams*)buffer)->slot, ((struct SecrSifDownloadGetKcParams*)buffer)->kc); return buffer; } -//0x00000358 -static void *SifRpcA05_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDownloadGetICVPS2Handler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDownloadGetIcvps2Params*)buffer)->result=SecrDownloadGetICVPS2(((struct SecrSifDownloadGetIcvps2Params*)buffer)->icvps2); return buffer; } -//0x00000424 -static void *SifRpcA06_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDiskBootHeaderHandler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDiskBootHeaderParams*)buffer)->result=SecrDiskBootHeader(((struct SecrSifDiskBootHeaderParams*)buffer)->buffer, &((struct SecrSifDiskBootHeaderParams*)buffer)->BitTable, &((struct SecrSifDiskBootHeaderParams*)buffer)->size); return buffer; } -//0x000004f8 -static void *SifRpcA07_handler(int function, void *buffer, int nbytes){ +static void *SifSecrDiskBootBlockHandler(int function, void *buffer, int nbytes) +{ ((struct SecrSifDiskBootBlockParams*)buffer)->result=SecrDiskBootBlock(((struct SecrSifDiskBootBlockParams*)buffer)->source, ((struct SecrSifDiskBootBlockParams*)buffer)->destination, ((struct SecrSifDiskBootBlockParams*)buffer)->size); - printf("sif_disk_boot_block %d %d\n", ((struct SecrSifDiskBootBlockParams*)buffer)->source, ((struct SecrSifDiskBootBlockParams*)buffer)->result); + printf("sif_disk_boot_block %p %ld\n", ((struct SecrSifDiskBootBlockParams*)buffer)->source, ((struct SecrSifDiskBootBlockParams*)buffer)->result); return buffer; } -//0x00000044 -static void func_00000044(void *parameters){ +static void SifSecrDownloadHeaderThread(void *parameters) +{ if(!sceSifCheckInit()){ printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData01, GetThreadId()); - sceSifRegisterRpc(&SifServerData01, 0x80000A01, &SifRpcA01_handler, SifServerBuffer01, NULL, NULL, &SifQueueData01); - sceSifRpcLoop(&SifQueueData01); + sceSifSetRpcQueue(&SifSecrDownloadHeaderQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDownloadHeaderData, SECRSIF_DOWNLOAD_HEADER, &SifSecrDownloadHeader, SifServerBuffer, NULL, NULL, &SifSecrDownloadHeaderQD); + sceSifRpcLoop(&SifSecrDownloadHeaderQD); } -//0x00000114 -static void func_00000114(void *parameters){ +static void SifSecrDownloadBlockThread(void *parameters) +{ if(!sceSifCheckInit()){ printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData02, GetThreadId()); - sceSifRegisterRpc(&SifServerData02, 0x80000A02, &SifRpcA02_handler, SifServerBuffer01, NULL, NULL, &SifQueueData02); - sceSifRpcLoop(&SifQueueData02); + sceSifSetRpcQueue(&SifSecrDownloadBlockQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDownloadBlockData, SECRSIF_DOWNLOAD_BLOCK, &SifSecrDownloadBlockHandler, SifServerBuffer, NULL, NULL, &SifSecrDownloadBlockQD); + sceSifRpcLoop(&SifSecrDownloadBlockQD); } -//0x000001e8 -static void func_000001e8(void *parameters){ +static void SifSecrDownloadGetKbitThread(void *parameters) +{ if(!sceSifCheckInit()){ printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData03, GetThreadId()); - sceSifRegisterRpc(&SifServerData03, 0x80000A03, &SifRpcA03_handler, SifServerBuffer01, NULL, NULL, &SifQueueData03); - sceSifRpcLoop(&SifQueueData03); + sceSifSetRpcQueue(&SifSecrDownloadGetKbitQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDownloadGetKbitData, SECRSIF_DOWNLOAD_GET_KBIT, &SifSecrDownloadGetKbitHandler, SifServerBuffer, NULL, NULL, &SifSecrDownloadGetKbitQD); + sceSifRpcLoop(&SifSecrDownloadGetKbitQD); } -//0x000002bc -static void func_000002bc(void *parameters){ +static void SifSecrDownloadGetKcThread(void *parameters) +{ if(!sceSifCheckInit()){ printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData04, GetThreadId()); - sceSifRegisterRpc(&SifServerData04, 0x80000A04, &SifRpcA04_handler, SifServerBuffer01, NULL, NULL, &SifQueueData04); - sceSifRpcLoop(&SifQueueData04); + sceSifSetRpcQueue(&SifSecrDownloadGetKcQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDownloadGetKcData, SECRSIF_DOWNLOAD_GET_KC, &SifSecrDownloadGetKcHandler, SifServerBuffer, NULL, NULL, &SifSecrDownloadGetKcQD); + sceSifRpcLoop(&SifSecrDownloadGetKcQD); } -//0x00000388 -static void func_00000388(void *parameters){ +static void SifSecrDownloadGetICVPS2Thread(void *parameters) +{ if(!sceSifCheckInit()){ printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData05, GetThreadId()); - sceSifRegisterRpc(&SifServerData05, 0x80000A05, &SifRpcA05_handler, SifServerBuffer01, NULL, NULL, &SifQueueData05); - sceSifRpcLoop(&SifQueueData05); + sceSifSetRpcQueue(&SifSecrDownloadGetICVPS2QD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDownloadGetICVPS2Data, SECRSIF_DOWNLOAD_GET_ICVPS2, &SifSecrDownloadGetICVPS2Handler, SifServerBuffer, NULL, NULL, &SifSecrDownloadGetICVPS2QD); + sceSifRpcLoop(&SifSecrDownloadGetICVPS2QD); } -//0x0000045c -static void func_0000045c(void *parameters){ - if(!sceSifCheckInit()){ +static void SifSecrDiskBootHeaderThread(void *parameters) +{ + if(!sceSifCheckInit()) + { printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData06, GetThreadId()); - sceSifRegisterRpc(&SifServerData06, 0x80000A06, &SifRpcA06_handler, SifServerBuffer01, NULL, NULL, &SifQueueData06); - sceSifRpcLoop(&SifQueueData06); + sceSifSetRpcQueue(&SifSecrDiskBootHeaderQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDiskBootHeaderData, SECRSIF_DISK_BOOT_HEADER, &SifSecrDiskBootHeaderHandler, SifServerBuffer, NULL, NULL, &SifSecrDiskBootHeaderQD); + sceSifRpcLoop(&SifSecrDiskBootHeaderQD); } -//0x00000544 -static void func_00000544(void *parameters){ - if(!sceSifCheckInit()){ +static void SifSecrDiskBootBlockThread(void *parameters) +{ + if(!sceSifCheckInit()) + { printf("yet sif hasn't been init\n"); sceSifInit(); } sceSifInitRpc(0); - sceSifSetRpcQueue(&SifQueueData07, GetThreadId()); - sceSifRegisterRpc(&SifServerData07, 0x80000A07, &SifRpcA07_handler, SifServerBuffer01, NULL, NULL, &SifQueueData07); - sceSifRpcLoop(&SifQueueData07); + sceSifSetRpcQueue(&SifSecrDiskBootBlockQD, GetThreadId()); + sceSifRegisterRpc(&SifSecrDiskBootBlockData, SECRSIF_DISK_BOOT_BLOCK, &SifSecrDiskBootBlockHandler, SifServerBuffer, NULL, NULL, &SifSecrDiskBootBlockQD); + sceSifRpcLoop(&SifSecrDiskBootBlockQD); } -//0x000005e0 -int _start(int argc, char *argv[]){ +int _start(int argc, char *argv[]) +{ int result; iop_thread_t thread; - if(RegisterLibraryEntries(&_exp_secrsif)==0){ + if(RegisterLibraryEntries(&_exp_secrsif)==0) + { thread.attr=TH_C; - thread.thread=&func_00000044; + thread.thread=&SifSecrDownloadHeaderThread; thread.priority=0x28; thread.stacksize=0x800; - if((SifRpcThread01=CreateThread(&thread))!=0){ - StartThread(SifRpcThread01, NULL); - - thread.thread=&func_00000114; - if((SifRpcThread02=CreateThread(&thread))!=0){ - StartThread(SifRpcThread02, NULL); - - thread.thread=&func_000001e8; - if((SifRpcThread03=CreateThread(&thread))!=0){ - StartThread(SifRpcThread03, NULL); - - thread.thread=&func_000002bc; - if((SifRpcThread04=CreateThread(&thread))!=0){ - StartThread(SifRpcThread04, NULL); - - thread.thread=&func_00000388; - if((SifRpcThread05=CreateThread(&thread))!=0){ - StartThread(SifRpcThread05, NULL); - - thread.thread=&func_0000045c; - if((SifRpcThread06=CreateThread(&thread))!=0){ - StartThread(SifRpcThread06, NULL); - - thread.thread=&func_00000544; - if((SifRpcThread07=CreateThread(&thread))!=0){ - StartThread(SifRpcThread07, NULL); + if((SifSecrDownloadHeaderThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDownloadHeaderThreadID, NULL); + + thread.thread=&SifSecrDownloadBlockThread; + if((SifSecrDownloadBlockThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDownloadBlockThreadID, NULL); + + thread.thread=&SifSecrDownloadGetKbitThread; + if((SifSecrDownloadGetKbitThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDownloadGetKbitThreadID, NULL); + + thread.thread=&SifSecrDownloadGetKcThread; + if((SifSecrDownloadGetKcThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDownloadGetKcThreadID, NULL); + + thread.thread=&SifSecrDownloadGetICVPS2Thread; + if((SifSecrDownloadGetICVPS2ThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDownloadGetICVPS2ThreadID, NULL); + + thread.thread=&SifSecrDiskBootHeaderThread; + if((SifSecrDiskBootHeaderThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDiskBootHeaderThreadID, NULL); + + thread.thread=&SifSecrDiskBootBlockThread; + if((SifSecrDiskBootBlockThreadID=CreateThread(&thread))!=0) + { + StartThread(SifSecrDiskBootBlockThreadID, NULL); result=MODULE_RESIDENT_END; } diff --git a/irx/source/secrsif/src/secrsif.h b/irx/source/secrsif/src/secrsif.h old mode 100755 new mode 100644 index e56ded5..38333e8 --- a/irx/source/secrsif/src/secrsif.h +++ b/irx/source/secrsif/src/secrsif.h @@ -1,44 +1,52 @@ struct SecrSifDownloadHeaderParams{ s32 port, slot; - u8 buffer[0x400]; //0x008 - SecrBitTable_t BitTable; //0x408 - s32 size; //0x808 - s32 result; //0x80C + u8 buffer[0x400]; + SecrBitTable_t BitTable; + s32 size; + s32 result; }; struct SecrSifDownloadBlockParams{ u8 buffer[0x400]; - s32 size; //0x400 - s32 result; //0x404 + s32 size; + s32 result; }; struct SecrSifDownloadGetKbitParams{ s32 port, slot; - u8 kbit[16]; //0x08 - s32 result; //0x18 + u8 kbit[16]; + s32 result; }; struct SecrSifDownloadGetKcParams{ s32 port, slot; - u8 kc[16]; //0x08 - s32 result; //0x18 + u8 kc[16]; + s32 result; }; struct SecrSifDownloadGetIcvps2Params{ - u8 icvps2[8]; //0x00 - s32 result; //0x08 + u8 icvps2[8]; + s32 result; }; struct SecrSifDiskBootHeaderParams{ u8 buffer[0x400]; - SecrBitTable_t BitTable; //0x400 - s32 size; //0x800 - s32 result; //0x804 + SecrBitTable_t BitTable; + s32 size; + s32 result; }; struct SecrSifDiskBootBlockParams{ u8 source[0x400]; - u8 destination[0x400]; //0x400 - s32 size; //0x800 - s32 result; //0x804 + u8 destination[0x400]; + s32 size; + s32 result; }; + +#define SECRSIF_DOWNLOAD_HEADER 0x80000A01 +#define SECRSIF_DOWNLOAD_BLOCK 0x80000A02 +#define SECRSIF_DOWNLOAD_GET_KBIT 0x80000A03 +#define SECRSIF_DOWNLOAD_GET_KC 0x80000A04 +#define SECRSIF_DOWNLOAD_GET_ICVPS2 0x80000A05 +#define SECRSIF_DISK_BOOT_HEADER 0x80000A06 +#define SECRSIF_DISK_BOOT_BLOCK 0x80000A07 diff --git a/lang.c b/lang.c index c8eac84..9d9b63f 100644 --- a/lang.c +++ b/lang.c @@ -62,8 +62,10 @@ static const char *DefaultLanguageStringTable[SYS_UI_MSG_COUNT]={ "The HardDisk Drive (HDD) unit has a problem.\nPlease run a disk check first.", "S.M.A.R.T. has reported that the HardDisk Drive (HDD) unit has failed.\n\nThe HDD unit must be replaced.", "This console does not support FMCB.\n\nHowever, you can still make installations with it.", - "While the multi-installation allows you to create a FMCB card that can boot on all PlayStation 2 consoles with the least space requirements, it goes against the design of the Memory Card by introducing controlled filesystem corruption.\n\nIt is hence strongly recommended to create a normal installation instead.", + "While the multi-installation can boot on all PlayStation 2 consoles with the least space requirements, it goes against the design of the Memory Card by introducing controlled filesystem corruption.\n\nIt is hence strongly recommended to create a normal installation instead.", "Quit program?", + "The HardDisk Drive (HDD) unit is not formatted. Format?\nWarning: All data will be erased.", + "Failed to format the HardDisk Drive (HDD) unit.", }; static const char *DefaultLanguageLabelStringTable[SYS_UI_LBL_COUNT]={ @@ -71,6 +73,12 @@ static const char *DefaultLanguageLabelStringTable[SYS_UI_LBL_COUNT]={ "Cancel", "Yes", "No", + "Next", + "Back", + "Enabled", + "Disabled", + "Toggle option", + "Select field", "Warning", "Error", "Information", diff --git a/lang.h b/lang.h index d46e6d4..ffa3a45 100644 --- a/lang.h +++ b/lang.h @@ -64,6 +64,8 @@ enum SYS_UI_MESSAGES{ SYS_UI_MSG_ROM_UNSUPPORTED, SYS_UI_MSG_MULTI_WARN, SYS_UI_MSG_QUIT, + SYS_UI_MSG_FORMAT_HDD, + SYS_UI_MSG_FORMAT_HDD_FAILED, SYS_UI_MSG_COUNT }; @@ -73,6 +75,12 @@ enum SYS_UI_LABEL_TEXT{ SYS_UI_LBL_CANCEL, SYS_UI_LBL_YES, SYS_UI_LBL_NO, + SYS_UI_LBL_NEXT, + SYS_UI_LBL_BACK, + SYS_UI_LBL_ENABLED, + SYS_UI_LBL_DISABLED, + SYS_UI_LBL_TOGGLE_OPTION, + SYS_UI_LBL_SELECT_FIELD, SYS_UI_LBL_WARNING, SYS_UI_LBL_ERROR, SYS_UI_LBL_INFO, diff --git a/libsecr.c b/libsecr.c old mode 100755 new mode 100644 diff --git a/libsecr.h b/libsecr.h old mode 100755 new mode 100644 diff --git a/linkfile b/linkfile old mode 100755 new mode 100644 index 97d1eb9..b138573 --- a/linkfile +++ b/linkfile @@ -91,11 +91,19 @@ SECTIONS { } _end_bss = .; + /* Symbols needed by crt0.s. */ + PROVIDE(_heap_size = 0x02000000 - _end); + PROVIDE(_stack_size = 0x2000); + + _stack = ALIGN(128); + PROVIDE(_stack = .); + . = _stack + _stack_size; + _end = . ; PROVIDE(end = .); - /* Symbols needed by crt0.s. */ - PROVIDE(_heap_size = -1); - PROVIDE(_stack = -1); - PROVIDE(_stack_size = 128 * 1024); + /* Unwanted stuff */ + /DISCARD/ : { + * ( .MIPS.abiflags ) + } } diff --git a/main.c b/main.c old mode 100755 new mode 100644 index 018bf13..55a191a --- a/main.c +++ b/main.c @@ -1,8 +1,6 @@ -#include #include #include #include -#include #include #include #include @@ -13,10 +11,12 @@ #include #include #include +#include #include #include "main.h" +#include "iop.h" #include "pad.h" #include "graphics.h" #include "font.h" @@ -28,191 +28,83 @@ #include "UI.h" #include "menu.h" -#include "ioprstctrl.h" - -extern unsigned char IOMANX_irx_start[]; -extern unsigned int IOMANX_irx_size; - -extern unsigned char FILEXIO_irx_start[]; -extern unsigned int FILEXIO_irx_size; - -extern unsigned char SIO2MAN_irx_start[]; -extern unsigned int SIO2MAN_irx_size; - -extern unsigned char PADMAN_irx_start[]; -extern unsigned int PADMAN_irx_size; - -extern unsigned char MCMAN_irx_start[]; -extern unsigned int MCMAN_irx_size; - -extern unsigned char MCSERV_irx_start[]; -extern unsigned int MCSERV_irx_size; - -extern unsigned char SECRSIF_irx_start[]; -extern unsigned int SECRSIF_irx_size; - -extern unsigned char MCTOOLS_irx_start[]; -extern unsigned int MCTOOLS_irx_size; - -extern unsigned char USBD_irx_start[]; -extern unsigned int USBD_irx_size; - -extern unsigned char USBHDFSD_irx_start[]; -extern unsigned int USBHDFSD_irx_size; - -extern unsigned char POWEROFF_irx_start[]; -extern unsigned int POWEROFF_irx_size; - -extern unsigned char DEV9_irx_start[]; -extern unsigned int DEV9_irx_size; - -extern unsigned char ATAD_irx_start[]; -extern unsigned int ATAD_irx_size; - -extern unsigned char HDD_irx_start[]; -extern unsigned int HDD_irx_size; - -extern unsigned char PFS_irx_start[]; -extern unsigned int PFS_irx_size; - -#ifdef DEBUG_TTY_FEEDBACK -extern unsigned char UDPTTY_irx_start[]; -extern unsigned int UDPTTY_irx_size; -#endif - int IsHDDUnitConnected=0; -extern unsigned char UDNL_irx_start[]; -extern unsigned int UDNL_irx_size; - int VBlankStartSema; +int InstallLockSema; static int VBlankStartHandler(int cause){ ee_sema_t sema; iReferSemaStatus(VBlankStartSema, &sema); if(sema.count=0){ - SifExecModuleBuffer(HDD_irx_start, HDD_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(PFS_irx_start, PFS_irx_size, sizeof(PS2FS_args), PS2FS_args, NULL); - } - - SifExecModuleBuffer(SECRSIF_irx_start, SECRSIF_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(MCSERV_irx_start, MCSERV_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(PADMAN_irx_start, PADMAN_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(MCTOOLS_irx_start, MCTOOLS_irx_size, 0, NULL, NULL); +static void DeinitServices(void) +{ + DisableIntc(kINTC_VBLANK_START); + RemoveIntcHandler(kINTC_VBLANK_START, 0); + DeleteSema(VBlankStartSema); + DeleteSema(InstallLockSema); - SignalSema(SystemInitParams->InitCompleteSema); - ExitDeleteThread(); + IopDeinit(); } -int main(int argc, char *argv[]){ - int SystemType; +int main(int argc, char *argv[]) +{ + int SystemType, InitSemaID, BootDevice, result; unsigned int FrameNum; - ee_sema_t ThreadSema; - struct SystemInitParams InitThreadParams; - void *SysInitThreadStack; + ee_sema_t sema; -/* argv[0] = "mass:/FMCBInstaller/FMCBInstaller.elf"; - chdir("mass:/FMCBInstaller/"); */ - if(argc<1 || GetBootDeviceID(argv[0])==BOOT_DEVICE_UNKNOWN){ + //chdir("mass:/FMCBInstaller/"); + if((BootDevice = GetBootDeviceID()) == BOOT_DEVICE_UNKNOWN) Exit(-1); - } - SifInitRpc(0); - SifIopResetBufferUDNL(UDNL_irx_start, UDNL_irx_size); + InitSemaID = IopInitStart(IOP_MOD_SET_MAIN); - //Do something useful while the IOP resets. - ThreadSema.init_count=0; - ThreadSema.max_count=1; - ThreadSema.attr=ThreadSema.option=0; - InitThreadParams.InitCompleteSema=CreateSema(&ThreadSema); + sema.init_count=0; + sema.max_count=1; + sema.attr=sema.option=0; + VBlankStartSema=CreateSema(&sema); - SysInitThreadStack=memalign(128, SYSTEM_INIT_THREAD_STACK_SIZE); - - ThreadSema.init_count=0; - ThreadSema.max_count=1; - ThreadSema.attr=ThreadSema.option=0; - VBlankStartSema=CreateSema(&ThreadSema); + sema.init_count=1; + sema.max_count=1; + sema.attr=sema.option=0; + InstallLockSema=CreateSema(&sema); AddIntcHandler(kINTC_VBLANK_START, &VBlankStartHandler, 0); EnableIntc(kINTC_VBLANK_START); - while(!SifIopSync()){} - - SifInitRpc(0); - SifInitIopHeap(); - SifLoadFileInit(); - sbv_patch_enable_lmb(); - - SifExecModuleBuffer(POWEROFF_irx_start, POWEROFF_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(DEV9_irx_start, DEV9_irx_size, 0, NULL, NULL); -#ifdef DEBUG_TTY_FEEDBACK - SifExecModuleBuffer(UDPTTY_irx_start, UDPTTY_irx_size, 0, NULL, NULL); -#endif - SifExecModuleBuffer(IOMANX_irx_start, IOMANX_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(FILEXIO_irx_start, FILEXIO_irx_size, 0, NULL, NULL); - - SifExecModuleBuffer(USBD_irx_start, USBD_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(USBHDFSD_irx_start, USBHDFSD_irx_size, 0, NULL, NULL); - - SifExecModuleBuffer(SIO2MAN_irx_start, SIO2MAN_irx_size, 0, NULL, NULL); - SifExecModuleBuffer(MCMAN_irx_start, MCMAN_irx_size, 0, NULL, NULL); - - SifLoadFileExit(); - fileXioInit(); - - sceCdInit(SCECdINoD); - - if(InitializeUI()!=0){ + if(InitializeUI(0)!=0){ SifExitRpc(); Exit(-1); } - SysCreateThread(SystemInitThread, SysInitThreadStack, SYSTEM_INIT_THREAD_STACK_SIZE, &InitThreadParams, 0x1); - FrameNum=0; /* Draw something nice here while waiting... */ do{ RedrawLoadingScreen(FrameNum); FrameNum++; - }while(PollSema(InitThreadParams.InitCompleteSema)!=InitThreadParams.InitCompleteSema); - DeleteSema(InitThreadParams.InitCompleteSema); - free(SysInitThreadStack); + }while(PollSema(InitSemaID)!=InitSemaID); + DeleteSema(InitSemaID); DEBUG_PRINTF("Modules loaded.\n"); - mcInit(MC_TYPE_XMC); - PadInitPads(); - - SecrInit(); - InitMCTOOLS(); - StartWorkerThread(); UpdateRegionalPaths(); SystemType = GetPs2Type(); - if(SystemType == PS2_SYSTEM_TYPE_PS2 || SystemType == PS2_SYSTEM_TYPE_DEX){ - if(hddCheckPresent()==0 && hddCheckFormatted()==0){ + if(SystemType == PS2_SYSTEM_TYPE_PS2 || SystemType == PS2_SYSTEM_TYPE_DEX) + { + result = HDDCheckStatus(); + if(result >= 0 && result <= 1) + { //Accept only if a usable disk is connected (formatted or not). IsHDDUnitConnected=1; } } - SecrInit(); - InitMCTOOLS(); - MainMenu(); ShutdownRPCsAndExit: @@ -221,22 +113,9 @@ int main(int argc, char *argv[]){ if(!IsHDDBootingEnabled()) fileXioDevctl("hdd0:", HDDCTL_DEV9_SHUTDOWN, NULL, 0, NULL, 0); - PadDeinitPads(); - - DisableIntc(kINTC_VBLANK_START); - RemoveIntcHandler(kINTC_VBLANK_START, 0); - DeleteSema(VBlankStartSema); - DeinitializeUI(); - - DeinitMCTOOLS(); - SecrDeinit(); - - sceCdInit(SCECdEXIT); - - fileXioExit(); - SifExitIopHeap(); - SifExitRpc(); + DeinitServices(); return 0; } + diff --git a/main.h b/main.h old mode 100755 new mode 100644 index 714fc13..55e0457 --- a/main.h +++ b/main.h @@ -6,7 +6,7 @@ #define DEBUG_PRINTF(args...) #endif -#define FMCB_INSTALLER_VERSION "0.973" +#define FMCB_INSTALLER_VERSION "0.987" /* The number of files and folders to crosslink (For multi-regional and cross-model installations). */ #define NUM_CROSSLINKED_FILES 8 diff --git a/mctools_rpc.c b/mctools_rpc.c old mode 100755 new mode 100644 index 195185d..46cf025 --- a/mctools_rpc.c +++ b/mctools_rpc.c @@ -9,6 +9,7 @@ static SifRpcClientData_t MCTOOLS_rpc_cd; static struct MCTools_AlignmentData MCTools_BufferAlignmentData ALIGNED(16); static void *IopBuffer; +static int AsyncRpcEndSema = -1; static unsigned int IopBufferSize; static unsigned char TransmitBuffer[1024] ALIGNED(64); @@ -19,8 +20,20 @@ static void MCTOOLS_RpcEndFunc(void *AlignmentData){ memcpy(((struct MCTools_AlignmentData *)UNCACHED_SEG(AlignmentData))->buffer2Address, ((struct MCTools_AlignmentData *)UNCACHED_SEG(AlignmentData))->buffer2, ((struct MCTools_AlignmentData *)UNCACHED_SEG(AlignmentData))->buffer2_len); } +static void MCTOOLS_ReadRpcEndFunc(void *end_param) +{ + MCTOOLS_RpcEndFunc(end_param); + iSignalSema(AsyncRpcEndSema); +} + +static void MCTOOLS_WriteRpcEndFunc(void *end_param) +{ + iSignalSema(AsyncRpcEndSema); +} + void InitMCTOOLS(void){ void *data; + ee_sema_t sema; while((SifBindRpc(&MCTOOLS_rpc_cd, MCTOOLS_RPC_NUM, 0)<0) || (MCTOOLS_rpc_cd.server == NULL)) nopdelay(); IopBufferSize=8192; @@ -28,11 +41,22 @@ void InitMCTOOLS(void){ data=&MCTools_BufferAlignmentData; SifCallRpc(&MCTOOLS_rpc_cd, MCTOOLS_Init, 0, &data, sizeof(void *), NULL, 0, NULL, NULL); + + sema.init_count = 1; + sema.max_count = 1; + sema.attr = 0; + sema.option = 0; + AsyncRpcEndSema = CreateSema(&sema); } void DeinitMCTOOLS(void){ memset(&MCTOOLS_rpc_cd, 0, sizeof(SifRpcClientData_t)); if(IopBuffer!=NULL) SifFreeIopHeap(IopBuffer); + if(AsyncRpcEndSema >= 0) + { + DeleteSema(AsyncRpcEndSema); + AsyncRpcEndSema = -1; + } } static int CheckIOPBufferSize(int size){ @@ -140,6 +164,8 @@ int MCToolsReadCluster(int port, int slot, unsigned int cluster, unsigned short struct MCTools_ReadWriteRPCData *ReadClusterRPCData; if(CheckIOPBufferSize(McSpecData->PageSize*ClusterSize)>=0){ + WaitSema(AsyncRpcEndSema); + ReadClusterRPCData=(struct MCTools_ReadWriteRPCData *)TransmitBuffer; ReadClusterRPCData->port=port; @@ -152,7 +178,10 @@ int MCToolsReadCluster(int port, int slot, unsigned int cluster, unsigned short SifWriteBackDCache(buffer, McSpecData->PageSize*ClusterSize); - result=SifCallRpc(&MCTOOLS_rpc_cd, MCTOOLS_ReadCluster, SIF_RPC_M_NOWAIT, ReadClusterRPCData, sizeof(struct MCTools_ReadWriteRPCData), ReceiveBuffer, sizeof(int), &MCTOOLS_RpcEndFunc, &MCTools_BufferAlignmentData); + if((result=SifCallRpc(&MCTOOLS_rpc_cd, MCTOOLS_ReadCluster, SIF_RPC_M_NOWAIT, ReadClusterRPCData, sizeof(struct MCTools_ReadWriteRPCData), ReceiveBuffer, sizeof(int), &MCTOOLS_ReadRpcEndFunc, &MCTools_BufferAlignmentData)) < 0) + { + SignalSema(AsyncRpcEndSema); + } } else result=-ENOMEM; @@ -167,6 +196,8 @@ int MCToolsWriteBlock(int port, int slot, unsigned int block, const struct MCToo BlockSize=McSpecData->PageSize*McSpecData->BlockSize; if(CheckIOPBufferSize(BlockSize)>=0){ + WaitSema(AsyncRpcEndSema); + WriteBlockRPCData=(struct MCTools_ReadWriteRPCData *)TransmitBuffer; dmat.src=buffer; @@ -185,7 +216,10 @@ int MCToolsWriteBlock(int port, int slot, unsigned int block, const struct MCToo while(SifDmaStat(DMATransferID)>=0){}; - result=SifCallRpc(&MCTOOLS_rpc_cd, MCTOOLS_WriteBlock, SIF_RPC_M_NOWAIT, WriteBlockRPCData, sizeof(struct MCTools_ReadWriteRPCData), ReceiveBuffer, sizeof(int), NULL, NULL); + if((result=SifCallRpc(&MCTOOLS_rpc_cd, MCTOOLS_WriteBlock, SIF_RPC_M_NOWAIT, WriteBlockRPCData, sizeof(struct MCTools_ReadWriteRPCData), ReceiveBuffer, sizeof(int), &MCTOOLS_WriteRpcEndFunc, NULL)) < 0) + { + SignalSema(AsyncRpcEndSema); + } } else result=-ENOMEM; @@ -197,10 +231,18 @@ int MCToolsSync(int mode){ switch(mode){ case 1: - result=SifCheckStatRpc(&MCTOOLS_rpc_cd); + if (PollSema(AsyncRpcEndSema) == AsyncRpcEndSema) + { + SignalSema(AsyncRpcEndSema); + return 0; + } + else{ + return 1; + } break; default: - while(SifCheckStatRpc(&MCTOOLS_rpc_cd)!=0){}; + WaitSema(AsyncRpcEndSema); + SignalSema(AsyncRpcEndSema); result=0; } diff --git a/mctools_rpc.h b/mctools_rpc.h old mode 100755 new mode 100644 diff --git a/menu.c b/menu.c old mode 100755 new mode 100644 index 2fc1edb..5441ea3 --- a/menu.c +++ b/menu.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include @@ -220,9 +222,37 @@ static void DrawMenuExitAnimation(void) } } -static int MainMenuUpdateCallback(struct UIMenu *menu, unsigned short int frame, int selection, int padstatus) +static int CheckFormat(void) { - if(padstatus != 0) + int status; + + status = HDDCheckStatus(); + switch(status) + { + case 1: //Not formatted + if(DisplayPromptMessage(SYS_UI_MSG_FORMAT_HDD, SYS_UI_LBL_CANCEL, SYS_UI_LBL_OK) == 2) + { + status = 0; + + if(hddFormat() != 0) + DisplayErrorMessage(SYS_UI_MSG_FORMAT_HDD_FAILED); + } + break; + case 0: //Formatted + break; + case 2: //Not a usable HDD + case 3: //No HDD connected + default: //Unknown errors + //DisplayErrorMessage(SYS_UI_MSG_NO_HDD); + break; + } + + return status; +} + +static int MainMenuUpdateCallback(struct UIMenu *menu, unsigned short int frame, int selection, u32 padstatus) +{ + if((padstatus != 0) || (frame == 0)) { if(selection >= 0) { @@ -389,8 +419,12 @@ void MainMenu(void) if(HasOldFMCBConfigFile(McPort, 0)) { - if(DisplayPromptMessage(SYS_UI_MSG_CNF_FOUND, SYS_UI_LBL_YES, SYS_UI_LBL_NO) <= 1) + result = DisplayPromptMessage(SYS_UI_MSG_CNF_FOUND, SYS_UI_LBL_YES, SYS_UI_LBL_NO); + + if(result == 1) //"YES" selected. flags|=INSTALL_MODE_FLAG_SKIP_CNF; + else if (result == 0) //User pressed back. + break; } if(event==EVENT_MULTI_INSTALL) @@ -605,6 +639,9 @@ void MainMenu(void) break; } + if(CheckFormat()) + break; + if(HDDCheckSectorErrorStatus() || HDDCheckPartErrorStatus()) { DisplayErrorMessage(SYS_UI_MSG_HDD_CORRUPTED); @@ -617,8 +654,12 @@ void MainMenu(void) if(HasOldFMCBConfigFileOnHDD()) { - if(DisplayPromptMessage(SYS_UI_MSG_CNF_HDD_FOUND, SYS_UI_LBL_YES, SYS_UI_LBL_NO) <= 1) + result = DisplayPromptMessage(SYS_UI_MSG_CNF_HDD_FOUND, SYS_UI_LBL_YES, SYS_UI_LBL_NO); + + if(result == 1) //"YES" selected. flags|=INSTALL_MODE_FLAG_SKIP_CNF; + else if (result == 0) //User pressed back. + break; } result=PerformHDDInstallation(flags); @@ -864,6 +905,7 @@ void DisplayOutOfSpaceMessageHDD(unsigned int AvailableSpace, unsigned int Requi void RedrawLoadingScreen(unsigned int frame) { + short int xRel, x, y; int NumDots; GS_RGBAQ rgbaq; @@ -872,19 +914,22 @@ void RedrawLoadingScreen(unsigned int frame) NumDots=frame%240/60; DrawBackground(&UIDrawGlobal, &BackgroundTexture); - FontPrintf(&UIDrawGlobal, 10, 10, 0, 1.5f, GS_WHITE_FONT, "FMCBInstaller v"FMCB_INSTALLER_VERSION); + FontPrintf(&UIDrawGlobal, 10, 10, 0, 2.5f, GS_WHITE_FONT, "FMCBInstaller v"FMCB_INSTALLER_VERSION); - FontPrintf(&UIDrawGlobal, 420, 380, 0, 1.0f, GS_WHITE_FONT, "Loading"); + x = 420; + y = 380; + FontPrintfWithFeedback(&UIDrawGlobal, x, y, 0, 1.8f, GS_WHITE_FONT, "Loading ", &xRel, NULL); + x += xRel; switch(NumDots) { case 1: - FontPrintf(&UIDrawGlobal, 560, 380, 0, 1.0f, GS_WHITE_FONT, "."); + FontPrintf(&UIDrawGlobal, x, y, 0, 1.8f, GS_WHITE_FONT, "."); break; case 2: - FontPrintf(&UIDrawGlobal, 560, 380, 0, 1.0f, GS_WHITE_FONT, ".."); + FontPrintf(&UIDrawGlobal, x, y, 0, 1.8f, GS_WHITE_FONT, ". ."); break; case 3: - FontPrintf(&UIDrawGlobal, 560, 380, 0, 1.0f, GS_WHITE_FONT, "..."); + FontPrintf(&UIDrawGlobal, x, y, 0, 1.8f, GS_WHITE_FONT, ". . ."); break; } diff --git a/menu.h b/menu.h old mode 100755 new mode 100644 diff --git a/pad.c b/pad.c old mode 100755 new mode 100644 index d243252..926fd0a --- a/pad.c +++ b/pad.c @@ -7,7 +7,7 @@ #include "pad.h" static unsigned char padArea[2][256] ALIGNED(64); -static u32 old_pad[2]={0, 0}; +static unsigned int old_pad[2]={0, 0}; void PadInitPads(void) { @@ -15,7 +15,8 @@ void PadInitPads(void) padPortOpen(0, 0, padArea[0]); padPortOpen(1, 0, padArea[1]); - memset(old_pad, 0, sizeof(old_pad)); + old_pad[0] = 0; + old_pad[1] = 0; } void PadDeinitPads(void) @@ -25,6 +26,22 @@ void PadDeinitPads(void) padEnd(); } +int ReadPadStatus_raw(int port, int slot){ + struct padButtonStatus buttons; + u32 paddata; + + paddata=0; + if(padRead(port, slot, &buttons) != 0){ + paddata = 0xffff ^ buttons.btns; + } + + return paddata; +} + +int ReadCombinedPadStatus_raw(void){ + return(ReadPadStatus_raw(0, 0)|ReadPadStatus_raw(1, 0)); +} + int ReadPadStatus(int port, int slot){ struct padButtonStatus buttons; u32 new_pad, paddata; diff --git a/pad.h b/pad.h old mode 100755 new mode 100644 index 17a7786..9a9acba --- a/pad.h +++ b/pad.h @@ -1,4 +1,7 @@ void PadInitPads(void); void PadDeinitPads(void); + +int ReadPadStatus_raw(int port, int slot); +int ReadCombinedPadStatus_raw(void); int ReadPadStatus(int port, int slot); int ReadCombinedPadStatus(void); diff --git a/resources/background.png b/resources/background.png old mode 100755 new mode 100644 diff --git a/system.c b/system.c old mode 100755 new mode 100644 index 3bf3f7a..d8b1fe6 --- a/system.c +++ b/system.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include @@ -21,6 +23,7 @@ #include #include "main.h" +#include "iop.h" #include "pad.h" #include "libsecr.h" #include "mctools_rpc.h" @@ -35,12 +38,52 @@ extern void *_gp; extern int errno __attribute__((section("data"))); extern unsigned short int SelectButton, CancelButton; - -int GetBootDeviceID(const char *path){ +extern u8 dev9Loaded; +extern int InstallLockSema; + +static int InitMCInfo(int port, int slot); +static int SignKELF(void *buffer, int size, unsigned char port, unsigned char slot); +static void GetKbitAndKc(void *buffer, u8 *Kbit, u8 *Kc); +static int SetKbitAndKc(void *buffer, u8 *Kbit, u8 *Kc); +static int TwinSignKELF(const char *RootFolder, void *buffer, int size, unsigned char port, unsigned char slot); +static char GetMGFolderLetter(unsigned char region); +static const char *GetMountParams(const char *command, char *BlockDevice); +static int DeleteFolder(const char *folder); +static int DeleteFolderIfEmpty(const char *folder); +static int AddDirContentsToFileCopyList(const char *RootFolderPath, const char *srcRelativePath, const char *destination, unsigned int CurrentLevel, struct FileCopyTarget **FileCopyList, unsigned int *CurrentNumFiles, unsigned int *CurrentNumDirs, unsigned int *TotalRequiredSpaceForFiles); +static int GetMcFreeSpace(int port, int slot); +static int EnableHDDBooting(void); +static int CopyFilesToHDD(const char *RootFolder, const struct FileCopyTarget *FileCopyList, unsigned int NumFilesEntries, unsigned int TotalNumBytes, unsigned int flags); +static int CreateBasicFoldersOnHDD(unsigned int flags); +static int _CleanupHDDTarget(void); +static int GetAllBaseFileStats(char MGLetter, const char *RootFolder, struct FileCopyTarget *FileCopyList, unsigned int NumFiles, unsigned int *TotalRequiredSpaceForFiles); +static int SyncMCFileWrite(int fd, int size, void *Buffer); +static int CopyFiles(const char *RootFolder, unsigned char port, unsigned char slot, const struct FileCopyTarget *FileCopyList, unsigned int NumFilesEntries, unsigned int TotalNumBytes, unsigned int flags); +static int CreateCrossLinkedFiles(int port, int slot); +static int GenerateUninstallFile(int port, int slot); +static void SetWorkerThreadCommand(int command, const void *arg); +static int GetWorkerThreadCommand(const void **arg); +static int DumpMemoryCard(int port, int slot, FILE *file, unsigned short int PagesPerCluster, const struct MCTools_McSpecData *McSpecData); +static int RestoreMemoryCard(int port, int slot, FILE *file, const struct MCTools_McSpecData *McSpecData); +static void WorkerThread(void *arg); +static int LoadOSDFile(const char *path, void **pBuffer, int *pSize, int *pRSize); + +int GetBootDeviceID(void) +{ + static int BootDevice = -2; + char path[256]; int result; - if(!strncmp(path, "mass:", 5) || !strncmp(path, "mass0:", 6)) result=BOOT_DEVICE_MASS; - else result=BOOT_DEVICE_UNKNOWN; + if(BootDevice < BOOT_DEVICE_UNKNOWN) + { + getcwd(path, sizeof(path)); + + if(!strncmp(path, "mass:", 5) || !strncmp(path, "mass0:", 6)) result=BOOT_DEVICE_MASS; + else result=BOOT_DEVICE_UNKNOWN; + + BootDevice = result; + } else + result = BootDevice; return result; } @@ -61,7 +104,7 @@ int GetConsoleRegion(void) region = CONSOLE_REGION_JAPAN; break; case 'A': - case 'H': + case 'H': //Asia, but it uses the same folder as USA. region = CONSOLE_REGION_USA; break; case 'E': @@ -85,7 +128,7 @@ int GetConsoleVMode(void) { case CONSOLE_REGION_EUROPE: return 1; - default: + default: //All other regions use NTSC return 0; } } @@ -143,8 +186,13 @@ static struct InstallationFile DEXSysFiles[DEX_SYS_INSTALL_NUM_FILES]={ } }; -#define PS2_SYS_HDDLOAD_INSTALL_NUM_FILES 2 +#define PS2_SYS_HDDLOAD_INSTALL_NUM_FILES 3 static struct InstallationFile PS2HDDLOADSysFiles[PS2_SYS_HDDLOAD_INSTALL_NUM_FILES]={ + { + "SYSTEM/DEV9.IRX", + "BIEXEC-SYSTEM/dev9.irx", + 0 + }, { "SYSTEM/ATAD.IRX", "BIEXEC-SYSTEM/atad.irx", @@ -258,8 +306,8 @@ static struct InstallationFile HDDBaseFiles[HDD_BASE_INSTALL_NUM_FILES]={ 0 }, { - "SYSTEM/FSCK/LANG/NotoSansCJKjp-Bold.otf", - "hdd0:__system:pfs:/fsck/lang/NotoSansCJKjp-Bold.otf", + "SYSTEM/FSCK/LANG/NotoSansJP-Bold.otf", + "hdd0:__system:pfs:/fsck/lang/NotoSansJP-Bold.otf", 0 }, { @@ -402,11 +450,35 @@ static char PSXSysExecFolder[]="BIEXEC-SYSTEM"; static char SysExecFile[12]; /* E.g. "osdmain.elf" or "osd110.elf" */ static char romver[16]; -static int GetMcFreeSpace(int port, int slot); -static int CopyFiles(const char *RootFolder, unsigned char port, unsigned char slot, const struct FileCopyTarget *FileCopyList, unsigned int NumFilesEntries, unsigned int TotalNumBytes, unsigned int flags); +static int InitMCInfo(int port, int slot) +{ + int result; + int type, space, format; + + mcGetInfo(port, slot, &type, &space, &format); + mcSync(0, NULL, &result); + + if(result >= sceMcResChangedCard && type==sceMcTypePS2) + { + result = 0; + } else + result = -ENODEV; + + return result; +} static int SignKELF(void *buffer, int size, unsigned char port, unsigned char slot){ - int result; + int result, InitSemaID, mcInitRes; + + /* An IOP reboot would be done by the Utility Disc, + to allow the SecrDownloadFile function of secrman_special to work on a DEX, + even though secrman_special was meant for a CEX. + + A DEX was designed so that card authentication will not work right when a CEX SECRMAN module is used. + This works since the memory card was authenticated by the ROM's SECRMAN module and SecrDownloadFile does not involve card authentication. + + However, to speed things up and to prevent more things from going wrong (particularly with USB support), we just reboot the IOP once at initialization and load all modules there. + Our SECRMAN module is a custom version that has a check to support the DEX natively. */ result=1; if(SecrDownloadFile(2+port, slot, buffer)==NULL){ @@ -611,6 +683,26 @@ static const char *GetMountParams(const char *command, char *BlockDevice){ return MountPath; } +static int createFolder(int port, int slot, const char *path){ + int result; + sceMcTblGetDir table; + + if((result=mcMkDir(port, slot, path))==0){ + mcSync(0, NULL, &result); + if(result==-4) result=0; //EEXIST doesn't count as an error. + } + + if(result == 0){ + // Set desired file attributes. + table.AttrFile = sceMcFileAttrReadable|sceMcFileAttrWriteable|sceMcFileAttrExecutable|sceMcFileAttrDupProhibit|sceMcFileAttrSubdir|sceMcFile0400; + if((result=mcSetFileInfo(port, slot, path, &table, sceMcFileInfoAttr))==0){ + mcSync(0, NULL, &result); + } + } + + return result; +} + static int CreateBasicFolders(int port, int slot, unsigned int flags){ unsigned int i; int result; @@ -630,36 +722,21 @@ static int CreateBasicFolders(int port, int slot, unsigned int flags){ if(result>=0){ if(!(flags&INSTALL_MODE_FLAG_MULTI_INST) && !(flags&INSTALL_MODE_FLAG_CROSS_REG)){ - if((result=mcMkDir(port, slot, (flags & INSTALL_MODE_FLAG_CROSS_PSX) ? PSXSysExecFolder : SysExecFolder))==0){ - mcSync(0, NULL, &result); - if(result==-4) result=0; //EEXIST doesn't count as an error. - } + result=createFolder(port, slot, (flags & INSTALL_MODE_FLAG_CROSS_PSX) ? PSXSysExecFolder : SysExecFolder); } else{ - if((result=mcMkDir(port, slot, "BIEXEC-SYSTEM"))==0){ - mcSync(0, NULL, &result); - if(result==-4) result=0; //EEXIST doesn't count as an error. - } + result=createFolder(port, slot, "BIEXEC-SYSTEM"); if(result>=0){ - if((result=mcMkDir(port, slot, "BEEXEC-SYSTEM"))==0){ - mcSync(0, NULL, &result); - if(result==-4) result=0; //EEXIST doesn't count as an error. - } + result=createFolder(port, slot, "BEEXEC-SYSTEM"); } if(result>=0){ - if((result=mcMkDir(port, slot, "BAEXEC-SYSTEM"))==0){ - mcSync(0, NULL, &result); - if(result==-4) result=0; //EEXIST doesn't count as an error. - } + result=createFolder(port, slot, "BAEXEC-SYSTEM"); } if(result>=0){ - if((result=mcMkDir(port, slot, "BCEXEC-SYSTEM"))==0){ - mcSync(0, NULL, &result); - if(result==-4) result=0; //EEXIST doesn't count as an error. - } + result=createFolder(port, slot, "BCEXEC-SYSTEM"); } } } @@ -1169,7 +1246,7 @@ static int CreateBasicFoldersOnHDD(unsigned int flags){ return result; } -int CleanupHDDTarget(void){ +static int _CleanupHDDTarget(void){ int result; /* Basically, do the opposite of CreateBasicFoldersOnHDD(). */ @@ -1196,6 +1273,18 @@ int CleanupHDDTarget(void){ return result; } +int CleanupHDDTarget(void){ + int result; + + WaitSema(InstallLockSema); + + result = _CleanupHDDTarget(); + + SignalSema(InstallLockSema); + + return result; +} + static int GetAllBaseFileStats(char MGLetter, const char *RootFolder, struct FileCopyTarget *FileCopyList, unsigned int NumFiles, unsigned int *TotalRequiredSpaceForFiles){ char *path; int result; @@ -1256,6 +1345,8 @@ int PerformHDDInstallation(unsigned int flags){ NumFiles--; } + WaitSema(InstallLockSema); + file=0; if((FileCopyList=malloc(NumFiles*sizeof(struct FileCopyTarget)))!=NULL){ memset(FileCopyList, 0, NumFiles*sizeof(struct FileCopyTarget)); @@ -1363,7 +1454,7 @@ int PerformHDDInstallation(unsigned int flags){ } if(result>=0 && !(flags & INSTALL_MODE_FLAG_SKIP_CLEANUP)){ - if((result=CleanupHDDTarget())<0){ + if((result=_CleanupHDDTarget())<0){ DisplayErrorMessage(SYS_UI_MSG_CLEANUP_FAILED); } } @@ -1393,6 +1484,8 @@ int PerformHDDInstallation(unsigned int flags){ } else result=-ENOMEM; + SignalSema(InstallLockSema); + return result; } @@ -1403,12 +1496,6 @@ int PerformInstallation(unsigned char port, unsigned char slot, unsigned int fla char RootFolder[256], MGLetter; unsigned char TargetSystemType; - if(flags&INSTALL_MODE_FLAG_MULTI_INST){ - if((result=MCToolsInitPageCache(port, slot))<0){ - return -EEXTCACHEINITERR; - } - } - if(!(flags&INSTALL_MODE_FLAG_CROSS_PSX)) { TargetSystemType = PS2SystemType; @@ -1421,6 +1508,8 @@ int PerformInstallation(unsigned char port, unsigned char slot, unsigned int fla getcwd(RootFolder, sizeof(RootFolder) - 8); strcat(RootFolder, "INSTALL"); + WaitSema(InstallLockSema); + //Generate the file copy list. NumFiles=BASE_INSTALL_NUM_FILES+SYS_FOLDER_RESOURCES_NUM_FILES; switch(TargetSystemType){ @@ -1745,12 +1834,12 @@ int PerformInstallation(unsigned char port, unsigned char slot, unsigned int fla if(result<0) result=-EEXTCRSLNKFAIL; } - - if(result>=0) result=MCToolsFlushPageCache(); //This must be strictly done immediately after crosslinking operation. } } else result=-ENOMEM; + SignalSema(InstallLockSema); + return result; } @@ -2056,15 +2145,30 @@ int CleanupMultiInstallation(int port, int slot){ char path[27], *FullPath; int result, FMCBUninstallFileVersion, NumCrosslinkedFiles; FILE *file; + int InitSemaID; + + //Reboot the IOP to load MCTOOLS.IRX in. This will also prevent MCMAN's cache from storing outdated content. + InitSemaID = IopInitStart(IOP_MOD_MCTOOLS|IOP_REBOOT); + + sprintf(path, "mc%u:SYS-CONF/FMCBUINST.dat", port); + memset(&FileHeader, 0, sizeof(struct UninstallationDataFileHeader)); + + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + + //Call sceMcGetInfo on the memory card to be accessed, after IOP reboots. Otherwise I/O operations may fail. + if((result = InitMCInfo(port, slot)) != 0) + return result; if((result=MCToolsInitPageCache(port, slot))<0){ return EEXTCACHEINITERR; } result=0; - sprintf(path, "mc%u:SYS-CONF/FMCBUINST.dat", port); - memset(&FileHeader, 0, sizeof(struct UninstallationDataFileHeader)); + WaitSema(InstallLockSema); if((file = fopen(path, "rb")) == NULL) { @@ -2208,15 +2312,26 @@ int CleanupMultiInstallation(int port, int slot){ if(LocalMcFileAlias!=NULL) free(LocalMcFileAlias); } + SignalSema(InstallLockSema); + + //Reboot the IOP to allow the remainder of the program to continue. + InitSemaID = IopInitStart(IOP_MOD_SET_MAIN|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + return result; } - -int CreateCrossLinkedFiles(int port, int slot){ +static int CreateCrossLinkedFiles(int port, int slot){ char path[27]; - int result, NumFiles; + int result, NumFiles, InitSemaID; unsigned int FileIndex; + //Reboot the IOP to load MCTOOLS.IRX in. This will also prevent MCMAN's cache from storing outdated content. + InitSemaID = IopInitStart(IOP_MOD_MCTOOLS|IOP_REBOOT); + sprintf(path, "%s/%s", SysExecFolder, SysExecFile); result=0; @@ -2227,6 +2342,19 @@ int CreateCrossLinkedFiles(int port, int slot){ } } + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + + //Call sceMcGetInfo on the memory card to be accessed, after IOP reboots. Otherwise I/O operations may fail. + if((result = InitMCInfo(port, slot)) != 0) + return result; + + if((result=MCToolsInitPageCache(port, slot))<0){ + return -EEXTCACHEINITERR; + } + for(; NumFiles>0; FileIndex+=result,NumFiles-=result){ if((result=MCToolsCreateCrossLinkedFiles(port, slot, path, &FileAlias[FileIndex], NumFiles))<=0){ result=-EIO; @@ -2243,10 +2371,20 @@ int CreateCrossLinkedFiles(int port, int slot){ } } + if(result>=0) + result=MCToolsFlushPageCache(); //This must be strictly done immediately after crosslinking operation. + + //Reboot the IOP to allow the remainder of the program to continue. + InitSemaID = IopInitStart(IOP_MOD_SET_MAIN|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + return result; } -int GenerateUninstallFile(int port, int slot){ +static int GenerateUninstallFile(int port, int slot){ unsigned char i, TotalNumEnts; int result; FILE *file; @@ -2368,18 +2506,31 @@ int PerformMemoryCardDump(int port, int slot) char filename[]="mc0.bin"; u32 CurrentCPUTicks, PreviousCPUTicks, PadStatus; unsigned char seconds, ClusterSize; - int result, WorkerThreadState; + int result, WorkerThreadState, InitSemaID; FILE *file; unsigned int ClusterSizeBytes, TimeElasped, rate, TotalSizeToTransferKB; float PercentageComplete; struct MCTools_McSpecData McSpecData; + //Reboot the IOP to load MCTOOLS.IRX in. This will also prevent MCMAN's cache from storing outdated content. + InitSemaID = IopInitStart(IOP_MOD_MCTOOLS|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + + //Call sceMcGetInfo on the memory card to be accessed, after IOP reboots. Otherwise I/O operations may fail. + if((result = InitMCInfo(port, slot)) != 0) + return result; + if((result=MCToolsGetMCInfo(port, slot, &McSpecData))<0) { DEBUG_PRINTF("MCToolsGetMCInfo() failed with error %d\n", result); return result; } + WaitSema(InstallLockSema); + MCToolsFlushMCMANClusterCache(port, slot); ClusterSize=(McSpecData.CardSize%32!=0)?2:32; //Sony wants to assume that the cluster size is 2, but try 32 to speed things up. @@ -2391,6 +2542,10 @@ int PerformMemoryCardDump(int port, int slot) DEBUG_PRINTF("Error creating file %s\n", filename); result = -errno; } else { + InitProgressScreen(SYS_UI_LBL_DUMPING_MC); + //Draw the progress screen once, so that loading the font will not compete with the actual dumping operation. + DrawMemoryCardDumpingProgressScreen(0, 0, 0); + TimeElasped=0; PreviousCPUTicks=cpu_ticks(); TotalSizeToTransferKB=McSpecData.CardSize*McSpecData.PageSize/1024; @@ -2402,8 +2557,6 @@ int PerformMemoryCardDump(int port, int slot) WorkerThreadParam.McSpecData=&McSpecData; SendWorkerThreadCommand(WORKER_THREAD_CMD_DUMP_MC, &WorkerThreadParam); - InitProgressScreen(SYS_UI_LBL_DUMPING_MC); - do{ WorkerThreadState=GetWorkerThreadState(); PercentageComplete=GetWorkerThreadProgress(); @@ -2425,7 +2578,7 @@ int PerformMemoryCardDump(int port, int slot) } rate=(TimeElasped>0)?PercentageComplete*TotalSizeToTransferKB/TimeElasped:0; - DrawMemoryCardDumpingProgressScreen(PercentageComplete, rate, rate>0?((1.0f-PercentageComplete)*TotalSizeToTransferKB)/rate:UINT_MAX); + DrawMemoryCardDumpingProgressScreen(PercentageComplete, rate, rate>0?((1.0f-PercentageComplete)*TotalSizeToTransferKB)/rate:UINT_MAX); }while(WorkerThreadState==WORKER_THREAD_RES_CMD_OK || WorkerThreadState==WORKER_THREAD_RES_BSY); result=(WorkerThreadState==WORKER_THREAD_RES_OK)?0:WorkerThreadState; @@ -2433,6 +2586,15 @@ int PerformMemoryCardDump(int port, int slot) fclose(file); } + SignalSema(InstallLockSema); + + //Reboot the IOP to allow the remainder of the program to continue. + InitSemaID = IopInitStart(IOP_MOD_SET_MAIN|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + return result; } @@ -2447,8 +2609,19 @@ int PerformMemoryCardRestore(int port, int slot) u32 CurrentCPUTicks, PreviousCPUTicks, PadStatus; float PercentageComplete; struct MCTools_McSpecData McSpecData; + int InitSemaID; result=0; + //Reboot the IOP to load MCTOOLS.IRX in. This will also prevent MCMAN's cache from storing outdated content. + InitSemaID = IopInitStart(IOP_MOD_MCTOOLS|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + + //Call sceMcGetInfo on the memory card to be accessed, after IOP reboots. Otherwise I/O operations may fail. + if((result = InitMCInfo(port, slot)) != 0) + return result; if((result=MCToolsGetMCInfo(port, slot, &McSpecData))<0){ DEBUG_PRINTF("MCToolsGetMCInfo() failed with error %d\n", result); @@ -2457,12 +2630,18 @@ int PerformMemoryCardRestore(int port, int slot) MCToolsFlushMCMANClusterCache(port, slot); + WaitSema(InstallLockSema); + filename[2] = '0' + port; if((file = fopen(filename, "rb")) == NULL) { DEBUG_PRINTF("Error opening file %s\n", filename); result = -errno; } else { + InitProgressScreen(SYS_UI_LBL_RESTORING_MC); + //Draw the progress screen once, so that loading the font will not compete with the actual restore operation. + DrawMemoryCardRestoreProgressScreen(0, 0, 0); + TimeElasped=0; PreviousCPUTicks=cpu_ticks(); TotalSizeToTransferKB=McSpecData.CardSize*McSpecData.PageSize/1024; @@ -2473,8 +2652,6 @@ int PerformMemoryCardRestore(int port, int slot) WorkerThreadParam.McSpecData=&McSpecData; SendWorkerThreadCommand(WORKER_THREAD_CMD_RESTORE_MC, &WorkerThreadParam); - InitProgressScreen(SYS_UI_LBL_RESTORING_MC); - do{ WorkerThreadState=GetWorkerThreadState(); PercentageComplete=GetWorkerThreadProgress(); @@ -2504,6 +2681,15 @@ int PerformMemoryCardRestore(int port, int slot) fclose(file); } + SignalSema(InstallLockSema); + + //Reboot the IOP to allow the remainder of the program to continue. + InitSemaID = IopInitStart(IOP_MOD_SET_MAIN|IOP_REBOOT); + WaitSema(InitSemaID); + DeleteSema(InitSemaID); + + ReinitializeUI(); + return result; } @@ -2996,3 +3182,35 @@ int HDDCheckHasSpace(unsigned int PartSize) //Partition size in MBytes return result; } + +int HDDCheckStatus(void) +{ + int status; + + status = fileXioDevctl("hdd0:", HDIOC_STATUS, NULL, 0, NULL, 0); + + if(status == 0) + fileXioRemove("hdd0:_tmp"); //Remove _tmp, if it exists. + + return status; +} + +void poweroffCallback(void *arg) +{ //Power button was pressed. If no installation is in progress, begin shutdown of the PS2. + if (PollSema(InstallLockSema) == InstallLockSema) + { + //If dev9.irx was loaded successfully, shut down DEV9. + if(dev9Loaded) + { + fileXioDevctl("pfs:", PDIOC_CLOSEALL, NULL, 0, NULL, 0); + while(fileXioDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0) < 0){}; + } + + // As required by some (typically 2.5") HDDs, issue the SCSI STOP UNIT command to avoid causing an emergency park. + fileXioDevctl("mass:", USBMASS_DEVCTL_STOP_ALL, NULL, 0, NULL, 0); + + /* Power-off the PlayStation 2 console. */ + poweroffShutdown(); + } +} + diff --git a/system.h b/system.h old mode 100755 new mode 100644 index 3776780..3130dc9 --- a/system.h +++ b/system.h @@ -92,7 +92,7 @@ struct WorkerThreadMcMaintParams{ //MC Maintanence parameters. For MC dumping an }; /* Function prototypes */ -int GetBootDeviceID(const char *path); +int GetBootDeviceID(void); int GetConsoleRegion(void); int GetConsoleVMode(void); int CleanupTarget(int port, int slot); @@ -104,11 +104,9 @@ int GetPs2Type(void); int HasOldFMCBConfigFileOnHDD(void); int HasOldFMCBConfigFile(int port, int slot); int HasOldMultiInstall(int port, int slot); -int CreateCrossLinkedFiles(int port, int slot); int CleanupMultiInstallation(int port, int slot); int PerformMemoryCardDump(int port, int slot); int PerformMemoryCardRestore(int port, int slot); -int GenerateUninstallFile(int port, int slot); int CheckPrerequisites(const struct McData *McData, unsigned char OperationMode); int GetNumMemcardsInserted(struct McData *McData); @@ -132,4 +130,7 @@ int HDDCheckSMARTStatus(void); int HDDCheckSectorErrorStatus(void); int HDDCheckPartErrorStatus(void); int HDDCheckHasSpace(unsigned int PartSize); +int HDDCheckStatus(void); + +void poweroffCallback(void *arg); From 07c571d46408fb4395d38acdb189ca748e8a2ffc Mon Sep 17 00:00:00 2001 From: Pellegrino Prevete Date: Mon, 1 Nov 2021 08:44:53 +0100 Subject: [PATCH 2/2] Update to 0.987 --- iop.c | 188 +++++ iop.h | 11 + irx/compiled/IOPRP.img | Bin 0 -> 15741 bytes irx/compiled/secrman.irx | Bin 0 -> 15533 bytes irx/source/Rules.bin.make | 17 + irx/source/Rules.make | 99 +++ irx/source/mctools/src/MCIO.c | 96 +++ irx/source/mctools/src/MCIO.h | 5 + irx/source/mctools/src/cache.c | 218 ++++++ irx/source/mctools/src/cache.h | 21 + irx/source/mctools/src/imports.lst | 71 ++ irx/source/mctools/src/irx_imports.h | 26 + irx/source/mctools/src/mctools.c | 866 ++++++++++++++++++++++ irx/source/mctools/src/mctools.h | 107 +++ irx/source/mctools/src/mctools_internal.h | 10 + resources/buttons.png | Bin 0 -> 6221 bytes 16 files changed, 1735 insertions(+) create mode 100644 iop.c create mode 100644 iop.h create mode 100644 irx/compiled/IOPRP.img create mode 100755 irx/compiled/secrman.irx create mode 100644 irx/source/Rules.bin.make create mode 100644 irx/source/Rules.make create mode 100644 irx/source/mctools/src/MCIO.c create mode 100644 irx/source/mctools/src/MCIO.h create mode 100644 irx/source/mctools/src/cache.c create mode 100644 irx/source/mctools/src/cache.h create mode 100644 irx/source/mctools/src/imports.lst create mode 100644 irx/source/mctools/src/irx_imports.h create mode 100644 irx/source/mctools/src/mctools.c create mode 100644 irx/source/mctools/src/mctools.h create mode 100644 irx/source/mctools/src/mctools_internal.h create mode 100644 resources/buttons.png diff --git a/iop.c b/iop.c new file mode 100644 index 0000000..2b1c94e --- /dev/null +++ b/iop.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "iop.h" +#include "system.h" + +extern unsigned char IOMANX_irx[]; +extern unsigned int size_IOMANX_irx; + +extern unsigned char FILEXIO_irx[]; +extern unsigned int size_FILEXIO_irx; + +extern unsigned char SIO2MAN_irx[]; +extern unsigned int size_SIO2MAN_irx; + +extern unsigned char PADMAN_irx[]; +extern unsigned int size_PADMAN_irx; + +extern unsigned char MCMAN_irx[]; +extern unsigned int size_MCMAN_irx; + +extern unsigned char MCSERV_irx[]; +extern unsigned int size_MCSERV_irx; + +extern unsigned char SECRSIF_irx[]; +extern unsigned int size_SECRSIF_irx; + +extern unsigned char MCTOOLS_irx[]; +extern unsigned int size_MCTOOLS_irx; + +extern unsigned char USBD_irx[]; +extern unsigned int size_USBD_irx; + +extern unsigned char USBHDFSD_irx[]; +extern unsigned int size_USBHDFSD_irx; + +extern unsigned char POWEROFF_irx[]; +extern unsigned int size_POWEROFF_irx; + +extern unsigned char DEV9_irx[]; +extern unsigned int size_DEV9_irx; + +extern unsigned char ATAD_irx[]; +extern unsigned int size_ATAD_irx; + +extern unsigned char HDD_irx[]; +extern unsigned int size_HDD_irx; + +extern unsigned char PFS_irx[]; +extern unsigned int size_PFS_irx; + +extern unsigned char IOPRP_img[]; +extern unsigned int size_IOPRP_img; + +u8 dev9Loaded; + +#define SYSTEM_INIT_THREAD_STACK_SIZE 0x1000 + +struct SystemInitParams{ + int InitCompleteSema; + unsigned int flags; +}; + +static void SystemInitThread(struct SystemInitParams *SystemInitParams) +{ + static const char PFS_args[]="-n\0""24\0""-o\0""8"; + int i; + + if(SystemInitParams->flags & IOP_MOD_HDD) + { + if(SifExecModuleBuffer(ATAD_irx, size_ATAD_irx, 0, NULL, NULL) >= 0) + { + SifExecModuleBuffer(HDD_irx, size_HDD_irx, 0, NULL, NULL); + SifExecModuleBuffer(PFS_irx, size_PFS_irx, sizeof(PFS_args), PFS_args, NULL); + } + } + + if(SystemInitParams->flags & IOP_MOD_SECRSIF) + { + SifExecModuleBuffer(SECRSIF_irx, size_SECRSIF_irx, 0, NULL, NULL); + SecrInit(); + } + + if(SystemInitParams->flags & IOP_MOD_MCTOOLS) + { + SifExecModuleBuffer(MCTOOLS_irx, size_MCTOOLS_irx, 0, NULL, NULL); + InitMCTOOLS(); + } + + SifExitIopHeap(); + SifLoadFileExit(); + + SignalSema(SystemInitParams->InitCompleteSema); + ExitDeleteThread(); +} + +int IopInitStart(unsigned int flags) +{ + ee_sema_t sema; + static struct SystemInitParams InitThreadParams; + static unsigned char SysInitThreadStack[SYSTEM_INIT_THREAD_STACK_SIZE] __attribute__((aligned(16))); + int stat, ret; + + if(!(flags & IOP_REBOOT)) + { + SifInitRpc(0); + } else { + PadDeinitPads(); + sceCdInit(SCECdEXIT); + DeinitMCTOOLS(); + SecrDeinit(); + fileXioExit(); + } + + if(!(flags & IOP_LIBSECR_IMG)) + { + SifIopReset("", 0); + } else { + SifIopRebootBuffer(IOPRP_img, size_IOPRP_img); + } + + //Do something useful while the IOP resets. + sema.init_count=0; + sema.max_count=1; + sema.attr=sema.option=0; + InitThreadParams.InitCompleteSema=CreateSema(&sema); + InitThreadParams.flags = flags; + + while(!SifIopSync()){}; + + SifInitRpc(0); + SifInitIopHeap(); + SifLoadFileInit(); + + sbv_patch_enable_lmb(); + + SifExecModuleBuffer(IOMANX_irx, size_IOMANX_irx, 0, NULL, NULL); + SifExecModuleBuffer(FILEXIO_irx, size_FILEXIO_irx, 0, NULL, NULL); + + fileXioInit(); + sceCdInit(SCECdINoD); + + SifExecModuleBuffer(POWEROFF_irx, size_POWEROFF_irx, 0, NULL, NULL); + ret = SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, &stat); + dev9Loaded = (ret >= 0 && stat == 0); //dev9.irx must have loaded successfully and returned RESIDENT END. + + SifExecModuleBuffer(SIO2MAN_irx, size_SIO2MAN_irx, 0, NULL, NULL); + SifExecModuleBuffer(PADMAN_irx, size_PADMAN_irx, 0, NULL, NULL); + SifExecModuleBuffer(MCMAN_irx, size_MCMAN_irx, 0, NULL, NULL); + SifExecModuleBuffer(MCSERV_irx, size_MCSERV_irx, 0, NULL, NULL); + + SifExecModuleBuffer(USBD_irx, size_USBD_irx, 0, NULL, NULL); + SifExecModuleBuffer(USBHDFSD_irx, size_USBHDFSD_irx, 0, NULL, NULL); + + SysCreateThread(SystemInitThread, SysInitThreadStack, SYSTEM_INIT_THREAD_STACK_SIZE, &InitThreadParams, 0x2); + + poweroffInit(); + poweroffSetCallback(&poweroffCallback, NULL); + mcInit(MC_TYPE_XMC); + PadInitPads(); + + return InitThreadParams.InitCompleteSema; +} + +void IopDeinit(void) +{ + PadDeinitPads(); + sceCdInit(SCECdEXIT); + DeinitMCTOOLS(); + SecrDeinit(); + + fileXioExit(); + SifExitRpc(); +} + diff --git a/iop.h b/iop.h new file mode 100644 index 0000000..44c1ddb --- /dev/null +++ b/iop.h @@ -0,0 +1,11 @@ +#define IOP_MOD_HDD 0x01 +#define IOP_MOD_SECRSIF 0x02 +#define IOP_MOD_MCTOOLS 0x04 +#define IOP_LIBSECR_IMG 0x40 +#define IOP_REBOOT 0x80 + +#define IOP_MOD_SET_MAIN (IOP_MOD_HDD|IOP_MOD_SECRSIF|IOP_LIBSECR_IMG) //Main module set + +int IopInitStart(unsigned int flags); +void IopDeinit(void); + diff --git a/irx/compiled/IOPRP.img b/irx/compiled/IOPRP.img new file mode 100644 index 0000000000000000000000000000000000000000..e51890d3b8c53a4b51f8378098611d96e73aabe6 GIT binary patch literal 15741 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 G7WqGG#kGV0 literal 0 HcmV?d00001 diff --git a/irx/compiled/secrman.irx b/irx/compiled/secrman.irx new file mode 100755 index 0000000000000000000000000000000000000000..c4c84ec342b9186b19a91fa80bedf92ac23cd704 GIT binary patch literal 15533 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 OwjPdM^~2q=$o~Q=vWk}g literal 0 HcmV?d00001 diff --git a/irx/source/Rules.bin.make b/irx/source/Rules.bin.make new file mode 100644 index 0000000..596ec24 --- /dev/null +++ b/irx/source/Rules.bin.make @@ -0,0 +1,17 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN_DIR ?= irx/ + +IOP_BIN ?= $(shell basename $(CURDIR)).irx +IOP_BIN := $(IOP_BIN:%=$(IOP_BIN_DIR)%) + +all:: $(IOP_BIN) + +clean:: + rm -f -r $(IOP_OBJS_DIR) $(IOP_BIN_DIR) diff --git a/irx/source/Rules.make b/irx/source/Rules.make new file mode 100644 index 0000000..1acddee --- /dev/null +++ b/irx/source/Rules.make @@ -0,0 +1,99 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_CC_VERSION := $(shell $(IOP_CC) --version 2>&1 | sed -n 's/^.*(GCC) //p') + +IOP_OBJS_DIR ?= obj/ +IOP_SRC_DIR ?= src/ +IOP_INC_DIR ?= include/ + +ifeq ($(IOP_CC_VERSION),3.2.2) +ASFLAGS_TARGET = -march=r3000 +endif + +ifeq ($(IOP_CC_VERSION),3.2.3) +ASFLAGS_TARGET = -march=r3000 +endif + +# include dir +IOP_INCS := $(IOP_INCS) -I$(IOP_SRC_DIR) -I$(IOP_SRC_DIR)include -I$(IOP_INC_DIR) -I$(PS2SDK)/iop/include -I$(PS2SDK)/common/include + +# C compiler flags +# -fno-builtin is required to prevent the GCC built-in functions from being included, +# for finer-grained control over what goes into each IRX. +IOP_CFLAGS := -D_IOP -fno-builtin -O2 -G0 -Wall $(IOP_INCS) $(IOP_CFLAGS) +# Linker flags +IOP_LDFLAGS := -nostdlib -s $(IOP_LDFLAGS) + +# Additional C compiler flags for GCC >=v5.3.0 +# -msoft-float is to "remind" GCC/Binutils that the soft-float ABI is to be used. This is due to a bug, which +# results in the ABI not being passed correctly to binutils and iop-as defaults to the hard-float ABI instead. +# -mno-explicit-relocs is required to work around the fact that GCC is now known to +# output multiple LO relocs after one HI reloc (which the IOP kernel cannot deal with). +# -fno-toplevel-reorder (for IOP import and export tables only) disables toplevel reordering by GCC v4.2 and later. +# Without it, the import and export tables can be broken apart by GCC's optimizations. +ifneq ($(IOP_CC_VERSION),3.2.2) +ifneq ($(IOP_CC_VERSION),3.2.3) +IOP_CFLAGS += -msoft-float -mno-explicit-relocs +IOP_IETABLE_CFLAGS := -fno-toplevel-reorder +endif +endif + +# Assembler flags +IOP_ASFLAGS := $(ASFLAGS_TARGET) -EL -G0 $(IOP_ASFLAGS) + +IOP_OBJS := $(IOP_OBJS:%=$(IOP_OBJS_DIR)%) + +# Externally defined variables: IOP_BIN, IOP_OBJS, IOP_LIB + +# These macros can be used to simplify certain build rules. +IOP_C_COMPILE = $(IOP_CC) $(IOP_CFLAGS) + +$(IOP_OBJS_DIR)%.o: $(IOP_SRC_DIR)%.c + $(IOP_C_COMPILE) -c $< -o $@ + +$(IOP_OBJS_DIR)%.o: $(IOP_SRC_DIR)%.S + $(IOP_C_COMPILE) -c $< -o $@ + +$(IOP_OBJS_DIR)%.o: $(IOP_SRC_DIR)%.s + $(IOP_AS) $(IOP_ASFLAGS) $< -o $@ + +.INTERMEDIATE: $(IOP_OBJS_DIR)build-imports.c $(IOP_OBJS_DIR)build-exports.c + +# Rules to build imports.lst. +$(IOP_OBJS_DIR)build-imports.c: $(IOP_SRC_DIR)imports.lst + $(ECHO) "#include \"irx_imports.h\"" > $@ + cat $< >> $@ + +$(IOP_OBJS_DIR)imports.o: $(IOP_OBJS_DIR)build-imports.c + $(IOP_C_COMPILE) $(IOP_IETABLE_CFLAGS) -c $< -o $@ + +# Rules to build exports.tab. +$(IOP_OBJS_DIR)build-exports.c: $(IOP_SRC_DIR)exports.tab + $(ECHO) "#include \"irx.h\"" > $@ + cat $< >> $@ + +$(IOP_OBJS_DIR)exports.o: $(IOP_OBJS_DIR)build-exports.c + $(IOP_C_COMPILE) $(IOP_IETABLE_CFLAGS) -c $< -o $@ + +$(IOP_OBJS_DIR): + $(MKDIR) -p $(IOP_OBJS_DIR) + +$(IOP_BIN_DIR): + $(MKDIR) -p $(IOP_BIN_DIR) + +$(IOP_LIB_DIR): + $(MKDIR) -p $(IOP_LIB_DIR) + +$(IOP_OBJS): | $(IOP_OBJS_DIR) + +$(IOP_BIN): $(IOP_OBJS) | $(IOP_BIN_DIR) + $(IOP_C_COMPILE) -o $(IOP_BIN) $(IOP_OBJS) $(IOP_LDFLAGS) $(IOP_LIBS) + +$(IOP_LIB): $(IOP_OBJS) | $(IOP_LIB_DIR) + $(IOP_AR) cru $(IOP_LIB) $(IOP_OBJS) diff --git a/irx/source/mctools/src/MCIO.c b/irx/source/mctools/src/MCIO.c new file mode 100644 index 0000000..d8f5b3f --- /dev/null +++ b/irx/source/mctools/src/MCIO.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#include "mctools_internal.h" +#include "mctools.h" +#include "cache.h" +#include "MCIO.h" + +int ReadBlock(int port, int slot, unsigned short int PageSize, unsigned short int BlockSize, unsigned int block, void *buffer){ + unsigned int i; + int result; + + result=sceMcResSucceed; + for(i=0; i=0){ + for(i=0; i +#include +#include +#include + +#include "mctools_internal.h" +#include "mctools.h" +#include "cache.h" +#include "MCIO.h" + +static struct PageCache PageCache[PAGE_CACHE_SIZE]; +static int CacheInitialized=0; +static unsigned short int CachePageLen=512, CacheBlockSize=2; +static unsigned int CacheCardSizeBlocks; +static int CacheMcPort, CacheMcSlot; + +static void DeinitPageCache(void){ + unsigned int i; + + if(CacheInitialized){ + /* Free the memory allocated for the cache. */ + for(i=0; i=0) CacheInitialized=1; + else DeinitPageCache(); + + return result; +} + +static void AddCacheBlockFlushList(struct CachePageFlushList *FlushList, unsigned int BlockPageOffset, void *buffer){ + unsigned int i; + + for(i=0; ; i++){ + if(FlushList[i].BlockPageOffset==(-1)){ + FlushList[i].BlockPageOffset=BlockPageOffset; + FlushList[i].buffer=buffer; + break; + } + } +} + +static int FlushBlock(unsigned port, unsigned char slot, unsigned char *BlockBuffer, unsigned int BlockNum, struct CachePageFlushList *FlushList, unsigned int NumPagesToFlush){ + unsigned int i; + int result; + + result=NumPagesToFlush; + if(NumPagesToFlush>0){ + DEBUG_PRINTF("Flushing block 0x%08x\n", BlockNum); + + if((result=ReadBlock(port, slot, CachePageLen, CacheBlockSize, BlockNum, BlockBuffer))>=0){ + for(i=0; i=0) result=WriteBlock(port, slot, CachePageLen, CacheBlockSize, BlockNum, BlockBuffer); + } + } + + return result; +} + +int FlushPageCache(void){ + unsigned char *BlockBuffer; + int result; + struct CachePageFlushList *FlushList; + unsigned int i, BlockNum, NumPagesToFlush; + + DEBUG_PRINTF("Flushing cache...\n"); + + result=0; + if(CacheInitialized){ + if((FlushList=malloc(sizeof(struct CachePageFlushList)*CacheBlockSize))==NULL) return -ENOMEM; + if((BlockBuffer=malloc(CachePageLen*CacheBlockSize))==NULL){ + free(FlushList); + return -ENOMEM; + } + + for(BlockNum=0; BlockNum=0) goto RetryPageRead; + } + } + } + else{ + result=McReadPage(CacheMcPort, CacheMcSlot, PageNum, buffer); + } + + return result; +} + +int WritePageCached(unsigned int PageNum, void *buffer){ + int result; + unsigned int i; + + DEBUG_PRINTF("Write page 0x%08x\n", PageNum); + + result=0; + if(CacheInitialized){ + for(i=0; i=0) goto RetryPageWrite; + } + } + } + else{ + result=-EINVAL; + } + + return result; +} diff --git a/irx/source/mctools/src/cache.h b/irx/source/mctools/src/cache.h new file mode 100644 index 0000000..b96a787 --- /dev/null +++ b/irx/source/mctools/src/cache.h @@ -0,0 +1,21 @@ +#define PAGE_CACHE_SIZE 128 /* Cache 256 pages (256*512=128KB) */ + +#define PAGE_CACHE_PAGE_EXISTS 0x01 +#define PAGE_CACHE_PAGE_IS_DIRTY 0x02 + +struct PageCache{ + unsigned int PageNum; + void *buffer; + unsigned int flags; +}; + +struct CachePageFlushList{ + int BlockPageOffset; + void *buffer; +}; + +int InitPageCache(int port, int slot); +int FlushPageCache(void); +int ReadPageCached(unsigned int PageNum, void *buffer); +int WritePageCached(unsigned int PageNum, void *buffer); + diff --git a/irx/source/mctools/src/imports.lst b/irx/source/mctools/src/imports.lst new file mode 100644 index 0000000..76b54fa --- /dev/null +++ b/irx/source/mctools/src/imports.lst @@ -0,0 +1,71 @@ +//--------------------------------------------------------------------------- +// File name: imports.lst +// Description: Used to generate code for IRX function imports +//--------------------------------------------------------------------------- + +intrman_IMPORTS_start +I_CpuSuspendIntr +I_CpuResumeIntr +intrman_IMPORTS_end + +xmcman_IMPORTS_start +I_McReadPage +I_McWritePage +I_McEraseBlock2 +I_McDataChecksum +I_McGetCardSpec +I_McCloseAll +I_McFlushCache +xmcman_IMPORTS_end + +sifcmd_IMPORTS_start +I_sceSifRegisterRpc +I_sceSifSetRpcQueue +I_sceSifRpcLoop +I_sceSifRemoveRpc +I_sceSifRemoveRpcQueue +sifcmd_IMPORTS_end + +sifman_IMPORTS_start +I_sceSifCheckInit +I_sceSifInit +I_sceSifInitRpc +I_sceSifSetDma +I_sceSifDmaStat +sifman_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +sysclib_IMPORTS_start +I_strtok +I_strcpy +I_strchr +I_strlen +I_strncmp +I_strncpy +I_memcpy +I_sprintf +I_memset +sysclib_IMPORTS_end + +sysmem_IMPORTS_start +I_AllocSysMemory +I_FreeSysMemory +sysmem_IMPORTS_end + +thbase_IMPORTS_start +I_CreateThread +I_StartThread +I_GetThreadId +I_ExitDeleteThread +I_ChangeThreadPriority +I_DelayThread +I_DeleteThread +I_TerminateThread +thbase_IMPORTS_end + +//--------------------------------------------------------------------------- +// End of file: imports.lst +//--------------------------------------------------------------------------- diff --git a/irx/source/mctools/src/irx_imports.h b/irx/source/mctools/src/irx_imports.h new file mode 100644 index 0000000..3276835 --- /dev/null +++ b/irx/source/mctools/src/irx_imports.h @@ -0,0 +1,26 @@ +/* + * irx_imports.h - Defines all IRX imports. + * + * NB: inapplicable old copyright claim to this material removed, as that + * NB: claim would only relate to the old material created by that author + */ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ +#include +#include +#include "mcman.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/irx/source/mctools/src/mctools.c b/irx/source/mctools/src/mctools.c new file mode 100644 index 0000000..dff5e7e --- /dev/null +++ b/irx/source/mctools/src/mctools.c @@ -0,0 +1,866 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mctools_internal.h" +#include "mctools.h" +#include "cache.h" +#include "MCIO.h" + +#define MODNAME "mctools_ee_driver" +IRX_ID(MODNAME, 0x01, 0x21); + +/* Data used for registering the RPC servers */ +static SifRpcServerData_t rpc_sdata; +static unsigned char rpc_buffer[1024]; +static unsigned char rpc_TX_buffer[16]; +static SifRpcDataQueue_t rpc_qdata; + +static struct MCTools_AlignmentData *EEAlignmentDataStructure; + +/* Function prototypes */ +static void mctools_RPC_srv(void *args); +static void *mctools_rpc_handler(int fno, void *buf, int size); + +/* Common thread creation data */ +static iop_thread_t thread_data={ + TH_C, /* rpc_thp.attr */ + 0, /* rpc_thp.option */ + &mctools_RPC_srv, /* rpc_thp.thread */ + 0x1000, /* rpc_thp.stacksize */ + 0x66, /* rpc_thp.piority */ +}; + +/* Entry point */ +int _start(int argc,char *argv[]) +{ + printf("MCTOOLs start.\n"); + + StartThread(CreateThread(&thread_data), NULL); + + return MODULE_RESIDENT_END; +} + +void *malloc(unsigned int size){ + int oldstate; + void *result; + + CpuSuspendIntr(&oldstate); + result=AllocSysMemory(ALLOC_FIRST, size, NULL); + CpuResumeIntr(oldstate); + + return result; +} + +void free(void *ptr){ + int oldstate; + + CpuSuspendIntr(&oldstate); + FreeSysMemory(ptr); + CpuResumeIntr(oldstate); +} + +static inline void DMATransferDataToEE(void *src, void *dest, int size, struct MCTools_AlignmentData *AlignmentData){ + SifDmaTransfer_t dmat[2]; + int DMATransferID, oldstate; + + dmat[0].src=src; + dmat[0].dest=dest; + dmat[0].size=size; + dmat[1].attr=dmat[0].attr=0; + + dmat[1].src=AlignmentData; + dmat[1].dest=EEAlignmentDataStructure; + dmat[1].size=sizeof(struct MCTools_AlignmentData); + + CpuSuspendIntr(&oldstate); + while((DMATransferID=sceSifSetDma(dmat, 2))==0); + while(sceSifDmaStat(DMATransferID)>=0){}; + CpuResumeIntr(oldstate); +} + +static void EE_memcpy(void *src, void *dest, int size){ + void *FinalDestPtr; + int DMATransferLen; + unsigned char AlignmentBufferLen; + struct MCTools_AlignmentData AlignmentData; + + FinalDestPtr=dest; + DMATransferLen=size; + + memset(&AlignmentData, 0, sizeof(struct MCTools_AlignmentData)); + + if((u32)dest&0x3F){ + FinalDestPtr=(void *)(((u32)dest+0x3F)&~0x3F); + AlignmentBufferLen=(u32)FinalDestPtr-(u32)dest; + memcpy(AlignmentData.buffer1, src, AlignmentBufferLen); + AlignmentData.buffer1_len=AlignmentBufferLen; + AlignmentData.buffer1Address=dest; + DMATransferLen-=AlignmentBufferLen; + } + + if(DMATransferLen&0x3F){ + AlignmentBufferLen=DMATransferLen&0x3F; + memcpy(AlignmentData.buffer2, &((unsigned char *)src)[size-AlignmentBufferLen], AlignmentBufferLen); + AlignmentData.buffer2_len=AlignmentBufferLen; + AlignmentData.buffer2Address=&((unsigned char *)dest)[size-AlignmentBufferLen]; + DMATransferLen-=AlignmentBufferLen; + } + + DMATransferDataToEE((unsigned char *)src+AlignmentData.buffer1_len, FinalDestPtr, DMATransferLen, &AlignmentData); +} + +static void mctools_RPC_srv(void *args){ + sceSifSetRpcQueue(&rpc_qdata, GetThreadId()); + + sceSifRegisterRpc(&rpc_sdata, MCTOOLS_RPC_NUM, &mctools_rpc_handler, rpc_buffer, NULL, NULL, &rpc_qdata); + sceSifRpcLoop(&rpc_qdata); +} + +static int FlushMCMANClusterCache(int port, int slot){ + //While file should not be opened while MCTOOLs is running (MCMAN's cache cannot be invalidated, by design), these steps are safeguards. + McCloseAll(); + McFlushCache(port, slot); + + return 0; +} + +static int UpdateFatTableIndexData(unsigned char port, unsigned char slot, unsigned int index, unsigned int data, struct SCE_MC_Superblock *SuperBlock){ + unsigned int NumEntriesPerFatCluster, *IndirectFatIndexTable, *FatTable; + unsigned int IndirectFATIndex, IndirectFATIndexOffset, IndirectFATDoubleIndex; + int result; + + if(index>=SuperBlock->clusters){ + return -EINVAL; + } + + /* Unlike FAT12/16/32, the FAT table is not contiguous. ifc_list contains the indexes of the FAT clusters, + hence double-indexing is required for accessing the clusters within the FAT. */ + + result=-1; + NumEntriesPerFatCluster=SuperBlock->pages_per_cluster*SuperBlock->page_len/4; /* Calculate the number of FAT entries contained within each FAT cluster. */ + IndirectFATIndex = index / NumEntriesPerFatCluster; /* Calculate the index within the indirect FAT table, that the FAT record resides in. */ + IndirectFATIndexOffset = IndirectFATIndex % NumEntriesPerFatCluster; /* Calculate the offset of the indirect FAT index table to retrieve from (It contains the FAT cluster number). */ + IndirectFATDoubleIndex = IndirectFATIndex / NumEntriesPerFatCluster; /* Calculate the index of the entry to retrieve from the table containing the cluster numbers of the clusters that make up the indirect FAT index table. */ + + IndirectFatIndexTable=malloc(SuperBlock->pages_per_cluster*SuperBlock->page_len); + FatTable=malloc(SuperBlock->pages_per_cluster*SuperBlock->page_len); + + if(ReadCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, SuperBlock->ifc_list[IndirectFATDoubleIndex], IndirectFatIndexTable)>=0){ + /* Update the FAT. */ + if(ReadCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, IndirectFatIndexTable[IndirectFATIndexOffset], FatTable)>=0){ + FatTable[index % NumEntriesPerFatCluster]=data; + result=WriteCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, IndirectFatIndexTable[IndirectFATIndexOffset], FatTable); + } + else DEBUG_PRINTF("Read fault while reading FAT cluster 0x%08x\n", IndirectFatIndexTable[IndirectFATIndexOffset]); + } + else DEBUG_PRINTF("Read fault while reading the indirect FAT index table\n"); + + free(IndirectFatIndexTable); + free(FatTable); + + return result; +} + +/* Returns the specifications of the card (And it's filesystem) present in the specified port and slot. */ +static int GetCardFilesystemSuperblock(int port, int slot, struct SCE_MC_Superblock *SuperBlock){ + unsigned char *buffer; + int result; + + DEBUG_PRINTF("GetCardFilesystemSuperblock() - Port %d Slot %d\n", port, slot); + + result=-ENOMEM; + if((buffer=malloc(1024))!=NULL){ /* Note: The maximum page size should only be 1024 bytes. */ + if((result=McReadPage(port, slot, 0, buffer))==sceMcResSucceed){ + memcpy(SuperBlock, buffer, sizeof(struct SCE_MC_Superblock)); + } + + free(buffer); + } + + return(result); +} + +static int GetCardSpecs(int port, int slot, u16 *PageSize, u16 *BlockSize, int *CardSize){ + u8 flags; + int result; + + result=McGetCardSpec(port, slot, PageSize, BlockSize, CardSize, &flags); + DEBUG_PRINTF("GetCardSpecs: port: %d, slot: %d, PageSize: %u, BlockSize: %u, CardSize: %u\n", port, slot, *PageSize, *BlockSize, *CardSize); + + return result; +} + +static int GetFatTableIndexData(unsigned char port, unsigned char slot, unsigned int index, struct SCE_MC_Superblock *SuperBlock, unsigned int *NextClusterNum){ + unsigned int NumEntriesPerFatCluster, *IndirectFatIndexTable, *FatTable; + unsigned int IndirectFATIndex, IndirectFATIndexOffset, IndirectFATDoubleIndex; + int result; + + if(index>=SuperBlock->clusters){ + return -EINVAL; + } + + /* Unlike FAT12/16/32, the FAT table is not contiguous. ifc_list contains the indexes of the FAT clusters, + hence double-indexing is required for accessing the clusters within the FAT. */ + + result=-1; + NumEntriesPerFatCluster=SuperBlock->pages_per_cluster*SuperBlock->page_len/4; /* Calculate the number of FAT entries contained within each FAT cluster. */ + IndirectFATIndex = index / NumEntriesPerFatCluster; /* Calculate the index within the indirect FAT table, that the FAT record resides in. */ + IndirectFATIndexOffset = IndirectFATIndex % NumEntriesPerFatCluster; /* Calculate the offset of the indirect FAT index table to retrieve from (It contains the FAT cluster number). */ + IndirectFATDoubleIndex = IndirectFATIndex / NumEntriesPerFatCluster; /* Calculate the index of the entry to retrieve from the table containing the cluster numbers of the clusters that make up the indirect FAT index table. */ + + if((IndirectFatIndexTable=malloc(SuperBlock->pages_per_cluster*SuperBlock->page_len))!=NULL){ + if((FatTable=malloc(SuperBlock->pages_per_cluster*SuperBlock->page_len))!=NULL){ + + if((result=ReadCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, SuperBlock->ifc_list[IndirectFATDoubleIndex], IndirectFatIndexTable))>=0){ + if((result=ReadCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, IndirectFatIndexTable[IndirectFATIndexOffset], FatTable))>=0){ + *NextClusterNum=FatTable[index % NumEntriesPerFatCluster]; /* Retrieve the next index contained within the FAT. */ + result=0; + } + else DEBUG_PRINTF("Read fault while reading FAT cluster 0x%08x\n", IndirectFatIndexTable[IndirectFATIndexOffset]); + } + else DEBUG_PRINTF("Read fault while reading the indirect FAT index table\n"); + + free(FatTable); + } + else result=-ENOMEM; + + free(IndirectFatIndexTable); + } + else result=-ENOMEM; + + return result; +} + +static int GetFatTableNextIndexData(unsigned char port, unsigned char slot, unsigned int index, struct SCE_MC_Superblock *SuperBlock, unsigned int *NextClusterNum){ + int result; + + result=GetFatTableIndexData(port, slot, index, SuperBlock, NextClusterNum); + if((result>=0) && (*NextClusterNum!=0xFFFFFFFF)) *NextClusterNum&=0x7FFFFFFF; + + return(result); +} + +/* + * Adds a new cluster to an existing FAT record chain within the FAT. + * Returns the cluster number of the new allocated cluster. Returns 0 on error. + */ +static unsigned int AddFATRecord(unsigned char port, unsigned char slot, struct SCE_MC_Superblock *SuperBlock, unsigned int FATChainStartCluster){ + unsigned int NewRecClusterNum, ClusterNum, NextClusterNum; + int result; + + /* Attempt to allocate a new cluster */ + for(NewRecClusterNum=0, result=0; result>=0; NewRecClusterNum++){ + if((result=GetFatTableIndexData(port, slot, NewRecClusterNum, SuperBlock, &NextClusterNum))>=0){ + if(!(NextClusterNum&0x80000000)){ + DEBUG_PRINTF("Free cluster found\n"); + break; + } + } + else DEBUG_PRINTF("Error %d\n", result); + } + + DEBUG_PRINTF("Free cluster at 0x%08x result %d\n", NewRecClusterNum, result); + + /* If a free cluster was identified */ + if(result>=0){ + DEBUG_PRINTF("FATChainStartCluster=0x%08x\n", FATChainStartCluster); + + /* Update the FAT chain by going through it to the end. */ + NextClusterNum=FATChainStartCluster; + do{ + ClusterNum=NextClusterNum; + if((result=GetFatTableNextIndexData(port, slot, ClusterNum, SuperBlock, &NextClusterNum))<0) break; + }while(NextClusterNum!=0xFFFFFFFF); + + DEBUG_PRINTF("Begining write operations... ClusterNum=0x%08x\n", ClusterNum); + + if(result>=0){ + //Update the last cluster's record to point to the newly-allocated cluster. + if((result=UpdateFatTableIndexData(port, slot, ClusterNum, 0x80000000|NewRecClusterNum, SuperBlock))>=0){ + //The new cluster will be at the end of the chain. + if((result=UpdateFatTableIndexData(port, slot, NewRecClusterNum, 0xFFFFFFFF, SuperBlock))>=0){ + result=NewRecClusterNum; + } + } + } + } + + return result; +} + +#if 0 +/* + * Removes a cluster from an existing FAT record chain within the FAT. + * Returns the cluster number of the cluster deleted. Returns 0 on error. + */ +static unsigned int DeleteFATRecord(unsigned char port, unsigned char slot, struct SCE_MC_Superblock *SuperBlock, unsigned int FATChainStartCluster, unsigned int ClusterToDelete){ + unsigned int PrevRecClusterNum, RecClusterNum, NextRecClusterNum; + unsigned int result; + + PrevRecClusterNum=NextRecClusterNum=RecClusterNum=FATChainStartCluster; + result=0; + + while((RecClusterNum!=0xFFFFFFFF) && ((RecClusterNum&0x7FFFFFFF)!=ClusterToDelete)){ + PrevRecClusterNum=RecClusterNum; + RecClusterNum=NextRecClusterNum; + + if(GetFatTableIndexData(port, slot, RecClusterNum&0x7FFFFFFF, SuperBlock, &NextRecClusterNum)<0){ + DEBUG_PRINTF("Error in GetFatTableIndexData()\n"); + goto DeleteFATRecord_end; + } + } + + if((RecClusterNum&0x7FFFFFFF)==ClusterToDelete){ + DEBUG_PRINTF("PrevRecClusterNum=0x%08x\nRecClusterNum=0x%08x\nNextRecClusterNum=0x%08x\n\n", PrevRecClusterNum, RecClusterNum, NextRecClusterNum); + //Point the previous cluster's record to the one after it. + if(UpdateFatTableIndexData(port, slot, PrevRecClusterNum&0x7FFFFFFF, NextRecClusterNum, SuperBlock)>=0){ + //Update the deleted record's next cluster address to unallocated. + if(UpdateFatTableIndexData(port, slot, RecClusterNum&0x7FFFFFFF, NextRecClusterNum&0x7FFFFFFF, SuperBlock)>=0){ + result=ClusterToDelete; + } + } + } + +DeleteFATRecord_end: + DEBUG_PRINTF("Delete result=0x%08x\n", result); + + return result; +} + +static int FreeUnusedFATRecords(unsigned char port, unsigned char slot, u32 DirEntStartCluster, u32 *NumValidRecords, struct SCE_MC_Superblock *SuperBlock){ + int result; + unsigned int LogicalPageNum, ClusterNum, PageNum, PrevClusterNum, recordID, NumDirEntRecords; + unsigned char NumberOfUnusedPages, ClustersFreed, NumValidRecordsInCluster; + void *PageBuffer; + + DEBUG_PRINTF("Freeing unused clusters...\n"); + + if((PageBuffer=malloc(SuperBlock->page_len))==NULL){ + return -ENOMEM; + } + + result=0; + recordID=0; + ClustersFreed=0; + NumberOfUnusedPages=0; + ClusterNum=DirEntStartCluster; + PageNum=(SuperBlock->alloc_start+ClusterNum)*SuperBlock->pages_per_cluster; + LogicalPageNum=0; + NumDirEntRecords=*NumValidRecords; + + *NumValidRecords=0; + NumValidRecordsInCluster=0; + + //Go through the FAT chain of the directory + while((result>=0) && (ClusterNum!=0xFFFFFFFF)){ + if((recordID>0) && (LogicalPageNum==0)){ + PrevClusterNum=ClusterNum; + + /* Get the cluster number of the next cluster. Break out of the loop if the last cluster has been reached (In other words, the file was not found). */ + if(GetFatTableNextIndexData(port, slot, ClusterNum, SuperBlock, &ClusterNum)<0){ + break; + } + + PageNum=(SuperBlock->alloc_start+ClusterNum)*SuperBlock->pages_per_cluster; + + //Count the number of unused pages in the cluster. If the whole cluster is unused, it can be freed. + if(NumberOfUnusedPages==SuperBlock->pages_per_cluster){ + DEBUG_PRINTF("Attempting to delete cluster 0x%08x\n", PrevClusterNum); + if(DeleteFATRecord(port, slot, SuperBlock, DirEntStartCluster, PrevClusterNum)!=PrevClusterNum){ + DEBUG_PRINTF("Error detected in DeleteFATRecord()\n"); + result=-1; + break; + } + else{ + ClustersFreed++; + (*NumValidRecords)-=NumValidRecordsInCluster; + } + } + + NumberOfUnusedPages=0; + LogicalPageNum=0; + NumValidRecordsInCluster=0; + } + + //Only if the end of the chain has not been reached. + if(ClusterNum!=0xFFFFFFFF){ + /* The actions in here are only valid for valid records (For both erased and existent). + Note: There can be unused pages in the last cluster, but that page might not have a valid directory record. + Don't treat it like it has valid information because it might even contain random garbage. + */ + if(recordIDname, ((struct SCE_MC_dirent *)PageBuffer)->mode); + + /* Count the number of consecutive pages that are unused. */ + if(!(((struct SCE_MC_dirent *)PageBuffer)->mode & 0x8000)){ + NumberOfUnusedPages++; + } + else{ + NumberOfUnusedPages=0; + } + + NumValidRecordsInCluster++; + (*NumValidRecords)++; + } + else NumberOfUnusedPages++; /* Otherwise, remember to count the unused pages that are not part of this directory record list that exist in the last cluster! */ + + recordID++; + LogicalPageNum++; + if(LogicalPageNum>=SuperBlock->pages_per_cluster) LogicalPageNum=0; + } + } + + free(PageBuffer); + + return((result>=0)?ClustersFreed:result); +} +#endif + +static int UpdateDirEntInformation(unsigned char port, unsigned char slot, struct SCE_MC_Superblock *SuperBlock, unsigned int TargetCluster, unsigned int TargetOffsetWithinCluster, struct SCE_MC_dirent *DirEntData){ + unsigned int ClusterSize; + int result; + unsigned char *buffer; + + DEBUG_PRINTF("TargetCluster=0x%08x offset 0x%08x\n", TargetCluster, TargetOffsetWithinCluster); + + ClusterSize=SuperBlock->page_len*SuperBlock->pages_per_cluster; + + /* Now, read in, modify and write the required clusters back onto the Memory Card. */ + if((buffer=malloc(ClusterSize))!=NULL){ + if((result=ReadCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, TargetCluster, buffer))>=0){ + memcpy(&buffer[TargetOffsetWithinCluster], DirEntData, sizeof(struct SCE_MC_dirent)); + DEBUG_PRINTF("Name: %s size 0x%08x\n", ((struct SCE_MC_dirent *)&buffer[TargetOffsetWithinCluster])->name, ((struct SCE_MC_dirent *)&buffer[TargetOffsetWithinCluster])->length); + + result=WriteCluster(SuperBlock->page_len, SuperBlock->pages_per_cluster, TargetCluster, buffer); + } + + free(buffer); + } + else result=-ENOMEM; + + return result; +} + +static int ScanThroughDirEnt(unsigned char port, unsigned char slot, unsigned short int mode, unsigned int nRecords, unsigned int *PageNum, unsigned int *LogicalPageNum, const char *dirent_name, unsigned int *ClusterNum, struct SCE_MC_Superblock *SuperBlock, void *PageBuffer){ + unsigned int recordID; + int result; + + recordID=0; + result=0; + + DEBUG_PRINTF("ScanThroughDirEnt called.\n"); + + /* Search through the file records for the file, going through all leading directories first. */ + do{ + if(recordID>0){ + (*LogicalPageNum)++; + if(*LogicalPageNum>=SuperBlock->pages_per_cluster) *LogicalPageNum=0; + + if(*LogicalPageNum==0){ + /* Get the cluster number of the next cluster. Break out of the loop if the last cluster has been reached (In other words, the file was not found). */ + if(((result=GetFatTableNextIndexData(port, slot, *ClusterNum, SuperBlock, ClusterNum))<0) || (*ClusterNum==0xFFFFFFFF)){ + DEBUG_PRINTF("End of DirEnt reached.\n"); + result=-ENOENT; + break; + } + + *PageNum=(SuperBlock->alloc_start+*ClusterNum)*SuperBlock->pages_per_cluster; + } + } + + if((result=ReadPageCached(*PageNum+*LogicalPageNum, PageBuffer))<0){ + DEBUG_PRINTF("Read fault. Page: %d Code: %d\n", *PageNum+*LogicalPageNum, result); + break; + } + + if((nRecords<1) && (recordID==0)){ + nRecords=((struct SCE_MC_dirent *)PageBuffer)->length; + } + + if(recordID>=nRecords){ + if((mode!=1)||(recordID%SuperBlock->pages_per_cluster)==0){ + if(mode!=1){ + DEBUG_PRINTF("Error: File not found.\n"); + } + else{ + DEBUG_PRINTF("End of DirEnt reached. No free pages found.\n"); + } + + result=-ENOENT; + break; + } + else{ + result=1; + break; + } + } + + if(((struct SCE_MC_dirent *)PageBuffer)->mode & 0x8000){ + DEBUG_PRINTF("Name: %s\nCluster: 0x%08x\nsize 0x%08x\n\n", ((struct SCE_MC_dirent *)PageBuffer)->name, ((struct SCE_MC_dirent *)PageBuffer)->cluster, ((struct SCE_MC_dirent *)PageBuffer)->length); + } + else{ + if(mode==1){ + result=2; + break; + } + } + + recordID++; + }while((mode==1) || (!(((struct SCE_MC_dirent *)PageBuffer)->mode & 0x8000)) || strncmp(dirent_name, ((struct SCE_MC_dirent *)PageBuffer)->name, sizeof(((struct SCE_MC_dirent *)PageBuffer)->name))!=0); + + DEBUG_PRINTF("ScanThroughDirEnt end.\n"); + + return result; +} + +/* + * Returns (and/or sets) the information of a file. To search for the root folder, pass "." as the path. + * mode = 0 -> Normal operation + * mode = 1 -> Write file data into the first unused page detected. + * + * On success >=0 is returned. + * Returns 1 when mode = 1 and the allocated page does not belong to any directory entry. + * Returns 2 when mode = 1 and the allocated page belonged to a deleted file. + */ +static int GetSetFileData(int port, int slot, int mode, const char *path, struct SCE_MC_dirent *entry, struct SCE_MC_dirent *NewDirEntData, struct SCE_MC_Superblock *SuperBlock){ + unsigned int ClusterNum, PageNum, LogicalPageNum, DirEntLength; + int result, AllocatedPageType; + char *dirent_name; + char *PathToFile; + void *PageBuffer; + + DEBUG_PRINTF("GetFileData(): File: %s mode: %d\n", path, mode); + PathToFile=malloc(strlen(path)+1); + strcpy(PathToFile, path); + + result=0; + AllocatedPageType=0; + if((PageBuffer=malloc(SuperBlock->page_len))!=NULL){ + dirent_name=strtok(PathToFile, "/\\"); + + ClusterNum=SuperBlock->rootdir_cluster; + DirEntLength=0; /* Unknown size. The size will then be retrieved later on within ScanThroughDirEnt() */ + + while((dirent_name!=NULL)&&(result>=0)){ + LogicalPageNum=0; + + if(ClusterNum!=0) ClusterNum=((struct SCE_MC_dirent *)PageBuffer)->cluster; + PageNum=(SuperBlock->alloc_start+ClusterNum)*SuperBlock->pages_per_cluster; + + DEBUG_PRINTF("Scanning for dirent %s\n", dirent_name); + + if(ClusterNum==0xFFFFFFFF) break; /* Do not enter the directory if it's empty (Or rather non-existent). */ + + result=ScanThroughDirEnt(port, slot, 0, DirEntLength, &PageNum, &LogicalPageNum, dirent_name, &ClusterNum, SuperBlock, PageBuffer); + + if(result>=0){ + DEBUG_PRINTF("DirEnt found. Cluster: 0x%08x size 0x%08x\n", ((struct SCE_MC_dirent *)PageBuffer)->cluster, ((struct SCE_MC_dirent *)PageBuffer)->length); + dirent_name=strtok(NULL, "/\\"); + DirEntLength=((struct SCE_MC_dirent *)PageBuffer)->length; + } + } + + if(result>=0){ + if(mode==1){ + if(ClusterNum!=0){ + ClusterNum=((struct SCE_MC_dirent *)PageBuffer)->cluster; + PageNum=(SuperBlock->alloc_start+ClusterNum)*SuperBlock->pages_per_cluster; + } + + LogicalPageNum=0; + + if((result=ScanThroughDirEnt(port, slot, mode, ((struct SCE_MC_dirent *)PageBuffer)->length, &PageNum, &LogicalPageNum, dirent_name, &ClusterNum, SuperBlock, PageBuffer))>=0){ + AllocatedPageType=result; + DEBUG_PRINTF("Detected free page: 0x%08x type %d\n", PageNum+LogicalPageNum, AllocatedPageType); + } + } + + if(result>=0){ + DEBUG_PRINTF("Found file.\n\n"); + + if(entry!=NULL){ + memcpy(entry, PageBuffer, sizeof(struct SCE_MC_dirent)); + } + + if(NewDirEntData!=NULL){ + unsigned int offset; + + offset=((PageNum+LogicalPageNum-SuperBlock->alloc_start*SuperBlock->pages_per_cluster)-ClusterNum*SuperBlock->pages_per_cluster)*SuperBlock->page_len; + + result=UpdateDirEntInformation(port, slot, SuperBlock, SuperBlock->alloc_start+ClusterNum, offset, NewDirEntData); + } + } + } + + free(PageBuffer); + } + else result=-ENOMEM; + + free(PathToFile); + + if((mode==1) && (result>=0)){ + result=AllocatedPageType; + } + + return result; +} + +/* + * Returns the information of a file. To search for the root folder, pass "." as the path. + */ +static int GetFileData(int port, int slot, const char *path, struct SCE_MC_dirent *entry, struct SCE_MC_Superblock *SuperBlock){ + return(GetSetFileData(port, slot, 0, path, entry, NULL, SuperBlock)); +} + +static int CreateNewVirtualDirent(unsigned char port, unsigned char slot, const char *path, struct SCE_MC_dirent *NewDirEntData, struct SCE_MC_Superblock *SuperBlock){ + struct SCE_MC_dirent ParentDirEnt; + unsigned int TargetCluster, TargetSubClusterPageNum, ClusterSize, TargetOffsetWithinCluster; + int result; + + DEBUG_PRINTF("CreateNewVirtualDirent: %s/%s\n", path, NewDirEntData->name); + + ClusterSize=SuperBlock->page_len*SuperBlock->pages_per_cluster; + + /* Get some information on the parent folder. */ + if((result=GetFileData(port, slot, path, &ParentDirEnt, SuperBlock))>=0){ + /* Decide whether the new record goes onto a page within an existing cluster or goes onto a page within a new cluster. + * + * First, look for an unused page within the currently allocated clusters. + */ + + /* Attempt to create the new directory record within the page in the cluster before writing the cluster back */ + if((result=GetSetFileData(port, slot, 1, path, NULL, NewDirEntData, SuperBlock))<0){ + DEBUG_PRINTF("No free pages. Allocating new cluster.\n"); + + result=0; + TargetSubClusterPageNum=0; + + /* Add a new record to the FAT. */ + if((TargetCluster=AddFATRecord(port, slot, SuperBlock, ParentDirEnt.cluster))==0){ + result=-ENOMEM; + } + + DEBUG_PRINTF("Allocated new cluster: 0x%08x\n", TargetCluster); + + TargetCluster+=SuperBlock->alloc_start; + + if(result>=0){ + /* Place the new record on the calculated page within the calculated cluster. */ + TargetOffsetWithinCluster=TargetSubClusterPageNum*SuperBlock->page_len; + + /* Create the new directory record within the page in the cluster before writing the cluster back */ + result=UpdateDirEntInformation(port, slot, SuperBlock, TargetCluster, TargetOffsetWithinCluster, NewDirEntData); + } + } + + if((result>=0) && (result!=2)){ + DEBUG_PRINTF("Updating parent directory information...\n"); + + /* Update the parent directory's information. */ + ParentDirEnt.length++; + result=GetSetFileData(port, slot, 0, path, NULL, &ParentDirEnt, SuperBlock); + } + } + + return result; +} + +static int DeleteVirtualDirent(unsigned char port, unsigned char slot, const char *path, const char *name, struct SCE_MC_Superblock *SuperBlock){ + char *PathToFile; + struct SCE_MC_dirent DirEntData, ParentDirEnt; + int result;//, ClustersFreed; + + DEBUG_PRINTF("DeleteVirtualDirent: %s/%s\n", path, name); + + if((PathToFile=malloc(strlen(path)+strlen(name)+2))!=NULL){ + sprintf(PathToFile, "%s/%s", path, name); + + /* Get the information on the file/folder. */ + if((result=GetFileData(port, slot, PathToFile, &DirEntData, SuperBlock))>=0){ + DirEntData.mode=0x7FFF; /* Clear the "exists" flag to make the entry now non-existent (SONY MCMAN sets mode to 0x7FFF). */ + result=GetSetFileData(port, slot, 0, PathToFile, NULL, &DirEntData, SuperBlock); + } + + free(PathToFile); + } + else result=-ENOMEM; + + if(result>=0){ + /* Get some information on the parent folder. */ + if((result=GetFileData(port, slot, path, &ParentDirEnt, SuperBlock))>=0){ + //The SONY MCMAN module doesn't seem to do this, so don't do this. +#if 0 + /* Now for some housekeeping: Free up unused clusters */ + ClustersFreed=FreeUnusedFATRecords(port, slot, ParentDirEnt.cluster, &ParentDirEnt.length, SuperBlock); + DEBUG_PRINTF("%d cluster(s) freed. Records existing: %u\n", ClustersFreed, ParentDirEnt.length); + + /* Update the length of the parent directory. */ + result=GetSetFileData(port, slot, 0, path, NULL, &ParentDirEnt, SuperBlock); +#endif + } + } + + return result; +} + +/* Creates a cross-linked entry + * WARNING! CREATING AN ENTRY OF AN EXISTING ENTRY MIGHT CAUSE DATA LOSS WHEN ONE IS DELETED! + */ +int CreateCrossLinkedFiles(int port, int slot, const char *path, struct FileAlias *NewAliases){ + struct SCE_MC_Superblock SuperBlock; + struct SCE_MC_dirent DirEnt, NewDirEnt; + int result; + unsigned int i, length; + char *PathToTarget, *pFilename; + + DEBUG_PRINTF("CreateCrossLinkedFiles\n"); + + FlushMCMANClusterCache(port, slot); + + if((result=GetCardFilesystemSuperblock(port, slot, &SuperBlock))<0){ + DEBUG_PRINTF("Error getting card specs for MC at port %d slot %d! Code %d\n", port, slot, result); + return result; + } + + DEBUG_PRINTF("MC Port: %d Slot: %d alloc_start: %u pagesize: %u blocksize: %u numpages %d flags: 0x%02x\n", port, slot, SuperBlock.alloc_start, SuperBlock.page_len, SuperBlock.pages_per_block, SuperBlock.clusters*SuperBlock.pages_per_cluster, SuperBlock.card_flags); + + /* Get the entry of the specified original file. */ + if((result=GetFileData(port, slot, path, &DirEnt, &SuperBlock))>=0){ + memcpy(&NewDirEnt, &DirEnt, sizeof(struct SCE_MC_dirent)); + result=0; + + /* Create the aliases (Cross-linked files). */ + for(i=0; (i=0){ + result++; + } + + free(PathToTarget); + } + } + + return(result); +} + +static int DeleteCrossLinkedFiles(int port, int slot, const char *path, struct FileAlias *Aliases){ + struct SCE_MC_Superblock SuperBlock; + int result; + unsigned int i, length, PathLength; + char *PathToTarget, *pFilename; + + DEBUG_PRINTF("DeleteCrossLinkedFiles\n"); + + FlushMCMANClusterCache(port, slot); + + if((result=GetCardFilesystemSuperblock(port, slot, &SuperBlock))<0){ + DEBUG_PRINTF("Error getting card specs for MC at port %d slot %d! Code %d\n", port, slot, result); + return result; + } + + DEBUG_PRINTF("MC Port: %d Slot: %d alloc_start: %u pagesize: %u blocksize: %u numpages %d flags: %u\n", port, slot, SuperBlock.alloc_start, SuperBlock.page_len, SuperBlock.pages_per_block, SuperBlock.clusters*SuperBlock.pages_per_cluster, SuperBlock.card_flags); + + /* Delete the aliases (Cross-linked files). */ + for(i=0; (i=0){ + result++; + } + + free(PathToTarget); + } + + return result; +} + +void *mctools_rpc_handler(int fno, void *buf, int size){ + unsigned int ClusterSize; + struct MCTools_GetMCInfoRPCResData *McSpecResData; + + DEBUG_PRINTF("mctools_rpc_handler func: 0x%02x\n", fno); + + switch(fno){ + case MCTOOLS_Init: + EEAlignmentDataStructure=*(void **)buf; + *(int*)rpc_TX_buffer=0; + break; + case MCTOOLS_CreateCrossLinkedEnts: + *(int*)rpc_TX_buffer=CreateCrossLinkedFiles(((struct MCTools_CrossLinkedEntRPCData *)buf)->port, ((struct MCTools_CrossLinkedEntRPCData *)buf)->slot, ((struct MCTools_CrossLinkedEntRPCData *)buf)->path, ((struct MCTools_CrossLinkedEntRPCData *)buf)->Aliases); + break; + case MCTOOLS_DeleteCrossLinkedEnts: + *(int*)rpc_TX_buffer=DeleteCrossLinkedFiles(((struct MCTools_CrossLinkedEntRPCData *)buf)->port, ((struct MCTools_CrossLinkedEntRPCData *)buf)->slot, ((struct MCTools_CrossLinkedEntRPCData *)buf)->path, ((struct MCTools_CrossLinkedEntRPCData *)buf)->Aliases); + break; + case MCTOOLS_GetMCInfo: + McSpecResData=(struct MCTools_GetMCInfoRPCResData*)rpc_TX_buffer; + McSpecResData->result=GetCardSpecs(((struct MCTools_GetMCInfoRPCReqData *)buf)->port, ((struct MCTools_GetMCInfoRPCReqData *)buf)->slot, &McSpecResData->SpecData.PageSize, &McSpecResData->SpecData.BlockSize, &McSpecResData->SpecData.CardSize); + break; + case MCTOOLS_ReadCluster: + ClusterSize=((struct MCTools_ReadWriteRPCData *)buf)->PageSize*((struct MCTools_ReadWriteRPCData *)buf)->BlockSize; + + *(int*)rpc_TX_buffer=ReadCluster_raw(((struct MCTools_ReadWriteRPCData *)buf)->port, ((struct MCTools_ReadWriteRPCData *)buf)->slot, ((struct MCTools_ReadWriteRPCData *)buf)->PageSize, ((struct MCTools_ReadWriteRPCData *)buf)->BlockSize, ((struct MCTools_ReadWriteRPCData *)buf)->offset, ((struct MCTools_ReadWriteRPCData *)buf)->IOPbuffer); + EE_memcpy(((struct MCTools_ReadWriteRPCData *)buf)->IOPbuffer, ((struct MCTools_ReadWriteRPCData *)buf)->EEbuffer, ClusterSize); + break; + case MCTOOLS_WriteBlock: + *(int*)rpc_TX_buffer=WriteBlock(((struct MCTools_ReadWriteRPCData *)buf)->port, ((struct MCTools_ReadWriteRPCData *)buf)->slot, ((struct MCTools_ReadWriteRPCData *)buf)->PageSize, ((struct MCTools_ReadWriteRPCData *)buf)->BlockSize, ((struct MCTools_ReadWriteRPCData *)buf)->offset, ((struct MCTools_ReadWriteRPCData *)buf)->IOPbuffer); + break; + case MCTOOLS_InitPageCache: + *(int*)rpc_TX_buffer=InitPageCache(((struct MCTools_CacheRPCData *)buf)->port, ((struct MCTools_CacheRPCData *)buf)->slot); + break; + case MCTOOLS_FlushPageCache: + *(int*)rpc_TX_buffer=FlushPageCache(); + break; + case MCTOOLS_FlushMCMANClusterCache: + *(int*)rpc_TX_buffer=FlushMCMANClusterCache(((struct MCTools_MCMANFlushCommandData*)buf)->port, ((struct MCTools_MCMANFlushCommandData*)buf)->slot); + break; + default: + *(int*)rpc_TX_buffer=-EINVAL; + } + + return rpc_TX_buffer; +} + diff --git a/irx/source/mctools/src/mctools.h b/irx/source/mctools/src/mctools.h new file mode 100644 index 0000000..6f247db --- /dev/null +++ b/irx/source/mctools/src/mctools.h @@ -0,0 +1,107 @@ +/* RPC function numbers */ +#define MCTOOLS_CreateCrossLinkedEnts 0x00 +#define MCTOOLS_DeleteCrossLinkedEnts 0x01 +#define MCTOOLS_GetMCInfo 0x02 +#define MCTOOLS_ReadCluster 0x03 +#define MCTOOLS_WriteBlock 0x04 +#define MCTOOLS_Init 0x80 +#define MCTOOLS_InitPageCache 0x81 +#define MCTOOLS_FlushPageCache 0x82 +#define MCTOOLS_FlushMCMANClusterCache 0x83 + +#define MCTOOLS_RPC_NUM 0x00001906 + +#define MAX_RPC_FILE_ENTRIES 8 + +/* 340 bytes long */ +struct SCE_MC_Superblock{ + u8 magic[28]; /* "Sony PS2 Memory Card Format" */ + u8 version[12]; /* E.g. "1.X.0.0". Version 1.2 indicates full support for the bad_block_list */ + u16 page_len; /* Length of each page in bytes. */ + u16 pages_per_cluster; + u16 pages_per_block; /* Must be 16 (?) */ + u16 unknown; /* Unknown. Value: 0xFF00 */ + u32 clusters; /* Total size of the card in clusters. */ + u32 alloc_start; /* The cluster number of the first allocatable cluster (The cluster immediately after the FAT) */ + u32 alloc_end; /* The cluster number of the cluster after the highest-allocatable cluster. Not used. */ + u32 rootdir_cluster; /* The first cluster representing the root directory relative to alloc_start. Must be zero. */ + u32 backup_block1; /* Erase block used as a backup area during programming. */ + u32 backup_block2; /* A block with it's content set to 1 during programming. */ + u8 unknown2[8]; /* Unused/unknown region. */ + u32 ifc_list[32]; /* List of indirect FAT clusters (On a standard 8M card there's only one indirect FAT cluster). */ + u32 bad_block_list[32]; /* List of erase blocks that have errors and shouldn't be used. */ + u8 card_type; /* Memory card type (2 = Playstation 2 Memory Card). */ + u8 card_flags; /* Physical characteristics of the memory card. */ +}; + +/* 512 bytes long (Occupies one page). 96 bytes long here. */ +struct SCE_MC_dirent{ + u16 mode; /* Attributes of this directory entry. */ + u16 unknown; + u32 length; /* Length in bytes if a file, or entries if a directory. */ + u8 created[8]; /* Creation time. */ + u32 cluster; /* First cluster of the file, or 0xFFFFFFFF for an empty file. In "." entries this the first cluster of this directory's parent directory instead. Relative to alloc_offset. */ + u32 dir_entry; /* Only in "." entries. Entry of this directory in its parent's directory. */ + u8 modified[8]; /* Modification time. */ + u32 attr; /* User defined attribute */ + u8 unknown2[28]; + u8 name[32]; /* Zero terminated name for this directory entry. */ +}; + +struct FileAlias{ + u16 mode; + s8 name[66]; //Note: Do not just update this! This affects the size of each record within the uninstallation file, and changing this may break older installers that expect the original size. Instead, update this and the uninstallation file's version number together to lock out the older installers. +}; + +/* RPC data structures. */ +struct MCTools_MCMANFlushCommandData{ + s32 port, slot; +}; + +struct MCTools_CrossLinkedEntRPCData{ + u8 port; + u8 slot; + s8 path[256]; + struct FileAlias Aliases[MAX_RPC_FILE_ENTRIES]; +}; + +struct MCTools_McSpecData{ + u16 PageSize, BlockSize; + int CardSize; +}; + +struct MCTools_GetMCInfoRPCReqData{ + u8 port; + u8 slot; + struct MCTools_McSpecData *SpecData; //On the EE +}; + +struct MCTools_GetMCInfoRPCResData{ + s32 result; + struct MCTools_McSpecData SpecData; +}; + +struct MCTools_ReadWriteRPCData{ + s32 port, slot; + u16 PageSize, BlockSize; //Or cluster size, when reading. + u32 offset; /* In blocks, clusters or pages. Depending on the RPC function used. */ + void *EEbuffer; + void *IOPbuffer; +}; + +struct MCTools_CacheRPCData{ + u16 port; + u16 slot; + struct MCTools_McSpecData SpecData; +}; + +struct MCTools_AlignmentData{ + void *buffer1Address; + void *buffer2Address; + + u8 buffer1[64]; + u8 buffer2[64]; + + u32 buffer1_len; + u32 buffer2_len; +}; diff --git a/irx/source/mctools/src/mctools_internal.h b/irx/source/mctools/src/mctools_internal.h new file mode 100644 index 0000000..3e10e09 --- /dev/null +++ b/irx/source/mctools/src/mctools_internal.h @@ -0,0 +1,10 @@ +//#define DEBUG_TTY_FEEDBACK /* Comment out to disable debugging messages */ + +#ifdef DEBUG_TTY_FEEDBACK + #define DEBUG_PRINTF(args...) printf(args) +#else + #define DEBUG_PRINTF(args...) +#endif + +void *malloc(unsigned int size); +void free(void *ptr); diff --git a/resources/buttons.png b/resources/buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..3e192fdc248824dbe77e2fe39fbbb6b9fecafd98 GIT binary patch literal 6221 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