Use enums and fix warnings in gba.cpp

Also fix not erasing the GBA save before writing
This commit is contained in:
Pk11 2021-11-02 22:02:01 -05:00
parent 568c4dde5f
commit ae3ddd0c6c
3 changed files with 91 additions and 134 deletions

View File

@ -757,8 +757,11 @@ void gbaCartSaveDump(const char *filename) {
font->print(0, 1, false, "Do not remove the GBA cart."); font->print(0, 1, false, "Do not remove the GBA cart.");
font->update(false); font->update(false);
u8 type = gbaGetSaveType(); saveTypeGBA type = gbaGetSaveType();
u32 size = gbaGetSaveSize(type); u32 size = gbaGetSaveSize(type);
if(size == 0)
return;
u8 *buffer = new u8[size]; u8 *buffer = new u8[size];
gbaReadSave(buffer, 0, size, type); gbaReadSave(buffer, 0, size, type);
@ -788,8 +791,10 @@ void gbaCartSaveRestore(const char *filename) {
} while (!(pressed & (KEY_A | KEY_B))); } while (!(pressed & (KEY_A | KEY_B)));
if (pressed & KEY_A) { if (pressed & KEY_A) {
u8 type = gbaGetSaveType(); saveTypeGBA type = gbaGetSaveType();
u32 size = gbaGetSaveSize(type); u32 size = gbaGetSaveSize(type);
if(size == 0)
return;
FILE *sourceFile = fopen(filename, "rb"); FILE *sourceFile = fopen(filename, "rb");
u8 *buffer = new u8[size]; u8 *buffer = new u8[size];
@ -810,6 +815,7 @@ void gbaCartSaveRestore(const char *filename) {
size_t length = ftell(sourceFile); size_t length = ftell(sourceFile);
fseek(sourceFile, 0, SEEK_SET); fseek(sourceFile, 0, SEEK_SET);
if(length != size) { if(length != size) {
delete[] buffer;
fclose(sourceFile); fclose(sourceFile);
saveWriteFailMsg(true); saveWriteFailMsg(true);
@ -834,6 +840,7 @@ void gbaCartSaveRestore(const char *filename) {
font->print(0, 1, false, "Do not remove the GBA cart."); font->print(0, 1, false, "Do not remove the GBA cart.");
font->update(false); font->update(false);
gbaFormatSave(type);
gbaWriteSave(0, buffer, size, type); gbaWriteSave(0, buffer, size, type);
delete[] buffer; delete[] buffer;

View File

@ -59,38 +59,6 @@ inline u32 max(u32 i, u32 j) { return (i > j) ? i : j;}
#define MAGIC_H1M_ 0x5f4d3148 #define MAGIC_H1M_ 0x5f4d3148
saveTypeGBA GetSlot2SaveType(cartTypeGBA type) {
if (type == CART_GBA_NONE)
return SAVE_GBA_NONE;
// Search for any one of the magic version strings in the ROM.
uint32 *data = (uint32*)0x08000000;
for (int i = 0; i < (0x02000000 >> 2); i++, data++) {
if (*data == MAGIC_EEPR)
return SAVE_GBA_EEPROM_8; // TODO: Try to figure out 512 bytes version...
if (*data == MAGIC_SRAM)
return SAVE_GBA_SRAM_32;
if (*data == MAGIC_FLAS) {
uint32 *data2 = data + 1;
if (*data2 == MAGIC_H1M_)
return SAVE_GBA_FLASH_128;
else
return SAVE_GBA_FLASH_64;
}
}
return SAVE_GBA_NONE;
};
cartTypeGBA GetSlot2Type(uint32 id)
{
if (id == 0x53534150)
// All conventional GBA flash cards identify themselves as "PASS"
return CART_GBA_FLASH;
else {
return CART_GBA_GAME;
}
};
// ----------------------------------------------------------- // -----------------------------------------------------------
bool gbaIsGame() bool gbaIsGame()
@ -106,58 +74,58 @@ bool gbaIsGame()
return false; return false;
} }
uint8 gbaGetSaveType() saveTypeGBA gbaGetSaveType() {
{
// Search for any one of the magic version strings in the ROM. They are always dword-aligned. // Search for any one of the magic version strings in the ROM. They are always dword-aligned.
uint32 *data = (uint32*)0x08000000; uint32 *data = (uint32*)0x08000000;
for (int i = 0; i < (0x02000000 >> 2); i++, data++) { for (int i = 0; i < (0x02000000 >> 2); i++, data++) {
if (*data == MAGIC_EEPR) { if (*data == MAGIC_EEPR) {
// 2 versions: 512 bytes / 8 kB return SAVE_GBA_EEPROM_8; // TODO: Try to figure out 512 bytes version...
return 2; // TODO: Try to figure out how to ID the 512 bytes version... hard way? write/restore!
} } else if (*data == MAGIC_SRAM) {
if (*data == MAGIC_SRAM) {
// *always* 32 kB // *always* 32 kB
return 3; return SAVE_GBA_SRAM_32;
} } else if (*data == MAGIC_FLAS) {
if (*data == MAGIC_FLAS) {
// 64 kB oder 128 kB // 64 kB oder 128 kB
uint32 *data2 = data + 1; uint32 *data2 = data + 1;
if (*data2 == MAGIC_H1M_) if (*data2 == MAGIC_H1M_)
return 5; return SAVE_GBA_FLASH_128;
else else
return 4; return SAVE_GBA_FLASH_64;
} }
} }
return 0; return SAVE_GBA_NONE;
} }
uint32 gbaGetSaveSizeLog2(uint8 type) uint32 gbaGetSaveSizeLog2(saveTypeGBA type)
{ {
if (type == 255) if (type == SAVE_GBA_NONE)
type = gbaGetSaveType(); type = gbaGetSaveType();
switch (type) { switch (type) {
case 1: case SAVE_GBA_EEPROM_05:
return 9; return 9;
case 2: case SAVE_GBA_EEPROM_8:
return 13; return 13;
case 3: case SAVE_GBA_SRAM_32:
return 15; return 15;
case 4: case SAVE_GBA_FLASH_64:
return 16; return 16;
case 5: case SAVE_GBA_FLASH_128:
return 17; return 17;
case 0: case SAVE_GBA_NONE:
default: default:
return 0; return 0;
} }
} }
uint32 gbaGetSaveSize(uint8 type) uint32 gbaGetSaveSize(saveTypeGBA type)
{ {
return 1 << gbaGetSaveSizeLog2(type); if (type == SAVE_GBA_NONE)
return 0;
else
return 1 << gbaGetSaveSizeLog2(type);
} }
// local function // local function
@ -342,16 +310,16 @@ void gbaEepromWrite8Bytes(u8 *out, u32 addr, bool short_addr = false)
#endif #endif
} }
bool gbaReadSave(u8 *dst, u32 src, u32 len, u8 type) bool gbaReadSave(u8 *dst, u32 src, u32 len, saveTypeGBA type)
{ {
int nbanks = 2; // for type 4,5 int nbanks = 2; // for type 4,5
bool eeprom_long = true; bool eeprom_long = true;
switch (type) { switch (type) {
case 1: { case SAVE_GBA_EEPROM_05: {
eeprom_long = false; eeprom_long = false;
} }
case 2: { case SAVE_GBA_EEPROM_8: {
int start, end; int start, end;
start = src >> 3; start = src >> 3;
end = (src + len - 1) >> 3; end = (src + len - 1) >> 3;
@ -364,7 +332,7 @@ bool gbaReadSave(u8 *dst, u32 src, u32 len, u8 type)
free(tmp); free(tmp);
break; break;
} }
case 3: { case SAVE_GBA_SRAM_32: {
// SRAM: blind copy // SRAM: blind copy
int start = 0x0a000000 + src; int start = 0x0a000000 + src;
u8 *tmpsrc = (u8*)start; u8 *tmpsrc = (u8*)start;
@ -373,19 +341,19 @@ bool gbaReadSave(u8 *dst, u32 src, u32 len, u8 type)
*dst = *tmpsrc; *dst = *tmpsrc;
break; break;
} }
case 4: case SAVE_GBA_FLASH_64:
// FLASH - must be opend by register magic, then blind copy // FLASH - must be opend by register magic, then blind copy
nbanks = 1; nbanks = 1;
case 5: case SAVE_GBA_FLASH_128:
for (int j = 0; j < nbanks; j++) { for (int j = 0; j < nbanks; j++) {
// we need to wait a few cycles before the hardware reacts! // we need to wait a few cycles before the hardware reacts!
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xb0; *(vu8*)0x0a005555 = 0xb0;
swiDelay(10); swiDelay(10);
*(u8*)0x0a000000 = (u8)j; *(vu8*)0x0a000000 = (u8)j;
swiDelay(10); swiDelay(10);
u32 start, sublen; u32 start, sublen;
if (j == 0) { if (j == 0) {
@ -401,27 +369,29 @@ bool gbaReadSave(u8 *dst, u32 src, u32 len, u8 type)
*dst = *tmpsrc; *dst = *tmpsrc;
} }
break; break;
case SAVE_GBA_NONE:
break;
} }
return true; return true;
} }
bool gbaIsAtmel() bool gbaIsAtmel()
{ {
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0x90; // ID mode *(vu8*)0x0a005555 = 0x90; // ID mode
swiDelay(10); swiDelay(10);
// //
u8 dev = *(u8*)0x0a000001; u8 dev = *(u8*)0x0a000001;
u8 man = *(u8*)0x0a000000; u8 man = *(u8*)0x0a000000;
// //
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xf0; // leave ID mode *(vu8*)0x0a005555 = 0xf0; // leave ID mode
swiDelay(10); swiDelay(10);
// //
//char txt[128]; //char txt[128];
@ -433,16 +403,16 @@ bool gbaIsAtmel()
return false; return false;
} }
bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type) bool gbaWriteSave(u32 dst, u8 *src, u32 len, saveTypeGBA type)
{ {
int nbanks = 2; // for type 4,5 int nbanks = 2; // for type 4,5
bool eeprom_long = true; bool eeprom_long = true;
switch (type) { switch (type) {
case 1: { case SAVE_GBA_EEPROM_05: {
eeprom_long = false; eeprom_long = false;
} }
case 2: { case SAVE_GBA_EEPROM_8: {
/* /*
int start, end; int start, end;
start = src >> 3; start = src >> 3;
@ -457,7 +427,7 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
*/ */
break; break;
} }
case 3: { case SAVE_GBA_SRAM_32: {
// SRAM: blind write // SRAM: blind write
u32 start = 0x0a000000 + dst; u32 start = 0x0a000000 + dst;
u8 *tmpdst = (u8*)start; u8 *tmpdst = (u8*)start;
@ -468,7 +438,7 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
} }
break; break;
} }
case 4: { case SAVE_GBA_FLASH_64: {
bool atmel = gbaIsAtmel(); bool atmel = gbaIsAtmel();
if (atmel) { if (atmel) {
// only 64k, no bank switching required // only 64k, no bank switching required
@ -476,11 +446,11 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
u8 *tmpdst = (u8*)(0x0a000000+dst); u8 *tmpdst = (u8*)(0x0a000000+dst);
for (u32 j = 0; j < len7; j++) { for (u32 j = 0; j < len7; j++) {
u32 ime = enterCriticalSection(); u32 ime = enterCriticalSection();
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xa0; *(vu8*)0x0a005555 = 0xa0;
swiDelay(10); swiDelay(10);
for (int i = 0; i < 128; i++) { for (int i = 0; i < 128; i++) {
*tmpdst = *src; *tmpdst = *src;
@ -493,18 +463,18 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
} }
nbanks = 1; nbanks = 1;
} }
case 5: case SAVE_GBA_FLASH_128:
// FLASH - must be opend by register magic, erased and then rewritten // FLASH - must be opend by register magic, erased and then rewritten
// FIXME: currently, you can only write "all or nothing" // FIXME: currently, you can only write "all or nothing"
nbanks = 2; nbanks = 2;
for (int j = 0; j < nbanks; j++) { for (int j = 0; j < nbanks; j++) {
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xb0; *(vu8*)0x0a005555 = 0xb0;
swiDelay(10); swiDelay(10);
*(u8*)0x0a000000 = (u8)j; *(vu8*)0x0a000000 = (u8)j;
swiDelay(10); swiDelay(10);
// //
u32 start, sublen; u32 start, sublen;
@ -519,11 +489,11 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
sysSetBusOwners(true, true); sysSetBusOwners(true, true);
for (u32 i = 0; i < sublen; i++, tmpdst++, src++) { for (u32 i = 0; i < sublen; i++, tmpdst++, src++) {
// we need to wait a few cycles before the hardware reacts! // we need to wait a few cycles before the hardware reacts!
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xa0; // write byte command *(vu8*)0x0a005555 = 0xa0; // write byte command
swiDelay(10); swiDelay(10);
// //
*tmpdst = *src; *tmpdst = *src;
@ -533,42 +503,46 @@ bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type)
} }
} }
break; break;
case SAVE_GBA_NONE:
break;
} }
return true; return true;
} }
bool gbaFormatSave(u8 type) bool gbaFormatSave(saveTypeGBA type)
{ {
switch (type) { switch (type) {
case 1: case SAVE_GBA_EEPROM_05:
case 2: case SAVE_GBA_EEPROM_8:
// TODO: eeprom is not supported yet // TODO: eeprom is not supported yet
break; break;
case 3: case SAVE_GBA_SRAM_32:
{ {
// memset(data, 0, 1 << 15); // memset(data, 0, 1 << 15);
u8 *data = new u8[1 << 15](); u8 *data = new u8[1 << 15]();
gbaWriteSave(0, data, 1 << 15, 3); gbaWriteSave(0, data, 1 << 15, SAVE_GBA_SRAM_32);
delete[] data; delete[] data;
} }
break; break;
case 4: case SAVE_GBA_FLASH_64:
case 5: case SAVE_GBA_FLASH_128:
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0x80; // erase command *(vu8*)0x0a005555 = 0x80; // erase command
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0xaa; *(vu8*)0x0a005555 = 0xaa;
swiDelay(10); swiDelay(10);
*(u8*)0x0a002aaa = 0x55; *(vu8*)0x0a002aaa = 0x55;
swiDelay(10); swiDelay(10);
*(u8*)0x0a005555 = 0x10; // erase entire chip *(vu8*)0x0a005555 = 0x10; // erase entire chip
swiDelay(10); swiDelay(10);
while (*(u8*)0x0a000000 != 0xff) while (*(u8*)0x0a000000 != 0xff)
swiDelay(10); swiDelay(10);
break; break;
case SAVE_GBA_NONE:
break;
} }
return true; return true;
} }

View File

@ -22,18 +22,8 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef __SLOT2_H__ #ifndef __GBA_H__
#define __SLOT2_H__ #define __GBA_H__
enum cartTypeGBA {
CART_GBA_NONE = 0,
CART_GBA_GAME,
CART_GBA_EMULATOR,
CART_GBA_3IN1_256_V1,
CART_GBA_3IN1_256_V2,
CART_GBA_3IN1_512_V3,
CART_GBA_FLASH
};
enum saveTypeGBA { enum saveTypeGBA {
SAVE_GBA_NONE = 0, SAVE_GBA_NONE = 0,
@ -44,30 +34,16 @@ enum saveTypeGBA {
SAVE_GBA_FLASH_128 // 128k SAVE_GBA_FLASH_128 // 128k
}; };
struct dataSlot2 {
cartTypeGBA type;
saveTypeGBA save;
uint32 ez_ID;
union {
char cid[5];
uint32 iid;
};
char name[13];
};
cartTypeGBA GetSlot2Type(uint32 id);
saveTypeGBA GetSlot2SaveType(cartTypeGBA type);
// -------------------- // --------------------
bool gbaIsGame(); bool gbaIsGame();
uint8 gbaGetSaveType(); saveTypeGBA gbaGetSaveType();
uint32 gbaGetSaveSize(uint8 type = 255); uint32 gbaGetSaveSize(saveTypeGBA type = SAVE_GBA_NONE);
uint32 gbaGetSaveSizeLog2(uint8 type = 255); uint32 gbaGetSaveSizeLog2(saveTypeGBA type = SAVE_GBA_NONE);
bool gbaReadSave(u8 *dst, u32 src, u32 len, u8 type); bool gbaReadSave(u8 *dst, u32 src, u32 len, saveTypeGBA type);
bool gbaWriteSave(u32 dst, u8 *src, u32 len, u8 type); bool gbaWriteSave(u32 dst, u8 *src, u32 len, saveTypeGBA type);
bool gbaFormatSave(u8 type); bool gbaFormatSave(saveTypeGBA type);
#endif // __SLOT2_H__ #endif // __SLOT2_H__