aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRaphaël Zumer <rzumer@tebako.net>2019-12-10 16:36:38 -0500
committerRaphaël Zumer <rzumer@tebako.net>2019-12-10 16:36:39 -0500
commit9128517b9086b9508dac375fb2764dcdc9ea3947 (patch)
tree3d68ccd534489ad4a65cb27e86bb532e51c5cd80 /src
parent00929371481ce0fa29adfe5a58e364f27713099a (diff)
Add basic GBA GPIO support, solar sensor detection
Diffstat (limited to 'src')
-rw-r--r--src/GBACart.cpp77
-rw-r--r--src/GBACart.h2
2 files changed, 76 insertions, 3 deletions
diff --git a/src/GBACart.cpp b/src/GBACart.cpp
index b544519..75bc1dc 100644
--- a/src/GBACart.cpp
+++ b/src/GBACart.cpp
@@ -448,11 +448,34 @@ void Write32(u32 addr, u32 val)
namespace GBACart
{
+const char SOLAR_SENSOR_GAMECODES[10][5] =
+{
+ "U3IJ", // Bokura no Taiyou - Taiyou Action RPG (Japan)
+ "U3IE", // Boktai - The Sun Is in Your Hand (USA)
+ "U3IP", // Boktai - The Sun Is in Your Hand (Europe)
+ "U32J", // Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)
+ "U32E", // Boktai 2 - Solar Boy Django (USA)
+ "U32P", // Boktai 2 - Solar Boy Django (Europe)
+ "U33J", // Shin Bokura no Taiyou - Gyakushuu no Sabata (Japan)
+ "A3IJ" // Boktai - The Sun Is in Your Hand (USA) (Sample)
+};
+
+
+struct GPIO
+{
+ bool has_solar_sensor;
+ u16 data;
+ u16 direction;
+ u16 control;
+};
+
+
bool CartInserted;
u8* CartROM;
u32 CartROMSize;
u32 CartCRC;
u32 CartID;
+GPIO CartGPIO; // overridden GPIO parameters
bool Init()
@@ -477,6 +500,7 @@ void Reset()
if (CartROM) delete[] CartROM;
CartROM = NULL;
CartROMSize = 0;
+ CartGPIO = {};
GBACart_SRAM::Reset();
}
@@ -506,10 +530,20 @@ bool LoadROM(const char* path, const char* sram)
while (CartROMSize < len)
CartROMSize <<= 1;
- u32 gamecode;
+ char gamecode[5] = { '\0' };
fseek(f, 0xAC, SEEK_SET);
- fread(&gamecode, 4, 1, f);
- printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24);
+ fread(&gamecode, 1, 4, f);
+ printf("Game code: %s\n", gamecode);
+
+ for (int i = 0; i < sizeof(SOLAR_SENSOR_GAMECODES)/sizeof(SOLAR_SENSOR_GAMECODES[0]); i++)
+ {
+ if (strcmp(gamecode, SOLAR_SENSOR_GAMECODES[i]) == 0) CartGPIO.has_solar_sensor = true;
+ }
+
+ if (CartGPIO.has_solar_sensor)
+ {
+ printf("GBA solar sensor support detected!\n");
+ }
CartROM = new u8[CartROMSize];
memset(CartROM, 0, CartROMSize);
@@ -536,4 +570,41 @@ void RelocateSave(const char* path, bool write)
GBACart_SRAM::RelocateSave(path, write);
}
+// referenced from mGBA
+void WriteGPIO(u32 addr, u16 val)
+{
+ switch (addr)
+ {
+ case 0xC4:
+ CartGPIO.data &= ~CartGPIO.direction;
+ CartGPIO.data |= val & CartGPIO.direction;
+ // TODO: process pins
+ break;
+ case 0xC6:
+ CartGPIO.direction = val;
+ break;
+ case 0xC8:
+ CartGPIO.control = val;
+ break;
+ default:
+ printf("Unknown GBA GPIO write 0x%02X @ 0x%04X\n", val, addr);
+ }
+
+ // write the GPIO values in the ROM (if writable)
+ if (CartGPIO.control & 1)
+ {
+ *(u16*)&CartROM[addr] = CartGPIO.data;
+ *(u16*)&CartROM[addr + 2] = CartGPIO.direction;
+ *(u16*)&CartROM[addr + 4] = CartGPIO.control;
+ }
+ else
+ {
+ // GBATEK: "in write-only mode, reads return 00h (or [possibly] other data (...))"
+ // ambiguous, but mGBA sets ROM to 00h when switching to write-only, so do the same
+ *(u16*)&CartROM[addr] = 0;
+ *(u16*)&CartROM[addr + 2] = 0;
+ *(u16*)&CartROM[addr + 4] = 0;
+ }
+}
+
}
diff --git a/src/GBACart.h b/src/GBACart.h
index 81fb222..22a3a60 100644
--- a/src/GBACart.h
+++ b/src/GBACart.h
@@ -55,6 +55,8 @@ void DoSavestate(Savestate* file);
bool LoadROM(const char* path, const char* sram);
void RelocateSave(const char* path, bool write);
+void WriteGPIO(u32 addr, u16 val);
+
}
#endif // GBACART_H