[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 ==== // ==== Memory ====
public Func<ushort, byte> ReadMemory; public Func<int, byte> ReadMemory21;
public Action<ushort, byte> WriteMemory; public Action<int, byte> WriteMemory21;
public Action<int, byte> WriteVDC; 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) private ushort ReadWord(ushort address)
{ {
byte l = ReadMemory(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. // 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. // 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 SF2MapperLatch;
private byte ReadMemorySF2(ushort addr) private byte ReadMemorySF2(int addr)
{ {
int page = Cpu.MPR[addr >> 13]; if (addr < 0x7FFFF) // read ROM
ushort addr13 = (ushort)(addr & 0x1FFF); 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. if (addr < 0x1FE400) return VDC1.ReadVDC(addr & 0x03);
return RomData[(page % RomPages << 13) | (addr13)]; if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
} if (addr < 0x1FE80F) return IOBuffer;
if (page < 0x80) if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
{ if (addr >= 0x1FF000 &&
// read rom with extended SF2 mapper. addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
return RomData[(((page << 13) | addr13) & 0x7FFFF) + ((SF2MapperLatch + 1)*0x80000)]; if ((addr & ~1) == 0x1FF400) return IOBuffer;
} if (addr == 0x1FF402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (page >= 0xF8 && page <= 0xFB) if (addr == 0x1FF403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
{
// read RAM.
return Ram[((page-0xF8) << 13) | addr13];
} }
if (page == 0xFF) Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
{
// 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);
return 0xFF; 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) if ((addr & 0x1FFC) == 0x1FF0)
{ {
// Set SF2 pager. // Set SF2 pager.
SF2MapperLatch = (byte) (addr & 0x03); SF2MapperLatch = (byte)(addr & 0x03);
return; return;
} }
if (page >= 0xF8 && page <= 0xFB) if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
{ Ram[addr & 0x1FFF] = value;
// write RAM.
Ram[addr13] = value;
}
if (page == 0xFF) else if (addr >= 0x1FE000) // hardware page.
{ {
// hardware page. if (addr < 0x1FE400) VDC1.WriteVDC(addr & 3, value);
if (addr13 < 0x400) else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
VDC1.WriteVDC(addr13 & 3, value); else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr13 < 0x800) else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
VCE.WriteVCE(addr13 & 7, value); else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr13 < 0x80A) else if (addr >= 0x1FF000 &&
PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr13 == 0x0C00) else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
Cpu.WriteTimer(value); else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else if (addr13 == 0x0C01) else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
Cpu.WriteTimerEnable(value);
else if (addr13 >= 0x1000 && addr13 < 0x1400)
WriteInput(value);
else if (addr13 == 0x1402)
Cpu.WriteIrqControl(value);
else if (addr13 == 0x1403)
Cpu.WriteIrqStatus();
} }
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 // The SuperGrafx has 32K of RAM and a different port configuration to allow
// I/O access to VDC1, VDC2, and the VPC. // 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]; if (addr < 0xFFFFF) // read ROM
ushort addr13 = (ushort)(addr & 0x1FFF); return RomData[addr % RomLength];
if (page < 0x80) // read ROM if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
return RomData[(page % RomPages << 13) | (addr13)]; return Ram[addr & 0x7FFF];
if (page >= 0xF8 && page <= 0xFB) // read RAM if (addr >= 0x1FE000) // hardware page.
return Ram[((page-0xF8) << 13) | addr13];
if (page == 0xFF) // hardware page.
{ {
if (addr13 < 0x400) if (addr < 0x1FE400)
{ {
addr13 &= 0x1F; addr &= 0x1F;
if (addr13 <= 0x07) return VDC1.ReadVDC(addr13 & 3); if (addr <= 0x07) return VDC1.ReadVDC(addr & 3);
if (addr13 <= 0x0F) return VPC.ReadVPC(addr13); if (addr <= 0x0F) return VPC.ReadVPC(addr);
if (addr13 <= 0x17) return VDC2.ReadVDC(addr13 & 3); if (addr <= 0x17) return VDC2.ReadVDC(addr & 3);
return 0xFF; return 0xFF;
} }
if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); }
if (addr13 < 0x080F) return IOBuffer; if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; } if (addr < 0x1FE80F) return IOBuffer;
if (addr13 >= 0x1000 && if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte)(Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; } if (addr >= 0x1FF000 &&
if ((addr13 & ~1) == 0x1400) return IOBuffer; addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; } if ((addr & ~1) == 0x1FF400) return IOBuffer;
if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); 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; return 0xFF;
} }
private void WriteMemorySGX(ushort addr, byte value) private void WriteMemorySGX(int addr, byte value)
{ {
int page = Cpu.MPR[addr >> 13]; if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
ushort addr13 = (ushort)(addr & 0x1FFF); Ram[addr & 0x7FFF] = value;
if (page >= 0xF8 && page <= 0xFB) // write RAM. else if (addr >= 0x1FE000) // hardware page.
Ram[((page-0xF8) << 13) | addr13] = value;
else if (page == 0xFF) // hardware page.
{ {
if (addr13 < 0x0400) if (addr < 0x1FE400)
{ {
addr13 &= 0x1F; addr &= 0x1F;
if (addr13 <= 0x07) VDC1.WriteVDC(addr13 & 3, value); if (addr <= 0x07) VDC1.WriteVDC(addr & 3, value);
else if (addr13 <= 0x0F) VPC.WriteVPC(addr13, value); else if (addr <= 0x0F) VPC.WriteVPC(addr, value);
else if (addr13 <= 0x17) VDC2.WriteVDC(addr13 & 3, value); else if (addr <= 0x17) VDC2.WriteVDC(addr & 3, value);
} }
else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); } else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); } else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); } else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr13 >= 0x1000 && else if (addr >= 0x1FF000 &&
addr13 < 0x1400) { IOBuffer = value; WriteInput(value); } addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); } else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); } else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value); 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 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 IOBuffer;
private byte ReadMemory(ushort addr) private byte ReadMemory(int addr)
{ {
int page = Cpu.MPR[addr >> 13]; if (addr < 0xFFFFF) // read ROM
ushort addr13 = (ushort)(addr & 0x1FFF); return RomData[addr % RomLength];
if (page < 0x80) // read ROM if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
return RomData[(page % RomPages << 13) | (addr13)]; return Ram[addr & 0x1FFF];
if (page >= 0xF8 && page <= 0xFB) // read RAM if (addr >= 0x1FE000) // hardware page.
return Ram[addr13];
if (page == 0xFF) // hardware page.
{ {
if (addr13 < 0x0400) return VDC1.ReadVDC(addr13 & 0x03); if (addr < 0x1FE400) return VDC1.ReadVDC(addr & 0x03);
if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); } if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr & 0x07)); }
if (addr13 < 0x080F) return IOBuffer; if (addr < 0x1FE80F) return IOBuffer;
if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; } if ((addr & ~1) == 0x1FEC00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; }
if (addr13 >= 0x1000 && if (addr >= 0x1FF000 &&
addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; } addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
if ((addr13 & ~1) == 0x1400) return IOBuffer; if ((addr & ~1) == 0x1FF400) return IOBuffer;
if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; } if (addr == 0x1FF402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; }
if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (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; return 0xFF;
} }
private void WriteMemory(ushort addr, byte value) private void WriteMemory(int addr, byte value)
{ {
int page = Cpu.MPR[addr >> 13]; if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
ushort addr13 = (ushort)(addr & 0x1FFF);
if (page >= 0xF8 && page <= 0xFB) // write RAM.
{ {
if (Cpu.debug) if (Cpu.debug)
Log.Note("MEM", "*Mem* Changed {0:X4} from {1:X2} to {2:X2}", addr13, Ram[addr13], value); Log.Note("MEM", "*Mem* Changed {0:X4} from {1:X2} to {2:X2}", addr & 0x1FFF, Ram[addr & 0x1FFF], value);
Ram[addr13] = value; Ram[addr & 0x1FFF] = value;
} }
if (page == 0xFF) // hardware page. else if (addr >= 0x1FE000) // hardware page.
{ {
if (addr13 < 0x0400) VDC1.WriteVDC(addr13 & 3, value); if (addr < 0x1FE400) VDC1.WriteVDC(addr & 3, value);
else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); } else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr & 7, value); }
else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); } else if (addr < 0x1FE80A) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); }
else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); } else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); }
else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); }
else if (addr13 >= 0x1000 && else if (addr >= 0x1FF000 &&
addr13 < 0x1400) { IOBuffer = value; WriteInput(value); } addr < 0x1FF400) { IOBuffer = value; WriteInput(value); }
else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); } else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); }
else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); } else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); }
else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value); 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 // ROM
public byte[] RomData; public byte[] RomData;
public int RomPages; public int RomLength;
// Machine // Machine
public NecSystemType Type; public NecSystemType Type;
@ -59,8 +59,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (TurboGrafx || TurboCD) if (TurboGrafx || TurboCD)
{ {
Ram = new byte[0x2000]; Ram = new byte[0x2000];
Cpu.ReadMemory = ReadMemory; Cpu.ReadMemory21 = ReadMemory;
Cpu.WriteMemory = WriteMemory; Cpu.WriteMemory21 = WriteMemory;
Cpu.WriteVDC = VDC1.WriteVDC; Cpu.WriteVDC = VDC1.WriteVDC;
} }
@ -69,8 +69,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
VDC2 = new VDC(Cpu, VCE); VDC2 = new VDC(Cpu, VCE);
VPC = new VPC(VDC1, VDC2, VCE, Cpu); VPC = new VPC(VDC1, VDC2, VCE, Cpu);
Ram = new byte[0x8000]; Ram = new byte[0x8000];
Cpu.ReadMemory = ReadMemorySGX; Cpu.ReadMemory21 = ReadMemorySGX;
Cpu.WriteMemory = WriteMemorySGX; Cpu.WriteMemory21 = WriteMemorySGX;
Cpu.WriteVDC = VDC1.WriteVDC; Cpu.WriteVDC = VDC1.WriteVDC;
} }
} }
@ -87,17 +87,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
RomData[i] = origRom[i]; RomData[i] = origRom[i];
for (int i = 0; i < 0x60000; i++) for (int i = 0; i < 0x60000; i++)
RomData[i+0x40000] = origRom[i]; RomData[i+0x40000] = origRom[i];
RomPages = RomData.Length/8192; RomLength = RomData.Length;
} else if (game.GetRomData().Length > 1024 * 1024) { } else if (game.GetRomData().Length > 1024 * 1024) {
// If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper // If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper
Cpu.ReadMemory = ReadMemorySF2; Cpu.ReadMemory21 = ReadMemorySF2;
Cpu.WriteMemory = WriteMemorySF2; Cpu.WriteMemory21 = WriteMemorySF2;
RomData = game.GetRomData(); RomData = game.GetRomData();
RomPages = RomData.Length / 8192; RomLength = RomData.Length;
} else { } else {
// normal rom. // normal rom.
RomData = game.GetRomData(); RomData = game.GetRomData();
RomPages = RomData.Length / 8192; RomLength = RomData.Length;
} }
Cpu.ResetPC(); Cpu.ResetPC();
SetupMemoryDomains(); SetupMemoryDomains();
@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.Write("RAM "); writer.Write("RAM ");
Ram.SaveAsHex(writer); Ram.SaveAsHex(writer);
writer.WriteLine("Frame " + Frame); writer.WriteLine("Frame " + Frame);
if (Cpu.ReadMemory == ReadMemorySF2) if (Cpu.ReadMemory21 == ReadMemorySF2)
writer.WriteLine("SF2MapperLatch " + SF2MapperLatch); writer.WriteLine("SF2MapperLatch " + SF2MapperLatch);
writer.WriteLine("IOBuffer {0:X2}", IOBuffer); writer.WriteLine("IOBuffer {0:X2}", IOBuffer);
writer.WriteLine(); writer.WriteLine();
@ -274,7 +274,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little, var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
addr => Ram[addr & 0x7FFF], addr => Ram[addr & 0x7FFF],
(addr, value) => Ram[addr & 0x7FFF] = value); (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(MainMemoryDomain);
domains.Add(SystemBusDomain);
memoryDomains = domains.AsReadOnly(); memoryDomains = domains.AsReadOnly();
} }

View File

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

View File

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