diff --git a/arm9/source/filesys/filetype.h b/arm9/source/filesys/filetype.h index 959032f56..c7ca32499 100644 --- a/arm9/source/filesys/filetype.h +++ b/arm9/source/filesys/filetype.h @@ -61,7 +61,7 @@ #define FTYPE_TITLEINFO(tp) (tp&(GAME_TIE|GAME_TICKET|GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_CDNTMD|GAME_TWLTMD|GAME_NDS|GAME_GBA|GAME_TAD|GAME_3DSX)) #define FTYPE_CIACHECK(tp) (tp&GAME_CIA) #define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA)) -#define FTYPE_TRIMABLE(tp) (tp&(IMG_NAND|GAME_NCCH|GAME_NCSD|GAME_NDS|SYS_FIRM)) +#define FTYPE_TRIMABLE(tp) (tp&(IMG_NAND|GAME_NCCH|GAME_NCSD|GAME_NDS|GAME_GBA|SYS_FIRM)) #define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR)) #define FTYPE_NCSDFIXABLE(tp) (tp&(HDR_NAND|NOIMG_NAND)) #define FTYPE_HASCODE(tp) (((u64) (tp&(GAME_NCCH|FLAG_CXI)) == (u64) (GAME_NCCH|FLAG_CXI))|(tp&GAME_NCSD)) diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 20a1a2a8a..1183b1162 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -3048,11 +3048,53 @@ u32 CompressCode(const char* path, const char* path_out) { return 0; } +u64 GetAnyFileTrimmedSize(const char* path) { + u64 fsize = 0; + u64 trimsize = 0; + u8 pad_byte = 0x7F; + FIL fp; + UINT br; + + if (fvx_open(&fp, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) + return 0; + + fsize = fvx_size(&fp); + u32 bufsize = min(STD_BUFFER_SIZE, fsize); + u8* buffer = (u8*) malloc(bufsize); + if (!buffer) return 0; + + for (s64 pos = align(fsize, bufsize) - bufsize; (pos >= 0) && !trimsize; pos -= bufsize) { + if ((fvx_lseek(&fp, (UINT) pos) != FR_OK) || + (fvx_read(&fp, buffer, bufsize, &br) != FR_OK) || !br) break; + if (pad_byte == 0x7F) { // start value + pad_byte = buffer[br-1]; + if ((pad_byte != 0x00) && (pad_byte != 0xFF)) break; + } + for (u8* b = buffer + (br-1); b >= buffer; b--) { + if (*b != pad_byte) { + trimsize = pos + (b-buffer) + 1; + break; + } + } + } + + fvx_close(&fp); + free(buffer); + + // 4 byte forced alignment + // 512 byte trimming minimum + trimsize = align(trimsize, 4); + if ((trimsize > fsize) || (fsize - trimsize < 0x200)) return 0; + return trimsize; +} + u64 GetGameFileTrimmedSize(const char* path) { u64 filetype = IdentifyFileType(path); u64 trimsize = 0; - if (filetype & GAME_NDS) { + if (filetype & GAME_GBA) { + trimsize = GetAnyFileTrimmedSize(path); + } else if (filetype & GAME_NDS) { TwlHeader hdr; if (fvx_qread(path, &hdr, 0, sizeof(TwlHeader), NULL) != FR_OK) return 0;