mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Merge remote-tracking branch 'upstream/master' into hex-editor
This commit is contained in:
commit
0efb21747d
@ -20,13 +20,29 @@ extern PrintConsole topConsole, bottomConsole;
|
|||||||
|
|
||||||
static sNDSHeaderExt ndsCardHeader;
|
static sNDSHeaderExt ndsCardHeader;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L74
|
||||||
|
// with Pokémon Mystery Dungeon - Explorers of Sky (128 KiB EEPROM) fixed
|
||||||
|
int cardEepromGetTypeFixed(void) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
int sr = cardEepromCommand(SPI_EEPROM_RDSR);
|
||||||
|
int id = cardEepromReadID();
|
||||||
|
|
||||||
|
if (( sr == 0xff && id == 0xffffff) || ( sr == 0 && id == 0 )) return -1;
|
||||||
|
if ( sr == 0xf0 && id == 0xffffff ) return 1;
|
||||||
|
if ( sr == 0x00 && id == 0xffffff ) return 2;
|
||||||
|
if ( id != 0xffffff || ( sr == 0x02 && id == 0xffffff )) return 3;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L88
|
// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L88
|
||||||
// with type 2 fixed if the first word and another % 8192 location are 0x00000000
|
// with type 2 fixed if the first word and another % 8192 location are 0x00000000
|
||||||
uint32 cardEepromGetSizeFixed() {
|
uint32 cardEepromGetSizeFixed() {
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
|
||||||
int type = cardEepromGetType();
|
int type = cardEepromGetTypeFixed();
|
||||||
|
|
||||||
if(type == -1)
|
if(type == -1)
|
||||||
return 0;
|
return 0;
|
||||||
@ -92,6 +108,13 @@ uint32 cardEepromGetSizeFixed() {
|
|||||||
if (device == 0x2211)
|
if (device == 0x2211)
|
||||||
return 128*1024; // 1Mbit(128KByte) - MX25L1021E
|
return 128*1024; // 1Mbit(128KByte) - MX25L1021E
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == 0xffffff) {
|
||||||
|
int sr = cardEepromCommand(SPI_EEPROM_RDSR);
|
||||||
|
if (sr == 2) { // Pokémon Mystery Dungeon - Explorers of Sky
|
||||||
|
return 128*1024; // 1Mbit (128KByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 256*1024; // 2Mbit(256KByte)
|
return 256*1024; // 2Mbit(256KByte)
|
||||||
@ -121,7 +144,7 @@ void ndsCardSaveDump(const char* filename) {
|
|||||||
auxspi_read_data(0, buffer, LEN*size_blocks, type, card_type);
|
auxspi_read_data(0, buffer, LEN*size_blocks, type, card_type);
|
||||||
fwrite(buffer, 1, LEN*size_blocks, out);
|
fwrite(buffer, 1, LEN*size_blocks, out);
|
||||||
} else {
|
} else {
|
||||||
int type = cardEepromGetType();
|
int type = cardEepromGetTypeFixed();
|
||||||
int size = cardEepromGetSizeFixed();
|
int size = cardEepromGetSizeFixed();
|
||||||
buffer = new unsigned char[size];
|
buffer = new unsigned char[size];
|
||||||
cardReadEeprom(0, buffer, size, type);
|
cardReadEeprom(0, buffer, size, type);
|
||||||
@ -187,7 +210,7 @@ void ndsCardSaveRestore(const char *filename) {
|
|||||||
LEN = 1 << shift;
|
LEN = 1 << shift;
|
||||||
num_blocks = 1 << (size - shift);
|
num_blocks = 1 << (size - shift);
|
||||||
} else {
|
} else {
|
||||||
type = cardEepromGetType();
|
type = cardEepromGetTypeFixed();
|
||||||
size = cardEepromGetSizeFixed();
|
size = cardEepromGetSizeFixed();
|
||||||
}
|
}
|
||||||
fseek(in, 0, SEEK_END);
|
fseek(in, 0, SEEK_END);
|
||||||
@ -315,7 +338,7 @@ void ndsCardDump(void) {
|
|||||||
char gameCode[7] = {0};
|
char gameCode[7] = {0};
|
||||||
tonccpy(gameCode, ndsCardHeader.gameCode, 6);
|
tonccpy(gameCode, ndsCardHeader.gameCode, 6);
|
||||||
char destSavPath[256];
|
char destSavPath[256];
|
||||||
sprintf(destSavPath, "%s:/gm9i/out/%s_%s_%x.sav", (sdMounted ? "sd" : "fat"), gameTitle, gameCode, ndsCardHeader.romversion);
|
sprintf(destSavPath, "%s:/gm9i/out/%s_%s_%02x.sav", (sdMounted ? "sd" : "fat"), gameTitle, gameCode, ndsCardHeader.romversion);
|
||||||
ndsCardSaveDump(destSavPath);
|
ndsCardSaveDump(destSavPath);
|
||||||
} else
|
} else
|
||||||
if ((pressed & KEY_A) || (pressed & KEY_Y)) {
|
if ((pressed & KEY_A) || (pressed & KEY_Y)) {
|
||||||
@ -386,7 +409,7 @@ void ndsCardDump(void) {
|
|||||||
if (gameCode[0] == 0 || gameCode[0] == 0x23 || gameCode[0] == 0xFF) {
|
if (gameCode[0] == 0 || gameCode[0] == 0x23 || gameCode[0] == 0xFF) {
|
||||||
sprintf(gameCode, "NONE00");
|
sprintf(gameCode, "NONE00");
|
||||||
}
|
}
|
||||||
sprintf(fileName, "%s_%s_%x%s", gameTitle, gameCode, ndsCardHeader.romversion, (trimRom ? "_trim" : ""));
|
sprintf(fileName, "%s_%s_%02x%s", gameTitle, gameCode, ndsCardHeader.romversion, (trimRom ? "_trim" : ""));
|
||||||
sprintf(destPath, "%s:/gm9i/out/%s.nds", (sdMounted ? "sd" : "fat"), fileName);
|
sprintf(destPath, "%s:/gm9i/out/%s.nds", (sdMounted ? "sd" : "fat"), fileName);
|
||||||
sprintf(destSavPath, "%s:/gm9i/out/%s.sav", (sdMounted ? "sd" : "fat"), fileName);
|
sprintf(destSavPath, "%s:/gm9i/out/%s.sav", (sdMounted ? "sd" : "fat"), fileName);
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "file_browse.h"
|
#include "file_browse.h"
|
||||||
|
|
||||||
#define copyBufSize 0x8000
|
#define copyBufSize 0x8000
|
||||||
|
#define shaChunkSize 0x10000
|
||||||
|
|
||||||
u32 copyBuf[copyBufSize];
|
u32 copyBuf[copyBufSize];
|
||||||
|
|
||||||
@ -68,6 +69,39 @@ off_t getFileSize(const char *fileName)
|
|||||||
return fsize;
|
return fsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool calculateSHA1(const char *fileName, u8 *sha1)
|
||||||
|
{
|
||||||
|
off_t fsize = getFileSize(fileName);
|
||||||
|
u8 *buf = (u8*) malloc(shaChunkSize);
|
||||||
|
if (!buf) {
|
||||||
|
iprintf("Could not allocate buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(fileName, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
iprintf("Could not open file for reading\n");
|
||||||
|
free(buf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(sha1, 0, 20);
|
||||||
|
swiSHA1context_t ctx;
|
||||||
|
ctx.sha_block=0; //this is weird but it has to be done
|
||||||
|
swiSHA1Init(&ctx);
|
||||||
|
while (true) {
|
||||||
|
size_t ret = fread(buf, 1, shaChunkSize, fp);
|
||||||
|
if (!ret) break;
|
||||||
|
swiSHA1Update(&ctx, buf, ret);
|
||||||
|
scanKeys();
|
||||||
|
int keys = keysHeld();
|
||||||
|
if (keys & KEY_START) return false;
|
||||||
|
iprintf("\x1b[1;A");
|
||||||
|
iprintf("%ld/%lld bytes processed\n", ftell(fp), fsize);
|
||||||
|
}
|
||||||
|
swiSHA1Final(sha1, &ctx);
|
||||||
|
free(buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void dirCopy(DirEntry* entry, int i, const char *destinationPath, const char *sourcePath) {
|
void dirCopy(DirEntry* entry, int i, const char *destinationPath, const char *sourcePath) {
|
||||||
std::vector<DirEntry> dirContents;
|
std::vector<DirEntry> dirContents;
|
||||||
dirContents.clear();
|
dirContents.clear();
|
||||||
|
|||||||
@ -23,6 +23,7 @@ extern void printBytes(int bytes);
|
|||||||
extern void printBytesAlign(int bytes);
|
extern void printBytesAlign(int bytes);
|
||||||
|
|
||||||
extern off_t getFileSize(const char *fileName);
|
extern off_t getFileSize(const char *fileName);
|
||||||
|
extern bool calculateSHA1(const char *fileName, u8 *sha1);
|
||||||
extern int fcopy(const char *sourcePath, const char *destinationPath);
|
extern int fcopy(const char *sourcePath, const char *destinationPath);
|
||||||
void changeFileAttribs(DirEntry* entry);
|
void changeFileAttribs(DirEntry* entry);
|
||||||
|
|
||||||
|
|||||||
@ -245,8 +245,13 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
|||||||
assignedOp[++maxCursors] = FileOperation::copyFatOut;
|
assignedOp[++maxCursors] = FileOperation::copyFatOut;
|
||||||
printf(" Copy to fat:/gm9i/out\n");
|
printf(" Copy to fat:/gm9i/out\n");
|
||||||
}
|
}
|
||||||
printf("\n");
|
// The bios SHA1 functions are only available on the DSi
|
||||||
printf("(<A> select, <B> cancel)");
|
// https://problemkaputt.de/gbatek.htm#biossha1functionsdsionly
|
||||||
|
if (isDSiMode()) {
|
||||||
|
assignedOp[++maxCursors] = FileOperation::calculateSHA1;
|
||||||
|
printf(" Calculate SHA1 hash\n");
|
||||||
|
}
|
||||||
|
printf("\n(<A> select, <B> cancel)");
|
||||||
consoleSelect(&bottomConsole);
|
consoleSelect(&bottomConsole);
|
||||||
printf ("\x1B[47m"); // Print foreground white color
|
printf ("\x1B[47m"); // Print foreground white color
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -306,7 +311,7 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
|||||||
// TODO Something less hacky lol
|
// TODO Something less hacky lol
|
||||||
chdir(isDSiMode()&&sdMounted ? "sd:/_nds" : "fat:/_nds");
|
chdir(isDSiMode()&&sdMounted ? "sd:/_nds" : "fat:/_nds");
|
||||||
// TODO Read header and check for homebrew flag, based on that runNdsFile nds-bootstrap(-hb)-release
|
// TODO Read header and check for homebrew flag, based on that runNdsFile nds-bootstrap(-hb)-release
|
||||||
entry->name = isDSiMode() ? "nds-bootstrap-release.nds" : "b4ds-release.nds";
|
entry->name = "nds-bootstrap-release.nds";
|
||||||
applaunch = true;
|
applaunch = true;
|
||||||
return FileOperation::bootFile;
|
return FileOperation::bootFile;
|
||||||
break;
|
break;
|
||||||
@ -380,6 +385,28 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
|||||||
break;
|
break;
|
||||||
} case FileOperation::hexEdit: {
|
} case FileOperation::hexEdit: {
|
||||||
hexEditor(entry->name.c_str(), currentDrive);
|
hexEditor(entry->name.c_str(), currentDrive);
|
||||||
|
} case FileOperation::calculateSHA1: {
|
||||||
|
iprintf("\x1b[2J");
|
||||||
|
iprintf("Calculating SHA1 hash of:\n%s\n", entry->name.c_str());
|
||||||
|
iprintf("Press <START> to cancel\n\n");
|
||||||
|
u8 sha1[20] = {0};
|
||||||
|
bool ret = calculateSHA1(strcat(getcwd(path, PATH_MAX), entry->name.c_str()), sha1);
|
||||||
|
if (!ret) break;
|
||||||
|
iprintf("SHA1 hash is: \n");
|
||||||
|
for (int i = 0; i < 20; ++i) iprintf("%02X", sha1[i]);
|
||||||
|
consoleSelect(&topConsole);
|
||||||
|
iprintf ("\x1B[30m"); // Print black color
|
||||||
|
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
|
||||||
|
int pressed;
|
||||||
|
do {
|
||||||
|
// Move to right side of screen
|
||||||
|
iprintf ("\x1b[0;26H");
|
||||||
|
// Print time
|
||||||
|
iprintf (" %s" ,RetTime().c_str());
|
||||||
|
scanKeys();
|
||||||
|
pressed = keysDownRepeat();
|
||||||
|
swiWaitForVBlank();
|
||||||
|
} while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X)));
|
||||||
break;
|
break;
|
||||||
} case FileOperation::none: {
|
} case FileOperation::none: {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -43,6 +43,7 @@ enum class FileOperation {
|
|||||||
showInfo,
|
showInfo,
|
||||||
copySdOut,
|
copySdOut,
|
||||||
copyFatOut,
|
copyFatOut,
|
||||||
|
calculateSHA1,
|
||||||
hexEdit,
|
hexEdit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,10 @@ def getBytes(e):
|
|||||||
if (sys.version_info.major == 2):
|
if (sys.version_info.major == 2):
|
||||||
return bytes(e)
|
return bytes(e)
|
||||||
else:
|
else:
|
||||||
return bytes(e, "utf-8")
|
try:
|
||||||
|
return e.encode('ascii')
|
||||||
|
except:
|
||||||
|
print("ERROR: {}".format(e))
|
||||||
#
|
#
|
||||||
# CRC16 MODULE
|
# CRC16 MODULE
|
||||||
#
|
#
|
||||||
@ -113,7 +116,7 @@ def skipUntilAddress(f_in,f_out, caddr, taddr):
|
|||||||
f_out.write(chunk)
|
f_out.write(chunk)
|
||||||
|
|
||||||
def writeBlankuntilAddress(f_out, caddr, taddr):
|
def writeBlankuntilAddress(f_out, caddr, taddr):
|
||||||
f_out.write(getBytes("\x00"*(taddr-caddr)))
|
f_out.write(b"\x00"*(taddr-caddr))
|
||||||
|
|
||||||
fname=args.file
|
fname=args.file
|
||||||
|
|
||||||
@ -400,21 +403,21 @@ else:
|
|||||||
# Fix srlSignedHeader
|
# Fix srlSignedHeader
|
||||||
if not args.read:
|
if not args.read:
|
||||||
srlSignedHeader=srlSignedHeader._replace(
|
srlSignedHeader=srlSignedHeader._replace(
|
||||||
arm7Sha1Hmac= '\xff'*20,
|
arm7Sha1Hmac= b'\xff'*20,
|
||||||
arm9WithSecAreaSha1Hmac= '\xff'*20,
|
arm9WithSecAreaSha1Hmac= b'\xff'*20,
|
||||||
bannerSha1Hmac= '\xff'*20,
|
bannerSha1Hmac= b'\xff'*20,
|
||||||
signature= '\xff'*128
|
signature= b'\xff'*128
|
||||||
)
|
)
|
||||||
if "dsi" in args.mode :
|
if "dsi" in args.mode :
|
||||||
srlSignedHeader=srlSignedHeader._replace(
|
srlSignedHeader=srlSignedHeader._replace(
|
||||||
arm7Sha1Hmac= '\xff'*20,
|
arm7Sha1Hmac= b'\xff'*20,
|
||||||
arm7iSha1Hmac= '\xff'*20,
|
arm7iSha1Hmac= b'\xff'*20,
|
||||||
arm9Sha1Hmac= '\xff'*20,
|
arm9Sha1Hmac= b'\xff'*20,
|
||||||
arm9WithSecAreaSha1Hmac= '\xff'*20,
|
arm9WithSecAreaSha1Hmac= b'\xff'*20,
|
||||||
arm9iSha1Hmac= '\xff'*20,
|
arm9iSha1Hmac= b'\xff'*20,
|
||||||
bannerSha1Hmac= '\xff'*20,
|
bannerSha1Hmac= b'\xff'*20,
|
||||||
digestMasterSha1Hmac= '\xff'*20,
|
digestMasterSha1Hmac= b'\xff'*20,
|
||||||
signature= '\xff'*128
|
signature= b'\xff'*128
|
||||||
)
|
)
|
||||||
if args.verbose or args.read:
|
if args.verbose or args.read:
|
||||||
pprint(dict(srlSignedHeader._asdict()))
|
pprint(dict(srlSignedHeader._asdict()))
|
||||||
@ -479,7 +482,7 @@ if not args.read:
|
|||||||
filew.write(data1)
|
filew.write(data1)
|
||||||
filew.write(data2)
|
filew.write(data2)
|
||||||
filew.write(data3[0:0xC80])
|
filew.write(data3[0:0xC80])
|
||||||
filew.write(getBytes('\xff'*16*8))
|
filew.write(b'\xff'*16*8)
|
||||||
writeBlankuntilAddress(filew,0x1000,0x4000)
|
writeBlankuntilAddress(filew,0x1000,0x4000)
|
||||||
|
|
||||||
if arm9Footer.nitrocode != 0xDEC00621:
|
if arm9Footer.nitrocode != 0xDEC00621:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user