From f6cd66e5b1eb02f1664a4de083085fb81e6816b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 17:43:25 -0500 Subject: [PATCH] Implement solar sensor processing --- src/GBACart.cpp | 67 +++++++++++++++++++++++++++++++++++++------------ src/GBACart.h | 19 ++++++++++++++ 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 75bc1dc3..5b819001 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); } } diff --git a/src/GBACart.h b/src/GBACart.h index 22a3a603..32a2171e 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -43,6 +43,14 @@ void Write32(u32 addr, u32 val); namespace GBACart { +struct GPIO +{ + bool has_solar_sensor; + u16 data; + u16 direction; + u16 control; +}; + extern bool CartInserted; extern u8* CartROM; extern u32 CartROMSize; @@ -59,4 +67,15 @@ void WriteGPIO(u32 addr, u16 val); } + +namespace GBACart_SolarSensor +{ + +extern u8 LightLevel; + +void Reset(); +void Process(GBACart::GPIO* gpio); + +} + #endif // GBACART_H