aboutsummaryrefslogtreecommitdiff
path: root/src/GBACart.cpp
diff options
context:
space:
mode:
authorRaphaël Zumer <rzumer@tebako.net>2019-12-10 17:43:25 -0500
committerRaphaël Zumer <rzumer@tebako.net>2019-12-10 17:43:25 -0500
commitf6cd66e5b1eb02f1664a4de083085fb81e6816b6 (patch)
tree606d94b235a87845603e087891ff8ae35952c83f /src/GBACart.cpp
parent9128517b9086b9508dac375fb2764dcdc9ea3947 (diff)
Implement solar sensor processing
Diffstat (limited to 'src/GBACart.cpp')
-rw-r--r--src/GBACart.cpp67
1 files changed, 51 insertions, 16 deletions
diff --git a/src/GBACart.cpp b/src/GBACart.cpp
index 75bc1dc..5b81900 100644
--- a/src/GBACart.cpp
+++ b/src/GBACart.cpp
@@ -461,15 +461,6 @@ const char SOLAR_SENSOR_GAMECODES[10][5] =
};
-struct GPIO
-{
- bool has_solar_sensor;
- u16 data;
- u16 direction;
- u16 control;
-};
-
-
bool CartInserted;
u8* CartROM;
u32 CartROMSize;
@@ -503,6 +494,7 @@ void Reset()
CartGPIO = {};
GBACart_SRAM::Reset();
+ GBACart_SolarSensor::Reset();
}
void DoSavestate(Savestate* file)
@@ -578,7 +570,7 @@ void WriteGPIO(u32 addr, u16 val)
case 0xC4:
CartGPIO.data &= ~CartGPIO.direction;
CartGPIO.data |= val & CartGPIO.direction;
- // TODO: process pins
+ if (CartGPIO.has_solar_sensor) GBACart_SolarSensor::Process(&CartGPIO);
break;
case 0xC6:
CartGPIO.direction = val;
@@ -593,17 +585,60 @@ void WriteGPIO(u32 addr, u16 val)
// 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;
+ *(u16*)&CartROM[0xC4] = CartGPIO.data;
+ *(u16*)&CartROM[0xC6] = CartGPIO.direction;
+ *(u16*)&CartROM[0xC8] = 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;
+ *(u16*)&CartROM[0xC4] = 0;
+ *(u16*)&CartROM[0xC6] = 0;
+ *(u16*)&CartROM[0xC8] = 0;
+ }
+}
+
+}
+
+
+namespace GBACart_SolarSensor
+{
+
+bool LightEdge;
+u8 LightCounter;
+u8 LightSample;
+u8 LightLevel; // 0-10 range
+
+// levels from mGBA
+const int GBA_LUX_LEVELS[11] = { 0, 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
+#define LIGHT_VALUE (0xFF - (0x16 + GBA_LUX_LEVELS[LightLevel]))
+
+
+void Reset()
+{
+ LightEdge = false;
+ LightCounter = 0;
+ LightSample = 0xFF;
+ LightLevel = 0;
+}
+
+void Process(GBACart::GPIO* gpio)
+{
+ if (gpio->data & 4) return; // Boktai chip select
+ if (gpio->data & 2) // Reset
+ {
+ LightCounter = 0;
+ LightSample = LIGHT_VALUE;
+ }
+ if (gpio->data & 1 && LightEdge) LightCounter++;
+
+ LightEdge = !(gpio->data & 1);
+
+ bool sendBit = LightCounter >= LightSample;
+ if (gpio->control & 1)
+ {
+ gpio->data = (gpio->data & gpio->direction) | ((sendBit << 3) & ~gpio->direction & 0xF);
}
}