diff --git a/console.html b/console.html index c8dba709..f32338c7 100644 --- a/console.html +++ b/console.html @@ -12,6 +12,7 @@ + diff --git a/index.html b/index.html index ded90968..87672ffc 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@ + diff --git a/js/gba.js b/js/gba.js index 6dadb17e..5e55628e 100644 --- a/js/gba.js +++ b/js/gba.js @@ -18,6 +18,7 @@ function GameBoyAdvance() { this.audio = new GameBoyAdvanceAudio(); this.video = new GameBoyAdvanceVideo(); this.keypad = new GameBoyAdvanceKeypad(); + this.sio = new GameBoyAdvanceSIO(); // TODO: simplify this graph this.cpu.mmu = this.mmu; @@ -36,6 +37,7 @@ function GameBoyAdvance() { this.io.audio = this.audio; this.io.video = this.video; this.io.keypad = this.keypad; + this.io.sio = this.sio; this.io.core = this; this.audio.cpu = this.cpu; @@ -46,6 +48,8 @@ function GameBoyAdvance() { this.keypad.core = this; + this.sio.core = this; + this.keypad.registerHandlers(); this.doStep = this.waitFrame; this.paused = false; @@ -131,6 +135,7 @@ GameBoyAdvance.prototype.reset = function() { this.io.clear(); this.audio.clear(); this.video.clear(); + this.sio.clear(); this.mmu.mmap(this.mmu.REGION_IO, this.io); this.mmu.mmap(this.mmu.REGION_PALETTE_RAM, this.video.renderPath.palette); diff --git a/js/io.js b/js/io.js index 7d45e2ad..7737ba43 100644 --- a/js/io.js +++ b/js/io.js @@ -108,8 +108,9 @@ function GameBoyAdvanceIO() { this.TM3CNT_HI = 0x10E; // SIO (note: some of these are repeated) - this.SIODATA32 = 0x120; + this.SIODATA32_LO = 0x120; this.SIOMULTI0 = 0x120; + this.SIODATA32_HI = 0x122; this.SIOMULTI1 = 0x122; this.SIOMULTI2 = 0x124; this.SIOMULTI3 = 0x126; @@ -139,14 +140,7 @@ function GameBoyAdvanceIO() { this.DEFAULT_SOUNDBIAS = 0x200; this.DEFAULT_BGPA = 1; this.DEFAULT_BGPD = 1; -}; - -GameBoyAdvanceIO.prototype.setCPU = function(cpu) { - this.cpu = cpu; -}; - -GameBoyAdvanceIO.prototype.setVideo = function(video) { - this.video = video; + this.DEFAULT_RCNT = 0x8000; }; GameBoyAdvanceIO.prototype.clear = function() { @@ -158,6 +152,7 @@ GameBoyAdvanceIO.prototype.clear = function() { this.registers[this.BG2PD >> 1] = this.DEFAULT_BGPD; this.registers[this.BG3PA >> 1] = this.DEFAULT_BGPA; this.registers[this.BG3PD >> 1] = this.DEFAULT_BGPD; + this.registers[this.RCNT >> 1] = this.RCNT; }; GameBoyAdvanceIO.prototype.freeze = function() { @@ -232,6 +227,8 @@ GameBoyAdvanceIO.prototype.loadU16 = function(offset) { case this.DMA1CNT_HI: case this.DMA2CNT_HI: case this.DMA3CNT_HI: + case this.RCNT: + case this.SIOCNT: case this.WAITCNT: case this.IE: case this.IF: @@ -274,13 +271,6 @@ GameBoyAdvanceIO.prototype.loadU16 = function(offset) { case this.TM3CNT_LO: return this.cpu.irq.timerRead(3); - case this.RCNT: - this.core.STUB('Reading from unimplemented RCNT'); - return 0x8000; - case this.SIOCNT: - this.core.STUB('Reading from unimplemented SIOCNT'); - return 0; - case this.KEYINPUT: return this.keypad.currentDown; case this.KEYCNT: @@ -722,10 +712,12 @@ GameBoyAdvanceIO.prototype.store16 = function(offset, value) { this.STUB_REG('SIO', offset); break; case this.RCNT: - this.STUB_REG('RCNT', offset); + this.sio.setMode(((value >> 12) & 0xC) | ((this.registers[this.SIOCNT >> 1] >> 12) & 0x3)); + this.sio.writeRCNT(value); break; case this.SIOCNT: - this.STUB_REG('SIOCNT', offset); + this.sio.setMode(((value >> 12) & 0x3) | ((this.registers[this.RCNT >> 1] >> 12) & 0xC)); + this.sio.writeSIOCNT(value); break; case this.JOYCNT: case this.JOYSTAT: diff --git a/js/sio.js b/js/sio.js new file mode 100644 index 00000000..a52c6b0a --- /dev/null +++ b/js/sio.js @@ -0,0 +1,54 @@ +function GameBoyAdvanceSIO() { + this.SIO_NORMAL_8 = 0; + this.SIO_NORMAL_32 = 1; + this.SIO_MULTI = 2; + this.SIO_UART = 3; + this.SIO_GPIO = 8; + this.SIO_JOYBUS = 12; +} + +GameBoyAdvanceSIO.prototype.clear = function() { + this.mode = this.SIO_GPIO; +}; + +GameBoyAdvanceSIO.prototype.setMode = function(mode) { + if (mode & 0x8) { + mode &= 0xC; + } else { + mode &= 0x3; + } + this.mode = mode; + + this.core.INFO('Setting SIO mode to ' + hex(mode, 1)); +}; + +GameBoyAdvanceSIO.prototype.writeRCNT = function(value) { + if (mode != this.SIO_GPIO) { + return; + } + + this.core.STUB('General purpose serial not supported'); +}; + +GameBoyAdvanceSIO.prototype.writeSIOCNT = function(value) { + switch (this.mode) { + case this.SIO_NORMAL_8: + this.core.STUB('8-bit transfer unsupported'); + break; + case this.SIO_NORMAL_32: + this.core.STUB('32-bit transfer unsupported'); + break; + case this.SIO_MULTI: + this.core.STUB('Multiplayer unsupported'); + break; + case this.SIO_UART: + this.core.STUB('UART unsupported'); + break; + case this.SIO_GPIO: + // Nothing to do + break; + case this.SIO_JOYBUS: + this.core.STUB('JOY BUS unsupported'); + break; + } +}; \ No newline at end of file