[PCE] Convert memory mappers from 16-bit addressing to 21-bit addressing

This commit is contained in:
beirich 2011-02-26 23:02:34 +00:00
parent 1b428b49ae
commit d381be67a6
7 changed files with 156 additions and 171 deletions

View File

@ -288,10 +288,22 @@ namespace BizHawk.Emulation.CPUs.H6280
// ==== Memory ====
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public Func<int, byte> ReadMemory21;
public Action<int, byte> WriteMemory21;
public Action<int, byte> WriteVDC;
public byte ReadMemory(ushort address)
{
byte page = MPR[address >> 13];
return ReadMemory21((page << 13) | (address & 0x1FFF));
}
public void WriteMemory(ushort address, byte value)
{
byte page = MPR[address >> 13];
WriteMemory21((page << 13) | (address & 0x1FFF), value);
}
private ushort ReadWord(ushort address)
{
byte l = ReadMemory(address);

View File

@ -4,87 +4,64 @@
{
// Street Fighter 2 was a 20-megabit HuCard. The PCE has a maximum 8-megabit addressable ROM space.
// Therefore SF2 had a special mapper to make this work.
// TODO: need to update SF2 mapper to reflect updates made to the primary mapper
// (ie, the IOBuffer)
// However, I believe more fixes will be made in the future, and SF2 works, so this is not
// currently a priority.
private byte SF2MapperLatch;
private byte ReadMemorySF2(ushort addr)
private byte ReadMemorySF2(int addr)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if (addr < 0x7FFFF) // read ROM
return RomData[addr];
if (page < 0x40)
if (addr < 0xFFFFF) // read ROM
return RomData[(addr & 0x7FFFF) + ((SF2MapperLatch + 1) * 0x80000)];
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
return Ram[addr & 0x1FFF];
if (addr >= 0x1FE000) // hardware page.
{
// read rom.
return RomData[(page % RomPages << 13) | (addr13)];
}
if (page < 0x80)
{
// read rom with extended SF2 mapper.
return RomData[(((page << 13) | addr13) & 0x7FFFF) + ((SF2MapperLatch + 1)*0x80000)];
}
if (page >= 0xF8 && page <= 0xFB)
{
// read RAM.
return Ram[((page-0xF8) << 13) | addr13];
if (addr < 0x1FE400) return VDC1.ReadVDC(addr & 0x03);
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
if (addr < 0x1FE80F) return IOBuffer;
if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr & ~1) == 0x1FF400) return IOBuffer;
if (addr == 0x1FF402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr == 0x1FF403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
}
if (page == 0xFF)
{
// hardware page.
if (addr13 < 0x400) return VDC1.ReadVDC(addr13 & 0x03);
if (addr13 < 0x800) return VCE.ReadVCE((addr13 & 0x07));
if ((addr13 & ~1) == 0x0C00) return Cpu.TimerValue;
if (addr13 >= 0x1000 && addr13 < 0x1400) return ReadInput();
if (addr13 == 0x1402) return Cpu.IRQControlByte;
if (addr13 == 0x1403) return Cpu.ReadIrqStatus();
}
Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13);
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
return 0xFF;
}
private void WriteMemorySF2(ushort addr, byte value)
private void WriteMemorySF2(int addr, byte value)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if ((addr & 0x1FFC) == 0x1FF0)
{
// Set SF2 pager.
SF2MapperLatch = (byte) (addr & 0x03);
SF2MapperLatch = (byte)(addr & 0x03);
return;
}
if (page >= 0xF8 && page <= 0xFB)
{
// write RAM.
Ram[addr13] = value;
}
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x1FFF] = value;
if (page == 0xFF)
else if (addr >= 0x1FE000) // hardware page.
{
// hardware page.
if (addr13 < 0x400)
VDC1.WriteVDC(addr13 & 3, value);
else if (addr13 < 0x800)
VCE.WriteVCE(addr13 & 7, value);
else if (addr13 < 0x80A)
PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles);
else if (addr13 == 0x0C00)
Cpu.WriteTimer(value);
else if (addr13 == 0x0C01)
Cpu.WriteTimerEnable(value);
else if (addr13 >= 0x1000 && addr13 < 0x1400)
WriteInput(value);
else if (addr13 == 0x1402)
Cpu.WriteIrqControl(value);
else if (addr13 == 0x1403)
Cpu.WriteIrqStatus();
if (addr < 0x1FE400) VDC1.WriteVDC(addr & 3, value);
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
}
else
Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value);
}
}
}

