mirror of https://github.com/mgba-emu/mgba.git
GB: Simplistic SIO implementation
This commit is contained in:
parent
488bc56d3c
commit
7bcda2daa9
11
src/gb/gb.c
11
src/gb/gb.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
11
src/gb/io.c
11
src/gb/io.c
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue