move Log.cs from BizHawk.Emulation to BizHawk.Common
This commit is contained in:
parent
7f3f116cd9
commit
4f5d8b89c9
|
@ -3,6 +3,7 @@ using System.Text;
|
|||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
#pragma warning disable 162
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<Compile Include="Buffer.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="HawkFile.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="MruStack.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="QuickCollections.cs" />
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
static Log()
|
||||
{
|
||||
// You can set current desired logging settings here.
|
||||
// Production builds should be done with all logging disabled.
|
||||
LogToConsole = true;
|
||||
//LogToFile = true;
|
||||
//LogFilename = "d:/bizhawk.log";
|
||||
//EnableDomain("CD");
|
||||
//EnableDomain("CPU");
|
||||
//EnableDomain("VDC");
|
||||
//EnableDomain("MEM");
|
||||
}
|
||||
|
||||
// ============== Logging Domain Configuration ==============
|
||||
|
||||
private static List<string> EnabledLogDomains = new List<string>();
|
||||
|
||||
public static void EnableDomain(string domain)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain) == false)
|
||||
EnabledLogDomains.Add(domain);
|
||||
}
|
||||
|
||||
public static void DisableDomain(string domain)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain))
|
||||
EnabledLogDomains.Remove(domain);
|
||||
}
|
||||
|
||||
// ============== Logging Action Configuration ==============
|
||||
|
||||
public static Action<string> LogAction = DefaultLogger;
|
||||
|
||||
// NOTEs are only logged if the domain is enabled.
|
||||
// ERRORs are logged regardless.
|
||||
|
||||
public static void Note(string domain, string msg, params object[] vals)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain))
|
||||
LogAction(String.Format(msg, vals));
|
||||
}
|
||||
|
||||
public static void Error(string domain, string msg, params object[] vals)
|
||||
{
|
||||
LogAction(String.Format(msg, vals));
|
||||
}
|
||||
|
||||
// ============== Default Logger Action ==============
|
||||
|
||||
public static Stream HACK_LOG_STREAM;
|
||||
|
||||
private static bool LogToConsole = false;
|
||||
private static bool LogToFile = false;
|
||||
|
||||
private static string LogFilename = "bizhawk.txt";
|
||||
private static StreamWriter writer;
|
||||
|
||||
private static void DefaultLogger(string message)
|
||||
{
|
||||
if (LogToConsole)
|
||||
Console.WriteLine(message);
|
||||
|
||||
if (LogToFile && writer == null)
|
||||
writer = new StreamWriter(LogFilename);
|
||||
|
||||
if (LogToFile)
|
||||
{
|
||||
writer.WriteLine(message);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -477,7 +477,6 @@
|
|||
<Compile Include="Interfaces\IEmulator.cs" />
|
||||
<Compile Include="Interfaces\ISoundProvider.cs" />
|
||||
<Compile Include="Interfaces\IVideoProvider.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="Consoles\PC Engine\Input.cs" />
|
||||
<Compile Include="Consoles\PC Engine\MemoryMap.cs" />
|
||||
<Compile Include="Consoles\PC Engine\MemoryMap.SF2.cs" />
|
||||
|
|
|
@ -1,62 +1,64 @@
|
|||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
// The Populous HuCard is the only traditional HuCard to have battery-backed saveRAM
|
||||
// built into it. There is 32k of save-RAM mapped at pages $40 - $44.
|
||||
|
||||
byte[] PopulousRAM;
|
||||
public partial class PCEngine
|
||||
{
|
||||
// The Populous HuCard is the only traditional HuCard to have battery-backed saveRAM
|
||||
// built into it. There is 32k of save-RAM mapped at pages $40 - $44.
|
||||
|
||||
byte ReadMemoryPopulous(int addr)
|
||||
{
|
||||
if (addr >= 0x80000 && addr < 0x88000)
|
||||
return PopulousRAM[addr & 0x7FFF];
|
||||
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
byte[] PopulousRAM;
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
byte ReadMemoryPopulous(int addr)
|
||||
{
|
||||
if (addr >= 0x80000 && addr < 0x88000)
|
||||
return PopulousRAM[addr & 0x7FFF];
|
||||
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
|
||||
void WriteMemoryPopulous(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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 if (addr >= 0x80000 && addr < 0x88000)
|
||||
PopulousRAM[addr & 0x7FFF] = value;
|
||||
else
|
||||
Log.Error("MEM","UNHANDLED WRITE: {0:X6}:{1:X2}",addr,value);
|
||||
}
|
||||
}
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void WriteMemoryPopulous(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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 if (addr >= 0x80000 && addr < 0x88000)
|
||||
PopulousRAM[addr & 0x7FFF] = value;
|
||||
else
|
||||
Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +1,69 @@
|
|||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
// 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.
|
||||
|
||||
byte SF2MapperLatch;
|
||||
public partial class PCEngine
|
||||
{
|
||||
// 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.
|
||||
|
||||
byte ReadMemorySF2(int addr)
|
||||
{
|
||||
if (addr < 0x7FFFF) // read ROM
|
||||
return RomData[addr];
|
||||
byte SF2MapperLatch;
|
||||
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[(addr & 0x7FFFF) + ((SF2MapperLatch + 1) * 0x80000)];
|
||||
byte ReadMemorySF2(int addr)
|
||||
{
|
||||
if (addr < 0x7FFFF) // read ROM
|
||||
return RomData[addr];
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[(addr & 0x7FFFF) + ((SF2MapperLatch + 1) * 0x80000)];
|
||||
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte) (Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void WriteMemorySF2(int addr, byte value)
|
||||
{
|
||||
if ((addr & 0x1FFC) == 0x1FF0)
|
||||
{
|
||||
// Set SF2 pager.
|
||||
SF2MapperLatch = (byte)(addr & 0x03);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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);
|
||||
}
|
||||
}
|
||||
void WriteMemorySF2(int addr, byte value)
|
||||
{
|
||||
if ((addr & 0x1FFC) == 0x1FF0)
|
||||
{
|
||||
// Set SF2 pager.
|
||||
SF2MapperLatch = (byte)(addr & 0x03);
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +1,71 @@
|
|||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
// The SuperGrafx has 32K of RAM and a different port configuration to allow
|
||||
// I/O access to VDC1, VDC2, and the VPC.
|
||||
public partial class PCEngine
|
||||
{
|
||||
// The SuperGrafx has 32K of RAM and a different port configuration to allow
|
||||
// I/O access to VDC1, VDC2, and the VPC.
|
||||
|
||||
byte ReadMemorySGX(int addr)
|
||||
{
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
byte ReadMemorySGX(int addr)
|
||||
{
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x7FFF];
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x7FFF];
|
||||
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400)
|
||||
{
|
||||
addr &= 0x1F;
|
||||
if (addr <= 0x07) return VDC1.ReadVDC(addr);
|
||||
if (addr <= 0x0F) return VPC.ReadVPC(addr);
|
||||
if (addr <= 0x17) return VDC2.ReadVDC(addr);
|
||||
return 0xFF;
|
||||
}
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400)
|
||||
{
|
||||
addr &= 0x1F;
|
||||
if (addr <= 0x07) return VDC1.ReadVDC(addr);
|
||||
if (addr <= 0x0F) return VPC.ReadVPC(addr);
|
||||
if (addr <= 0x17) return VDC2.ReadVDC(addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
}
|
||||
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void WriteMemorySGX(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x7FFF] = value;
|
||||
void WriteMemorySGX(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x7FFF] = value;
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400)
|
||||
{
|
||||
addr &= 0x1F;
|
||||
if (addr <= 0x07) VDC1.WriteVDC(addr, value);
|
||||
else if (addr <= 0x0F) VPC.WriteVPC(addr, value);
|
||||
else if (addr <= 0x17) VDC2.WriteVDC(addr, value);
|
||||
}
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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);
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400)
|
||||
{
|
||||
addr &= 0x1F;
|
||||
if (addr <= 0x07) VDC1.WriteVDC(addr, value);
|
||||
else if (addr <= 0x0F) VPC.WriteVPC(addr, value);
|
||||
else if (addr <= 0x17) VDC2.WriteVDC(addr, value);
|
||||
}
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +1,100 @@
|
|||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
byte ReadMemoryCD(int addr)
|
||||
{
|
||||
if (addr < 0x80000) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
public partial class PCEngine
|
||||
{
|
||||
byte ReadMemoryCD(int addr)
|
||||
{
|
||||
if (addr < 0x80000) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // read RAM
|
||||
return Ram[addr & 0x1FFF];
|
||||
|
||||
if (addr >= 0x100000 && addr < 0x110000) // read CD RAM
|
||||
return CDRam[addr & 0xFFFF];
|
||||
if (addr >= 0x100000 && addr < 0x110000) // read CD RAM
|
||||
return CDRam[addr & 0xFFFF];
|
||||
|
||||
if (addr >= 0xD0000 && addr < 0x100000 && SuperRam != null) // Super SysCard RAM
|
||||
return SuperRam[addr - 0xD0000];
|
||||
if (addr >= 0xD0000 && addr < 0x100000 && SuperRam != null) // Super SysCard RAM
|
||||
return SuperRam[addr - 0xD0000];
|
||||
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
if (addr >= 0x1FF800) return ReadCD(addr);
|
||||
}
|
||||
if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) return VDC1.ReadVDC(addr);
|
||||
if (addr < 0x1FE800) { Cpu.PendingCycles--; return VCE.ReadVCE(addr); }
|
||||
if (addr < 0x1FEC00) return IOBuffer;
|
||||
if (addr < 0x1FF000) { IOBuffer = (byte)(Cpu.ReadTimerValue() | (IOBuffer & 0x80)); return IOBuffer; }
|
||||
if (addr >= 0x1FF000 &&
|
||||
addr < 0x1FF400) { IOBuffer = ReadInput(); return IOBuffer; }
|
||||
if ((addr & ~1) == 0x1FF400) return IOBuffer;
|
||||
if (addr == 0x1FF402) { IOBuffer = Cpu.IRQControlByte; return IOBuffer; }
|
||||
if (addr == 0x1FF403) { IOBuffer = (byte)(Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; }
|
||||
if (addr >= 0x1FF800) return ReadCD(addr);
|
||||
}
|
||||
|
||||
if (addr >= 0x80000 && addr < 0x88000 && ArcadeCard)
|
||||
{
|
||||
var page = ArcadePage[(addr >> 13) & 3];
|
||||
byte value = ArcadeRam[page.EffectiveAddress];
|
||||
page.Increment();
|
||||
return value;
|
||||
}
|
||||
if (addr >= 0x80000 && addr < 0x88000 && ArcadeCard)
|
||||
{
|
||||
var page = ArcadePage[(addr >> 13) & 3];
|
||||
byte value = ArcadeRam[page.EffectiveAddress];
|
||||
page.Increment();
|
||||
return value;
|
||||
}
|
||||
|
||||
if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM
|
||||
{
|
||||
if (BramEnabled && BramLocked == false)
|
||||
return BRAM[addr & 0x7FF];
|
||||
return 0xFF;
|
||||
}
|
||||
if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM
|
||||
{
|
||||
if (BramEnabled && BramLocked == false)
|
||||
return BRAM[addr & 0x7FF];
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
Log.Error("MEM", "UNHANDLED READ: {0:X6}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void WriteMemoryCD(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
void WriteMemoryCD(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
||||
else if (addr >= 0x100000 && addr < 0x110000) // write CD-RAM
|
||||
CDRam[addr & 0xFFFF] = value;
|
||||
else if (addr >= 0x100000 && addr < 0x110000) // write CD-RAM
|
||||
CDRam[addr & 0xFFFF] = value;
|
||||
|
||||
else if (addr >= 0xD0000 && addr < 0x100000 && SuperRam != null) // Super SysCard RAM
|
||||
SuperRam[addr - 0xD0000] = value;
|
||||
else if (addr >= 0xD0000 && addr < 0x100000 && SuperRam != null) // Super SysCard RAM
|
||||
SuperRam[addr - 0xD0000] = value;
|
||||
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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 if (addr >= 0x1FF800) { WriteCD(addr, value); }
|
||||
else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
|
||||
}
|
||||
else if (addr >= 0x1FE000) // hardware page.
|
||||
{
|
||||
if (addr < 0x1FE400) VDC1.WriteVDC(addr, value);
|
||||
else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); }
|
||||
else if (addr < 0x1FEC00) { 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 if (addr >= 0x1FF800) { WriteCD(addr, value); }
|
||||
else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value);
|
||||
}
|
||||
|
||||
else if (addr >= 0x80000 && addr < 0x88000 && ArcadeCard) // Arcade Card
|
||||
{
|
||||
var page = ArcadePage[(addr >> 13) & 3];
|
||||
ArcadeRam[page.EffectiveAddress] = value;
|
||||
page.Increment();
|
||||
}
|
||||
else if (addr >= 0x80000 && addr < 0x88000 && ArcadeCard) // Arcade Card
|
||||
{
|
||||
var page = ArcadePage[(addr >> 13) & 3];
|
||||
ArcadeRam[page.EffectiveAddress] = value;
|
||||
page.Increment();
|
||||
}
|
||||
|
||||
else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM
|
||||
{
|
||||
if (BramEnabled && BramLocked == false)
|
||||
{
|
||||
BRAM[addr & 0x7FF] = value;
|
||||
SaveRamModified = true;
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM
|
||||
{
|
||||
if (BramEnabled && BramLocked == false)
|
||||
{
|
||||
BRAM[addr & 0x7FF] = value;
|
||||
SaveRamModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
|
|
|
@ -1,312 +1,313 @@
|
|||
using System;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
public byte[] CdIoPorts = new byte[16];
|
||||
public partial class PCEngine
|
||||
{
|
||||
public byte[] CdIoPorts = new byte[16];
|
||||
|
||||
public bool IntADPCM // INTA
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x04) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x04) | (value ? 0x04 : 0x00)); }
|
||||
}
|
||||
public bool IntStop // INTSTOP
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x08) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x08) | (value ? 0x8 : 0x00)); }
|
||||
}
|
||||
public bool IntSubchannel // INTSUB
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x10) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x10) | (value ? 0x10 : 0x00)); }
|
||||
}
|
||||
public bool IntDataTransferComplete // INTM
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x20) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x20) | (value ? 0x20 : 0x00)); }
|
||||
}
|
||||
public bool IntDataTransferReady // INTD
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x40) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x40) | (value ? 0x40 : 0x00)); }
|
||||
}
|
||||
public bool IntADPCM // INTA
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x04) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x04) | (value ? 0x04 : 0x00)); }
|
||||
}
|
||||
public bool IntStop // INTSTOP
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x08) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x08) | (value ? 0x8 : 0x00)); }
|
||||
}
|
||||
public bool IntSubchannel // INTSUB
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x10) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x10) | (value ? 0x10 : 0x00)); }
|
||||
}
|
||||
public bool IntDataTransferComplete // INTM
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x20) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x20) | (value ? 0x20 : 0x00)); }
|
||||
}
|
||||
public bool IntDataTransferReady // INTD
|
||||
{
|
||||
get { return (CdIoPorts[3] & 0x40) != 0; }
|
||||
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x40) | (value ? 0x40 : 0x00)); }
|
||||
}
|
||||
|
||||
void SetCDAudioCallback()
|
||||
{
|
||||
CDAudio.CallbackAction = () =>
|
||||
{
|
||||
IntDataTransferReady = false;
|
||||
IntDataTransferComplete = true;
|
||||
CDAudio.Stop();
|
||||
};
|
||||
}
|
||||
void SetCDAudioCallback()
|
||||
{
|
||||
CDAudio.CallbackAction = () =>
|
||||
{
|
||||
IntDataTransferReady = false;
|
||||
IntDataTransferComplete = true;
|
||||
CDAudio.Stop();
|
||||
};
|
||||
}
|
||||
|
||||
void WriteCD(int addr, byte value)
|
||||
{
|
||||
if (!TurboCD && !BramEnabled)
|
||||
return; // flee if no turboCD hooked up
|
||||
if (!TurboCD && addr != 0x1FF807)
|
||||
return; // only bram port available unless full TurobCD mode.
|
||||
void WriteCD(int addr, byte value)
|
||||
{
|
||||
if (!TurboCD && !BramEnabled)
|
||||
return; // flee if no turboCD hooked up
|
||||
if (!TurboCD && addr != 0x1FF807)
|
||||
return; // only bram port available unless full TurobCD mode.
|
||||
|
||||
switch (addr & 0x1FFF)
|
||||
{
|
||||
case 0x1800: // SCSI Drive Control Line
|
||||
CdIoPorts[0] = value;
|
||||
SCSI.SEL = true;
|
||||
SCSI.Think();
|
||||
SCSI.SEL = false;
|
||||
SCSI.Think();
|
||||
break;
|
||||
switch (addr & 0x1FFF)
|
||||
{
|
||||
case 0x1800: // SCSI Drive Control Line
|
||||
CdIoPorts[0] = value;
|
||||
SCSI.SEL = true;
|
||||
SCSI.Think();
|
||||
SCSI.SEL = false;
|
||||
SCSI.Think();
|
||||
break;
|
||||
|
||||
case 0x1801: // CDC Command
|
||||
CdIoPorts[1] = value;
|
||||
SCSI.DataBits = value;
|
||||
SCSI.Think();
|
||||
break;
|
||||
case 0x1801: // CDC Command
|
||||
CdIoPorts[1] = value;
|
||||
SCSI.DataBits = value;
|
||||
SCSI.Think();
|
||||
break;
|
||||
|
||||
case 0x1802: // ACK and Interrupt Control
|
||||
CdIoPorts[2] = value;
|
||||
SCSI.ACK = ((value & 0x80) != 0);
|
||||
case 0x1802: // ACK and Interrupt Control
|
||||
CdIoPorts[2] = value;
|
||||
SCSI.ACK = ((value & 0x80) != 0);
|
||||
|
||||
SCSI.Think();
|
||||
RefreshIRQ2();
|
||||
break;
|
||||
SCSI.Think();
|
||||
RefreshIRQ2();
|
||||
break;
|
||||
|
||||
case 0x1804: // CD Reset Command
|
||||
CdIoPorts[4] = value;
|
||||
SCSI.RST = ((value & 0x02) != 0);
|
||||
SCSI.Think();
|
||||
if (SCSI.RST)
|
||||
{
|
||||
CdIoPorts[3] &= 0x8F; // Clear interrupt control bits
|
||||
RefreshIRQ2();
|
||||
}
|
||||
break;
|
||||
case 0x1804: // CD Reset Command
|
||||
CdIoPorts[4] = value;
|
||||
SCSI.RST = ((value & 0x02) != 0);
|
||||
SCSI.Think();
|
||||
if (SCSI.RST)
|
||||
{
|
||||
CdIoPorts[3] &= 0x8F; // Clear interrupt control bits
|
||||
RefreshIRQ2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1805:
|
||||
case 0x1806:
|
||||
// Latch CDDA data... no action needed for us (because we cheat)
|
||||
break;
|
||||
case 0x1805:
|
||||
case 0x1806:
|
||||
// Latch CDDA data... no action needed for us (because we cheat)
|
||||
break;
|
||||
|
||||
case 0x1807: // BRAM Unlock
|
||||
if (BramEnabled && (value & 0x80) != 0)
|
||||
BramLocked = false;
|
||||
break;
|
||||
case 0x1807: // BRAM Unlock
|
||||
if (BramEnabled && (value & 0x80) != 0)
|
||||
BramLocked = false;
|
||||
break;
|
||||
|
||||
case 0x1808: // ADPCM address LSB
|
||||
ADPCM.IOAddress &= 0xFF00;
|
||||
ADPCM.IOAddress |= value;
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
Console.WriteLine("doing silly thing");
|
||||
break;
|
||||
case 0x1808: // ADPCM address LSB
|
||||
ADPCM.IOAddress &= 0xFF00;
|
||||
ADPCM.IOAddress |= value;
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
Console.WriteLine("doing silly thing");
|
||||
break;
|
||||
|
||||
case 0x1809: // ADPCM address MSB
|
||||
ADPCM.IOAddress &= 0x00FF;
|
||||
ADPCM.IOAddress |= (ushort)(value << 8);
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
Console.WriteLine("doing silly thing");
|
||||
break;
|
||||
case 0x1809: // ADPCM address MSB
|
||||
ADPCM.IOAddress &= 0x00FF;
|
||||
ADPCM.IOAddress |= (ushort)(value << 8);
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
Console.WriteLine("doing silly thing");
|
||||
break;
|
||||
|
||||
case 0x180A: // ADPCM Memory Read/Write Port
|
||||
ADPCM.Port180A = value;
|
||||
break;
|
||||
case 0x180A: // ADPCM Memory Read/Write Port
|
||||
ADPCM.Port180A = value;
|
||||
break;
|
||||
|
||||
case 0x180B: // ADPCM DMA Control
|
||||
ADPCM.Port180B = value;
|
||||
break;
|
||||
case 0x180B: // ADPCM DMA Control
|
||||
ADPCM.Port180B = value;
|
||||
break;
|
||||
|
||||
case 0x180D: // ADPCM Address Control
|
||||
ADPCM.AdpcmControlWrite(value);
|
||||
break;
|
||||
case 0x180D: // ADPCM Address Control
|
||||
ADPCM.AdpcmControlWrite(value);
|
||||
break;
|
||||
|
||||
case 0x180E: // ADPCM Playback Rate
|
||||
ADPCM.Port180E = value;
|
||||
break;
|
||||
case 0x180E: // ADPCM Playback Rate
|
||||
ADPCM.Port180E = value;
|
||||
break;
|
||||
|
||||
case 0x180F: // Audio Fade Timer
|
||||
CdIoPorts[0x0F] = value;
|
||||
// TODO ADPCM fades/vol control also.
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
CDAudio.LogicalVolume = 100;
|
||||
break;
|
||||
case 0x180F: // Audio Fade Timer
|
||||
CdIoPorts[0x0F] = value;
|
||||
// TODO ADPCM fades/vol control also.
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
CDAudio.LogicalVolume = 100;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
if (CDAudio.FadeOutFramesRemaining == 0)
|
||||
CDAudio.FadeOut(360); // 6 seconds
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
if (CDAudio.FadeOutFramesRemaining == 0)
|
||||
CDAudio.FadeOut(360); // 6 seconds
|
||||
break;
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
if (CDAudio.FadeOutFramesRemaining == 0)
|
||||
CDAudio.FadeOut(120); // 2 seconds
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
if (CDAudio.FadeOutFramesRemaining == 0)
|
||||
CDAudio.FadeOut(120); // 2 seconds
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Arcade Card ports
|
||||
case 0x1AE0:
|
||||
ShiftRegister &= ~0xFF;
|
||||
ShiftRegister |= value;
|
||||
break;
|
||||
case 0x1AE1:
|
||||
ShiftRegister &= ~0xFF00;
|
||||
ShiftRegister |= value << 8;
|
||||
break;
|
||||
case 0x1AE2:
|
||||
ShiftRegister &= ~0xFF0000;
|
||||
ShiftRegister |= value << 16;
|
||||
break;
|
||||
case 0x1AE3:
|
||||
ShiftRegister &= 0xFFFFFF;
|
||||
ShiftRegister |= value << 24;
|
||||
break;
|
||||
case 0x1AE4:
|
||||
ShiftAmount = (byte) (value & 0x0F);
|
||||
if (ShiftAmount != 0)
|
||||
{
|
||||
if ((ShiftAmount & 8) != 0)
|
||||
ShiftRegister >>= 16 - ShiftAmount;
|
||||
else
|
||||
ShiftRegister <<= ShiftAmount;
|
||||
}
|
||||
break;
|
||||
case 0x1AE5:
|
||||
RotateAmount = value;
|
||||
// rotate not implemented, as no test case exists
|
||||
break;
|
||||
// Arcade Card ports
|
||||
case 0x1AE0:
|
||||
ShiftRegister &= ~0xFF;
|
||||
ShiftRegister |= value;
|
||||
break;
|
||||
case 0x1AE1:
|
||||
ShiftRegister &= ~0xFF00;
|
||||
ShiftRegister |= value << 8;
|
||||
break;
|
||||
case 0x1AE2:
|
||||
ShiftRegister &= ~0xFF0000;
|
||||
ShiftRegister |= value << 16;
|
||||
break;
|
||||
case 0x1AE3:
|
||||
ShiftRegister &= 0xFFFFFF;
|
||||
ShiftRegister |= value << 24;
|
||||
break;
|
||||
case 0x1AE4:
|
||||
ShiftAmount = (byte)(value & 0x0F);
|
||||
if (ShiftAmount != 0)
|
||||
{
|
||||
if ((ShiftAmount & 8) != 0)
|
||||
ShiftRegister >>= 16 - ShiftAmount;
|
||||
else
|
||||
ShiftRegister <<= ShiftAmount;
|
||||
}
|
||||
break;
|
||||
case 0x1AE5:
|
||||
RotateAmount = value;
|
||||
// rotate not implemented, as no test case exists
|
||||
break;
|
||||
|
||||
default:
|
||||
if (addr >= 0x1FFA00 && addr < 0x1FFA40)
|
||||
WriteArcadeCard(addr & 0x1FFF, value);
|
||||
else
|
||||
Log.Error("CD", "unknown write to {0:X4}:{1:X2} pc={2:X4}", addr, value, Cpu.PC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
if (addr >= 0x1FFA00 && addr < 0x1FFA40)
|
||||
WriteArcadeCard(addr & 0x1FFF, value);
|
||||
else
|
||||
Log.Error("CD", "unknown write to {0:X4}:{1:X2} pc={2:X4}", addr, value, Cpu.PC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadCD(int addr)
|
||||
{
|
||||
if (!TurboCD && !BramEnabled)
|
||||
return 0xFF; //bail if no TurboCD.
|
||||
if (!TurboCD && addr != 0x1FF803) // only allow access to $1803 unless full TurboCD mode.
|
||||
return 0xFF;
|
||||
public byte ReadCD(int addr)
|
||||
{
|
||||
if (!TurboCD && !BramEnabled)
|
||||
return 0xFF; //bail if no TurboCD.
|
||||
if (!TurboCD && addr != 0x1FF803) // only allow access to $1803 unless full TurboCD mode.
|
||||
return 0xFF;
|
||||
|
||||
byte returnValue = 0;
|
||||
short sample;
|
||||
byte returnValue = 0;
|
||||
short sample;
|
||||
|
||||
switch (addr & 0x1FFF)
|
||||
{
|
||||
case 0x1800: // SCSI Drive Control Line
|
||||
if (SCSI.IO) returnValue |= 0x08;
|
||||
if (SCSI.CD) returnValue |= 0x10;
|
||||
if (SCSI.MSG) returnValue |= 0x20;
|
||||
if (SCSI.REQ) returnValue |= 0x40;
|
||||
if (SCSI.BSY) returnValue |= 0x80;
|
||||
return returnValue;
|
||||
switch (addr & 0x1FFF)
|
||||
{
|
||||
case 0x1800: // SCSI Drive Control Line
|
||||
if (SCSI.IO) returnValue |= 0x08;
|
||||
if (SCSI.CD) returnValue |= 0x10;
|
||||
if (SCSI.MSG) returnValue |= 0x20;
|
||||
if (SCSI.REQ) returnValue |= 0x40;
|
||||
if (SCSI.BSY) returnValue |= 0x80;
|
||||
return returnValue;
|
||||
|
||||
case 0x1801: // Read data bus
|
||||
return SCSI.DataBits;
|
||||
case 0x1801: // Read data bus
|
||||
return SCSI.DataBits;
|
||||
|
||||
case 0x1802: // ADPCM / CD Control
|
||||
return CdIoPorts[2];
|
||||
case 0x1802: // ADPCM / CD Control
|
||||
return CdIoPorts[2];
|
||||
|
||||
case 0x1803: // BRAM Lock
|
||||
if (BramEnabled)
|
||||
BramLocked = true;
|
||||
case 0x1803: // BRAM Lock
|
||||
if (BramEnabled)
|
||||
BramLocked = true;
|
||||
|
||||
returnValue = CdIoPorts[3];
|
||||
CdIoPorts[3] ^= 2;
|
||||
return returnValue;
|
||||
returnValue = CdIoPorts[3];
|
||||
CdIoPorts[3] ^= 2;
|
||||
return returnValue;
|
||||
|
||||
case 0x1804: // CD Reset
|
||||
return CdIoPorts[4];
|
||||
case 0x1804: // CD Reset
|
||||
return CdIoPorts[4];
|
||||
|
||||
case 0x1805: // CD audio data Low
|
||||
if ((CdIoPorts[3] & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte) sample;
|
||||
case 0x1805: // CD audio data Low
|
||||
if ((CdIoPorts[3] & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte)sample;
|
||||
|
||||
case 0x1806: // CD audio data High
|
||||
if ((CdIoPorts[3] & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte) (sample >> 8);
|
||||
case 0x1806: // CD audio data High
|
||||
if ((CdIoPorts[3] & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte)(sample >> 8);
|
||||
|
||||
case 0x1808: // Auto Handshake Data Input
|
||||
returnValue = SCSI.DataBits;
|
||||
if (SCSI.REQ && SCSI.IO && !SCSI.CD)
|
||||
{
|
||||
SCSI.ACK = false;
|
||||
SCSI.REQ = false;
|
||||
SCSI.Think();
|
||||
}
|
||||
return returnValue;
|
||||
case 0x1808: // Auto Handshake Data Input
|
||||
returnValue = SCSI.DataBits;
|
||||
if (SCSI.REQ && SCSI.IO && !SCSI.CD)
|
||||
{
|
||||
SCSI.ACK = false;
|
||||
SCSI.REQ = false;
|
||||
SCSI.Think();
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
case 0x180A: // ADPCM Memory Read/Write Port
|
||||
return ADPCM.Port180A;
|
||||
case 0x180A: // ADPCM Memory Read/Write Port
|
||||
return ADPCM.Port180A;
|
||||
|
||||
case 0x180B: // ADPCM Data Transfer Control
|
||||
return ADPCM.Port180B;
|
||||
case 0x180B: // ADPCM Data Transfer Control
|
||||
return ADPCM.Port180B;
|
||||
|
||||
case 0x180C: // ADPCM Status
|
||||
returnValue = 0;
|
||||
if (ADPCM.EndReached)
|
||||
returnValue |= 0x01;
|
||||
if (ADPCM.AdpcmIsPlaying)
|
||||
returnValue |= 0x08;
|
||||
if (ADPCM.AdpcmBusyWriting)
|
||||
returnValue |= 0x04;
|
||||
if (ADPCM.AdpcmBusyReading)
|
||||
returnValue |= 0x80;
|
||||
//Log.Error("CD", "Read ADPCM Status {0:X2}", returnValue);
|
||||
case 0x180C: // ADPCM Status
|
||||
returnValue = 0;
|
||||
if (ADPCM.EndReached)
|
||||
returnValue |= 0x01;
|
||||
if (ADPCM.AdpcmIsPlaying)
|
||||
returnValue |= 0x08;
|
||||
if (ADPCM.AdpcmBusyWriting)
|
||||
returnValue |= 0x04;
|
||||
if (ADPCM.AdpcmBusyReading)
|
||||
returnValue |= 0x80;
|
||||
//Log.Error("CD", "Read ADPCM Status {0:X2}", returnValue);
|
||||
|
||||
return returnValue;
|
||||
return returnValue;
|
||||
|
||||
case 0x180D: // ADPCM Play Control
|
||||
return CdIoPorts[0x0D];
|
||||
case 0x180D: // ADPCM Play Control
|
||||
return CdIoPorts[0x0D];
|
||||
|
||||
case 0x180F: // Audio Fade Timer
|
||||
return CdIoPorts[0x0F];
|
||||
case 0x180F: // Audio Fade Timer
|
||||
return CdIoPorts[0x0F];
|
||||
|
||||
// These are some retarded version check
|
||||
case 0x18C1: return 0xAA;
|
||||
case 0x18C2: return 0x55;
|
||||
case 0x18C3: return 0x00;
|
||||
case 0x18C5: return 0xAA;
|
||||
case 0x18C6: return 0x55;
|
||||
case 0x18C7: return 0x03;
|
||||
// These are some retarded version check
|
||||
case 0x18C1: return 0xAA;
|
||||
case 0x18C2: return 0x55;
|
||||
case 0x18C3: return 0x00;
|
||||
case 0x18C5: return 0xAA;
|
||||
case 0x18C6: return 0x55;
|
||||
case 0x18C7: return 0x03;
|
||||
|
||||
// Arcade Card ports
|
||||
case 0x1AE0: return ArcadeCard ? (byte) (ShiftRegister >> 0) : (byte) 0xFF;
|
||||
case 0x1AE1: return ArcadeCard ? (byte) (ShiftRegister >> 8) : (byte) 0xFF;
|
||||
case 0x1AE2: return ArcadeCard ? (byte) (ShiftRegister >> 16) : (byte) 0xFF;
|
||||
case 0x1AE3: return ArcadeCard ? (byte) (ShiftRegister >> 24) : (byte) 0xFF;
|
||||
case 0x1AE4: return ArcadeCard ? ShiftAmount : (byte) 0xFF;
|
||||
case 0x1AE5: return ArcadeCard ? RotateAmount : (byte) 0xFF;
|
||||
// Arcade Card ports
|
||||
case 0x1AE0: return ArcadeCard ? (byte)(ShiftRegister >> 0) : (byte)0xFF;
|
||||
case 0x1AE1: return ArcadeCard ? (byte)(ShiftRegister >> 8) : (byte)0xFF;
|
||||
case 0x1AE2: return ArcadeCard ? (byte)(ShiftRegister >> 16) : (byte)0xFF;
|
||||
case 0x1AE3: return ArcadeCard ? (byte)(ShiftRegister >> 24) : (byte)0xFF;
|
||||
case 0x1AE4: return ArcadeCard ? ShiftAmount : (byte)0xFF;
|
||||
case 0x1AE5: return ArcadeCard ? RotateAmount : (byte)0xFF;
|
||||
|
||||
case 0x1AFE: return ArcadeCard ? (byte) 0x10 : (byte) 0xFF;
|
||||
case 0x1AFF: return ArcadeCard ? (byte) 0x51 : (byte) 0xFF;
|
||||
case 0x1AFE: return ArcadeCard ? (byte)0x10 : (byte)0xFF;
|
||||
case 0x1AFF: return ArcadeCard ? (byte)0x51 : (byte)0xFF;
|
||||
|
||||
default:
|
||||
if (addr >= 0x1FFA00 && addr < 0x1FFA40)
|
||||
return ReadArcadeCard(addr & 0x1FFF);
|
||||
else
|
||||
Log.Error("CD", "unknown read to {0:X4}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
default:
|
||||
if (addr >= 0x1FFA00 && addr < 0x1FFA40)
|
||||
return ReadArcadeCard(addr & 0x1FFF);
|
||||
else
|
||||
Log.Error("CD", "unknown read to {0:X4}", addr);
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshIRQ2()
|
||||
{
|
||||
int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C;
|
||||
Cpu.IRQ2Assert = (mask != 0);
|
||||
}
|
||||
}
|
||||
public void RefreshIRQ2()
|
||||
{
|
||||
int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C;
|
||||
Cpu.IRQ2Assert = (mask != 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,111 +1,112 @@
|
|||
using System;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Sega
|
||||
{
|
||||
public partial class GenVDP
|
||||
{
|
||||
// TODO: make this a requirement of constructor?
|
||||
public Func<int, short> DmaReadFrom68000; // TODO make ushort
|
||||
public partial class GenVDP
|
||||
{
|
||||
// TODO: make this a requirement of constructor?
|
||||
public Func<int, short> DmaReadFrom68000; // TODO make ushort
|
||||
|
||||
public int DmaLength { get { return Registers[19] | (Registers[20] << 8); } }
|
||||
public int DmaMode { get { return (Registers[23] >> 6) & 3; } }
|
||||
public int DmaLength { get { return Registers[19] | (Registers[20] << 8); } }
|
||||
public int DmaMode { get { return (Registers[23] >> 6) & 3; } }
|
||||
|
||||
public int DmaSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((Registers[23] & 0x80) == 0) // 68000 -> VRAM copy mode
|
||||
return ((Registers[21] << 1) | (Registers[22] << 9) | (Registers[23] << 17)) & 0xFFFFFE;
|
||||
|
||||
// Else VRAM/VRAM copy mode
|
||||
return (Registers[21] | (Registers[22] << 8)) & 0xFFFFFE;
|
||||
}
|
||||
}
|
||||
public int DmaSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((Registers[23] & 0x80) == 0) // 68000 -> VRAM copy mode
|
||||
return ((Registers[21] << 1) | (Registers[22] << 9) | (Registers[23] << 17)) & 0xFFFFFE;
|
||||
|
||||
bool DmaFillModePending;
|
||||
// Else VRAM/VRAM copy mode
|
||||
return (Registers[21] | (Registers[22] << 8)) & 0xFFFFFE;
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteVramFill(ushort data)
|
||||
{
|
||||
if (data != 0)
|
||||
Console.WriteLine("fill word is not zero {0:X4}", data);
|
||||
bool DmaFillModePending;
|
||||
|
||||
Log.Note("VDP", "DMA FILL REQD, WRITE {0:X4}, {1:X4} times, at {2:X4}", data, DmaLength, VdpDataAddr);
|
||||
void ExecuteVramFill(ushort data)
|
||||
{
|
||||
if (data != 0)
|
||||
Console.WriteLine("fill word is not zero {0:X4}", data);
|
||||
|
||||
// TODO: It should spread this out, not do it all at once.
|
||||
Log.Note("VDP", "DMA FILL REQD, WRITE {0:X4}, {1:X4} times, at {2:X4}", data, DmaLength, VdpDataAddr);
|
||||
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
// TODO: It should spread this out, not do it all at once.
|
||||
|
||||
byte fillByte = (byte)(data >> 8);
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
|
||||
do
|
||||
{
|
||||
VRAM[VdpDataAddr] = fillByte;
|
||||
Log.Note("VDP", "VRAM DMA FILL Write: [{0:X4}] = {1:X2}", VdpDataAddr, fillByte);
|
||||
UpdatePatternBuffer(VdpDataAddr);
|
||||
VdpDataAddr += Registers[15];
|
||||
} while (--length > 0);
|
||||
byte fillByte = (byte)(data >> 8);
|
||||
|
||||
// TOOD: test if the length register updated? One would assume so...
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
do
|
||||
{
|
||||
VRAM[VdpDataAddr] = fillByte;
|
||||
Log.Note("VDP", "VRAM DMA FILL Write: [{0:X4}] = {1:X2}", VdpDataAddr, fillByte);
|
||||
UpdatePatternBuffer(VdpDataAddr);
|
||||
VdpDataAddr += Registers[15];
|
||||
} while (--length > 0);
|
||||
|
||||
// TODO: Source registers should be incremented also (even for Fill)
|
||||
// TOOD: test if the length register updated? One would assume so...
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
|
||||
DmaFillModePending = false;
|
||||
}
|
||||
// TODO: Source registers should be incremented also (even for Fill)
|
||||
|
||||
void Execute68000VramCopy()
|
||||
{
|
||||
Log.Note("VDP", "DMA 68000 -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
||||
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
DmaFillModePending = false;
|
||||
}
|
||||
|
||||
int source = DmaSource;
|
||||
void Execute68000VramCopy()
|
||||
{
|
||||
Log.Note("VDP", "DMA 68000 -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
||||
|
||||
do
|
||||
{
|
||||
ushort value = (ushort) DmaReadFrom68000(source);
|
||||
source += 2;
|
||||
// TODO funky source behavior
|
||||
WriteVdpData(value);
|
||||
} while (--length > 0);
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
int source = DmaSource;
|
||||
|
||||
// TODO: update DMA source registers.
|
||||
// TODO: find correct number of 68k cycles to burn
|
||||
}
|
||||
do
|
||||
{
|
||||
ushort value = (ushort)DmaReadFrom68000(source);
|
||||
source += 2;
|
||||
// TODO funky source behavior
|
||||
WriteVdpData(value);
|
||||
} while (--length > 0);
|
||||
|
||||
void ExecuteVramVramCopy()
|
||||
{
|
||||
Log.Note("VDP", "DMA VRAM -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
// TODO: update DMA source registers.
|
||||
// TODO: find correct number of 68k cycles to burn
|
||||
}
|
||||
|
||||
int source = DmaSource;
|
||||
void ExecuteVramVramCopy()
|
||||
{
|
||||
Log.Note("VDP", "DMA VRAM -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
||||
|
||||
do
|
||||
{
|
||||
byte data = VRAM[source];
|
||||
VRAM[VdpDataAddr] = data;
|
||||
UpdatePatternBuffer(VdpDataAddr);
|
||||
Log.Note("VDP", "VRAM/VRAM Copy VRAM[{0:X4}] = {1:X2}", VdpDataAddr, data);
|
||||
source = (source + 1) & 0xFFFF;
|
||||
VdpDataAddr += Registers[0xF];
|
||||
} while (--length > 0);
|
||||
int length = DmaLength;
|
||||
if (length == 0)
|
||||
length = 0x10000;
|
||||
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
int source = DmaSource;
|
||||
|
||||
// TODO: length, source registers should be updated....
|
||||
// TODO: find correct number of 68k cycles to burn
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
byte data = VRAM[source];
|
||||
VRAM[VdpDataAddr] = data;
|
||||
UpdatePatternBuffer(VdpDataAddr);
|
||||
Log.Note("VDP", "VRAM/VRAM Copy VRAM[{0:X4}] = {1:X2}", VdpDataAddr, data);
|
||||
source = (source + 1) & 0xFFFF;
|
||||
VdpDataAddr += Registers[0xF];
|
||||
} while (--length > 0);
|
||||
|
||||
Registers[19] = 0;
|
||||
Registers[20] = 0;
|
||||
|
||||
// TODO: length, source registers should be updated....
|
||||
// TODO: find correct number of 68k cycles to burn
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,128 +1,132 @@
|
|||
namespace BizHawk.Emulation.Consoles.Sega
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Sega
|
||||
{
|
||||
partial class Genesis
|
||||
{
|
||||
bool SegaCD = false;
|
||||
partial class Genesis
|
||||
{
|
||||
bool SegaCD = false;
|
||||
|
||||
class IOPort
|
||||
{
|
||||
public byte Data;
|
||||
public byte Control;
|
||||
public byte TxData;
|
||||
public byte RxData;
|
||||
public byte SCtrl;
|
||||
// TODO- a reference to connected device? That gets into the issue of configuring different types of controllers. :|
|
||||
class IOPort
|
||||
{
|
||||
public byte Data;
|
||||
public byte Control;
|
||||
public byte TxData;
|
||||
public byte RxData;
|
||||
public byte SCtrl;
|
||||
// TODO- a reference to connected device? That gets into the issue of configuring different types of controllers. :|
|
||||
|
||||
public bool TH { get { return (Data & 0x40) != 0; } }
|
||||
}
|
||||
public bool TH { get { return (Data & 0x40) != 0; } }
|
||||
}
|
||||
|
||||
IOPort[] IOPorts = new IOPort[]
|
||||
{
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF }
|
||||
};
|
||||
IOPort[] IOPorts = new IOPort[]
|
||||
{
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
||||
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF }
|
||||
};
|
||||
|
||||
byte ReadIO(int offset)
|
||||
{
|
||||
offset >>= 1;
|
||||
offset &= 0x0F;
|
||||
if (offset > 1)
|
||||
Log.Note("CPU", "^^^ IO Read {0}: 00", offset);
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // version
|
||||
byte value = (byte) (SegaCD ? 0x00 : 0x20);
|
||||
switch((char)RomData[0x01F0])
|
||||
{
|
||||
case 'J': value |= 0x00; break;
|
||||
case 'U': value |= 0x80; break;
|
||||
case 'E': value |= 0xC0; break;
|
||||
case 'A': value |= 0xC0; break;
|
||||
case '4': value |= 0x80; break;
|
||||
default: value |= 0x80; break;
|
||||
}
|
||||
//value |= 1; // US
|
||||
Log.Note("CPU", "^^^ IO Read 0: {0:X2}", value);
|
||||
return value;
|
||||
case 1: // Port A
|
||||
byte ReadIO(int offset)
|
||||
{
|
||||
offset >>= 1;
|
||||
offset &= 0x0F;
|
||||
if (offset > 1)
|
||||
Log.Note("CPU", "^^^ IO Read {0}: 00", offset);
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // version
|
||||
byte value = (byte)(SegaCD ? 0x00 : 0x20);
|
||||
switch ((char)RomData[0x01F0])
|
||||
{
|
||||
case 'J': value |= 0x00; break;
|
||||
case 'U': value |= 0x80; break;
|
||||
case 'E': value |= 0xC0; break;
|
||||
case 'A': value |= 0xC0; break;
|
||||
case '4': value |= 0x80; break;
|
||||
default: value |= 0x80; break;
|
||||
}
|
||||
//value |= 1; // US
|
||||
Log.Note("CPU", "^^^ IO Read 0: {0:X2}", value);
|
||||
return value;
|
||||
case 1: // Port A
|
||||
lagged = false;
|
||||
ReadController(ref IOPorts[0].Data);
|
||||
Log.Note("CPU", "^^^ IO Read 1: {0:X2}", IOPorts[0].Data);
|
||||
return IOPorts[0].Data;
|
||||
case 2: return 0xFF;
|
||||
case 3: return 0xFF;
|
||||
ReadController(ref IOPorts[0].Data);
|
||||
Log.Note("CPU", "^^^ IO Read 1: {0:X2}", IOPorts[0].Data);
|
||||
return IOPorts[0].Data;
|
||||
case 2: return 0xFF;
|
||||
case 3: return 0xFF;
|
||||
|
||||
case 0x04: return IOPorts[0].Control;
|
||||
case 0x05: return IOPorts[1].Control;
|
||||
case 0x06: return IOPorts[2].Control;
|
||||
case 0x04: return IOPorts[0].Control;
|
||||
case 0x05: return IOPorts[1].Control;
|
||||
case 0x06: return IOPorts[2].Control;
|
||||
|
||||
case 0x07: return IOPorts[0].TxData;
|
||||
case 0x08: return IOPorts[0].RxData;
|
||||
case 0x09: return IOPorts[0].SCtrl;
|
||||
case 0x07: return IOPorts[0].TxData;
|
||||
case 0x08: return IOPorts[0].RxData;
|
||||
case 0x09: return IOPorts[0].SCtrl;
|
||||
|
||||
case 0x0A: return IOPorts[1].TxData;
|
||||
case 0x0B: return IOPorts[1].RxData;
|
||||
case 0x0C: return IOPorts[1].SCtrl;
|
||||
case 0x0A: return IOPorts[1].TxData;
|
||||
case 0x0B: return IOPorts[1].RxData;
|
||||
case 0x0C: return IOPorts[1].SCtrl;
|
||||
|
||||
case 0x0D: return IOPorts[2].TxData;
|
||||
case 0x0E: return IOPorts[2].RxData;
|
||||
case 0x0F: return IOPorts[2].SCtrl;
|
||||
}
|
||||
Log.Note("CPU", "^^^ IO Read {0}: {1:X2}", offset, 0xFF);
|
||||
return 0xFF;
|
||||
}
|
||||
case 0x0D: return IOPorts[2].TxData;
|
||||
case 0x0E: return IOPorts[2].RxData;
|
||||
case 0x0F: return IOPorts[2].SCtrl;
|
||||
}
|
||||
Log.Note("CPU", "^^^ IO Read {0}: {1:X2}", offset, 0xFF);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void WriteIO(int offset, int value)
|
||||
{
|
||||
offset >>= 1;
|
||||
offset &= 0x0F;
|
||||
void WriteIO(int offset, int value)
|
||||
{
|
||||
offset >>= 1;
|
||||
offset &= 0x0F;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: break;
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: break;
|
||||
|
||||
case 0x01: IOPorts[0].Data = (byte) value; break;
|
||||
case 0x02: IOPorts[1].Data = (byte) value; break;
|
||||
case 0x03: IOPorts[2].Data = (byte) value; break;
|
||||
case 0x01: IOPorts[0].Data = (byte)value; break;
|
||||
case 0x02: IOPorts[1].Data = (byte)value; break;
|
||||
case 0x03: IOPorts[2].Data = (byte)value; break;
|
||||
|
||||
case 0x04: IOPorts[0].Control = (byte) value; break;
|
||||
case 0x05: IOPorts[1].Control = (byte) value; break;
|
||||
case 0x06: IOPorts[2].Control = (byte) value; break;
|
||||
case 0x04: IOPorts[0].Control = (byte)value; break;
|
||||
case 0x05: IOPorts[1].Control = (byte)value; break;
|
||||
case 0x06: IOPorts[2].Control = (byte)value; break;
|
||||
|
||||
case 0x07: IOPorts[0].TxData = (byte) value; break;
|
||||
case 0x08: IOPorts[0].RxData = (byte) value; break;
|
||||
case 0x09: IOPorts[0].SCtrl = (byte) value; break;
|
||||
case 0x07: IOPorts[0].TxData = (byte)value; break;
|
||||
case 0x08: IOPorts[0].RxData = (byte)value; break;
|
||||
case 0x09: IOPorts[0].SCtrl = (byte)value; break;
|
||||
|
||||
case 0x0A: IOPorts[1].TxData = (byte) value; break;
|
||||
case 0x0B: IOPorts[1].RxData = (byte) value; break;
|
||||
case 0x0C: IOPorts[1].SCtrl = (byte) value; break;
|
||||
case 0x0A: IOPorts[1].TxData = (byte)value; break;
|
||||
case 0x0B: IOPorts[1].RxData = (byte)value; break;
|
||||
case 0x0C: IOPorts[1].SCtrl = (byte)value; break;
|
||||
|
||||
case 0x0D: IOPorts[2].TxData = (byte) value; break;
|
||||
case 0x0E: IOPorts[2].RxData = (byte) value; break;
|
||||
case 0x0F: IOPorts[2].SCtrl = (byte) value; break;
|
||||
}
|
||||
}
|
||||
case 0x0D: IOPorts[2].TxData = (byte)value; break;
|
||||
case 0x0E: IOPorts[2].RxData = (byte)value; break;
|
||||
case 0x0F: IOPorts[2].SCtrl = (byte)value; break;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadController(ref byte data)
|
||||
{
|
||||
void ReadController(ref byte data)
|
||||
{
|
||||
if (CoreComm.InputCallback != null) CoreComm.InputCallback();
|
||||
data &= 0xC0;
|
||||
if ((data & 0x40) != 0) // TH high
|
||||
{
|
||||
if (Controller["P1 Up"] == false) data |= 0x01;
|
||||
if (Controller["P1 Down"] == false) data |= 0x02;
|
||||
if (Controller["P1 Left"] == false) data |= 0x04;
|
||||
if (Controller["P1 Right"] == false) data |= 0x08;
|
||||
if (Controller["P1 B"] == false) data |= 0x10;
|
||||
if (Controller["P1 C"] == false) data |= 0x20;
|
||||
} else { // TH low
|
||||
if (Controller["P1 Up"] == false) data |= 0x01;
|
||||
if (Controller["P1 Down"] == false) data |= 0x02;
|
||||
if (Controller["P1 A"] == false) data |= 0x10;
|
||||
if (Controller["P1 Start"] == false) data |= 0x20;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ((data & 0x40) != 0) // TH high
|
||||
{
|
||||
if (Controller["P1 Up"] == false) data |= 0x01;
|
||||
if (Controller["P1 Down"] == false) data |= 0x02;
|
||||
if (Controller["P1 Left"] == false) data |= 0x04;
|
||||
if (Controller["P1 Right"] == false) data |= 0x08;
|
||||
if (Controller["P1 B"] == false) data |= 0x10;
|
||||
if (Controller["P1 C"] == false) data |= 0x20;
|
||||
}
|
||||
else
|
||||
{ // TH low
|
||||
if (Controller["P1 Up"] == false) data |= 0x01;
|
||||
if (Controller["P1 Down"] == false) data |= 0x02;
|
||||
if (Controller["P1 A"] == false) data |= 0x10;
|
||||
if (Controller["P1 Start"] == false) data |= 0x20;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,19 +35,19 @@ namespace BizHawk
|
|||
|
||||
Dictionary<string, string> Options = new Dictionary<string, string>();
|
||||
|
||||
public GameInfo() { }
|
||||
public GameInfo() { }
|
||||
|
||||
public static GameInfo GetNullGame()
|
||||
{
|
||||
return new GameInfo()
|
||||
{
|
||||
Name = "Null",
|
||||
System = "NULL",
|
||||
Hash = "",
|
||||
Status = RomStatus.GoodDump,
|
||||
NotInDatabase = false
|
||||
};
|
||||
}
|
||||
public static GameInfo GetNullGame()
|
||||
{
|
||||
return new GameInfo()
|
||||
{
|
||||
Name = "Null",
|
||||
System = "NULL",
|
||||
Hash = "",
|
||||
Status = RomStatus.GoodDump,
|
||||
NotInDatabase = false
|
||||
};
|
||||
}
|
||||
|
||||
internal GameInfo(CompactGameInfo cgi)
|
||||
{
|
||||
|
@ -91,15 +91,15 @@ namespace BizHawk
|
|||
return null;
|
||||
}
|
||||
|
||||
public int GetIntValue(string option)
|
||||
{
|
||||
return int.Parse(Options[option]);
|
||||
}
|
||||
public int GetIntValue(string option)
|
||||
{
|
||||
return int.Parse(Options[option]);
|
||||
}
|
||||
|
||||
public int GetHexValue(string option)
|
||||
{
|
||||
return int.Parse(Options[option], NumberStyles.HexNumber);
|
||||
}
|
||||
public int GetHexValue(string option)
|
||||
{
|
||||
return int.Parse(Options[option], NumberStyles.HexNumber);
|
||||
}
|
||||
|
||||
/// <param name="parameter">The option to look up</param>
|
||||
/// <param name="defaultVal">The value to return if the option is invalid or doesn't exist</param>
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
static Log()
|
||||
{
|
||||
// You can set current desired logging settings here.
|
||||
// Production builds should be done with all logging disabled.
|
||||
LogToConsole = true;
|
||||
//LogToFile = true;
|
||||
//LogFilename = "d:/bizhawk.log";
|
||||
//EnableDomain("CD");
|
||||
//EnableDomain("CPU");
|
||||
//EnableDomain("VDC");
|
||||
//EnableDomain("MEM");
|
||||
}
|
||||
|
||||
// ============== Logging Domain Configuration ==============
|
||||
|
||||
private static List<string> EnabledLogDomains = new List<string>();
|
||||
|
||||
public static void EnableDomain(string domain)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain) == false)
|
||||
EnabledLogDomains.Add(domain);
|
||||
}
|
||||
|
||||
public static void DisableDomain(string domain)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain))
|
||||
EnabledLogDomains.Remove(domain);
|
||||
}
|
||||
|
||||
// ============== Logging Action Configuration ==============
|
||||
|
||||
public static Action<string> LogAction = DefaultLogger;
|
||||
|
||||
// NOTEs are only logged if the domain is enabled.
|
||||
// ERRORs are logged regardless.
|
||||
|
||||
public static void Note(string domain, string msg, params object[] vals)
|
||||
{
|
||||
if (EnabledLogDomains.Contains(domain))
|
||||
LogAction(String.Format(msg, vals));
|
||||
}
|
||||
|
||||
public static void Error(string domain, string msg, params object[] vals)
|
||||
{
|
||||
LogAction(String.Format(msg, vals));
|
||||
}
|
||||
|
||||
// ============== Default Logger Action ==============
|
||||
|
||||
public static Stream HACK_LOG_STREAM;
|
||||
|
||||
private static bool LogToConsole = false;
|
||||
private static bool LogToFile = false;
|
||||
|
||||
private static string LogFilename = "bizhawk.txt";
|
||||
private static StreamWriter writer;
|
||||
|
||||
private static void DefaultLogger(string message)
|
||||
{
|
||||
if (LogToConsole)
|
||||
Console.WriteLine(message);
|
||||
|
||||
if (LogToFile && writer == null)
|
||||
writer = new StreamWriter(LogFilename);
|
||||
|
||||
if (LogToFile)
|
||||
{
|
||||
writer.WriteLine(message);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue