addons:
- GBAgame: add flash memory support. Pokemons migrate work now (need use external BIOS without SWI, I will fix it later) :)
This commit is contained in:
parent
8e53ad6bd7
commit
7f418a40e0
|
@ -29,12 +29,217 @@
|
|||
|
||||
//SRAM is going to be stored just above the rom.
|
||||
//that is convenient for us, since it mirrors the nds memory map
|
||||
#define GBA_ROMSIZE (32 * 1024 * 1024) + 1
|
||||
#define GBA_SAVESIZE (512 * 1024) + 1
|
||||
|
||||
static u8 *GBArom = NULL;
|
||||
static u8 *saveData = NULL;
|
||||
static u8 saveType = 0xFF;
|
||||
|
||||
#define GBA_ROMSIZE (32 * 1024 * 1024)
|
||||
#define GBA_RAMSIZE (64 * 1024)
|
||||
#define GBA_SIZE (GBA_ROMSIZE+GBA_RAMSIZE)
|
||||
//================================================================================== Flash GBA
|
||||
typedef struct
|
||||
{
|
||||
u8 state;
|
||||
u8 cmd;
|
||||
u32 size;
|
||||
u8 idDevice;
|
||||
u8 idManufacturer;
|
||||
u8 bank;
|
||||
} FLASH_GBA;
|
||||
|
||||
FLASH_GBA gbaFlash = {0};
|
||||
|
||||
static void gbaWriteFlash(u32 adr, u8 val)
|
||||
{
|
||||
switch (gbaFlash.state)
|
||||
{
|
||||
case 0:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
if (val == 0xF0)
|
||||
{
|
||||
//INFO("GBAslot: Flash: reset\n");
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
if (val == 0xAA)
|
||||
{
|
||||
gbaFlash.state = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (adr == 0x0A000000)
|
||||
{
|
||||
if (gbaFlash.cmd == 0xB0)
|
||||
{
|
||||
gbaFlash.bank = val;
|
||||
gbaFlash.cmd = 0;
|
||||
//INFO("GBAslot: Flash: change bank %i\n", val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 2;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
//INFO("GBAslot: Flash: send command flash 0x%02X\n", val);
|
||||
switch (val)
|
||||
{
|
||||
case 0x80: // Erase
|
||||
gbaFlash.state = 0x80;
|
||||
break;
|
||||
|
||||
case 0xA0: // Write
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
}
|
||||
gbaFlash.cmd = val;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
// erase
|
||||
case 0x80:
|
||||
if ( (adr == 0x0A005555) && (val == 0xAA) )
|
||||
{
|
||||
gbaFlash.state = 0x81;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 0x82;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x82:
|
||||
if (val == 0x30)
|
||||
{
|
||||
u32 ofs = (adr & 0x0000F000);
|
||||
//INFO("GBAslot: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000);
|
||||
for (int i = ofs; i < (ofs + 0x1000); i++)
|
||||
saveData[i] = 0xFF;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbaFlash.cmd == 0xA0) // write
|
||||
{
|
||||
saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)] = val;
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
//INFO("GBAslot: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val);
|
||||
}
|
||||
|
||||
static u8 gbaReadFlash(u32 adr)
|
||||
{
|
||||
if (gbaFlash.cmd == 0)
|
||||
{
|
||||
//INFO("GBAslot: flash read at 0x%08X = 0x%02X\n", adr, saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)]);
|
||||
return saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)];
|
||||
}
|
||||
|
||||
//INFO("GBAslot: flash read at 0x%08X\n", adr);
|
||||
|
||||
switch (gbaFlash.cmd)
|
||||
{
|
||||
case 0x90: // Chip Identification
|
||||
if (adr == 0x0A000000) return gbaFlash.idManufacturer;
|
||||
if (adr == 0x0A000001) return gbaFlash.idDevice;
|
||||
break;
|
||||
|
||||
case 0xF0: //
|
||||
//INFO("GBAslot: Flash: reset2\n");
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
break;
|
||||
|
||||
case 0xB0: // Bank switching
|
||||
break;
|
||||
|
||||
default:
|
||||
INFO("GBAslot: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
//==================================================================================
|
||||
|
||||
static u8 getSaveTypeGBA(const u8 *data, const u32 size)
|
||||
{
|
||||
u8 type = 0;
|
||||
u8 *dat = (u8 *)data;
|
||||
|
||||
for (int i = 0; i < (size / 4); i++)
|
||||
{
|
||||
u32 tmp = T1ReadLong(dat, i);
|
||||
|
||||
if (tmp == 0x52504545)
|
||||
{
|
||||
if(memcmp(dat, "EEPROM_", 7) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp == 0x4D415253)
|
||||
{
|
||||
if(memcmp(dat, "SRAM_", 5) == 0)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp == 0x53414C46)
|
||||
{
|
||||
if(memcmp(dat, "FLASH1M_", 8) == 0)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp == 0x52494953)
|
||||
{
|
||||
if(memcmp(dat, "SIIRTC_V", 8) == 0)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
if(memcmp(dat, "FLASH", 5) == 0)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
dat += 4;
|
||||
}
|
||||
|
||||
return 0xFF; // NONE
|
||||
}
|
||||
|
||||
static BOOL GBAgame_init(void)
|
||||
{
|
||||
|
@ -43,20 +248,29 @@ static BOOL GBAgame_init(void)
|
|||
|
||||
static void GBAgame_reset(void)
|
||||
{
|
||||
memset(&gbaFlash, 0, sizeof(gbaFlash));
|
||||
|
||||
if (GBArom)
|
||||
{
|
||||
delete [] GBArom;
|
||||
GBArom = NULL;
|
||||
}
|
||||
GBArom = new u8 [GBA_SIZE];
|
||||
memset(GBArom, 0, GBA_SIZE);
|
||||
GBArom = new u8 [GBA_ROMSIZE];
|
||||
memset(GBArom, 0xFF, GBA_ROMSIZE);
|
||||
|
||||
if (saveData)
|
||||
{
|
||||
delete [] saveData;
|
||||
saveData = NULL;
|
||||
}
|
||||
saveData = new u8 [GBA_SAVESIZE];
|
||||
memset(saveData, 0xFF, GBA_SAVESIZE);
|
||||
|
||||
if (!strlen(GBAgameName)) return;
|
||||
FILE *fgame = 0;
|
||||
|
||||
fgame = fopen(GBAgameName,"rb");
|
||||
if (!fgame) return;
|
||||
INFO("Loaded \"%s\" in GBA slot\n", GBAgameName);
|
||||
fseek(fgame, 0, SEEK_END);
|
||||
u32 size = ftell(fgame);
|
||||
rewind(fgame);
|
||||
|
@ -66,9 +280,11 @@ static void GBAgame_reset(void)
|
|||
fclose(fgame);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fgame);
|
||||
|
||||
saveType = getSaveTypeGBA(GBArom, size);
|
||||
INFO("Loaded \"%s\" in GBA slot (save type %i)\n", GBAgameName, saveType);
|
||||
|
||||
//try loading the sram
|
||||
char * dot = strrchr(GBAgameName,'.');
|
||||
if(!dot) return;
|
||||
|
@ -76,11 +292,32 @@ static void GBAgame_reset(void)
|
|||
sram_fname.resize(dot-GBAgameName);
|
||||
sram_fname += ".sav";
|
||||
fgame = fopen(sram_fname.c_str(),"rb");
|
||||
if(fgame)
|
||||
if(!fgame) return;
|
||||
|
||||
fseek(fgame, 0, SEEK_END);
|
||||
size = ftell(fgame);
|
||||
rewind(fgame);
|
||||
|
||||
if (!fread(saveData, 1, size, fgame))
|
||||
{
|
||||
fread(GBArom+GBA_ROMSIZE,1,GBA_RAMSIZE,fgame);
|
||||
fclose(fgame);
|
||||
return;
|
||||
}
|
||||
fclose(fgame);
|
||||
|
||||
gbaFlash.size = size;
|
||||
if (gbaFlash.size <= (64 * 1024))
|
||||
{
|
||||
gbaFlash.idDevice = 0x1B;
|
||||
gbaFlash.idManufacturer = 0x32;
|
||||
}
|
||||
else
|
||||
{
|
||||
gbaFlash.idDevice = 0x09;
|
||||
gbaFlash.idManufacturer = 0xC2;
|
||||
}
|
||||
|
||||
INFO("Loaded save \"%s\" in GBA slot\n", sram_fname.c_str());
|
||||
}
|
||||
|
||||
static void GBAgame_close(void)
|
||||
|
@ -90,35 +327,109 @@ static void GBAgame_close(void)
|
|||
delete [] GBArom;
|
||||
GBArom = NULL;
|
||||
}
|
||||
|
||||
if (saveData)
|
||||
{
|
||||
delete [] saveData;
|
||||
saveData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void GBAgame_config(void) {}
|
||||
static void GBAgame_write08(u32 adr, u8 val){}
|
||||
static void GBAgame_write16(u32 adr, u16 val) {}
|
||||
static void GBAgame_write32(u32 adr, u32 val) {}
|
||||
|
||||
static void GBAgame_write08(u32 adr, u8 val)
|
||||
{
|
||||
//INFO("GBAslot: write08 at 0x%08X val=0x%02X\n", adr, val);
|
||||
if ( (adr >= 0x0A000000) && (adr < 0x0A010000) )
|
||||
{
|
||||
switch (saveType)
|
||||
{
|
||||
case 3: // Flash
|
||||
case 5:
|
||||
gbaWriteFlash(adr, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//return (u8)T1ReadByte(saveData, (adr - 0x0A000000));
|
||||
}
|
||||
}
|
||||
static void GBAgame_write16(u32 adr, u16 val)
|
||||
{
|
||||
//INFO("GBAgame: write16 at 0x%08X val=0x%04X\n", adr, val);
|
||||
}
|
||||
|
||||
static void GBAgame_write32(u32 adr, u32 val)
|
||||
{
|
||||
//INFO("GBAgame: write32 at 0x%08X val=0x%08X\n", adr, val);
|
||||
}
|
||||
|
||||
static u8 GBAgame_read08(u32 adr)
|
||||
{
|
||||
//INFO("Read08 at 0x%08X value 0x%02X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)));
|
||||
if ( (adr >= 0x08000004) && (adr < 0x080000A0) )
|
||||
return MMU.MMU_MEM[0][0xFF][(adr +0x1C) & MMU.MMU_MASK[0][0xFF]];
|
||||
return (u8)T1ReadByte(GBArom, (adr - 0x08000000));
|
||||
|
||||
//INFO("GBAgame: read08 at 0x%08X value 0x%02X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)));
|
||||
|
||||
if (adr < 0x0A000000)
|
||||
return (u8)T1ReadByte(GBArom, (adr - 0x08000000));
|
||||
|
||||
if (adr < 0x0A010000)
|
||||
{
|
||||
switch (saveType)
|
||||
{
|
||||
case 3: // Flash
|
||||
case 5:
|
||||
return gbaReadFlash(adr);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//INFO("Read08 at 0x%08X val=0x%08X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)) );
|
||||
return (u8)T1ReadByte(saveData, (adr - 0x0A000000));
|
||||
}
|
||||
|
||||
//INFO("Read08 at 0x%08X val=0x%08X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)) );
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
static u16 GBAgame_read16(u32 adr)
|
||||
{
|
||||
//INFO("Read16 at 0x%08X value 0x%04X\n", adr, (u16)T1ReadWord(GBArom, (adr - 0x08000000)));
|
||||
if ( (adr >= 0x08000004) && (adr < 0x080000A0) )
|
||||
return T1ReadWord(MMU.MMU_MEM[0][0xFF], (adr +0x1C) & MMU.MMU_MASK[0][0xFF]);
|
||||
return (u16)T1ReadWord(GBArom, (adr - 0x08000000));
|
||||
|
||||
//INFO("GBAgame: read16 at 0x%08X value 0x%04X\n", adr, (u16)T1ReadWord(GBArom, (adr - 0x08000000)));
|
||||
|
||||
if (adr < 0x0A000000)
|
||||
return (u16)T1ReadWord(GBArom, (adr - 0x08000000));
|
||||
|
||||
if (adr < 0x0A010000)
|
||||
{
|
||||
//INFO("GBAslot: flash read16 at 0x%08X\n", adr);
|
||||
return (u16)T1ReadWord(saveData, (adr - 0x0A000000));
|
||||
}
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
static u32 GBAgame_read32(u32 adr)
|
||||
{
|
||||
//INFO("Read32 at 0x%08X value 0x%08X\n", adr, (u32)T1ReadLong(GBArom, (adr - 0x08000000)));
|
||||
if ( (adr >= 0x08000004) && (adr < 0x080000A0) )
|
||||
return T1ReadLong(MMU.MMU_MEM[0][0xFF], (adr +0x1C) & MMU.MMU_MASK[0][0xFF]);
|
||||
return (u32)T1ReadLong(GBArom, (adr - 0x08000000));
|
||||
|
||||
//INFO("GBAgame: read32 at 0x%08X value 0x%08X\n", adr, (u32)T1ReadLong(GBArom, (adr - 0x08000000)));
|
||||
|
||||
if (adr < 0x0A000000)
|
||||
return (u32)T1ReadLong(GBArom, (adr - 0x08000000));
|
||||
|
||||
if (adr < 0x0A010000)
|
||||
{
|
||||
//INFO("GBAslot: flash read32 at 0x%08X\n", adr);
|
||||
return (u32)T1ReadLong(saveData, (adr - 0x0A000000));
|
||||
}
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static void GBAgame_info(char *info)
|
||||
|
|
Loading…
Reference in New Issue