all repos — mgba @ 7bcda2daa9cae93ec37e3806d22cb0fe1f259588

mGBA Game Boy Advance Emulator

GB: Simplistic SIO implementation
Jeffrey Pfau jeffrey@endrift.com
Fri, 26 Aug 2016 14:45:43 -0700
commit

7bcda2daa9cae93ec37e3806d22cb0fe1f259588

parent

488bc56d3c76debc4cb3cd5ab9f3e54f389450bf

5 files changed, 106 insertions(+), 4 deletions(-)

jump to
M src/gb/gb.csrc/gb/gb.c

@@ -54,6 +54,9 @@

gb->audio.p = gb; GBAudioInit(&gb->audio, 2048, &gb->memory.io[REG_NR52], GB_AUDIO_DMG); // TODO: Remove magic constant + gb->sio.p = gb; + GBSIOInit(&gb->sio); + gb->timer.p = gb; gb->biosVf = 0;

@@ -163,6 +166,8 @@ void GBDestroy(struct GB* gb) {

GBUnloadROM(gb); GBMemoryDeinit(gb); + GBVideoDeinit(&gb->video); + GBSIODeinit(&gb->sio); } void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {

@@ -256,6 +261,7 @@ GBVideoReset(&gb->video);

GBTimerReset(&gb->timer); GBIOReset(gb); GBAudioReset(&gb->audio); + GBSIOReset(&gb->sio); } void GBUpdateIRQs(struct GB* gb) {

@@ -328,6 +334,11 @@ }

} testEvent = GBTimerProcessEvents(&gb->timer, cycles); + if (testEvent < nextEvent) { + nextEvent = testEvent; + } + + testEvent = GBSIOProcessEvents(&gb->sio, cycles); if (testEvent < nextEvent) { nextEvent = testEvent; }
M src/gb/gb.hsrc/gb/gb.h

@@ -15,6 +15,7 @@

#include "gb/audio.h" #include "gb/interface.h" #include "gb/memory.h" +#include "gb/sio.h" #include "gb/timer.h" #include "gb/video.h"

@@ -51,6 +52,7 @@ struct GBMemory memory;

struct GBVideo video; struct GBTimer timer; struct GBAudio audio; + struct GBSIO sio; enum GBModel model; struct mCoreSync* sync;
M src/gb/io.csrc/gb/io.c

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

#include "io.h" #include "gb/gb.h" +#include "gb/sio.h" #include "gb/serialize.h" mLOG_DEFINE_CATEGORY(GB_IO, "GB I/O");

@@ -157,6 +158,9 @@ }

void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { switch (address) { + case REG_SC: + GBSIOWriteSC(&gb->sio, value); + break; case REG_DIV: GBTimerDivReset(&gb->timer); return;

@@ -334,6 +338,7 @@ gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;

} break; case REG_JOYP: + case REG_SB: case REG_TIMA: case REG_TMA: case REG_LYC:

@@ -461,10 +466,6 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {

switch (address) { case REG_JOYP: return _readKeys(gb); - case REG_SB: - case REG_SC: - // TODO - break; case REG_IE: return gb->memory.ie; case REG_WAVE_0:

@@ -493,6 +494,8 @@ } else {

return gb->audio.ch3.wavedata8[address - REG_WAVE_0]; } break; + case REG_SB: + case REG_SC: case REG_IF: case REG_NR10: case REG_NR11:
A src/gb/sio.c

@@ -0,0 +1,53 @@

+/* Copyright (c) 2013-2016 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 "sio.h" + +#include "gb/gb.h" +#include "gb/io.h" +#include "gb/serialize.h" + +void GBSIOInit(struct GBSIO* sio) { + sio->pendingSB = 0xFF; +} + +void GBSIOReset(struct GBSIO* sio) { + sio->nextEvent = INT_MAX; + sio->remainingBits = 0; +} + +void GBSIODeinit(struct GBSIO* sio) { + UNUSED(sio); + // Nothing to do yet +} + +int32_t GBSIOProcessEvents(struct GBSIO* sio, int32_t cycles) { + if (sio->nextEvent != INT_MAX) { + sio->nextEvent -= cycles; + } + if (sio->nextEvent <= 0) { + --sio->remainingBits; + sio->p->memory.io[REG_SB] &= ~(8 >> sio->remainingBits); + sio->p->memory.io[REG_SB] |= sio->pendingSB & ~(8 >> sio->remainingBits); + if (!sio->remainingBits) { + sio->p->memory.io[REG_IF] |= (1 << GB_IRQ_SIO); + sio->p->memory.io[REG_SC] = GBRegisterSCClearEnable(sio->p->memory.io[REG_SC]); + GBUpdateIRQs(sio->p); + sio->nextEvent = INT_MAX; + } else { + sio->nextEvent += sio->period; + } + } + return sio->nextEvent; +} + +void GBSIOWriteSC(struct GBSIO* sio, uint8_t sc) { + sio->period = 0x1000; // TODO Shift Clock + if (GBRegisterSCIsEnable(sc)) { + sio->nextEvent = sio->p->cpu->cycles + sio->period; + sio->remainingBits = 8; + } +} +
A src/gb/sio.h

@@ -0,0 +1,33 @@

+/* Copyright (c) 2013-2016 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 GB_SIO_H +#define GB_SIO_H + +#include "util/common.h" + +struct GB; +struct GBSIO { + struct GB* p; + + int32_t nextEvent; + int32_t period; + int remainingBits; + + uint8_t pendingSB; +}; + +DECL_BITFIELD(GBRegisterSC, uint8_t); +DECL_BIT(GBRegisterSC, ShiftClock, 0); +DECL_BIT(GBRegisterSC, ClockSpeed, 1); +DECL_BIT(GBRegisterSC, Enable, 7); + +void GBSIOInit(struct GBSIO* sio); +void GBSIOReset(struct GBSIO* sio); +void GBSIODeinit(struct GBSIO* sio); +int32_t GBSIOProcessEvents(struct GBSIO* sio, int32_t cycles); +void GBSIOWriteSC(struct GBSIO* sio, uint8_t sc); + +#endif