View File

@ -5,67 +5,65 @@
// The SuperGrafx has 32K of RAM and a different port configuration to allow
// I/O access to VDC1, VDC2, and the VPC.
private byte ReadMemorySGX(ushort addr)
private byte ReadMemorySGX(int addr)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if (addr < 0xFFFFF) // read ROM
return RomData[addr % RomLength];
if (page < 0x80) // read ROM
return RomData[(page % RomPages << 13) | (addr13)];
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
return Ram[addr & 0x7FFF];
if (page >= 0xF8 && page <= 0xFB) // read RAM
return Ram[((page-0xF8) << 13) | addr13];
if (page == 0xFF) // hardware page.
if (addr >= 0x1FE000) // hardware page.
{
if (addr13 < 0x400)
if (addr < 0x1FE400)
{
addr13 &= 0x1F;
if (addr13 <= 0x07) return VDC1.ReadVDC(addr13 & 3);
if (addr13 <= 0x0F) return VPC.ReadVPC(addr13);
if (addr13 <= 0x17) return VDC2.ReadVDC(addr13 & 3);
return 0xFF;
addr &= 0x1F;
if (addr <= 0x07) return VDC1.ReadVDC(addr & 3);
if (addr <= 0x0F) return VPC.ReadVPC(addr);
if (addr <= 0x17) return VDC2.ReadVDC(addr & 3);
return 0xFF;
}
if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); }
if (addr13 < 0x080F) return IOBuffer;
if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr13 >= 0x1000 &&
addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr13 & ~1) == 0x1400) return IOBuffer;
if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
if (addr < 0x1FE80F) return IOBuffer;
if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte)(Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr & ~1) == 0x1FF400) return IOBuffer;
if (addr == 0x1FF402) { IOBuffer = (byte)(Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
}
Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13);
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
return 0xFF;
}
private void WriteMemorySGX(ushort addr, byte value)
private void WriteMemorySGX(int addr, byte value)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x7FFF] = value;
if (page >= 0xF8 && page <= 0xFB) // write RAM.
Ram[((page-0xF8) << 13) | addr13] = value;
else if (page == 0xFF) // hardware page.
else if (addr >= 0x1FE000) // hardware page.
{
if (addr13 < 0x0400)
if (addr < 0x1FE400)
{
addr13 &= 0x1F;
if (addr13 <= 0x07) VDC1.WriteVDC(addr13 & 3, value);
else if (addr13 <= 0x0F) VPC.WriteVPC(addr13, value);
else if (addr13 <= 0x17) VDC2.WriteVDC(addr13 & 3, value);
addr &= 0x1F;
if (addr <= 0x07) VDC1.WriteVDC(addr & 3, value);
else if (addr <= 0x0F) VPC.WriteVPC(addr, value);
else if (addr <= 0x17) VDC2.WriteVDC(addr & 3, value);
}
else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); }
else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); }
else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr13 >= 0x1000 &&
addr13 < 0x1400) { IOBuffer = value; WriteInput(value); }
else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value);
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
}
else
Log.Error("MEM","UNHANDLED WRITE: {0:X6}:{1:X2}",addr,value);
}
}
}

View File

