bsnes/higan/ws/apu/io.cpp

249 lines
6.3 KiB
C++

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 (
channel5.r.volume << 0
| channel5.r.scale << 2
| channel5.r.speed << 4
| channel5.r.enable << 7
);
//SND_HYPER_CHAN_CTRL
if(addr == 0x006b) return (
channel5.r.unknown << 0
| channel5.r.leftEnable << 5
| channel5.r.rightEnable << 6
);
//SND_CH1_PITCH
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 == 0x0082) return channel2.r.pitch.bits(0, 7);
if(addr == 0x0083) return channel2.r.pitch.bits(8,11);
//SND_CH3_PITCH
if(addr == 0x0084) return channel3.r.pitch.bits(0, 7);
if(addr == 0x0085) return channel3.r.pitch.bits(8,11);
//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 == 0x0088) return (
channel1.r.volumeRight << 0
| channel1.r.volumeLeft << 4
);
//SND_CH2_VOL
if(addr == 0x0089) return (
channel2.r.volumeRight << 0
| channel2.r.volumeLeft << 4
);
//SND_CH3_VOL
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 channel3.r.sweepValue;
//SND_SWEEP_TIME
if(addr == 0x008d) return channel3.r.sweepTime;
//SND_NOISE
//(noiseReset [bit 3] always reads as zero)
if(addr == 0x008e) return (
channel4.r.noiseMode << 0
| channel4.r.noiseUpdate << 4
);
//SND_WAVE_BASE
if(addr == 0x008f) return r.waveBase;
//SND_CTRL
if(addr == 0x0090) return (
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
if(addr == 0x0091) return (
r.speakerEnable << 0
| r.speakerShift << 1
| r.headphoneEnable << 3
| 1 << 7 //headphone connected
);
//SND_RANDOM
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 (
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) {
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) {
channel5.r.unknown = data.bits(0,3);
channel5.r.leftEnable = data.bit (5);
channel5.r.rightEnable = data.bit (6);
}
//SND_CH1_PITCH
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 == 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 == 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_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 == 0x0088) {
channel1.r.volumeRight = data.bits(0,3);
channel1.r.volumeLeft = data.bits(4,7);
}
//SND_CH2_VOL
if(addr == 0x0089) {
channel2.r.volumeRight = data.bits(0,3);
channel2.r.volumeLeft = data.bits(4,7);
}
//SND_CH3_VOL
if(addr == 0x008a) {
channel3.r.volumeRight = data.bits(0,3);
channel3.r.volumeLeft = data.bits(4,7);
}
//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) channel3.r.sweepValue = data;
//SND_SWEEP_TIME
if(addr == 0x008d) channel3.r.sweepTime = data.bits(0,4);
//SND_NOISE
if(addr == 0x008e) {
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;
//SND_CTRL
if(addr == 0x0090) {
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
if(addr == 0x0091) {
r.speakerEnable = data.bit (0);
r.speakerShift = data.bits(1,2);
r.headphoneEnable = data.bit (3);
}
//SND_VOICE_CTRL
if(addr == 0x0094) {
channel2.r.voiceEnableRight = data.bits(0,1);
channel2.r.voiceEnableLeft = data.bits(2,3);
}
}