diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 260b391e..1718d867 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.25"; + static const string Version = "097.26"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/v30mz/algorithms.cpp b/higan/processor/v30mz/algorithms.cpp index a75eae95..4165dc98 100644 --- a/higan/processor/v30mz/algorithms.cpp +++ b/higan/processor/v30mz/algorithms.cpp @@ -119,7 +119,7 @@ auto V30MZ::alRcl(Size size, uint16 x, uint5 y) -> uint16 { uint16 result = x; for(uint n = 0; n < y; n++) { bool carry = result & sign; - result = (result << 1) | carry; + result = (result << 1) | r.f.c; r.f.c = carry; } r.f.v = (x ^ result) & sign; @@ -130,7 +130,7 @@ auto V30MZ::alRcr(Size size, uint16 x, uint5 y) -> uint16 { uint16 result = x; for(uint n = 0; n < y; n++) { bool carry = result & 1; - result = (carry ? sign : 0) | (result >> 1); + result = (r.f.c ? sign : 0) | (result >> 1); r.f.c = carry; } r.f.v = (x ^ result) & sign; diff --git a/higan/processor/v30mz/instructions-alu.cpp b/higan/processor/v30mz/instructions-alu.cpp index 1ed3255b..89334dbe 100644 --- a/higan/processor/v30mz/instructions-alu.cpp +++ b/higan/processor/v30mz/instructions-alu.cpp @@ -134,7 +134,7 @@ auto V30MZ::opTestMemReg(Size size) { auto V30MZ::opMultiplySignedRegMemImm(Size size) { wait(2); modRM(); - setReg(size, alMuli(size, getMem(size), size == Word ? (int16_t)fetch(Word) : (int8_t)fetch(Byte))); + setReg(Word, alMuli(Word, getMem(Word), size == Word ? (int16_t)fetch(Word) : (int8_t)fetch(Byte))); } //40 inc ax diff --git a/higan/processor/v30mz/v30mz.cpp b/higan/processor/v30mz/v30mz.cpp index 11bf214a..e1efd74b 100644 --- a/higan/processor/v30mz/v30mz.cpp +++ b/higan/processor/v30mz/v30mz.cpp @@ -18,7 +18,7 @@ namespace Processor { #include "disassembler.cpp" auto V30MZ::debug(string text) -> void { - print(text, "\n"); +//print(text, "\n"); } auto V30MZ::power() -> void { diff --git a/higan/profile/WonderSwan Color.sys/manifest.bml b/higan/profile/WonderSwan Color.sys/manifest.bml index 22c9faea..3422d5f1 100644 --- a/higan/profile/WonderSwan Color.sys/manifest.bml +++ b/higan/profile/WonderSwan Color.sys/manifest.bml @@ -1,2 +1,2 @@ system name:WonderSwan Color - eeprom name=internal.rom size=2048 + eeprom name=internal.ram size=2048 diff --git a/higan/profile/WonderSwan.sys/manifest.bml b/higan/profile/WonderSwan.sys/manifest.bml index 9c778cc0..26aa0503 100644 --- a/higan/profile/WonderSwan.sys/manifest.bml +++ b/higan/profile/WonderSwan.sys/manifest.bml @@ -1,2 +1,2 @@ system name:WonderSwan - eeprom name=internal.rom size=128 + eeprom name=internal.ram size=128 diff --git a/higan/ws/apu/apu.cpp b/higan/ws/apu/apu.cpp index c4a1801e..6e135616 100644 --- a/higan/ws/apu/apu.cpp +++ b/higan/ws/apu/apu.cpp @@ -4,56 +4,54 @@ namespace WonderSwan { APU apu; #include "io.cpp" -#include "channel.cpp" -#include "channel0.cpp" +#include "dma.cpp" #include "channel1.cpp" #include "channel2.cpp" #include "channel3.cpp" #include "channel4.cpp" +#include "channel5.cpp" auto APU::Enter() -> void { while(true) scheduler.synchronize(), apu.main(); } auto APU::main() -> void { - channel0.run(); + dma.run(); channel1.run(); channel2.run(); channel3.run(); - - if(s.clock.bits(0,12) == 0) { - channel2.sweep(); - } - - if(s.clock.bits(0,6) == 0) { - channel4.run(); - dacRun(); - } - + channel4.run(); + channel5.run(); + if(s.clock.bits(0,12) == 0) channel3.sweep(); + if(s.clock.bits(0, 6) == 0) dacRun(); s.clock++; step(1); } +auto APU::sample(uint channel, uint5 index) -> uint4 { + uint8 data = iram.read((r.waveBase << 6) + (--channel << 4) + (index >> 1)); + if(index.bit(0) == 0) return data.bits(0,3); + if(index.bit(0) == 1) return data.bits(4,7); +} + auto APU::dacRun() -> void { int left = 0; - if(channel0.r.enable) left += channel0.o.left; if(channel1.r.enable) left += channel1.o.left; if(channel2.r.enable) left += channel2.o.left; if(channel3.r.enable) left += channel3.o.left; - left = (left >> r.speakerShift) << 5; if(channel4.r.enable) left += channel4.o.left; - left = sclamp<16>(left << 3); + if(channel5.r.enable) left += (int11)channel5.o.left >> 3; + left = sclamp<16>(left << 5); int right = 0; - if(channel0.r.enable) right += channel0.o.right; if(channel1.r.enable) right += channel1.o.right; if(channel2.r.enable) right += channel2.o.right; if(channel3.r.enable) right += channel3.o.right; - right = (right >> r.speakerShift) << 5; if(channel4.r.enable) right += channel4.o.right; - right = sclamp<16>(right << 3); + if(channel5.r.enable) right += (int11)channel5.o.right >> 3; + right = sclamp<16>(right << 5); - if(!r.speakerEnable) { + if(!r.headphoneEnable) { left = 0; right = 0; } @@ -69,8 +67,11 @@ auto APU::step(uint clocks) -> void { auto APU::power() -> void { create(APU::Enter, 3'072'000); - for(uint n = 0x006a; n <= 0x006b; n++) iomap[n] = this; - for(uint n = 0x0080; n <= 0x0094; n++) iomap[n] = this; + bus.map(this, 0x004a, 0x004c); + bus.map(this, 0x004e, 0x0050); + bus.map(this, 0x0052); + bus.map(this, 0x006a, 0x006b); + bus.map(this, 0x0080, 0x0095); s.clock = 0; r.waveBase = 0; @@ -78,14 +79,17 @@ auto APU::power() -> void { r.speakerShift = 0; r.headphoneEnable = 0; - channel0.o.left = 0; - channel0.o.right = 0; - channel0.s.period = 0; - channel0.s.sampleOffset = 0; - channel0.r.pitch = 0; - channel0.r.volumeLeft = 0; - channel0.r.volumeRight = 0; - channel0.r.enable = 0; + dma.s.clock = 0; + dma.s.source = 0; + dma.s.length = 0; + dma.r.source = 0; + dma.r.length = 0; + dma.r.rate = 0; + dma.r.unknown = 0; + dma.r.loop = 0; + dma.r.target = 0; + dma.r.direction = 0; + dma.r.enable = 0; channel1.o.left = 0; channel1.o.right = 0; @@ -95,48 +99,58 @@ auto APU::power() -> void { channel1.r.volumeLeft = 0; channel1.r.volumeRight = 0; channel1.r.enable = 0; - channel1.r.voice = 0; - channel1.r.voiceEnableLeft = 0; - channel1.r.voiceEnableRight = 0; channel2.o.left = 0; channel2.o.right = 0; channel2.s.period = 0; channel2.s.sampleOffset = 0; - channel2.s.sweepCounter = 0; channel2.r.pitch = 0; channel2.r.volumeLeft = 0; channel2.r.volumeRight = 0; - channel2.r.sweepValue = 0; - channel2.r.sweepTime = 0; channel2.r.enable = 0; - channel2.r.sweep = 0; + channel2.r.voice = 0; + channel2.r.voiceEnableLeft = 0; + channel2.r.voiceEnableRight = 0; channel3.o.left = 0; channel3.o.right = 0; channel3.s.period = 0; channel3.s.sampleOffset = 0; - channel3.s.noiseOutput = 0; - channel3.s.noiseLFSR = 0; + channel3.s.sweepCounter = 0; channel3.r.pitch = 0; channel3.r.volumeLeft = 0; channel3.r.volumeRight = 0; - channel3.r.noiseMode = 0; - channel3.r.noiseReset = 0; - channel3.r.noiseUpdate = 0; + channel3.r.sweepValue = 0; + channel3.r.sweepTime = 0; channel3.r.enable = 0; - channel3.r.noise = 0; + channel3.r.sweep = 0; channel4.o.left = 0; channel4.o.right = 0; - channel4.s.data = 0; - channel4.r.volume = 0; - channel4.r.scale = 0; - channel4.r.speed = 0; + channel4.s.period = 0; + channel4.s.sampleOffset = 0; + channel4.s.noiseOutput = 0; + channel4.s.noiseLFSR = 0; + channel4.r.pitch = 0; + channel4.r.volumeLeft = 0; + channel4.r.volumeRight = 0; + channel4.r.noiseMode = 0; + channel4.r.noiseReset = 0; + channel4.r.noiseUpdate = 0; channel4.r.enable = 0; - channel4.r.unknown = 0; - channel4.r.leftEnable = 0; - channel4.r.rightEnable = 0; + channel4.r.noise = 0; + + channel5.o.left = 0; + channel5.o.right = 0; + channel5.s.clock = 0; + channel5.s.data = 0; + channel5.r.volume = 0; + channel5.r.scale = 0; + channel5.r.speed = 0; + channel5.r.enable = 0; + channel5.r.unknown = 0; + channel5.r.leftEnable = 0; + channel5.r.rightEnable = 0; } } diff --git a/higan/ws/apu/apu.hpp b/higan/ws/apu/apu.hpp index 641fbe04..db124068 100644 --- a/higan/ws/apu/apu.hpp +++ b/higan/ws/apu/apu.hpp @@ -1,6 +1,7 @@ struct APU : Thread, IO { static auto Enter() -> void; auto main() -> void; + auto sample(uint channel, uint5 index) -> uint4; auto dacRun() -> void; auto step(uint clocks) -> void; auto power() -> void; @@ -13,7 +14,47 @@ struct APU : Thread, IO { uint13 clock; } s; + struct DMA { + auto run() -> void; + + struct State { + uint clock; + uint20 source; + uint20 length; + } s; + + struct Registers { + //$004a-$004c SDMA_SRC + uint20 source; + + //$004e-$0050 SDMA_LEN + uint20 length; + + //$0052 SDMA_CTRL + uint2 rate; + uint1 unknown; + uint1 loop; + uint1 target; + uint1 direction; + uint1 enable; + } r; + } dma; + struct Registers { + //$004a-$004c SDMA_SRC + uint20 dmaSource; + + //$004e-$0050 SDMA_LEN + uint20 dmaLength; + + //$0052 SDMA_CTRL + uint2 dmaRate; + uint1 dmaUnknown; + uint1 dmaLoop; + uint1 dmaTarget; + uint1 dmaDirection; + uint1 dmaEnable; + //$008f SND_WAVE_BASE uint8 waveBase; @@ -23,21 +64,13 @@ struct APU : Thread, IO { uint1 headphoneEnable; } r; - struct Channel { - Channel(uint id); - auto sample(uint5 index) -> uint4; - - const uint id; + struct Channel1 { + auto run() -> void; struct Output { - int16 left; - int16 right; + uint8 left; + uint8 right; } o; - }; - - struct Channel0 : Channel { - Channel0(); - auto run() -> void; struct State { uint11 period; @@ -45,32 +78,36 @@ struct APU : Thread, IO { } s; struct Registers { - //$0080-0081 SND_CH0_PITCH + //$0080-0081 SND_CH1_PITCH uint11 pitch; - //$0088 SND_CH0_VOL + //$0088 SND_CH1_VOL uint4 volumeLeft; uint4 volumeRight; //$0090 SND_CTRL uint1 enable; } r; - } channel0; + } channel1; - struct Channel1 : Channel { - Channel1(); + struct Channel2 { auto run() -> void; + struct Output { + uint8 left; + uint8 right; + } o; + struct State { uint11 period; uint5 sampleOffset; } s; struct Registers { - //$0082-0083 SND_CH1_PITCH + //$0082-0083 SND_CH2_PITCH uint11 pitch; - //$0089 SND_CH1_VOL + //$0089 SND_CH2_VOL uint4 volumeLeft; uint4 volumeRight; @@ -78,17 +115,21 @@ struct APU : Thread, IO { uint1 enable; uint1 voice; - //$0092 SND_VOICE_CTRL + //$0094 SND_VOICE_CTRL uint2 voiceEnableLeft; uint2 voiceEnableRight; } r; - } channel1; + } channel2; - struct Channel2 : Channel { - Channel2(); + struct Channel3 { auto sweep() -> void; auto run() -> void; + struct Output { + uint8 left; + uint8 right; + } o; + struct State { uint11 period; uint5 sampleOffset; @@ -97,10 +138,10 @@ struct APU : Thread, IO { } s; struct Registers { - //$0084-0085 SND_CH2_PITCH + //$0084-0085 SND_CH3_PITCH uint11 pitch; - //$008a SND_CH2_VOL + //$008a SND_CH3_VOL uint4 volumeLeft; uint4 volumeRight; @@ -114,13 +155,17 @@ struct APU : Thread, IO { uint1 enable; uint1 sweep; } r; - } channel2; + } channel3; - struct Channel3 : Channel { - Channel3(); + struct Channel4 { auto noiseSample() -> uint4; auto run() -> void; + struct Output { + uint8 left; + uint8 right; + } o; + struct State { uint11 period; uint5 sampleOffset; @@ -130,10 +175,10 @@ struct APU : Thread, IO { } s; struct Registers { - //$0086-0087 SND_CH3_PITCH + //$0086-0087 SND_CH4_PITCH uint11 pitch; - //$008b SND_CH3_VOL + //$008b SND_CH4_VOL uint4 volumeLeft; uint4 volumeRight; @@ -146,14 +191,19 @@ struct APU : Thread, IO { uint1 enable; uint1 noise; } r; - } channel3; + } channel4; - struct Channel4 : Channel { - Channel4(); + struct Channel5 { auto run() -> void; + struct Output { + uint11 left; + uint11 right; + } o; + struct State { - int8 data; + uint clock; + uint8 data; } s; struct Registers { @@ -168,7 +218,7 @@ struct APU : Thread, IO { uint1 leftEnable; uint1 rightEnable; } r; - } channel4; + } channel5; }; extern APU apu; diff --git a/higan/ws/apu/channel.cpp b/higan/ws/apu/channel.cpp deleted file mode 100644 index c0218fdc..00000000 --- a/higan/ws/apu/channel.cpp +++ /dev/null @@ -1,8 +0,0 @@ -APU::Channel::Channel(uint id) : id(id) { -} - -auto APU::Channel::sample(uint5 index) -> uint4 { - auto data = iram.read((apu.r.waveBase << 6) + (id << 4) + (index >> 1)); - if(index.bit(0) == 0) return data.bits(0,3); - if(index.bit(0) == 1) return data.bits(4,7); -} diff --git a/higan/ws/apu/channel0.cpp b/higan/ws/apu/channel0.cpp deleted file mode 100644 index 548c1425..00000000 --- a/higan/ws/apu/channel0.cpp +++ /dev/null @@ -1,11 +0,0 @@ -APU::Channel0::Channel0() : Channel(0) { -} - -auto APU::Channel0::run() -> void { - if(--s.period == r.pitch) { - s.period = 0; - auto output = sample(s.sampleOffset++); - o.left = output * r.volumeLeft; - o.right = output * r.volumeRight; - } -} diff --git a/higan/ws/apu/channel1.cpp b/higan/ws/apu/channel1.cpp index 7c70a887..18c10201 100644 --- a/higan/ws/apu/channel1.cpp +++ b/higan/ws/apu/channel1.cpp @@ -1,14 +1,7 @@ -APU::Channel1::Channel1() : Channel(1) { -} - auto APU::Channel1::run() -> void { - if(r.voice) { - uint8 volume = r.volumeLeft << 4 | r.volumeRight << 0; - o.left = r.voiceEnableLeft ? volume : (uint8)0x80; - o.right = r.voiceEnableRight ? volume : (uint8)0x80; - } else if(--s.period == r.pitch) { + if(--s.period == r.pitch) { s.period = 0; - auto output = sample(s.sampleOffset++); + auto output = apu.sample(1, s.sampleOffset++); o.left = output * r.volumeLeft; o.right = output * r.volumeRight; } diff --git a/higan/ws/apu/channel2.cpp b/higan/ws/apu/channel2.cpp index ec7110dd..42cf8fc0 100644 --- a/higan/ws/apu/channel2.cpp +++ b/higan/ws/apu/channel2.cpp @@ -1,17 +1,11 @@ -APU::Channel2::Channel2() : Channel(2) { -} - -auto APU::Channel2::sweep() -> void { - if(r.sweep && --s.sweepCounter < 0) { - s.sweepCounter = r.sweepTime; - r.pitch += r.sweepTime; - } -} - auto APU::Channel2::run() -> void { - if(--s.period == r.pitch) { + if(r.voice) { + uint8 volume = r.volumeLeft << 4 | r.volumeRight << 0; + o.left = r.voiceEnableLeft ? volume : (uint8)0; + o.right = r.voiceEnableRight ? volume : (uint8)0; + } else if(--s.period == r.pitch) { s.period = 0; - auto output = sample(s.sampleOffset++); + auto output = apu.sample(2, s.sampleOffset++); o.left = output * r.volumeLeft; o.right = output * r.volumeRight; } diff --git a/higan/ws/apu/channel3.cpp b/higan/ws/apu/channel3.cpp index d628fad4..2ee6211a 100644 --- a/higan/ws/apu/channel3.cpp +++ b/higan/ws/apu/channel3.cpp @@ -1,30 +1,15 @@ -APU::Channel3::Channel3() : Channel(3) { -} - -auto APU::Channel3::noiseSample() -> uint4 { - return s.noiseOutput ? 0xf : 0x0; +auto APU::Channel3::sweep() -> void { + if(r.sweep && --s.sweepCounter < 0) { + s.sweepCounter = r.sweepTime; + r.pitch += r.sweepTime; + } } auto APU::Channel3::run() -> void { if(--s.period == r.pitch) { s.period = 0; - - auto output = r.noise ? noiseSample() : sample(s.sampleOffset++); + auto output = apu.sample(3, s.sampleOffset++); o.left = output * r.volumeLeft; o.right = output * r.volumeRight; - - if(r.noiseReset) { - r.noiseReset = 0; - s.noiseLFSR = 0; - s.noiseOutput = 0; - } - - if(r.noiseUpdate) { - static const int taps[8] = {14, 10, 13, 4, 8, 6, 9, 11}; - auto tap = taps[r.noiseMode]; - - s.noiseOutput = (1 ^ (s.noiseLFSR >> 7) ^ (s.noiseLFSR >> tap)) & 1; - s.noiseLFSR = s.noiseLFSR << 1 | s.noiseOutput; - } } } diff --git a/higan/ws/apu/channel4.cpp b/higan/ws/apu/channel4.cpp index 30366416..c71da08d 100644 --- a/higan/ws/apu/channel4.cpp +++ b/higan/ws/apu/channel4.cpp @@ -1,11 +1,27 @@ -APU::Channel4::Channel4() : Channel(4) { +auto APU::Channel4::noiseSample() -> uint4 { + return s.noiseOutput ? 0xf : 0x0; } auto APU::Channel4::run() -> void { - int16 sample = s.data << 8; - if(r.scale != 3) sample >>= r.volume; - if(r.scale == 1) sample |= 0x70000 >> r.volume; + if(--s.period == r.pitch) { + s.period = 0; - o.left = r.leftEnable ? sample : (int16)0; - o.right = r.rightEnable ? sample : (int16)0; + auto output = r.noise ? noiseSample() : apu.sample(4, s.sampleOffset++); + o.left = output * r.volumeLeft; + o.right = output * r.volumeRight; + + if(r.noiseReset) { + r.noiseReset = 0; + s.noiseLFSR = 0; + s.noiseOutput = 0; + } + + if(r.noiseUpdate) { + static const int taps[8] = {14, 10, 13, 4, 8, 6, 9, 11}; + auto tap = taps[r.noiseMode]; + + s.noiseOutput = (1 ^ (s.noiseLFSR >> 7) ^ (s.noiseLFSR >> tap)) & 1; + s.noiseLFSR = s.noiseLFSR << 1 | s.noiseOutput; + } + } } diff --git a/higan/ws/apu/channel5.cpp b/higan/ws/apu/channel5.cpp new file mode 100644 index 00000000..50cf2009 --- /dev/null +++ b/higan/ws/apu/channel5.cpp @@ -0,0 +1,17 @@ +auto APU::Channel5::run() -> void { + if(r.speed <= 5 && s.clock++ < 1536) return; //2000hz + if(r.speed == 6 && s.clock++ < 2048) return; //1500hz + if(r.speed == 7 && s.clock++ < 3072) return; //1000hz + s.clock = 0; + + uint11 output = s.data; + switch(r.scale) { + case 0: output <<= 3 - r.volume; break; + case 1: output <<= 3 - r.volume; output |= -0x100 << (3 - r.volume); break; + case 2: output <<= 3 - r.volume; break; + case 3: output <<= r.volume; break; + } + + o.left = r.leftEnable ? output : (uint11)0; + o.right = r.rightEnable ? output : (uint11)0; +} diff --git a/higan/ws/apu/dma.cpp b/higan/ws/apu/dma.cpp new file mode 100644 index 00000000..c33c1c80 --- /dev/null +++ b/higan/ws/apu/dma.cpp @@ -0,0 +1,29 @@ +auto APU::DMA::run() -> void { + if(!r.enable) return; + + if(r.rate == 0 && ++s.clock < 768) return; // 4000hz + if(r.rate == 1 && ++s.clock < 512) return; // 6000hz + if(r.rate == 2 && ++s.clock < 256) return; //12000hz + if(r.rate == 3 && ++s.clock < 128) return; //24000hz + s.clock = 0; + + uint8 data = bus.read(s.source); + if(r.direction == 0) s.source++; + if(r.direction == 1) s.source--; + + if(r.target == 0) { + apu.channel2.r.volumeRight = data.bits(0,3); + apu.channel2.r.volumeLeft = data.bits(4,7); + } else { + apu.channel5.s.data = data; + } + + if(--s.length) return; + + if(r.loop) { + s.source = r.source; + s.length = r.length; + } else { + r.enable = false; + } +} diff --git a/higan/ws/apu/io.cpp b/higan/ws/apu/io.cpp index 14b3ea0d..2ce2890e 100644 --- a/higan/ws/apu/io.cpp +++ b/higan/ws/apu/io.cpp @@ -1,70 +1,90 @@ auto APU::portRead(uint16 addr) -> uint8 { + //SDMA_SRC + if(addr == 0x004a) return dma.s.source.bits( 0, 7); + if(addr == 0x004b) return dma.s.source.bits( 8,15); + if(addr == 0x004c) return dma.s.source.bits(16,19); + + //SDMA_LEN + if(addr == 0x004e) return dma.s.length.bits( 0, 7); + if(addr == 0x004f) return dma.s.length.bits( 8,15); + if(addr == 0x0050) return dma.s.length.bits(16,19); + + //SDMA_CTRL + if(addr == 0x0052) return ( + dma.r.rate << 0 + | dma.r.unknown << 2 + | dma.r.loop << 3 + | dma.r.target << 4 + | dma.r.direction << 6 + | dma.r.enable << 7 + ); + //SND_HYPER_CTRL if(addr == 0x006a) return ( - channel4.r.volume << 0 - | channel4.r.scale << 2 - | channel4.r.speed << 4 - | channel4.r.enable << 7 + channel5.r.volume << 0 + | channel5.r.scale << 2 + | channel5.r.speed << 4 + | channel5.r.enable << 7 ); //SND_HYPER_CHAN_CTRL if(addr == 0x006b) return ( - channel4.r.unknown << 0 - | channel4.r.leftEnable << 5 - | channel4.r.rightEnable << 6 + channel5.r.unknown << 0 + | channel5.r.leftEnable << 5 + | channel5.r.rightEnable << 6 ); - //SND_CH0_PITCH - if(addr == 0x0080) return channel0.r.pitch.bits(0, 7); - if(addr == 0x0081) return channel0.r.pitch.bits(8,11); - //SND_CH1_PITCH - if(addr == 0x0082) return channel1.r.pitch.bits(0, 7); - if(addr == 0x0083) return channel1.r.pitch.bits(8,11); + if(addr == 0x0080) return channel1.r.pitch.bits(0, 7); + if(addr == 0x0081) return channel1.r.pitch.bits(8,11); //SND_CH2_PITCH - if(addr == 0x0084) return channel2.r.pitch.bits(0, 7); - if(addr == 0x0085) return channel2.r.pitch.bits(8,11); + if(addr == 0x0082) return channel2.r.pitch.bits(0, 7); + if(addr == 0x0083) return channel2.r.pitch.bits(8,11); //SND_CH3_PITCH - if(addr == 0x0086) return channel3.r.pitch.bits(0, 7); - if(addr == 0x0087) return channel3.r.pitch.bits(8,11); + if(addr == 0x0084) return channel3.r.pitch.bits(0, 7); + if(addr == 0x0085) return channel3.r.pitch.bits(8,11); - //SND_CH0_VOL - if(addr == 0x0088) return ( - channel0.r.volumeRight << 0 - | channel0.r.volumeLeft << 4 - ); + //SND_CH4_PITCH + if(addr == 0x0086) return channel4.r.pitch.bits(0, 7); + if(addr == 0x0087) return channel4.r.pitch.bits(8,11); //SND_CH1_VOL - if(addr == 0x0089) return ( + if(addr == 0x0088) return ( channel1.r.volumeRight << 0 | channel1.r.volumeLeft << 4 ); //SND_CH2_VOL - if(addr == 0x008a) return ( + if(addr == 0x0089) return ( channel2.r.volumeRight << 0 | channel2.r.volumeLeft << 4 ); //SND_CH3_VOL - if(addr == 0x008b) return ( + if(addr == 0x008a) return ( channel3.r.volumeRight << 0 | channel3.r.volumeLeft << 4 ); + //SND_CH4_VOL + if(addr == 0x008b) return ( + channel4.r.volumeRight << 0 + | channel4.r.volumeLeft << 4 + ); + //SND_SWEEP_VALUE - if(addr == 0x008c) return channel2.r.sweepValue; + if(addr == 0x008c) return channel3.r.sweepValue; //SND_SWEEP_TIME - if(addr == 0x008d) return channel2.r.sweepTime; + if(addr == 0x008d) return channel3.r.sweepTime; //SND_NOISE //(noiseReset [bit 3] always reads as zero) if(addr == 0x008e) return ( - channel3.r.noiseMode << 0 - | channel3.r.noiseUpdate << 4 + channel4.r.noiseMode << 0 + | channel4.r.noiseUpdate << 4 ); //SND_WAVE_BASE @@ -72,13 +92,13 @@ auto APU::portRead(uint16 addr) -> uint8 { //SND_CTRL if(addr == 0x0090) return ( - channel0.r.enable << 0 - | channel1.r.enable << 1 - | channel2.r.enable << 2 - | channel3.r.enable << 3 - | channel1.r.voice << 5 - | channel2.r.sweep << 6 - | channel3.r.noise << 7 + channel1.r.enable << 0 + | channel2.r.enable << 1 + | channel3.r.enable << 2 + | channel4.r.enable << 3 + | channel2.r.voice << 5 + | channel3.r.sweep << 6 + | channel4.r.noise << 7 ); //SND_OUTPUT @@ -90,114 +110,127 @@ auto APU::portRead(uint16 addr) -> uint8 { ); //SND_RANDOM - if(addr == 0x0092) return channel3.s.noiseLFSR.bits(0, 7); - if(addr == 0x0093) return channel3.s.noiseLFSR.bits(8,14); + if(addr == 0x0092) return channel4.s.noiseLFSR.bits(0, 7); + if(addr == 0x0093) return channel4.s.noiseLFSR.bits(8,14); //SND_VOICE_CTRL if(addr == 0x0094) return ( - channel1.r.voiceEnableRight << 0 - | channel1.r.voiceEnableLeft << 2 + channel2.r.voiceEnableRight << 0 + | channel2.r.voiceEnableLeft << 2 ); + //SND_HYPERVOICE + if(addr == 0x0095) return channel5.s.data; + return 0x00; } auto APU::portWrite(uint16 addr, uint8 data) -> void { + //SDMA_SRC + if(addr == 0x004a) dma.r.source.bits( 0, 7) = data.bits(0,7); + if(addr == 0x004b) dma.r.source.bits( 8,15) = data.bits(0,7); + if(addr == 0x004c) dma.r.source.bits(16,19) = data.bits(0,3); + + //SDMA_LEN + if(addr == 0x004e) dma.r.length.bits( 0, 7) = data.bits(0,7); + if(addr == 0x004f) dma.r.length.bits( 8,15) = data.bits(0,7); + if(addr == 0x0050) dma.r.length.bits(16,19) = data.bits(0,3); + + //SDMA_CTRL + if(addr == 0x0052) { + bool trigger = !dma.r.enable && data.bit(7); + dma.r.rate = data.bits(0,1); + dma.r.unknown = data.bit (2); + dma.r.loop = data.bit (3); + dma.r.target = data.bit (4); + dma.r.direction = data.bit (6); + dma.r.enable = data.bit (7); + if(trigger) { + dma.s.source = dma.r.source; + dma.s.length = dma.r.length; + } + } + //SND_HYPER_CTRL if(addr == 0x006a) { - channel4.r.volume = data.bits(0,1); - channel4.r.scale = data.bits(2,3); - channel4.r.speed = data.bits(4,6); - channel4.r.enable = data.bit (7); + channel5.r.volume = data.bits(0,1); + channel5.r.scale = data.bits(2,3); + channel5.r.speed = data.bits(4,6); + channel5.r.enable = data.bit (7); } //SND_HYPER_CHAN_CTRL if(addr == 0x006b) { - channel4.r.unknown = data.bits(0,3); - channel4.r.leftEnable = data.bit (5); - channel4.r.rightEnable = data.bit (6); + channel5.r.unknown = data.bits(0,3); + channel5.r.leftEnable = data.bit (5); + channel5.r.rightEnable = data.bit (6); } - //SND_CH0_PITCH - if(addr == 0x0080) { channel0.r.pitch.bits(0, 7) = data.bits(0,7); return; } - if(addr == 0x0081) { channel0.r.pitch.bits(8,11) = data.bits(0,3); return; } - //SND_CH1_PITCH - if(addr == 0x0082) { channel1.r.pitch.bits(0, 7) = data.bits(0,7); return; } - if(addr == 0x0083) { channel1.r.pitch.bits(8,11) = data.bits(0,3); return; } + if(addr == 0x0080) channel1.r.pitch.bits(0, 7) = data.bits(0,7); + if(addr == 0x0081) channel1.r.pitch.bits(8,11) = data.bits(0,3); //SND_CH2_PITCH - if(addr == 0x0084) { channel2.r.pitch.bits(0, 7) = data.bits(0,7); return; } - if(addr == 0x0085) { channel2.r.pitch.bits(8,11) = data.bits(0,3); return; } + if(addr == 0x0082) channel2.r.pitch.bits(0, 7) = data.bits(0,7); + if(addr == 0x0083) channel2.r.pitch.bits(8,11) = data.bits(0,3); //SND_CH3_PITCH - if(addr == 0x0086) { channel3.r.pitch.bits(0, 7) = data.bits(0,7); return; } - if(addr == 0x0087) { channel3.r.pitch.bits(8,11) = data.bits(0,3); return; } + if(addr == 0x0084) channel3.r.pitch.bits(0, 7) = data.bits(0,7); + if(addr == 0x0085) channel3.r.pitch.bits(8,11) = data.bits(0,3); - //SND_CH0_VOL - if(addr == 0x0088) { - channel0.r.volumeRight = data.bits(0,3); - channel0.r.volumeLeft = data.bits(4,7); - return; - } + //SND_CH4_PITCH + if(addr == 0x0086) channel4.r.pitch.bits(0, 7) = data.bits(0,7); + if(addr == 0x0087) channel4.r.pitch.bits(8,11) = data.bits(0,3); //SND_CH1_VOL - if(addr == 0x0089) { + if(addr == 0x0088) { channel1.r.volumeRight = data.bits(0,3); channel1.r.volumeLeft = data.bits(4,7); - return; } //SND_CH2_VOL - if(addr == 0x008a) { + if(addr == 0x0089) { channel2.r.volumeRight = data.bits(0,3); channel2.r.volumeLeft = data.bits(4,7); - return; } //SND_CH3_VOL - if(addr == 0x008b) { + if(addr == 0x008a) { channel3.r.volumeRight = data.bits(0,3); channel3.r.volumeLeft = data.bits(4,7); - return; + } + + //SND_CH4_VOL + if(addr == 0x008b) { + channel4.r.volumeRight = data.bits(0,3); + channel4.r.volumeLeft = data.bits(4,7); } //SND_SWEEP_VALUE - if(addr == 0x008c) { - channel2.r.sweepValue = data; - return; - } + if(addr == 0x008c) channel3.r.sweepValue = data; //SND_SWEEP_TIME - if(addr == 0x008d) { - channel2.r.sweepTime = data.bits(0,4); - return; - } + if(addr == 0x008d) channel3.r.sweepTime = data.bits(0,4); //SND_NOISE if(addr == 0x008e) { - channel3.r.noiseMode = data.bits(0,2); - channel3.r.noiseReset = data.bit (3); - channel3.r.noiseUpdate = data.bit (4); - return; + channel4.r.noiseMode = data.bits(0,2); + channel4.r.noiseReset = data.bit (3); + channel4.r.noiseUpdate = data.bit (4); } //SND_WAVE_BASE - if(addr == 0x008f) { - r.waveBase = data; - return; - } + if(addr == 0x008f) r.waveBase = data; //SND_CTRL if(addr == 0x0090) { - channel0.r.enable = data.bit(0); - channel1.r.enable = data.bit(1); - channel2.r.enable = data.bit(2); - channel3.r.enable = data.bit(3); - channel1.r.voice = data.bit(5); - channel2.r.sweep = data.bit(6); - channel3.r.noise = data.bit(7); - return; + channel1.r.enable = data.bit(0); + channel2.r.enable = data.bit(1); + channel3.r.enable = data.bit(2); + channel4.r.enable = data.bit(3); + channel2.r.voice = data.bit(5); + channel3.r.sweep = data.bit(6); + channel4.r.noise = data.bit(7); } //SND_OUTPUT @@ -205,13 +238,11 @@ auto APU::portWrite(uint16 addr, uint8 data) -> void { r.speakerEnable = data.bit (0); r.speakerShift = data.bits(1,2); r.headphoneEnable = data.bit (3); - return; } //SND_VOICE_CTRL if(addr == 0x0094) { - channel1.r.voiceEnableRight = data.bits(0,1); - channel1.r.voiceEnableLeft = data.bits(2,3); - return; + channel2.r.voiceEnableRight = data.bits(0,1); + channel2.r.voiceEnableLeft = data.bits(2,3); } } diff --git a/higan/ws/cartridge/cartridge.cpp b/higan/ws/cartridge/cartridge.cpp index ba6815a3..6be7d5dd 100644 --- a/higan/ws/cartridge/cartridge.cpp +++ b/higan/ws/cartridge/cartridge.cpp @@ -60,7 +60,7 @@ auto Cartridge::unload() -> void { auto Cartridge::power() -> void { eeprom.power(); - for(uint n = 0x00c0; n <= 0x00c8; n++) iomap[n] = this; + bus.map(this, 0x00c0, 0x00c8); r.bank_rom0 = 0xff; r.bank_rom1 = 0xff; diff --git a/higan/ws/cpu/cpu.cpp b/higan/ws/cpu/cpu.cpp index ec1045e2..7b90308a 100644 --- a/higan/ws/cpu/cpu.cpp +++ b/higan/ws/cpu/cpu.cpp @@ -37,27 +37,27 @@ auto CPU::write(uint20 addr, uint8 data) -> void { } auto CPU::in(uint16 port) -> uint8 { - return iomap[port]->portRead(port); + return bus.portRead(port); } auto CPU::out(uint16 port, uint8 data) -> void { - return iomap[port]->portWrite(port, data); + return bus.portWrite(port, data); } auto CPU::power() -> void { V30MZ::power(); create(CPU::Enter, 3'072'000); - iomap[0x00a0] = this; - iomap[0x00b0] = this; - iomap[0x00b2] = this; - iomap[0x00b4] = this; - iomap[0x00b5] = this; - iomap[0x00b6] = this; + bus.map(this, 0x00a0); + bus.map(this, 0x00b0); + bus.map(this, 0x00b2); + bus.map(this, 0x00b4); + bus.map(this, 0x00b5); + bus.map(this, 0x00b6); if(system.model() != Model::WonderSwan) { - for(uint p = 0x0040; p <= 0x0049; p++) iomap[p] = this; - iomap[0x0062] = this; + bus.map(this, 0x0040, 0x0049); + bus.map(this, 0x0062); } r.dmaSource = 0; diff --git a/higan/ws/memory/memory.cpp b/higan/ws/memory/memory.cpp index acb11ab2..1fed6c9b 100644 --- a/higan/ws/memory/memory.cpp +++ b/higan/ws/memory/memory.cpp @@ -2,24 +2,9 @@ namespace WonderSwan { -IO* iomap[64 * 1024] = {nullptr}; InternalRAM iram; Bus bus; -auto IO::power() -> void { - static IO unmapped; - for(auto& n : iomap) n = &unmapped; -} - -auto IO::portRead(uint16 addr) -> uint8 { -//print("[", hex(addr, 4L), "]: port unmapped\n"); - return 0x00; -} - -auto IO::portWrite(uint16 addr, uint8 data) -> void { -//print("[", hex(addr, 4L), "] = ", hex(data, 2L), ": port unmapped\n"); -} - auto InternalRAM::power() -> void { for(auto& byte : memory) byte = 0x00; } @@ -37,6 +22,10 @@ auto InternalRAM::write(uint16 addr, uint8 data) -> void { memory[addr] = data; } +auto Bus::power() -> void { + for(auto& io : port) io = nullptr; +} + auto Bus::read(uint20 addr) -> uint8 { if(addr.bits(16,19) == 0) return iram.read(addr); if(addr.bits(16,19) == 1) return cartridge.ramRead(addr); @@ -50,4 +39,17 @@ auto Bus::write(uint20 addr, uint8 data) -> void { if(addr.bits(16,19) >= 2) return cartridge.romWrite(addr, data); } +auto Bus::map(IO* io, uint16_t lo, maybe hi) -> void { + for(uint addr = lo; addr <= (hi ? hi() : lo); addr++) port[addr] = io; +} + +auto Bus::portRead(uint16 addr) -> uint8 { + if(auto io = port[addr]) return io->portRead(addr); + return 0x00; +} + +auto Bus::portWrite(uint16 addr, uint8 data) -> void { + if(auto io = port[addr]) return io->portWrite(addr, data); +} + } diff --git a/higan/ws/memory/memory.hpp b/higan/ws/memory/memory.hpp index bc16ce87..c6997679 100644 --- a/higan/ws/memory/memory.hpp +++ b/higan/ws/memory/memory.hpp @@ -1,8 +1,6 @@ struct IO { - static auto power() -> void; - - virtual auto portRead(uint16 addr) -> uint8; - virtual auto portWrite(uint16 addr, uint8 data) -> void; + virtual auto portRead(uint16 addr) -> uint8 = 0; + virtual auto portWrite(uint16 addr, uint8 data) -> void = 0; }; struct InternalRAM { @@ -16,10 +14,18 @@ private: }; struct Bus { + auto power() -> void; + auto read(uint20 addr) -> uint8; auto write(uint20 addr, uint8 data) -> void; + + auto map(IO* io, uint16_t lo, maybe hi = nothing) -> void; + auto portRead(uint16 addr) -> uint8; + auto portWrite(uint16 addr, uint8 data) -> void; + +private: + IO* port[64 * 1024] = {nullptr}; }; -extern IO* iomap[64 * 1024]; extern InternalRAM iram; extern Bus bus; diff --git a/higan/ws/ppu/ppu.cpp b/higan/ws/ppu/ppu.cpp index 995d0a74..c5490bd3 100644 --- a/higan/ws/ppu/ppu.cpp +++ b/higan/ws/ppu/ppu.cpp @@ -15,8 +15,9 @@ auto PPU::Enter() -> void { auto PPU::main() -> void { if(status.vclk < 144) { + renderSpriteFetch(); renderSpriteDecode(); - for(uint x = 0; x < 224; x++) { + for(auto x : range(256)) { if(!system.color()) { renderMonoBack(); renderMonoScreenOne(); @@ -86,12 +87,13 @@ auto PPU::step(uint clocks) -> void { auto PPU::power() -> void { create(PPU::Enter, 3'072'000); - for(uint n = 0x0000; n <= 0x0017; n++) iomap[n] = this; - for(uint n = 0x001c; n <= 0x003f; n++) iomap[n] = this; - iomap[0x00a2] = this; - for(uint n = 0x00a4; n <= 0x00ab; n++) iomap[n] = this; + bus.map(this, 0x0000, 0x0017); + bus.map(this, 0x001c, 0x003f); + bus.map(this, 0x00a2); + bus.map(this, 0x00a4, 0x00ab); for(auto& n : output) n = 0; + for(auto& n : oam) n = 0; status.vclk = 0; status.hclk = 0; diff --git a/higan/ws/ppu/ppu.hpp b/higan/ws/ppu/ppu.hpp index b63cb23e..58baab0d 100644 --- a/higan/ws/ppu/ppu.hpp +++ b/higan/ws/ppu/ppu.hpp @@ -13,10 +13,12 @@ struct PPU : Thread, IO { auto portWrite(uint16 addr, uint8 data) -> void override; //render-sprite.cpp + auto renderSpriteFetch() -> void; auto renderSpriteDecode() -> void; //render-mono.cpp auto renderMonoFetch(uint14 offset, uint3 y, uint3 x) -> uint2; + auto renderMonoPalette(uint4 palette, uint2 index) -> uint12; auto renderMonoBack() -> void; auto renderMonoScreenOne() -> void; auto renderMonoScreenTwo() -> void; @@ -24,6 +26,7 @@ struct PPU : Thread, IO { //render-color.cpp auto renderColorFetch(uint16 offset, uint3 y, uint3 x) -> uint4; + auto renderColorPalette(uint4 palette, uint4 index) -> uint12; auto renderColorBack() -> void; auto renderColorScreenOne() -> void; auto renderColorScreenTwo() -> void; @@ -31,6 +34,7 @@ struct PPU : Thread, IO { //state uint12 output[224 * 144]; + uint32 oam[128]; struct Status { uint vclk; diff --git a/higan/ws/ppu/render-color.cpp b/higan/ws/ppu/render-color.cpp index 76212836..fae8b517 100644 --- a/higan/ws/ppu/render-color.cpp +++ b/higan/ws/ppu/render-color.cpp @@ -17,6 +17,10 @@ auto PPU::renderColorFetch(uint16 offset, uint3 y, uint3 x) -> uint4 { return color; } +auto PPU::renderColorPalette(uint4 palette, uint4 index) -> uint12 { + return iram.read(0xfe00 + (palette << 5) + (index << 1), Word); +} + auto PPU::renderColorBack() -> void { uint12 color = iram.read(0xfe00 + (r.backColor << 1), Word); pixel = {Pixel::Source::Back, color}; @@ -39,8 +43,7 @@ auto PPU::renderColorScreenOne() -> void { uint4 tileColor = renderColorFetch(tileOffset, tileY, tileX); if(tileColor == 0) return; - uint12 color = iram.read(0xfe00 + (tile.bits(9, 12) << 5) + (tileColor << 1), Word); - pixel = {Pixel::Source::ScreenOne, color}; + pixel = {Pixel::Source::ScreenOne, renderColorPalette(tile.bits(9, 12), tileColor)}; } auto PPU::renderColorScreenTwo() -> void { @@ -65,8 +68,7 @@ auto PPU::renderColorScreenTwo() -> void { uint4 tileColor = renderColorFetch(tileOffset, tileY, tileX); if(tileColor == 0) return; - uint12 color = iram.read(0xfe00 + (tile.bits(9,12) << 5) + (tileColor << 1), Word); - pixel = {Pixel::Source::ScreenTwo, color}; + pixel = {Pixel::Source::ScreenTwo, renderColorPalette(tile.bits(9, 12), tileColor)}; } auto PPU::renderColorSprite() -> void { @@ -85,8 +87,7 @@ auto PPU::renderColorSprite() -> void { if(tileColor == 0) continue; if(!sprite.priority && pixel.source == Pixel::Source::ScreenTwo) continue; - uint12 color = iram.read(0xfe00 + (sprite.palette << 5) + (tileColor << 1), Word); - pixel = {Pixel::Source::Sprite, color}; + pixel = {Pixel::Source::Sprite, renderColorPalette(sprite.palette, tileColor)}; break; } } diff --git a/higan/ws/ppu/render-mono.cpp b/higan/ws/ppu/render-mono.cpp index f5955852..497319a1 100644 --- a/higan/ws/ppu/render-mono.cpp +++ b/higan/ws/ppu/render-mono.cpp @@ -15,6 +15,12 @@ auto PPU::renderMonoFetch(uint14 offset, uint3 y, uint3 x) -> uint2 { return color; } +auto PPU::renderMonoPalette(uint4 palette, uint2 index) -> uint12 { + uint3 paletteColor = r.palette[palette].color[index]; + uint4 poolColor = 15 - r.pool[paletteColor]; + return poolColor << 0 | poolColor << 4 | poolColor << 8; +} + auto PPU::renderMonoBack() -> void { uint4 poolColor = 15 - r.pool[r.backColor.bits(0,2)]; pixel = {Pixel::Source::Back, poolColor << 0 | poolColor << 4 | poolColor << 8}; @@ -37,9 +43,7 @@ auto PPU::renderMonoScreenOne() -> void { uint2 tileColor = renderMonoFetch(tileOffset, tileY, tileX); if(tile.bit(11) && tileColor == 0) return; - uint3 paletteColor = r.palette[tile.bits(9,12)].color[tileColor]; - uint4 poolColor = 15 - r.pool[paletteColor]; - pixel = {Pixel::Source::ScreenOne, poolColor << 0 | poolColor << 4 | poolColor << 8}; + pixel = {Pixel::Source::ScreenOne, renderMonoPalette(tile.bits(9,12), tileColor)}; } auto PPU::renderMonoScreenTwo() -> void { @@ -50,8 +54,8 @@ auto PPU::renderMonoScreenTwo() -> void { windowInside ^= r.screenTwoWindowInvert; if(r.screenTwoWindowEnable && !windowInside) return; - uint8 scrollX = status.hclk + r.scrollTwoX; uint8 scrollY = status.vclk + r.scrollTwoY; + uint8 scrollX = status.hclk + r.scrollTwoX; uint14 tilemapOffset = r.screenTwoMapBase.bits(0,2) << 11; tilemapOffset += (scrollY >> 3) << 6; @@ -64,9 +68,7 @@ auto PPU::renderMonoScreenTwo() -> void { uint2 tileColor = renderMonoFetch(tileOffset, tileY, tileX); if(tile.bit(11) && tileColor == 0) return; - uint3 paletteColor = r.palette[tile.bits(9,12)].color[tileColor]; - uint4 poolColor = 15 - r.pool[paletteColor]; - pixel = {Pixel::Source::ScreenTwo, poolColor << 0 | poolColor << 4 | poolColor << 8}; + pixel = {Pixel::Source::ScreenTwo, renderMonoPalette(tile.bits(9,12), tileColor)}; } auto PPU::renderMonoSprite() -> void { @@ -85,9 +87,7 @@ auto PPU::renderMonoSprite() -> void { if(sprite.palette.bit(2) && tileColor == 0) continue; if(!sprite.priority && pixel.source == Pixel::Source::ScreenTwo) continue; - uint3 paletteColor = r.palette[sprite.palette].color[tileColor]; - uint4 poolColor = 15 - r.pool[paletteColor]; - pixel = {Pixel::Source::Sprite, poolColor << 0 | poolColor << 4 | poolColor << 8}; + pixel = {Pixel::Source::Sprite, renderMonoPalette(sprite.palette, tileColor)}; break; } } diff --git a/higan/ws/ppu/render-sprite.cpp b/higan/ws/ppu/render-sprite.cpp index 5c20c333..f255bbcc 100644 --- a/higan/ws/ppu/render-sprite.cpp +++ b/higan/ws/ppu/render-sprite.cpp @@ -1,3 +1,10 @@ +auto PPU::renderSpriteFetch() -> void { + uint16 spriteBase = r.spriteBase.bits(0, 4 + system.depth()) << 9; + for(auto spriteIndex : range(128)) { + oam[spriteIndex] = iram.read(spriteBase + (spriteIndex << 2), Long); + } +} + auto PPU::renderSpriteDecode() -> void { sprites.reset(); sprites.reserve(32); @@ -9,7 +16,7 @@ auto PPU::renderSpriteDecode() -> void { uint7 spriteIndex = r.spriteFirst; uint8 spriteCount = min(128, (uint)r.spriteCount); while(spriteCount--) { - uint32 attributes = iram.read(spriteBase + (spriteIndex++ << 2), Long); + uint32 attributes = oam[spriteIndex++]; Sprite sprite; sprite.x = attributes.bits(24,31); diff --git a/higan/ws/system/system.cpp b/higan/ws/system/system.cpp index f86a303b..dabfe54d 100644 --- a/higan/ws/system/system.cpp +++ b/higan/ws/system/system.cpp @@ -50,7 +50,7 @@ auto System::unload() -> void { } auto System::power() -> void { - IO::power(); + bus.power(); iram.power(); eeprom.power(); cpu.power(); @@ -59,8 +59,8 @@ auto System::power() -> void { cartridge.power(); scheduler.power(); - iomap[0x0060] = this; - for(uint n = 0x00ba; n <= 0x00be; n++) iomap[n] = this; + bus.map(this, 0x0060); + bus.map(this, 0x00ba, 0x00be); r.depth = 0; r.color = 0;