2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::calculateFIR(signed i, bool channel) -> signed {
|
|
|
|
signed s = state.echoHistory[channel][state.echoHistoryOffset + i + 1];
|
|
|
|
return (s * (int8)REG(FIR + i * 0x10)) >> 6;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echoOutput(bool channel) -> signed {
|
|
|
|
signed output = (int16)((state._mainOut[channel] * (int8)REG(MVOLL + channel * 0x10)) >> 7)
|
|
|
|
+ (int16)((state._echoIn [channel] * (int8)REG(EVOLL + channel * 0x10)) >> 7);
|
2010-08-09 13:28:56 +00:00
|
|
|
return sclamp<16>(output);
|
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echoRead(bool channel) -> void {
|
|
|
|
unsigned addr = state._echoPointer + channel * 2;
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
uint8 lo = smp.apuram[(uint16)(addr + 0)];
|
|
|
|
uint8 hi = smp.apuram[(uint16)(addr + 1)];
|
2015-10-10 02:16:12 +00:00
|
|
|
signed s = (int16)((hi << 8) + lo);
|
|
|
|
state.echoHistory[channel].write(state.echoHistoryOffset, s >> 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echoWrite(bool channel) -> void {
|
|
|
|
if(!(state._echoDisabled & 0x20)) {
|
|
|
|
unsigned addr = state._echoPointer + channel * 2;
|
|
|
|
signed s = state._echoOut[channel];
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
smp.apuram[(uint16)(addr + 0)] = s;
|
|
|
|
smp.apuram[(uint16)(addr + 1)] = s >> 8;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoOut[channel] = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo22() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
//history
|
2015-10-10 02:16:12 +00:00
|
|
|
state.echoHistoryOffset++;
|
|
|
|
if(state.echoHistoryOffset >= EchoHistorySize) state.echoHistoryOffset = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoPointer = (uint16)((state._esa << 8) + state.echoOffset);
|
|
|
|
echoRead(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//FIR
|
2015-10-10 02:16:12 +00:00
|
|
|
signed l = calculateFIR(0, 0);
|
|
|
|
signed r = calculateFIR(0, 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoIn[0] = l;
|
|
|
|
state._echoIn[1] = r;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo23() -> void {
|
|
|
|
signed l = calculateFIR(1, 0) + calculateFIR(2, 0);
|
|
|
|
signed r = calculateFIR(1, 1) + calculateFIR(2, 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoIn[0] += l;
|
|
|
|
state._echoIn[1] += r;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
echoRead(1);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo24() -> void {
|
|
|
|
signed l = calculateFIR(3, 0) + calculateFIR(4, 0) + calculateFIR(5, 0);
|
|
|
|
signed r = calculateFIR(3, 1) + calculateFIR(4, 1) + calculateFIR(5, 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoIn[0] += l;
|
|
|
|
state._echoIn[1] += r;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo25() -> void {
|
|
|
|
signed l = state._echoIn[0] + calculateFIR(6, 0);
|
|
|
|
signed r = state._echoIn[1] + calculateFIR(6, 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
l = (int16)l;
|
|
|
|
r = (int16)r;
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
l += (int16)calculateFIR(7, 0);
|
|
|
|
r += (int16)calculateFIR(7, 1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoIn[0] = sclamp<16>(l) & ~1;
|
|
|
|
state._echoIn[1] = sclamp<16>(r) & ~1;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo26() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
//left output volumes
|
|
|
|
//(save sample for next clock so we can output both together)
|
2015-10-10 02:16:12 +00:00
|
|
|
state._mainOut[0] = echoOutput(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//echo feedback
|
2015-10-10 02:16:12 +00:00
|
|
|
signed l = state._echoOut[0] + (int16)((state._echoIn[0] * (int8)REG(EFB)) >> 7);
|
|
|
|
signed r = state._echoOut[1] + (int16)((state._echoIn[1] * (int8)REG(EFB)) >> 7);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoOut[0] = sclamp<16>(l) & ~1;
|
|
|
|
state._echoOut[1] = sclamp<16>(r) & ~1;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo27() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
//output
|
2015-10-10 02:16:12 +00:00
|
|
|
signed outl = state._mainOut[0];
|
|
|
|
signed outr = echoOutput(1);
|
|
|
|
state._mainOut[0] = 0;
|
|
|
|
state._mainOut[1] = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//TODO: global muting isn't this simple
|
|
|
|
//(turns DAC on and off or something, causing small ~37-sample pulse when first muted)
|
2015-10-10 02:16:12 +00:00
|
|
|
if(REG(FLG) & 0x40) {
|
2010-08-09 13:28:56 +00:00
|
|
|
outl = 0;
|
|
|
|
outr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//output sample to DAC
|
|
|
|
audio.sample(outl, outr);
|
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo28() -> void {
|
|
|
|
state._echoDisabled = REG(FLG);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo29() -> void {
|
|
|
|
state._esa = REG(ESA);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
if(!state.echoOffset) state.echoLength = (REG(EDL) & 0x0f) << 11;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state.echoOffset += 4;
|
|
|
|
if(state.echoOffset >= state.echoLength) state.echoOffset = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//write left echo
|
2015-10-10 02:16:12 +00:00
|
|
|
echoWrite(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
state._echoDisabled = REG(FLG);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::echo30() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
//write right echo
|
2015-10-10 02:16:12 +00:00
|
|
|
echoWrite(1);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|