@ -2,63 +2,57 @@
{
public partial class PCEngine
{
// Much to my surprise, this silly I/O Buffer mechanic described in Charles MacDonald's doc is actually used by games.
// As one example, Cyber Core requires emulation of the IOBuffer to boot.
private byte IOBuffer;
private byte ReadMemory(ushort addr)
private byte ReadMemory(int addr)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if (addr < 0xFFFFF) // read ROM
return RomData[addr % RomLength];
if (page < 0x80) // read ROM
return RomData[(page % RomPages << 13) | (addr13)];
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
return Ram[addr & 0x1FFF];
if (page >= 0xF8 && page <= 0xFB) // read RAM
return Ram[addr13];
if (page == 0xFF) // hardware page.
if (addr >= 0x1FE000) // hardware page.
{
if (addr13 < 0x0400) return VDC1.ReadVDC(addr13 & 0x03);
if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); }
if (addr13 < 0x080F) return IOBuffer;
if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr13 >= 0x1000 &&
addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr13 & ~1) == 0x1400) return IOBuffer;
if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr < 0x1FE400) return VDC1.ReadVDC(addr & 0x03);
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
if (addr < 0x1FE80F) return IOBuffer;
if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr & ~1) == 0x1FF400) return IOBuffer;
if (addr == 0x1FF402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr == 0x1FF403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
}
Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13);
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
return 0xFF;
}
private void WriteMemory(ushort addr, byte value)
private void WriteMemory(int addr, byte value)
{
int page = Cpu.MPR[addr >> 13];
ushort addr13 = (ushort)(addr & 0x1FFF);
if (page >= 0xF8 && page <= 0xFB) // write RAM.
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
{
if (Cpu.debug)
Log.Note("MEM", "*Mem* Changed {0:X4} from {1:X2} to {2:X2}", addr13, Ram[addr13], value);
Ram[addr13] = value;
Log.Note("MEM", "*Mem* Changed {0:X4} from {1:X2} to {2:X2}", addr & 0x1FFF, Ram[addr & 0x1FFF], value);
Ram[addr & 0x1FFF] = value;
}
if (page == 0xFF) // hardware page.
else if (addr >= 0x1FE000) // hardware page.
{
if (addr13 < 0x0400) VDC1.WriteVDC(addr13 & 3, value);
else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); }
else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); }
else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr13 >= 0x1000 &&
addr13 < 0x1400) { IOBuffer = value; WriteInput(value); }
else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value);
if (addr < 0x1FE400) VDC1.WriteVDC(addr & 3, value);
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr >= 0x1FF000 &&
addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
}
else
Log.Error("MEM","UNHANDLED WRITE: {0:X6}:{1:X2}",addr,value);
}
}
}

View File

@ -18,7 +18,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{
// ROM
public byte[] RomData;
public int RomPages;
public int RomLength;
// Machine
public NecSystemType Type;
@ -59,8 +59,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (TurboGrafx || TurboCD)
{
Ram = new byte[0x2000];
Cpu.ReadMemory = ReadMemory;
Cpu.WriteMemory = WriteMemory;
Cpu.ReadMemory21 = ReadMemory;
Cpu.WriteMemory21 = WriteMemory;
Cpu.WriteVDC = VDC1.WriteVDC;
}
@ -69,8 +69,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
VDC2 = new VDC(Cpu, VCE);
VPC = new VPC(VDC1, VDC2, VCE, Cpu);
Ram = new byte[0x8000];
Cpu.ReadMemory = ReadMemorySGX;
Cpu.WriteMemory = WriteMemorySGX;
Cpu.ReadMemory21 = ReadMemorySGX;
Cpu.WriteMemory21 = WriteMemorySGX;
Cpu.WriteVDC = VDC1.WriteVDC;
}
}
@ -87,17 +87,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
RomData[i] = origRom[i];
for (int i = 0; i < 0x60000; i++)
RomData[i+0x40000] = origRom[i];
RomPages = RomData.Length/8192;
RomLength = RomData.Length;
} else if (game.GetRomData().Length > 1024 * 1024) {
// If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper
Cpu.ReadMemory = ReadMemorySF2;
Cpu.WriteMemory = WriteMemorySF2;
Cpu.ReadMemory21 = ReadMemorySF2;
Cpu.WriteMemory21 = WriteMemorySF2;
RomData = game.GetRomData();
RomPages = RomData.Length / 8192;
RomLength = RomData.Length;
} else {
// normal rom.
RomData = game.GetRomData();
RomPages = RomData.Length / 8192;
RomLength = RomData.Length;
}
Cpu.ResetPC();
SetupMemoryDomains();
@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.Write("RAM ");
Ram.SaveAsHex(writer);
writer.WriteLine("Frame " + Frame);
if (Cpu.ReadMemory == ReadMemorySF2)
if (Cpu.ReadMemory21 == ReadMemorySF2)
writer.WriteLine("SF2MapperLatch " + SF2MapperLatch);
writer.WriteLine("IOBuffer {0:X2}", IOBuffer);
writer.WriteLine();
@ -274,7 +274,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
addr => Ram[addr & 0x7FFF],
(addr, value) => Ram[addr & 0x7FFF] = value);
var SystemBusDomain = new MemoryDomain("System Bus", 0x2F0000, Endian.Little,
addr => Cpu.ReadMemory21(addr),
(addr, value) => Cpu.WriteMemory21(addr, value));
domains.Add(MainMemoryDomain);
domains.Add(SystemBusDomain);
memoryDomains = domains.AsReadOnly();
}

