Core (v0.9.10):
- Backport changes from r4946 to the 0.9.10 branch.
This commit is contained in:
parent
71231d8c24
commit
50d040a3a1
|
@ -179,61 +179,10 @@ void NDS_DeInit(void)
|
||||||
|
|
||||||
NDS_header * NDS_getROMHeader(void)
|
NDS_header * NDS_getROMHeader(void)
|
||||||
{
|
{
|
||||||
NDS_header * header = new NDS_header;
|
NDS_header *newHeader = new NDS_header;
|
||||||
|
memcpy(newHeader, &gameInfo.header, sizeof(NDS_header));
|
||||||
memcpy(header, &gameInfo.header, sizeof(gameInfo.header));
|
|
||||||
|
return newHeader;
|
||||||
//endian swap necessary fields. It would be better if we made accessors for these. I wonder if you could make a macro for a field accessor that would take the bitsize and do the swap on the fly
|
|
||||||
struct FieldSwap {
|
|
||||||
size_t offset;
|
|
||||||
int bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const FieldSwap fieldSwaps[] = {
|
|
||||||
{ offsetof(NDS_header,makerCode), 2},
|
|
||||||
|
|
||||||
{ offsetof(NDS_header,ARM9src), 4},
|
|
||||||
{ offsetof(NDS_header,ARM9exe), 4},
|
|
||||||
{ offsetof(NDS_header,ARM9cpy), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7src), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7exe), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7cpy), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7binSize), 4},
|
|
||||||
{ offsetof(NDS_header,FNameTblOff), 4},
|
|
||||||
{ offsetof(NDS_header,FNameTblSize), 4},
|
|
||||||
{ offsetof(NDS_header,FATOff), 4},
|
|
||||||
{ offsetof(NDS_header,FATSize), 4},
|
|
||||||
{ offsetof(NDS_header,ARM9OverlayOff), 4},
|
|
||||||
{ offsetof(NDS_header,ARM9OverlaySize), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7OverlayOff), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7OverlaySize), 4},
|
|
||||||
{ offsetof(NDS_header,normalCmd), 4},
|
|
||||||
{ offsetof(NDS_header,Key1Cmd), 4},
|
|
||||||
{ offsetof(NDS_header,IconOff), 4},
|
|
||||||
|
|
||||||
{ offsetof(NDS_header,CRC16), 2},
|
|
||||||
{ offsetof(NDS_header,ROMtimeout), 2},
|
|
||||||
|
|
||||||
{ offsetof(NDS_header,ARM9autoload), 4},
|
|
||||||
{ offsetof(NDS_header,ARM7autoload), 4},
|
|
||||||
{ offsetof(NDS_header,endROMoffset), 4},
|
|
||||||
{ offsetof(NDS_header,HeaderSize), 4},
|
|
||||||
|
|
||||||
{ offsetof(NDS_header, ARM9module), 4},
|
|
||||||
{ offsetof(NDS_header, ARM7module), 4},
|
|
||||||
|
|
||||||
{ offsetof(NDS_header,logoCRC16), 2},
|
|
||||||
{ offsetof(NDS_header,headerCRC16), 2},
|
|
||||||
};
|
|
||||||
|
|
||||||
for(int i=0;i<ARRAY_SIZE(fieldSwaps);i++)
|
|
||||||
switch(fieldSwaps[i].bytes)
|
|
||||||
{
|
|
||||||
case 2: HostWriteWord((u8*)header,fieldSwaps[i].offset,T1ReadWord(header,fieldSwaps[i].offset));
|
|
||||||
case 4: HostWriteLong((u8*)header,fieldSwaps[i].offset,T1ReadLong((u8*)header,fieldSwaps[i].offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,11 +281,7 @@ void GameInfo::populate()
|
||||||
"AUS", // U
|
"AUS", // U
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NDS_header * _header = NDS_getROMHeader();
|
|
||||||
header = *_header;
|
|
||||||
delete _header;
|
|
||||||
|
|
||||||
memset(ROMserial, 0, sizeof(ROMserial));
|
memset(ROMserial, 0, sizeof(ROMserial));
|
||||||
memset(ROMname, 0, sizeof(ROMname));
|
memset(ROMname, 0, sizeof(ROMname));
|
||||||
|
|
||||||
|
@ -376,8 +321,6 @@ void GameInfo::populate()
|
||||||
trim(ROMfullName[i]);
|
trim(ROMfullName[i]);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameInfo::loadROM(std::string fname, u32 type)
|
bool GameInfo::loadROM(std::string fname, u32 type)
|
||||||
|
@ -398,6 +341,67 @@ bool GameInfo::loadROM(std::string fname, u32 type)
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
|
#ifndef LOCAL_LE
|
||||||
|
//endian swap necessary fields. It would be better if we made accessors for these. I wonder if you could make a macro for a field accessor that would take the bitsize and do the swap on the fly
|
||||||
|
struct FieldSwap {
|
||||||
|
const size_t offset;
|
||||||
|
const size_t bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const FieldSwap fieldSwaps[] = {
|
||||||
|
{ offsetof(NDS_header,makerCode), 2},
|
||||||
|
|
||||||
|
{ offsetof(NDS_header,ARM9src), 4},
|
||||||
|
{ offsetof(NDS_header,ARM9exe), 4},
|
||||||
|
{ offsetof(NDS_header,ARM9cpy), 4},
|
||||||
|
{ offsetof(NDS_header,ARM9binSize), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7src), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7exe), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7cpy), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7binSize), 4},
|
||||||
|
{ offsetof(NDS_header,FNameTblOff), 4},
|
||||||
|
{ offsetof(NDS_header,FNameTblSize), 4},
|
||||||
|
{ offsetof(NDS_header,FATOff), 4},
|
||||||
|
{ offsetof(NDS_header,FATSize), 4},
|
||||||
|
{ offsetof(NDS_header,ARM9OverlayOff), 4},
|
||||||
|
{ offsetof(NDS_header,ARM9OverlaySize), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7OverlayOff), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7OverlaySize), 4},
|
||||||
|
{ offsetof(NDS_header,normalCmd), 4},
|
||||||
|
{ offsetof(NDS_header,Key1Cmd), 4},
|
||||||
|
{ offsetof(NDS_header,IconOff), 4},
|
||||||
|
|
||||||
|
{ offsetof(NDS_header,CRC16), 2},
|
||||||
|
{ offsetof(NDS_header,ROMtimeout), 2},
|
||||||
|
|
||||||
|
{ offsetof(NDS_header,ARM9autoload), 4},
|
||||||
|
{ offsetof(NDS_header,ARM7autoload), 4},
|
||||||
|
{ offsetof(NDS_header,endROMoffset), 4},
|
||||||
|
{ offsetof(NDS_header,HeaderSize), 4},
|
||||||
|
|
||||||
|
{ offsetof(NDS_header, ARM9module), 4},
|
||||||
|
{ offsetof(NDS_header, ARM7module), 4},
|
||||||
|
|
||||||
|
{ offsetof(NDS_header,logoCRC16), 2},
|
||||||
|
{ offsetof(NDS_header,headerCRC16), 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
for(size_t i = 0; i < ARRAY_SIZE(fieldSwaps); i++)
|
||||||
|
{
|
||||||
|
const u8 *fieldAddr = (u8 *)&header + fieldSwaps[i].offset;
|
||||||
|
|
||||||
|
switch(fieldSwaps[i].bytes)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
*(u16 *)fieldAddr = LE_TO_LOCAL_16(*(u16 *)fieldAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
*(u32 *)fieldAddr = LE_TO_LOCAL_32(*(u32 *)fieldAddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
cardSize = (128 * 1024) << header.cardSize;
|
cardSize = (128 * 1024) << header.cardSize;
|
||||||
mask = (cardSize - 1);
|
mask = (cardSize - 1);
|
||||||
mask |= (mask >>1);
|
mask |= (mask >>1);
|
||||||
|
@ -421,14 +425,24 @@ bool GameInfo::loadROM(std::string fname, u32 type)
|
||||||
{
|
{
|
||||||
delete [] romdata; romdata = NULL;
|
delete [] romdata; romdata = NULL;
|
||||||
romsize = 0;
|
romsize = 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasRomBanner())
|
if(hasRomBanner())
|
||||||
|
{
|
||||||
memcpy(&banner, romdata + header.IconOff, sizeof(RomBanner));
|
memcpy(&banner, romdata + header.IconOff, sizeof(RomBanner));
|
||||||
|
|
||||||
_isDSiEnhanced = ((*(u32*)(romdata + 0x180) == 0x8D898581U) && (*(u32*)(romdata + 0x184) == 0x8C888480U));
|
banner.version = LE_TO_LOCAL_16(banner.version);
|
||||||
|
banner.crc16 = LE_TO_LOCAL_16(banner.crc16);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++)
|
||||||
|
{
|
||||||
|
banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_isDSiEnhanced = (LE_TO_LOCAL_32(*(u32*)(romdata + 0x180) == 0x8D898581U) && LE_TO_LOCAL_32(*(u32*)(romdata + 0x184) == 0x8C888480U));
|
||||||
fclose(fROM); fROM = NULL;
|
fclose(fROM); fROM = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -437,6 +451,14 @@ bool GameInfo::loadROM(std::string fname, u32 type)
|
||||||
{
|
{
|
||||||
fseek(fROM, header.IconOff + headerOffset, SEEK_SET);
|
fseek(fROM, header.IconOff + headerOffset, SEEK_SET);
|
||||||
fread(&banner, 1, sizeof(RomBanner), fROM);
|
fread(&banner, 1, sizeof(RomBanner), fROM);
|
||||||
|
|
||||||
|
banner.version = LE_TO_LOCAL_16(banner.version);
|
||||||
|
banner.crc16 = LE_TO_LOCAL_16(banner.crc16);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++)
|
||||||
|
{
|
||||||
|
banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fseek(fROM, headerOffset, SEEK_SET);
|
fseek(fROM, headerOffset, SEEK_SET);
|
||||||
lastReadPos = 0;
|
lastReadPos = 0;
|
||||||
|
@ -471,10 +493,10 @@ u32 GameInfo::readROM(u32 pos)
|
||||||
fseek(fROM, pos + headerOffset, SEEK_SET);
|
fseek(fROM, pos + headerOffset, SEEK_SET);
|
||||||
u32 num = fread(&data, 1, 4, fROM);
|
u32 num = fread(&data, 1, 4, fROM);
|
||||||
lastReadPos = (pos + num);
|
lastReadPos = (pos + num);
|
||||||
return data;
|
return LE_TO_LOCAL_32(data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return *(u32*)(romdata + pos);
|
return LE_TO_LOCAL_32(*(u32*)(romdata + pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rom_init_path(const char *filename, const char *physicalName, const char *logicalFilename)
|
static int rom_init_path(const char *filename, const char *physicalName, const char *logicalFilename)
|
||||||
|
@ -2175,7 +2197,7 @@ bool NDS_FakeBoot()
|
||||||
u32 dst = header->ARM9cpy;
|
u32 dst = header->ARM9cpy;
|
||||||
for(u32 i = 0; i < header->ARM9binSize; i+=4)
|
for(u32 i = 0; i < header->ARM9binSize; i+=4)
|
||||||
{
|
{
|
||||||
u32 tmp = (hasSecureArea && ((src >= 0x4000) && (src < 0x8000)))?*(u32*)(gameInfo.secureArea + (src - 0x4000)):gameInfo.readROM(src);
|
u32 tmp = (hasSecureArea && ((src >= 0x4000) && (src < 0x8000)))?LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + (src - 0x4000))):gameInfo.readROM(src);
|
||||||
|
|
||||||
_MMU_write32<ARMCPU_ARM9>(dst, tmp);
|
_MMU_write32<ARMCPU_ARM9>(dst, tmp);
|
||||||
|
|
||||||
|
@ -2215,12 +2237,12 @@ bool NDS_FakeBoot()
|
||||||
{
|
{
|
||||||
//dsi needs this copied later in memory. there are probably a number of things that get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
|
//dsi needs this copied later in memory. there are probably a number of things that get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
|
||||||
for (int i = 0; i < (0x170); i+=4)
|
for (int i = 0; i < (0x170); i+=4)
|
||||||
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, LE_TO_LOCAL_32(gameInfo.readROM(i)));
|
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, gameInfo.readROM(i));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (0x170); i+=4)
|
for (int i = 0; i < (0x170); i+=4)
|
||||||
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, LE_TO_LOCAL_32(gameInfo.readROM(i)));
|
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, gameInfo.readROM(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
//the firmware will be booting to these entrypoint addresses via BX (well, the arm9 at least; is unverified for the arm7)
|
//the firmware will be booting to these entrypoint addresses via BX (well, the arm9 at least; is unverified for the arm7)
|
||||||
|
|
|
@ -95,7 +95,11 @@ void Slot1Comp_Protocol::write_command_KEY1(GC_Command command)
|
||||||
|
|
||||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||||
{
|
{
|
||||||
|
#ifdef LOCAL_LE
|
||||||
u64 cmd64 = bswap64(*(u64*)command.bytes);
|
u64 cmd64 = bswap64(*(u64*)command.bytes);
|
||||||
|
#else
|
||||||
|
u64 cmd64 = *(u64*)command.bytes;
|
||||||
|
#endif
|
||||||
//todo - parse into blocknumber
|
//todo - parse into blocknumber
|
||||||
address = (u32)((cmd64 >> 32) & 0xF000);
|
address = (u32)((cmd64 >> 32) & 0xF000);
|
||||||
}
|
}
|
||||||
|
@ -129,7 +133,12 @@ void Slot1Comp_Protocol::write_command_NORMAL(GC_Command command)
|
||||||
operation = eSlot1Operation_B7_Read;
|
operation = eSlot1Operation_B7_Read;
|
||||||
|
|
||||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||||
|
#ifdef LOCAL_LE
|
||||||
u64 cmd64 = bswap64(*(u64*)command.bytes);
|
u64 cmd64 = bswap64(*(u64*)command.bytes);
|
||||||
|
#else
|
||||||
|
u64 cmd64 = *(u64*)command.bytes;
|
||||||
|
#endif
|
||||||
|
|
||||||
address = (u32)((cmd64 >> 24));
|
address = (u32)((cmd64 >> 24));
|
||||||
length = 0x200;
|
length = 0x200;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ u32 Slot1Comp_Rom::read()
|
||||||
{
|
{
|
||||||
//see B7 for details
|
//see B7 for details
|
||||||
address &= gameInfo.mask; //sanity check
|
address &= gameInfo.mask; //sanity check
|
||||||
u32 ret = *(u32*)(gameInfo.secureArea + (address - 0x4000));
|
u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + (address - 0x4000)));
|
||||||
address = (address&~0xFFF) + ((address+4)&0xFFF);
|
address = (address&~0xFFF) + ((address+4)&0xFFF);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,10 +256,10 @@ typedef int desmume_BOOL;
|
||||||
#ifdef LOCAL_BE /* local arch is big endian */
|
#ifdef LOCAL_BE /* local arch is big endian */
|
||||||
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||||
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||||
# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff0000)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||||
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||||
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||||
# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff0000)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||||
#else /* local arch is little endian */
|
#else /* local arch is little endian */
|
||||||
# define LE_TO_LOCAL_16(x) (x)
|
# define LE_TO_LOCAL_16(x) (x)
|
||||||
# define LE_TO_LOCAL_32(x) (x)
|
# define LE_TO_LOCAL_32(x) (x)
|
||||||
|
|
|
@ -68,14 +68,14 @@
|
||||||
*/
|
*/
|
||||||
int DetectRomType(const Header& header, char* secure)
|
int DetectRomType(const Header& header, char* secure)
|
||||||
{
|
{
|
||||||
unsigned int * data = (unsigned int*)(secure);
|
const u64 data = LE_TO_LOCAL_64(*(u64 *)secure);
|
||||||
|
|
||||||
//this is attempting to check for an utterly invalid nds header
|
//this is attempting to check for an utterly invalid nds header
|
||||||
if(header.unitcode < 0 && header.unitcode > 3) return ROMTYPE_INVALID;
|
if(header.unitcode > 3) return ROMTYPE_INVALID;
|
||||||
|
|
||||||
if (header.arm9_rom_offset < 0x4000) return ROMTYPE_HOMEBREW;
|
if (header.arm9_rom_offset < 0x4000) return ROMTYPE_HOMEBREW;
|
||||||
if (data[0] == 0x00000000 && data[1] == 0x00000000) return ROMTYPE_MULTIBOOT;
|
else if (data == 0x0000000000000000ULL) return ROMTYPE_MULTIBOOT;
|
||||||
if (data[0] == 0xE7FFDEFF && data[1] == 0xE7FFDEFF) return ROMTYPE_NDSDUMPED;
|
else if (data == 0xE7FFDEFFE7FFDEFFULL) return ROMTYPE_NDSDUMPED;
|
||||||
//TODO
|
//TODO
|
||||||
//for (int i=0x200; i<0x4000; i++)
|
//for (int i=0x200; i<0x4000; i++)
|
||||||
// if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;)
|
// if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;)
|
||||||
|
|
Loading…
Reference in New Issue