move Log.cs from BizHawk.Emulation to BizHawk.Common

This commit is contained in:
adelikat 2013-11-04 00:45:23 +00:00
parent 7f3f116cd9
commit 4f5d8b89c9
14 changed files with 828 additions and 811 deletions

View File

@ -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

View File

@ -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" />

81
BizHawk.Common/Log.cs Normal file
View File

@ -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();
}
}
}
}

View File

@ -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" />

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -1,4 +1,6 @@
namespace BizHawk.Emulation.Consoles.TurboGrafx
using BizHawk.Common;
namespace BizHawk.Emulation.Consoles.TurboGrafx
{
public partial class PCEngine
{

View File

@ -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);
}
}
}

View File

@ -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
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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>

View File

@ -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();
}
}
}
}