all repos — mgba @ 4b5efa2365db0eaf537b6ba8ff70e588f4213cc3

mGBA Game Boy Advance Emulator

GBA Hardware: I know this e-Reader code is wrong
Vicki Pfau vi@endrift.com
Mon, 16 Oct 2017 22:43:02 -0700
commit

4b5efa2365db0eaf537b6ba8ff70e588f4213cc3

parent

40a22eba776e0e47658deaf7f3a97cc9eaa7812b

M include/mgba/gba/interface.hinclude/mgba/gba/interface.h

@@ -88,6 +88,12 @@ };

void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate*); +#define EREADER_BLOCK_SIZE 40 + +struct GBAEReaderDataSource { + bool (*readBlock)(struct GBAEReaderDataSource*, void*); +}; + CXX_GUARD_END #endif
M include/mgba/internal/gba/hardware.hinclude/mgba/internal/gba/hardware.h

@@ -172,6 +172,7 @@ enum EReaderCommand eReaderCommand;

uint8_t eReaderActiveRegister; uint8_t eReaderByte; uint8_t eReaderDelay; + struct GBAEReaderDataSource* eReaderSource; }; void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);

@@ -196,6 +197,7 @@ void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value);

void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value); uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address); uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address); +void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, struct GBAEReaderDataSource* source); void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba);
M src/gba/hardware.csrc/gba/hardware.c

@@ -39,6 +39,7 @@

static void _eReaderReset(struct GBACartridgeHardware* hw); static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value); static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value); +static void _eReaderReadData(struct GBACartridgeHardware* hw); static const int RTC_BYTES[8] = { 0, // Force reset

@@ -666,6 +667,14 @@ return 0;

} } +void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, struct GBAEReaderDataSource* source) { + if (!EReaderControl0IsScan(hw->eReaderRegisterControl0)) { + return; + } + hw->eReaderSource = source; + _eReaderReadData(hw); +} + void _eReaderReset(struct GBACartridgeHardware* hw) { memset(hw->eReaderData, 0, sizeof(hw->eReaderData)); hw->eReaderRegisterUnk = 0;

@@ -738,7 +747,7 @@ }

++hw->eReaderActiveRegister; break; default: - mLOG(GBA_HW, ERROR, "???"); + mLOG(GBA_HW, ERROR, "Hit undefined state in e-Reader state machine"); break; } hw->eReaderState = EREADER_SERIAL_BIT_0;

@@ -759,13 +768,31 @@ // Clear the error bit

control = EReaderControl0ClearData(control); } hw->eReaderRegisterControl0 = control; + if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) { + _eReaderReadData(hw); + } mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value); } void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) { EReaderControl1 control = (value & 0x32) | 0x80; hw->eReaderRegisterControl1 = control; + if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) { + _eReaderReadData(hw); + } mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value); +} + +void _eReaderReadData(struct GBACartridgeHardware* hw) { + if (!hw->eReaderSource) { + return; + } + memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE); + hw->eReaderSource->readBlock(hw->eReaderSource, hw->eReaderData); + hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1); + if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) { + GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0); + } } // == Serialization
M src/platform/qt/CoreController.cppsrc/platform/qt/CoreController.cpp

@@ -680,6 +680,24 @@ m_threadContext.core->rtc.override = RTC_FAKE_EPOCH;

m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); } +void CoreController::scanCard(const QString& path) { +#ifdef M_CORE_GBA + if (m_eReader.file.isOpen()) { + m_eReader.file.close(); + } + m_eReader.file.setFileName(path); + if (!m_eReader.file.open(QIODevice::ReadOnly)) { + return; + } + + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) { + CoreController* controller = static_cast<CoreController*>(thread->userData); + GBAHardwareEReaderScan(&static_cast<GBA*>(thread->core->board)->memory.hw, &controller->m_eReader); + }); +#endif +} + + void CoreController::importSharkport(const QString& path) { #ifdef M_CORE_GBA if (platform() != PLATFORM_GBA) {
M src/platform/qt/CoreController.hsrc/platform/qt/CoreController.h

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#pragma once #include <QByteArray> +#include <QFile> #include <QList> #include <QMutex> #include <QObject>

@@ -127,6 +128,7 @@ void saveBackupState();

void loadSave(const QString&, bool temporary); void loadPatch(const QString&); + void scanCard(const QString&); void replaceGame(const QString&); void yankPak();

@@ -256,6 +258,10 @@ #endif

#ifdef M_CORE_GBA GBASIOBattlechipGate m_battlechip; + struct GameControllerEReader : GBAEReaderDataSource { + CoreController* p; + QFile file; + } m_eReader; #endif };
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -423,6 +423,13 @@ }

} } +void Window::scanCard() { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select e-Reader dotcode")); + if (!filename.isEmpty()) { + m_controller->scanCard(filename); + } +} + void Window::openView(QWidget* widget) { connect(this, &Window::shutdown, widget, &QWidget::close); widget->setAttribute(Qt::WA_DeleteOnClose);

@@ -1118,6 +1125,7 @@ }, "file");

#endif m_actions.addAction(tr("Replace ROM..."), "replaceROM", this, &Window::replaceROM, "file"); + m_actions.addAction(tr("Scan e-Reader dotcode..."), "scanCard", this, &Window::scanCard, "file"); Action* romInfo = addGameAction(tr("ROM &info..."), "romInfo", openControllerTView<ROMInfo>(), "file");
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -75,6 +75,7 @@ #endif

void selectSave(bool temporary); void selectState(bool load); void selectPatch(); + void scanCard(); void enterFullScreen(); void exitFullScreen(); void toggleFullScreen();