GBA: Refactor gba-sensors and gba-gpio into gba-hardware
@@ -1,459 +0,0 @@
-/* Copyright (c) 2013-2014 Jeffrey Pfau - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "gba.h" - -#include "gba-gpio.h" -#include "gba-sensors.h" -#include "gba-serialize.h" - -#include <time.h> - -static void _readPins(struct GBACartridgeGPIO* gpio); -static void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins); - -static void _rtcReadPins(struct GBACartridgeGPIO* gpio); -static unsigned _rtcOutput(struct GBACartridgeGPIO* gpio); -static void _rtcProcessByte(struct GBACartridgeGPIO* gpio); -static void _rtcUpdateClock(struct GBACartridgeGPIO* gpio); -static unsigned _rtcBCD(unsigned value); - -static void _gyroReadPins(struct GBACartridgeGPIO* gpio); - -static void _rumbleReadPins(struct GBACartridgeGPIO* gpio); - -static void _lightReadPins(struct GBACartridgeGPIO* gpio); - -static const int RTC_BYTES[8] = { - 0, // Force reset - 0, // Empty - 7, // Date/Time - 0, // Force IRQ - 1, // Control register - 0, // Empty - 3, // Time - 0 // Empty -}; - -void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* base) { - gpio->gpioBase = base; - GBAGPIOClear(gpio); -} - -void GBAGPIOClear(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices = GPIO_NONE; - gpio->direction = GPIO_WRITE_ONLY; - gpio->pinState = 0; - gpio->direction = 0; -} - -void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t value) { - switch (address) { - case GPIO_REG_DATA: - gpio->pinState &= ~gpio->direction; - gpio->pinState |= value; - _readPins(gpio); - break; - case GPIO_REG_DIRECTION: - gpio->direction = value; - break; - case GPIO_REG_CONTROL: - gpio->readWrite = value; - break; - default: - GBALog(gpio->p, GBA_LOG_WARN, "Invalid GPIO address"); - } - if (gpio->readWrite) { - uint16_t old = gpio->gpioBase[0]; - old &= ~gpio->direction; - gpio->gpioBase[0] = old | gpio->pinState; - } else { - gpio->gpioBase[0] = 0; - } -} - -void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices |= GPIO_RTC; - gpio->rtc.bytesRemaining = 0; - - gpio->rtc.transferStep = 0; - - gpio->rtc.bitsRead = 0; - gpio->rtc.bits = 0; - gpio->rtc.commandActive = 0; - gpio->rtc.command.packed = 0; - gpio->rtc.control.packed = 0x40; - memset(gpio->rtc.time, 0, sizeof(gpio->rtc.time)); -} - -void _readPins(struct GBACartridgeGPIO* gpio) { - if (gpio->gpioDevices & GPIO_RTC) { - _rtcReadPins(gpio); - } - - if (gpio->gpioDevices & GPIO_GYRO) { - _gyroReadPins(gpio); - } - - if (gpio->gpioDevices & GPIO_RUMBLE) { - _rumbleReadPins(gpio); - } - - if (gpio->gpioDevices & GPIO_LIGHT_SENSOR) { - _lightReadPins(gpio); - } -} - -void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins) { - if (gpio->readWrite) { - uint16_t old = gpio->gpioBase[0]; - old &= gpio->direction; - gpio->pinState = old | (pins & ~gpio->direction & 0xF); - gpio->gpioBase[0] = gpio->pinState; - } -} - -// == RTC - -void _rtcReadPins(struct GBACartridgeGPIO* gpio) { - // Transfer sequence: - // P: 0 | 1 | 2 | 3 - // == Initiate - // > HI | - | LO | - - // > HI | - | HI | - - // == Transfer bit (x8) - // > LO | x | HI | - - // > HI | - | HI | - - // < ?? | x | ?? | - - // == Terminate - // > - | - | LO | - - switch (gpio->rtc.transferStep) { - case 0: - if ((gpio->pinState & 5) == 1) { - gpio->rtc.transferStep = 1; - } - break; - case 1: - if ((gpio->pinState & 5) == 5) { - gpio->rtc.transferStep = 2; - } - break; - case 2: - if (!gpio->p0) { - gpio->rtc.bits &= ~(1 << gpio->rtc.bitsRead); - gpio->rtc.bits |= gpio->p1 << gpio->rtc.bitsRead; - } else { - if (gpio->p2) { - // GPIO direction should always != reading - if (gpio->dir1) { - if (gpio->rtc.command.reading) { - GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode"); - } - ++gpio->rtc.bitsRead; - if (gpio->rtc.bitsRead == 8) { - _rtcProcessByte(gpio); - } - } else { - _outputPins(gpio, 5 | (_rtcOutput(gpio) << 1)); - ++gpio->rtc.bitsRead; - if (gpio->rtc.bitsRead == 8) { - --gpio->rtc.bytesRemaining; - if (gpio->rtc.bytesRemaining <= 0) { - gpio->rtc.commandActive = 0; - gpio->rtc.command.reading = 0; - } - gpio->rtc.bitsRead = 0; - } - } - } else { - gpio->rtc.bitsRead = 0; - gpio->rtc.bytesRemaining = 0; - gpio->rtc.commandActive = 0; - gpio->rtc.command.reading = 0; - gpio->rtc.transferStep = 0; - } - } - break; - } -} - -void _rtcProcessByte(struct GBACartridgeGPIO* gpio) { - --gpio->rtc.bytesRemaining; - if (!gpio->rtc.commandActive) { - union RTCCommandData command; - command.packed = gpio->rtc.bits; - if (command.magic == 0x06) { - gpio->rtc.command = command; - - gpio->rtc.bytesRemaining = RTC_BYTES[gpio->rtc.command.command]; - gpio->rtc.commandActive = gpio->rtc.bytesRemaining > 0; - switch (command.command) { - case RTC_RESET: - gpio->rtc.control.packed = 0; - break; - case RTC_DATETIME: - case RTC_TIME: - _rtcUpdateClock(gpio); - break; - case RTC_FORCE_IRQ: - case RTC_CONTROL: - break; - } - } else { - GBALog(gpio->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", gpio->rtc.bits); - } - } else { - switch (gpio->rtc.command.command) { - case RTC_CONTROL: - gpio->rtc.control.packed = gpio->rtc.bits; - break; - case RTC_FORCE_IRQ: - GBALog(gpio->p, GBA_LOG_STUB, "Unimplemented RTC command %u", gpio->rtc.command.command); - break; - case RTC_RESET: - case RTC_DATETIME: - case RTC_TIME: - break; - } - } - - gpio->rtc.bits = 0; - gpio->rtc.bitsRead = 0; - if (!gpio->rtc.bytesRemaining) { - gpio->rtc.commandActive = 0; - gpio->rtc.command.reading = 0; - } -} - -unsigned _rtcOutput(struct GBACartridgeGPIO* gpio) { - uint8_t outputByte = 0; - switch (gpio->rtc.command.command) { - case RTC_CONTROL: - outputByte = gpio->rtc.control.packed; - break; - case RTC_DATETIME: - case RTC_TIME: - outputByte = gpio->rtc.time[7 - gpio->rtc.bytesRemaining]; - break; - case RTC_FORCE_IRQ: - case RTC_RESET: - break; - } - unsigned output = (outputByte >> gpio->rtc.bitsRead) & 1; - return output; -} - -void _rtcUpdateClock(struct GBACartridgeGPIO* gpio) { - time_t t; - struct GBARTCSource* rtc = gpio->p->rtcSource; - if (rtc) { - rtc->sample(rtc); - t = rtc->unixTime(rtc); - } else { - t = time(0); - } - struct tm date; -#ifdef _WIN32 - date = *localtime(&t); -#else - localtime_r(&t, &date); -#endif - gpio->rtc.time[0] = _rtcBCD(date.tm_year - 100); - gpio->rtc.time[1] = _rtcBCD(date.tm_mon + 1); - gpio->rtc.time[2] = _rtcBCD(date.tm_mday); - gpio->rtc.time[3] = _rtcBCD(date.tm_wday); - if (gpio->rtc.control.hour24) { - gpio->rtc.time[4] = _rtcBCD(date.tm_hour); - } else { - gpio->rtc.time[4] = _rtcBCD(date.tm_hour % 12); - } - gpio->rtc.time[5] = _rtcBCD(date.tm_min); - gpio->rtc.time[6] = _rtcBCD(date.tm_sec); -} - -unsigned _rtcBCD(unsigned value) { - int counter = value % 10; - value /= 10; - counter += (value % 10) << 4; - return counter; -} - -// == Gyro - -void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices |= GPIO_GYRO; - gpio->gyroSample = 0; - gpio->gyroEdge = 0; -} - -void _gyroReadPins(struct GBACartridgeGPIO* gpio) { - struct GBARotationSource* gyro = gpio->p->rotationSource; - if (!gyro) { - return; - } - - if (gpio->p0) { - if (gyro->sample) { - gyro->sample(gyro); - } - int32_t sample = gyro->readGyroZ(gyro); - - // Normalize to ~12 bits, focused on 0x6C0 - gpio->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative - } - - if (gpio->gyroEdge && !gpio->p1) { - // Write bit on falling edge - unsigned bit = gpio->gyroSample >> 15; - gpio->gyroSample <<= 1; - _outputPins(gpio, bit << 2); - } - - gpio->gyroEdge = gpio->p1; -} - -// == Rumble - -void GBAGPIOInitRumble(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices |= GPIO_RUMBLE; -} - -void _rumbleReadPins(struct GBACartridgeGPIO* gpio) { - struct GBARumble* rumble = gpio->p->rumble; - if (!rumble) { - return; - } - - rumble->setRumble(rumble, gpio->p3); -} - -// == Light sensor - -void GBAGPIOInitLightSensor(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices |= GPIO_LIGHT_SENSOR; - gpio->lightCounter = 0; - gpio->lightEdge = false; - gpio->lightSample = 0xFF; -} - -void _lightReadPins(struct GBACartridgeGPIO* gpio) { - if (gpio->p2) { - // Boktai chip select - return; - } - if (gpio->p1) { - struct GBALuminanceSource* lux = gpio->p->luminanceSource; - GBALog(gpio->p, GBA_LOG_DEBUG, "[SOLAR] Got reset"); - gpio->lightCounter = 0; - if (lux) { - lux->sample(lux); - gpio->lightSample = lux->readLuminance(lux); - } else { - gpio->lightSample = 0xFF; - } - } - if (gpio->p0 && gpio->lightEdge) { - ++gpio->lightCounter; - } - gpio->lightEdge = !gpio->p0; - - bool sendBit = gpio->lightCounter >= gpio->lightSample; - _outputPins(gpio, sendBit << 3); - GBALog(gpio->p, GBA_LOG_DEBUG, "[SOLAR] Output %u with pins %u", gpio->lightCounter, gpio->pinState); -} - -// == Tilt (not technically GPIO) - -void GBAGPIOInitTilt(struct GBACartridgeGPIO* gpio) { - gpio->gpioDevices |= GPIO_TILT; - gpio->tiltX = 0xFFF; - gpio->tiltY = 0xFFF; - gpio->tiltState = 0; -} - -void GBAGPIOTiltWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint8_t value) { - switch (address) { - case 0x8000: - if (value == 0x55) { - gpio->tiltState = 1; - } else { - GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value); - } - break; - case 0x8100: - if (value == 0xAA && gpio->tiltState == 1) { - gpio->tiltState = 0; - struct GBARotationSource* rotationSource = gpio->p->rotationSource; - if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) { - return; - } - if (rotationSource->sample) { - rotationSource->sample(rotationSource); - } - int32_t x = rotationSource->readTiltX(rotationSource); - int32_t y = rotationSource->readTiltY(rotationSource); - // Normalize to ~12 bits, focused on 0x3A0 - gpio->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative - gpio->tiltY = (y >> 21) + 0x3A0; - } else { - GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value); - } - break; - default: - GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value); - break; - } -} - -uint8_t GBAGPIOTiltRead(struct GBACartridgeGPIO* gpio, uint32_t address) { - switch (address) { - case 0x8200: - return gpio->tiltX & 0xFF; - case 0x8300: - return ((gpio->tiltX >> 8) & 0xF) | 0x80; - case 0x8400: - return gpio->tiltY & 0xFF; - case 0x8500: - return (gpio->tiltY >> 8) & 0xF; - default: - GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor read from %04x", address); - break; - } - return 0xFF; -} - -// == Serialization - -void GBAGPIOSerialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) { - state->gpio.readWrite = gpio->readWrite; - state->gpio.pinState = gpio->pinState; - state->gpio.pinDirection = gpio->direction; - state->gpio.devices = gpio->gpioDevices; - state->gpio.rtc = gpio->rtc; - state->gpio.gyroSample = gpio->gyroSample; - state->gpio.gyroEdge = gpio->gyroEdge; - state->gpio.tiltSampleX = gpio->tiltX; - state->gpio.tiltSampleY = gpio->tiltY; - state->gpio.tiltState = gpio->tiltState; - state->gpio.lightCounter = gpio->lightCounter; - state->gpio.lightSample = gpio->lightSample; - state->gpio.lightEdge = gpio->lightEdge; -} - -void GBAGPIODeserialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) { - gpio->readWrite = state->gpio.readWrite; - gpio->pinState = state->gpio.pinState; - gpio->direction = state->gpio.pinDirection; - // TODO: Deterministic RTC - gpio->rtc = state->gpio.rtc; - gpio->gyroSample = state->gpio.gyroSample; - gpio->gyroEdge = state->gpio.gyroEdge; - gpio->tiltX = state->gpio.tiltSampleX; - gpio->tiltY = state->gpio.tiltSampleY; - gpio->tiltState = state->gpio.tiltState; - gpio->lightCounter = state->gpio.lightCounter; - gpio->lightSample = state->gpio.lightSample; - gpio->lightEdge = state->gpio.lightEdge; -}
@@ -1,134 +0,0 @@
-/* Copyright (c) 2013-2014 Jeffrey Pfau - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef GBA_GPIO_H -#define GBA_GPIO_H - -#include "util/common.h" - -#define IS_GPIO_REGISTER(reg) ((reg) == GPIO_REG_DATA || (reg) == GPIO_REG_DIRECTION || (reg) == GPIO_REG_CONTROL) - -enum GPIODevice { - GPIO_NO_OVERRIDE = 0x8000, - GPIO_NONE = 0, - GPIO_RTC = 1, - GPIO_RUMBLE = 2, - GPIO_LIGHT_SENSOR = 4, - GPIO_GYRO = 8, - GPIO_TILT = 16 -}; - -enum GPIORegister { - GPIO_REG_DATA = 0xC4, - GPIO_REG_DIRECTION = 0xC6, - GPIO_REG_CONTROL = 0xC8 -}; - -enum GPIODirection { - GPIO_WRITE_ONLY = 0, - GPIO_READ_WRITE = 1 -}; - -union RTCControl { - struct { - unsigned : 3; - unsigned minIRQ : 1; - unsigned : 2; - unsigned hour24 : 1; - unsigned poweroff : 1; - }; - uint8_t packed; -}; - -enum RTCCommand { - RTC_RESET = 0, - RTC_DATETIME = 2, - RTC_FORCE_IRQ = 3, - RTC_CONTROL = 4, - RTC_TIME = 6 -}; - -union RTCCommandData { - struct { - unsigned magic : 4; - enum RTCCommand command : 3; - unsigned reading : 1; - }; - uint8_t packed; -}; - -struct GBARTC { - int bytesRemaining; - int transferStep; - int bitsRead; - int bits; - int commandActive; - union RTCCommandData command; - union RTCControl control; - uint8_t time[7]; -} __attribute__((packed)); - -struct GBARumble { - void (*setRumble)(struct GBARumble*, int enable); -}; - -struct GBACartridgeGPIO { - struct GBA* p; - int gpioDevices; - enum GPIODirection readWrite; - uint16_t* gpioBase; - - union { - struct { - unsigned p0 : 1; - unsigned p1 : 1; - unsigned p2 : 1; - unsigned p3 : 1; - }; - uint16_t pinState; - }; - - union { - struct { - unsigned dir0 : 1; - unsigned dir1 : 1; - unsigned dir2 : 1; - unsigned dir3 : 1; - }; - uint16_t direction; - }; - - struct GBARTC rtc; - - uint16_t gyroSample; - bool gyroEdge; - - unsigned lightCounter : 12; - uint8_t lightSample; - bool lightEdge; - - uint16_t tiltX; - uint16_t tiltY; - int tiltState; -}; - -void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* gpioBase); -void GBAGPIOClear(struct GBACartridgeGPIO* gpio); -void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t value); - -void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio); -void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio); -void GBAGPIOInitRumble(struct GBACartridgeGPIO* gpio); -void GBAGPIOInitLightSensor(struct GBACartridgeGPIO* gpio); -void GBAGPIOInitTilt(struct GBACartridgeGPIO* gpio); - -void GBAGPIOTiltWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint8_t value); -uint8_t GBAGPIOTiltRead(struct GBACartridgeGPIO* gpio, uint32_t address); - -struct GBASerializedState; -void GBAGPIOSerialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state); -void GBAGPIODeserialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state); - -#endif
@@ -0,0 +1,458 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gba.h" + +#include "gba-hardware.h" +#include "gba-serialize.h" + +#include <time.h> + +static void _readPins(struct GBACartridgeHardware* hw); +static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins); + +static void _rtcReadPins(struct GBACartridgeHardware* hw); +static unsigned _rtcOutput(struct GBACartridgeHardware* hw); +static void _rtcProcessByte(struct GBACartridgeHardware* hw); +static void _rtcUpdateClock(struct GBACartridgeHardware* hw); +static unsigned _rtcBCD(unsigned value); + +static void _gyroReadPins(struct GBACartridgeHardware* hw); + +static void _rumbleReadPins(struct GBACartridgeHardware* hw); + +static void _lightReadPins(struct GBACartridgeHardware* hw); + +static const int RTC_BYTES[8] = { + 0, // Force reset + 0, // Empty + 7, // Date/Time + 0, // Force IRQ + 1, // Control register + 0, // Empty + 3, // Time + 0 // Empty +}; + +void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) { + hw->gpioBase = base; + GBAHardwareClear(hw); +} + +void GBAHardwareClear(struct GBACartridgeHardware* hw) { + hw->devices = HW_NONE; + hw->direction = GPIO_WRITE_ONLY; + hw->pinState = 0; + hw->direction = 0; +} + +void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { + switch (address) { + case GPIO_REG_DATA: + hw->pinState &= ~hw->direction; + hw->pinState |= value; + _readPins(hw); + break; + case GPIO_REG_DIRECTION: + hw->direction = value; + break; + case GPIO_REG_CONTROL: + hw->readWrite = value; + break; + default: + GBALog(hw->p, GBA_LOG_WARN, "Invalid GPIO address"); + } + if (hw->readWrite) { + uint16_t old = hw->gpioBase[0]; + old &= ~hw->direction; + hw->gpioBase[0] = old | hw->pinState; + } else { + hw->gpioBase[0] = 0; + } +} + +void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) { + hw->devices |= HW_RTC; + hw->rtc.bytesRemaining = 0; + + hw->rtc.transferStep = 0; + + hw->rtc.bitsRead = 0; + hw->rtc.bits = 0; + hw->rtc.commandActive = 0; + hw->rtc.command.packed = 0; + hw->rtc.control.packed = 0x40; + memset(hw->rtc.time, 0, sizeof(hw->rtc.time)); +} + +void _readPins(struct GBACartridgeHardware* hw) { + if (hw->devices & HW_RTC) { + _rtcReadPins(hw); + } + + if (hw->devices & HW_GYRO) { + _gyroReadPins(hw); + } + + if (hw->devices & HW_RUMBLE) { + _rumbleReadPins(hw); + } + + if (hw->devices & HW_LIGHT_SENSOR) { + _lightReadPins(hw); + } +} + +void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) { + if (hw->readWrite) { + uint16_t old = hw->gpioBase[0]; + old &= hw->direction; + hw->pinState = old | (pins & ~hw->direction & 0xF); + hw->gpioBase[0] = hw->pinState; + } +} + +// == RTC + +void _rtcReadPins(struct GBACartridgeHardware* hw) { + // Transfer sequence: + // P: 0 | 1 | 2 | 3 + // == Initiate + // > HI | - | LO | - + // > HI | - | HI | - + // == Transfer bit (x8) + // > LO | x | HI | - + // > HI | - | HI | - + // < ?? | x | ?? | - + // == Terminate + // > - | - | LO | - + switch (hw->rtc.transferStep) { + case 0: + if ((hw->pinState & 5) == 1) { + hw->rtc.transferStep = 1; + } + break; + case 1: + if ((hw->pinState & 5) == 5) { + hw->rtc.transferStep = 2; + } + break; + case 2: + if (!hw->p0) { + hw->rtc.bits &= ~(1 << hw->rtc.bitsRead); + hw->rtc.bits |= hw->p1 << hw->rtc.bitsRead; + } else { + if (hw->p2) { + // GPIO direction should always != reading + if (hw->dir1) { + if (hw->rtc.command.reading) { + GBALog(hw->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode"); + } + ++hw->rtc.bitsRead; + if (hw->rtc.bitsRead == 8) { + _rtcProcessByte(hw); + } + } else { + _outputPins(hw, 5 | (_rtcOutput(hw) << 1)); + ++hw->rtc.bitsRead; + if (hw->rtc.bitsRead == 8) { + --hw->rtc.bytesRemaining; + if (hw->rtc.bytesRemaining <= 0) { + hw->rtc.commandActive = 0; + hw->rtc.command.reading = 0; + } + hw->rtc.bitsRead = 0; + } + } + } else { + hw->rtc.bitsRead = 0; + hw->rtc.bytesRemaining = 0; + hw->rtc.commandActive = 0; + hw->rtc.command.reading = 0; + hw->rtc.transferStep = 0; + } + } + break; + } +} + +void _rtcProcessByte(struct GBACartridgeHardware* hw) { + --hw->rtc.bytesRemaining; + if (!hw->rtc.commandActive) { + union RTCCommandData command; + command.packed = hw->rtc.bits; + if (command.magic == 0x06) { + hw->rtc.command = command; + + hw->rtc.bytesRemaining = RTC_BYTES[hw->rtc.command.command]; + hw->rtc.commandActive = hw->rtc.bytesRemaining > 0; + switch (command.command) { + case RTC_RESET: + hw->rtc.control.packed = 0; + break; + case RTC_DATETIME: + case RTC_TIME: + _rtcUpdateClock(hw); + break; + case RTC_FORCE_IRQ: + case RTC_CONTROL: + break; + } + } else { + GBALog(hw->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", hw->rtc.bits); + } + } else { + switch (hw->rtc.command.command) { + case RTC_CONTROL: + hw->rtc.control.packed = hw->rtc.bits; + break; + case RTC_FORCE_IRQ: + GBALog(hw->p, GBA_LOG_STUB, "Unimplemented RTC command %u", hw->rtc.command.command); + break; + case RTC_RESET: + case RTC_DATETIME: + case RTC_TIME: + break; + } + } + + hw->rtc.bits = 0; + hw->rtc.bitsRead = 0; + if (!hw->rtc.bytesRemaining) { + hw->rtc.commandActive = 0; + hw->rtc.command.reading = 0; + } +} + +unsigned _rtcOutput(struct GBACartridgeHardware* hw) { + uint8_t outputByte = 0; + switch (hw->rtc.command.command) { + case RTC_CONTROL: + outputByte = hw->rtc.control.packed; + break; + case RTC_DATETIME: + case RTC_TIME: + outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining]; + break; + case RTC_FORCE_IRQ: + case RTC_RESET: + break; + } + unsigned output = (outputByte >> hw->rtc.bitsRead) & 1; + return output; +} + +void _rtcUpdateClock(struct GBACartridgeHardware* hw) { + time_t t; + struct GBARTCSource* rtc = hw->p->rtcSource; + if (rtc) { + rtc->sample(rtc); + t = rtc->unixTime(rtc); + } else { + t = time(0); + } + struct tm date; +#ifdef _WIN32 + date = *localtime(&t); +#else + localtime_r(&t, &date); +#endif + hw->rtc.time[0] = _rtcBCD(date.tm_year - 100); + hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1); + hw->rtc.time[2] = _rtcBCD(date.tm_mday); + hw->rtc.time[3] = _rtcBCD(date.tm_wday); + if (hw->rtc.control.hour24) { + hw->rtc.time[4] = _rtcBCD(date.tm_hour); + } else { + hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12); + } + hw->rtc.time[5] = _rtcBCD(date.tm_min); + hw->rtc.time[6] = _rtcBCD(date.tm_sec); +} + +unsigned _rtcBCD(unsigned value) { + int counter = value % 10; + value /= 10; + counter += (value % 10) << 4; + return counter; +} + +// == Gyro + +void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) { + hw->devices |= HW_GYRO; + hw->gyroSample = 0; + hw->gyroEdge = 0; +} + +void _gyroReadPins(struct GBACartridgeHardware* hw) { + struct GBARotationSource* gyro = hw->p->rotationSource; + if (!gyro) { + return; + } + + if (hw->p0) { + if (gyro->sample) { + gyro->sample(gyro); + } + int32_t sample = gyro->readGyroZ(gyro); + + // Normalize to ~12 bits, focused on 0x6C0 + hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative + } + + if (hw->gyroEdge && !hw->p1) { + // Write bit on falling edge + unsigned bit = hw->gyroSample >> 15; + hw->gyroSample <<= 1; + _outputPins(hw, bit << 2); + } + + hw->gyroEdge = hw->p1; +} + +// == Rumble + +void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) { + hw->devices |= HW_RUMBLE; +} + +void _rumbleReadPins(struct GBACartridgeHardware* hw) { + struct GBARumble* rumble = hw->p->rumble; + if (!rumble) { + return; + } + + rumble->setRumble(rumble, hw->p3); +} + +// == Light sensor + +void GBAHardwareInitLight(struct GBACartridgeHardware* hw) { + hw->devices |= HW_LIGHT_SENSOR; + hw->lightCounter = 0; + hw->lightEdge = false; + hw->lightSample = 0xFF; +} + +void _lightReadPins(struct GBACartridgeHardware* hw) { + if (hw->p2) { + // Boktai chip select + return; + } + if (hw->p1) { + struct GBALuminanceSource* lux = hw->p->luminanceSource; + GBALog(hw->p, GBA_LOG_DEBUG, "[SOLAR] Got reset"); + hw->lightCounter = 0; + if (lux) { + lux->sample(lux); + hw->lightSample = lux->readLuminance(lux); + } else { + hw->lightSample = 0xFF; + } + } + if (hw->p0 && hw->lightEdge) { + ++hw->lightCounter; + } + hw->lightEdge = !hw->p0; + + bool sendBit = hw->lightCounter >= hw->lightSample; + _outputPins(hw, sendBit << 3); + GBALog(hw->p, GBA_LOG_DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState); +} + +// == Tilt + +void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) { + hw->devices |= HW_TILT; + hw->tiltX = 0xFFF; + hw->tiltY = 0xFFF; + hw->tiltState = 0; +} + +void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) { + switch (address) { + case 0x8000: + if (value == 0x55) { + hw->tiltState = 1; + } else { + GBALog(hw->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value); + } + break; + case 0x8100: + if (value == 0xAA && hw->tiltState == 1) { + hw->tiltState = 0; + struct GBARotationSource* rotationSource = hw->p->rotationSource; + if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) { + return; + } + if (rotationSource->sample) { + rotationSource->sample(rotationSource); + } + int32_t x = rotationSource->readTiltX(rotationSource); + int32_t y = rotationSource->readTiltY(rotationSource); + // Normalize to ~12 bits, focused on 0x3A0 + hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative + hw->tiltY = (y >> 21) + 0x3A0; + } else { + GBALog(hw->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value); + } + break; + default: + GBALog(hw->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value); + break; + } +} + +uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) { + switch (address) { + case 0x8200: + return hw->tiltX & 0xFF; + case 0x8300: + return ((hw->tiltX >> 8) & 0xF) | 0x80; + case 0x8400: + return hw->tiltY & 0xFF; + case 0x8500: + return (hw->tiltY >> 8) & 0xF; + default: + GBALog(hw->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor read from %04x", address); + break; + } + return 0xFF; +} + +// == Serialization + +void GBAHardwareSerialize(struct GBACartridgeHardware* hw, struct GBASerializedState* state) { + state->hw.readWrite = hw->readWrite; + state->hw.pinState = hw->pinState; + state->hw.pinDirection = hw->direction; + state->hw.devices = hw->devices; + state->hw.rtc = hw->rtc; + state->hw.gyroSample = hw->gyroSample; + state->hw.gyroEdge = hw->gyroEdge; + state->hw.tiltSampleX = hw->tiltX; + state->hw.tiltSampleY = hw->tiltY; + state->hw.tiltState = hw->tiltState; + state->hw.lightCounter = hw->lightCounter; + state->hw.lightSample = hw->lightSample; + state->hw.lightEdge = hw->lightEdge; +} + +void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, struct GBASerializedState* state) { + hw->readWrite = state->hw.readWrite; + hw->pinState = state->hw.pinState; + hw->direction = state->hw.pinDirection; + // TODO: Deterministic RTC + hw->rtc = state->hw.rtc; + hw->gyroSample = state->hw.gyroSample; + hw->gyroEdge = state->hw.gyroEdge; + hw->tiltX = state->hw.tiltSampleX; + hw->tiltY = state->hw.tiltSampleY; + hw->tiltState = state->hw.tiltState; + hw->lightCounter = state->hw.lightCounter; + hw->lightSample = state->hw.lightSample; + hw->lightEdge = state->hw.lightEdge; +}
@@ -0,0 +1,155 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_HARDWARE_H +#define GBA_HARDWARE_H + +#include "util/common.h" + +#define IS_GPIO_REGISTER(reg) ((reg) == GPIO_REG_DATA || (reg) == GPIO_REG_DIRECTION || (reg) == GPIO_REG_CONTROL) + +struct GBARotationSource { + void (*sample)(struct GBARotationSource*); + + int32_t (*readTiltX)(struct GBARotationSource*); + int32_t (*readTiltY)(struct GBARotationSource*); + + int32_t (*readGyroZ)(struct GBARotationSource*); +}; + +struct GBALuminanceSource { + void (*sample)(struct GBALuminanceSource*); + + uint8_t (*readLuminance)(struct GBALuminanceSource*); +}; + +struct GBARTCSource { + void (*sample)(struct GBARTCSource*); + + time_t (*unixTime)(struct GBARTCSource*); +}; + +enum GBAHardwareDevice { + HW_NO_OVERRIDE = 0x8000, + HW_NONE = 0, + HW_RTC = 1, + HW_RUMBLE = 2, + HW_LIGHT_SENSOR = 4, + HW_GYRO = 8, + HW_TILT = 16 +}; + +enum GPIORegister { + GPIO_REG_DATA = 0xC4, + GPIO_REG_DIRECTION = 0xC6, + GPIO_REG_CONTROL = 0xC8 +}; + +enum GPIODirection { + GPIO_WRITE_ONLY = 0, + GPIO_READ_WRITE = 1 +}; + +union RTCControl { + struct { + unsigned : 3; + unsigned minIRQ : 1; + unsigned : 2; + unsigned hour24 : 1; + unsigned poweroff : 1; + }; + uint8_t packed; +}; + +enum RTCCommand { + RTC_RESET = 0, + RTC_DATETIME = 2, + RTC_FORCE_IRQ = 3, + RTC_CONTROL = 4, + RTC_TIME = 6 +}; + +union RTCCommandData { + struct { + unsigned magic : 4; + enum RTCCommand command : 3; + unsigned reading : 1; + }; + uint8_t packed; +}; + +struct GBARTC { + int bytesRemaining; + int transferStep; + int bitsRead; + int bits; + int commandActive; + union RTCCommandData command; + union RTCControl control; + uint8_t time[7]; +} __attribute__((packed)); + +struct GBARumble { + void (*setRumble)(struct GBARumble*, int enable); +}; + +struct GBACartridgeHardware { + struct GBA* p; + int devices; + enum GPIODirection readWrite; + uint16_t* gpioBase; + + union { + struct { + unsigned p0 : 1; + unsigned p1 : 1; + unsigned p2 : 1; + unsigned p3 : 1; + }; + uint16_t pinState; + }; + + union { + struct { + unsigned dir0 : 1; + unsigned dir1 : 1; + unsigned dir2 : 1; + unsigned dir3 : 1; + }; + uint16_t direction; + }; + + struct GBARTC rtc; + + uint16_t gyroSample; + bool gyroEdge; + + unsigned lightCounter : 12; + uint8_t lightSample; + bool lightEdge; + + uint16_t tiltX; + uint16_t tiltY; + int tiltState; +}; + +void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase); +void GBAHardwareClear(struct GBACartridgeHardware* gpio); + +void GBAHardwareInitRTC(struct GBACartridgeHardware* gpio); +void GBAHardwareInitGyro(struct GBACartridgeHardware* gpio); +void GBAHardwareInitRumble(struct GBACartridgeHardware* gpio); +void GBAHardwareInitLight(struct GBACartridgeHardware* gpio); +void GBAHardwareInitTilt(struct GBACartridgeHardware* gpio); + +void GBAHardwareGPIOWrite(struct GBACartridgeHardware* gpio, uint32_t address, uint16_t value); +void GBAHardwareTiltWrite(struct GBACartridgeHardware* gpio, uint32_t address, uint8_t value); +uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* gpio, uint32_t address); + +struct GBASerializedState; +void GBAHardwareSerialize(struct GBACartridgeHardware* gpio, struct GBASerializedState* state); +void GBAHardwareDeserialize(struct GBACartridgeHardware* gpio, struct GBASerializedState* state); + +#endif
@@ -672,7 +672,7 @@ state->dma[i].nextEvent = gba->memory.dma[i].nextEvent;
} memcpy(state->timers, gba->timers, sizeof(state->timers)); - GBAGPIOSerialize(&gba->memory.gpio, state); + GBAHardwareSerialize(&gba->memory.hw, state); } void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {@@ -701,5 +701,5 @@ if (gba->timers[i].enable) {
gba->timersEnabled |= 1 << i; } } - GBAGPIODeserialize(&gba->memory.gpio, state); + GBAHardwareDeserialize(&gba->memory.hw, state); }
@@ -8,7 +8,7 @@
#include "macros.h" #include "decoder.h" -#include "gba-gpio.h" +#include "gba-hardware.h" #include "gba-io.h" #include "gba-serialize.h" #include "hle-bios.h"@@ -46,7 +46,7 @@ gba->memory.fullBios = 0;
gba->memory.wram = 0; gba->memory.iwram = 0; gba->memory.rom = 0; - gba->memory.gpio.p = gba; + gba->memory.hw.p = gba; int i; for (i = 0; i < 16; ++i) {@@ -566,8 +566,8 @@ if (memory->savedata.type == SAVEDATA_SRAM) {
value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)]; } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { value = GBASavedataReadFlash(&memory->savedata, address); - } else if (memory->gpio.gpioDevices & GPIO_TILT) { - value = GBAGPIOTiltRead(&memory->gpio, address & OFFSET_MASK); + } else if (memory->hw.devices & HW_TILT) { + value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address); value = 0xFF;@@ -710,9 +710,9 @@ STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1); break; case REGION_CART0: - if (memory->gpio.gpioDevices != GPIO_NONE && IS_GPIO_REGISTER(address & 0xFFFFFF)) { + if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFF)) { uint32_t reg = address & 0xFFFFFF; - GBAGPIOWrite(&memory->gpio, reg, value); + GBAHardwareGPIOWrite(&memory->hw, reg, value); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address); }@@ -787,8 +787,8 @@ if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
GBASavedataWriteFlash(&memory->savedata, address, value); } else if (memory->savedata.type == SAVEDATA_SRAM) { memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value; - } else if (memory->gpio.gpioDevices & GPIO_TILT) { - GBAGPIOTiltWrite(&memory->gpio, address & OFFSET_MASK, value); + } else if (memory->hw.devices & HW_TILT) { + GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address); }
@@ -11,7 +11,7 @@
#include "arm.h" #include "macros.h" -#include "gba-gpio.h" +#include "gba-hardware.h" #include "gba-savedata.h" enum GBAMemoryRegion {@@ -116,7 +116,7 @@ uint32_t* iwram;
uint32_t* rom; uint16_t io[SIZE_IO >> 1]; - struct GBACartridgeGPIO gpio; + struct GBACartridgeHardware hw; struct GBASavedata savedata; size_t romSize; uint16_t romID;
@@ -6,107 +6,107 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gba-overrides.h" #include "gba.h" -#include "gba-gpio.h" +#include "gba-hardware.h" #include "util/configuration.h" static const struct GBACartridgeOverride _overrides[] = { // Boktai: The Sun is in Your Hand - { "U3IJ", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, - { "U3IE", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, - { "U3IP", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U3IJ", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U3IE", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U3IP", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, // Boktai 2: Solar Boy Django - { "U32J", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, - { "U32E", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, - { "U32P", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U32J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U32E", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U32P", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, // Drill Dozer - { "V49J", SAVEDATA_SRAM, GPIO_RUMBLE, IDLE_LOOP_NONE }, - { "V49E", SAVEDATA_SRAM, GPIO_RUMBLE, IDLE_LOOP_NONE }, + { "V49J", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE }, + { "V49E", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE }, // Final Fantasy Tactics Advance - { "AFXE", SAVEDATA_FLASH512, GPIO_NONE, 0x8000428 }, + { "AFXE", SAVEDATA_FLASH512, HW_NONE, 0x8000428 }, // Koro Koro Puzzle - Happy Panechu! - { "KHPJ", SAVEDATA_EEPROM, GPIO_TILT, IDLE_LOOP_NONE }, + { "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE }, // Mega Man Battle Network - { "AREE", SAVEDATA_SRAM, GPIO_NONE, 0x800032E }, + { "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E }, // Pokemon Ruby - { "AXVJ", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVE", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVP", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVI", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVS", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVD", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXVF", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, + { "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXVF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, // Pokemon Sapphire - { "AXPJ", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPE", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPP", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPI", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPS", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPD", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "AXPF", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, + { "AXPJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "AXPF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, // Pokemon Emerald - { "BPEJ", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPEE", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPEP", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPEI", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPES", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPED", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, - { "BPEF", SAVEDATA_FLASH1M, GPIO_RTC, IDLE_LOOP_NONE }, + { "BPEJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPEE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPEP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPEI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPES", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPED", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, + { "BPEF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE }, // Pokemon Mystery Dungeon - { "B24J", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "B24E", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "B24P", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "B24U", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, + { "B24J", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "B24E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "B24P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "B24U", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, // Pokemon FireRed - { "BPRJ", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "BPRE", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "BPRP", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, + { "BPRJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "BPRE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "BPRP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, // Pokemon LeafGreen - { "BPGJ", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "BPGE", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "BPGP", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, + { "BPGJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "BPGE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "BPGP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, // RockMan EXE 4.5 - Real Operation - { "BR4J", SAVEDATA_FLASH512, GPIO_RTC, IDLE_LOOP_NONE }, + { "BR4J", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE }, // Shin Bokura no Taiyou: Gyakushuu no Sabata - { "U33J", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, IDLE_LOOP_NONE }, + { "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE }, // Super Mario Advance 4 - { "AX4J", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "AX4E", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, - { "AX4P", SAVEDATA_FLASH1M, GPIO_NONE, IDLE_LOOP_NONE }, + { "AX4J", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "AX4E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, + { "AX4P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE }, // Top Gun - Combat Zones - { "A2YE", SAVEDATA_FORCE_NONE, GPIO_NONE, IDLE_LOOP_NONE }, + { "A2YE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE }, // Wario Ware Twisted - { "RZWJ", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, IDLE_LOOP_NONE }, - { "RZWE", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, IDLE_LOOP_NONE }, - { "RZWP", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, IDLE_LOOP_NONE }, + { "RZWJ", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE }, + { "RZWE", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE }, + { "RZWP", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE }, // Yoshi's Universal Gravitation - { "KYGJ", SAVEDATA_EEPROM, GPIO_TILT, IDLE_LOOP_NONE }, - { "KYGE", SAVEDATA_EEPROM, GPIO_TILT, IDLE_LOOP_NONE }, - { "KYGP", SAVEDATA_EEPROM, GPIO_TILT, IDLE_LOOP_NONE }, + { "KYGJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE }, + { "KYGE", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE }, + { "KYGP", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE }, { { 0, 0, 0, 0 }, 0, 0, IDLE_LOOP_NONE } }; bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) { override->savetype = SAVEDATA_AUTODETECT; - override->hardware = GPIO_NONE; + override->hardware = HW_NONE; override->idleLoop = IDLE_LOOP_NONE; bool found;@@ -197,7 +197,7 @@ break;
} ConfigurationSetValue(config, sectionName, "savetype", savetype); - if (override->hardware != GPIO_NO_OVERRIDE) { + if (override->hardware != HW_NO_OVERRIDE) { ConfigurationSetIntValue(config, sectionName, "hardware", override->hardware); } else { ConfigurationClearValue(config, sectionName, "hardware");@@ -215,27 +215,27 @@ if (override->savetype != SAVEDATA_AUTODETECT) {
GBASavedataForceType(&gba->memory.savedata, override->savetype); } - if (override->hardware != GPIO_NO_OVERRIDE) { - GBAGPIOClear(&gba->memory.gpio); + if (override->hardware != HW_NO_OVERRIDE) { + GBAHardwareClear(&gba->memory.hw); - if (override->hardware & GPIO_RTC) { - GBAGPIOInitRTC(&gba->memory.gpio); + if (override->hardware & HW_RTC) { + GBAHardwareInitRTC(&gba->memory.hw); } - if (override->hardware & GPIO_GYRO) { - GBAGPIOInitGyro(&gba->memory.gpio); + if (override->hardware & HW_GYRO) { + GBAHardwareInitGyro(&gba->memory.hw); } - if (override->hardware & GPIO_RUMBLE) { - GBAGPIOInitRumble(&gba->memory.gpio); + if (override->hardware & HW_RUMBLE) { + GBAHardwareInitRumble(&gba->memory.hw); } - if (override->hardware & GPIO_LIGHT_SENSOR) { - GBAGPIOInitLightSensor(&gba->memory.gpio); + if (override->hardware & HW_LIGHT_SENSOR) { + GBAHardwareInitLight(&gba->memory.hw); } - if (override->hardware & GPIO_TILT) { - GBAGPIOInitTilt(&gba->memory.gpio); + if (override->hardware & HW_TILT) { + GBAHardwareInitTilt(&gba->memory.hw); } }
@@ -1,32 +0,0 @@
-/* Copyright (c) 2013-2014 Jeffrey Pfau - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef GBA_SENSORS_H -#define GBA_SENSORS_H - -#include "util/common.h" - -struct GBARotationSource { - void (*sample)(struct GBARotationSource*); - - int32_t (*readTiltX)(struct GBARotationSource*); - int32_t (*readTiltY)(struct GBARotationSource*); - - int32_t (*readGyroZ)(struct GBARotationSource*); -}; - -struct GBALuminanceSource { - void (*sample)(struct GBALuminanceSource*); - - uint8_t (*readLuminance)(struct GBALuminanceSource*); -}; - -struct GBARTCSource { - void (*sample)(struct GBARTCSource*); - - time_t (*unixTime)(struct GBARTCSource*); -}; - -#endif
@@ -129,7 +129,7 @@ * | 0x0028C - 0x0028F: DMA next event
* 0x00290 - 0x002C3: GPIO state * | 0x00290 - 0x00291: Pin state * | 0x00292 - 0x00293: Direction state - * | 0x00294 - 0x002B6: RTC state (see gba-gpio.h for format) + * | 0x00294 - 0x002B6: RTC state (see gba-hardware.h for format) * | 0x002B7 - 0x002B7: GPIO devices * | bit 0: Has RTC values * | bit 1: Has rumble value (reserved)@@ -269,9 +269,9 @@ unsigned lightCounter : 12;
unsigned lightSample : 8; unsigned tiltState : 2; unsigned : 22; - } gpio; + } hw; - uint32_t reservedGpio[12]; + uint32_t reservedHardware[12]; uint32_t biosPrefetch; uint32_t cpuPrefetch[2];
@@ -364,7 +364,7 @@ gba->activeFile = fname;
gba->memory.romSize = gba->pristineRomSize; gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize); GBASavedataInit(&gba->memory.savedata, sav); - GBAGPIOInit(&gba->memory.gpio, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]); + GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]); // TODO: error check }
@@ -13,7 +13,7 @@ #include <QMutex>
#include <QString> extern "C" { -#include "gba-sensors.h" +#include "gba-hardware.h" #include "gba-thread.h" #ifdef BUILD_SDL #include "sdl-events.h"
@@ -58,26 +58,26 @@ void OverrideView::updateOverrides() {
m_override = (GBACartridgeOverride) { "", static_cast<SavedataType>(m_ui.savetype->currentIndex() - 1), - GPIO_NO_OVERRIDE, + HW_NO_OVERRIDE, IDLE_LOOP_NONE }; if (!m_ui.hwAutodetect->isChecked()) { - m_override.hardware = GPIO_NONE; + m_override.hardware = HW_NONE; if (m_ui.hwRTC->isChecked()) { - m_override.hardware |= GPIO_RTC; + m_override.hardware |= HW_RTC; } if (m_ui.hwGyro->isChecked()) { - m_override.hardware |= GPIO_GYRO; + m_override.hardware |= HW_GYRO; } if (m_ui.hwLight->isChecked()) { - m_override.hardware |= GPIO_LIGHT_SENSOR; + m_override.hardware |= HW_LIGHT_SENSOR; } if (m_ui.hwTilt->isChecked()) { - m_override.hardware |= GPIO_TILT; + m_override.hardware |= HW_TILT; } if (m_ui.hwRumble->isChecked()) { - m_override.hardware |= GPIO_RUMBLE; + m_override.hardware |= HW_RUMBLE; } }@@ -87,7 +87,7 @@ if (ok) {
m_override.idleLoop = parsedIdleLoop; } - if (m_override.savetype != SAVEDATA_AUTODETECT || m_override.hardware != GPIO_NO_OVERRIDE || m_override.idleLoop != IDLE_LOOP_NONE) { + if (m_override.savetype != SAVEDATA_AUTODETECT || m_override.hardware != HW_NO_OVERRIDE || m_override.idleLoop != IDLE_LOOP_NONE) { m_controller->setOverride(m_override); } else { m_controller->clearOverride();@@ -109,11 +109,11 @@ m_ui.hwLight->setEnabled(false);
m_ui.hwTilt->setEnabled(false); m_ui.hwRumble->setEnabled(false); - m_ui.hwRTC->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_RTC); - m_ui.hwGyro->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_GYRO); - m_ui.hwLight->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_LIGHT_SENSOR); - m_ui.hwTilt->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_TILT); - m_ui.hwRumble->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_RUMBLE); + m_ui.hwRTC->setChecked(thread->gba->memory.hw.devices & HW_RTC); + m_ui.hwGyro->setChecked(thread->gba->memory.hw.devices & HW_GYRO); + m_ui.hwLight->setChecked(thread->gba->memory.hw.devices & HW_LIGHT_SENSOR); + m_ui.hwTilt->setChecked(thread->gba->memory.hw.devices & HW_TILT); + m_ui.hwRumble->setChecked(thread->gba->memory.hw.devices & HW_RUMBLE); if (thread->gba->idleLoop != IDLE_LOOP_NONE) { m_ui.idleLoop->setText(QString::number(thread->gba->idleLoop, 16));@@ -123,7 +123,7 @@
} GBAGetGameCode(thread->gba, m_override.id); - m_override.hardware = thread->gba->memory.gpio.gpioDevices; + m_override.hardware = thread->gba->memory.hw.devices; m_override.savetype = thread->gba->memory.savedata.type; m_override.idleLoop = thread->gba->idleLoop;