GB: Simplistic SIO implementation

This commit is contained in:
Jeffrey Pfau 2016-08-26 14:45:43 -07:00
parent 488bc56d3c
commit 7bcda2daa9
5 changed files with 106 additions and 4 deletions

View File

@ -54,6 +54,9 @@ static void GBInit(void* cpu, struct mCPUComponent* component) {
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 @@ void GBReset(struct LR35902Core* cpu) {
GBTimerReset(&gb->timer);
GBIOReset(gb);
GBAudioReset(&gb->audio);
GBSIOReset(&gb->sio);
}
void GBUpdateIRQs(struct GB* gb) {
@ -332,6 +338,11 @@ void GBProcessEvents(struct LR35902Core* cpu) {
nextEvent = testEvent;
}
testEvent = GBSIOProcessEvents(&gb->sio, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
testEvent = GBMemoryProcessEvents(gb, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;

View File

@ -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 GB {
struct GBVideo video;
struct GBTimer timer;
struct GBAudio audio;
struct GBSIO sio;
enum GBModel model;
struct mCoreSync* sync;

View File

@ -6,6 +6,7 @@
#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 GBIOReset(struct GB* gb) {
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 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t 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 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
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:

53
src/gb/sio.c Normal file
View File

@ -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;
}
}

33
src/gb/sio.h Normal file
View File

@ -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