View File

@ -29,7 +29,7 @@ namespace BizHawk
public ControllerDefinition ControllerDefinition { get { return NullController; } }
public IController Controller { get; set; }
public string GetControllersAsMnemonic() { return "|.|0|"; }
public string GetControllersAsMnemonic() { return "|.||"; }
public int Frame { get; set; }
public byte[] SaveRam { get { return new byte[0]; } }

View File

@ -61,42 +61,42 @@ namespace BizHawk.Emulation.Sound
frameStopTime = cycles;
}
public void WritePSG(ushort register, byte value, int cycles)
public void WritePSG(byte register, byte value, int cycles)
{
commands.Enqueue(new QueuedCommand { Register = register, Value = value, Time = cycles-frameStartTime });
}
public void WritePSGImmediate(ushort register, byte value)
public void WritePSGImmediate(int register, byte value)
{
switch (register)
{
case 0x800: // Set Voice Latch
case 0: // Set Voice Latch
VoiceLatch = (byte) (value & 7);
break;
case 0x801: // Global Volume select;
case 1: // Global Volume select;
MainVolumeLeft = (byte) ((value >> 4) & 0x0F);
MainVolumeRight = (byte) (value & 0x0F);
break;
case 0x802: // Frequency LSB
case 2: // Frequency LSB
Channels[VoiceLatch].Frequency &= 0xFF00;
Channels[VoiceLatch].Frequency |= value;
break;
case 0x803: // Frequency MSB
case 3: // Frequency MSB
Channels[VoiceLatch].Frequency &= 0x00FF;
Channels[VoiceLatch].Frequency |= (ushort)(value << 8);
Channels[VoiceLatch].Frequency &= 0x0FFF;
break;
case 0x804: // Voice Volume
case 4: // Voice Volume
Channels[VoiceLatch].Volume = (byte) (value & 0x1F);
Channels[VoiceLatch].Enabled = (value & 0x80) != 0;
Channels[VoiceLatch].DDA = (value & 0x40) != 0;
if (Channels[VoiceLatch].Enabled == false && Channels[VoiceLatch].DDA)
WaveTableWriteOffset = 0;
break;
case 0x805: // Panning
case 5: // Panning
Channels[VoiceLatch].Panning = value;
break;
case 0x806: // Wave data
case 6: // Wave data
if (Channels[VoiceLatch].DDA == false)
{
Channels[VoiceLatch].Wave[WaveTableWriteOffset++] = (short) ((value*2047) - 32767);
@ -105,16 +105,16 @@ namespace BizHawk.Emulation.Sound
Channels[VoiceLatch].DDAValue = (short)((value * 2047) - 32767);
}
break;
case 0x807: // Noise
case 7: // Noise
Channels[VoiceLatch].NoiseChannel = ((value & 0x80) != 0) && VoiceLatch >= 4;
if ((value & 0x1F) == 0x1F)
value &= 0xFE;
Channels[VoiceLatch].NoiseFreq = (ushort) (PsgBase/(64*(0x1F - (value & 0x1F))));
break;
case 0x0808: // LFO
case 8: // LFO
// TODO: implement LFO
break;
case 0x809: // LFO Control
case 9: // LFO Control
if ((value & 0x80) == 0 && (value & 3) != 0)
{
Channels[1].Enabled = false;
@ -330,7 +330,7 @@ namespace BizHawk.Emulation.Sound
class QueuedCommand
{
public ushort Register;
public byte Register;
public byte Value;
public int Time;
}