diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index 4c85a02848..0703028e19 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -112,6 +112,8 @@
+
+
diff --git a/BizHawk.Emulation/CPUs/HuC6280/Execute.cs b/BizHawk.Emulation/CPUs/HuC6280/Execute.cs
index a314c04818..8f81b4f7d2 100644
--- a/BizHawk.Emulation/CPUs/HuC6280/Execute.cs
+++ b/BizHawk.Emulation/CPUs/HuC6280/Execute.cs
@@ -44,14 +44,37 @@ namespace BizHawk.Emulation.CPUs.H6280
PendingCycles -= 8;
}
+ if (IRQ2Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ2Selector) == 0)
+ {
+ Console.WriteLine("ENTERING IRQ2 INTERRUPT");
+ WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));
+ WriteMemory((ushort)(S-- + 0x2100), (byte)PC);
+ WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));
+ FlagD = false;
+ FlagI = true;
+ PC = ReadWord(IRQ2Vector);
+ PendingCycles -= 8;
+ }
+
IRQControlByte = IRQNextControlByte;
LagIFlag = FlagI;
+ //Console.WriteLine(State());
byte opcode = ReadMemory(PC++);
switch (opcode)
{
case 0x00: // BRK
-throw new Exception("break");
+ Console.WriteLine("EXEC BRK"); // TODO CpuCoreGenerator needs updated, but I dont even know if this works yet
+ PC++;
+ WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));
+ WriteMemory((ushort)(S-- + 0x2100), (byte)PC);
+ WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));
+ FlagT = false;
+ FlagB = true;
+ FlagD = false;
+ FlagI = true;
+ PC = ReadWord(IRQ2Vector);
+ PendingCycles -= 8;
break;
case 0x01: // ORA (addr,X)
value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000)));
diff --git a/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs b/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs
index 47b54ab6af..aa8570d994 100644
--- a/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs
+++ b/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs
@@ -43,6 +43,7 @@ namespace BizHawk.Emulation.CPUs.H6280
public bool LagIFlag;
public bool IRQ1Assert;
+ public bool IRQ2Assert;
public bool TimerAssert;
public byte IRQControlByte, IRQNextControlByte;
@@ -191,9 +192,6 @@ namespace BizHawk.Emulation.CPUs.H6280
public void WriteIrqControl(byte value)
{
// There is a single-instruction delay before writes to the IRQ Control Byte take effect.
- // After Burner requires this to function, as it ACKs the timer interrupt AFTER un-masking
- // the interrupt.
-
value &= 7;
IRQNextControlByte = value;
}
@@ -206,7 +204,7 @@ namespace BizHawk.Emulation.CPUs.H6280
public byte ReadIrqStatus()
{
byte status = 0;
- //if (IRQ2Assert) status |= 1;
+ if (IRQ2Assert) status |= 1;
if (IRQ1Assert) status |= 2;
if (TimerAssert) status |= 4;
return status;
@@ -232,6 +230,8 @@ namespace BizHawk.Emulation.CPUs.H6280
{
if (TimerTickCounter + 5 > 1024)
{
+ // There exists a slight delay between when the timer counter is decremented and when
+ // the interrupt fires; games can detect it, so we hack it this way.
return (byte) ((TimerValue - 1) & 0x7F);
}
return TimerValue;
diff --git a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
index d3a2dd75d7..d5550b6453 100644
--- a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
+++ b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using BizHawk.Emulation.CPUs.H6280;
using BizHawk.Emulation.Sound;
+using BizHawk.Disc;
namespace BizHawk.Emulation.Consoles.TurboGrafx
{
@@ -40,6 +41,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// Memory system
public byte[] Ram;
+ // Disc
+ //private Disc.Disc disc = Disc.Disc.FromCuePath("d:/lib/roms/Turbo CD/Cosmic Fantasy II/Cosmic Fantasy II [U][CD][WTG990301][Telenet Japan][1992][PCE][thx-1138-darkwater].cue");
+
// PC Engine timings:
// 21,477,270 Machine clocks / sec
// 7,159,090 Cpu cycles / sec
@@ -109,6 +113,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
}
+ if (game.GetOptions().Contains("PopulousSRAM"))
+ {
+ PopulousRAM = new byte[0x8000];
+ Cpu.ReadMemory21 = ReadMemoryPopulous;
+ Cpu.WriteMemory21 = WriteMemoryPopulous;
+ }
+
Cpu.ResetPC();
SetupMemoryDomains();
}
@@ -171,6 +182,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.WriteLine("[PCEngine]");
writer.Write("RAM ");
Ram.SaveAsHex(writer);
+ if (PopulousRAM != null)
+ {
+ writer.Write("PopulousRAM ");
+ PopulousRAM.SaveAsHex(writer);
+ }
writer.WriteLine("Frame " + Frame);
writer.WriteLine("Lag " + _lagcount);
if (Cpu.ReadMemory21 == ReadMemorySF2)
@@ -215,6 +231,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
IOBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "RAM")
Ram.ReadFromHex(args[1]);
+ else if (args[0] == "PopulousRAM" && PopulousRAM != null)
+ PopulousRAM.ReadFromHex(args[1]);
else if (args[0] == "[HuC6280]")
Cpu.LoadStateText(reader);
else if (args[0] == "[PSG]")
@@ -237,8 +255,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (SuperGrafx == false)
{
writer.Write(Ram);
+ if (PopulousRAM != null)
+ writer.Write(PopulousRAM);
writer.Write(Frame);
-// writer.Write(_lagcount); //TODO: why does this fail?
+ writer.Write(_lagcount);
writer.Write(SF2MapperLatch);
writer.Write(IOBuffer);
Cpu.SaveStateBinary(writer);
@@ -248,7 +268,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} else {
writer.Write(Ram);
writer.Write(Frame);
-// writer.Write(_lagcount);
+ writer.Write(_lagcount);
writer.Write(IOBuffer);
Cpu.SaveStateBinary(writer);
VCE.SaveStateBinary(writer);
@@ -264,8 +284,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (SuperGrafx == false)
{
Ram = reader.ReadBytes(0x2000);
+ if (PopulousRAM != null)
+ PopulousRAM = reader.ReadBytes(0x8000);
Frame = reader.ReadInt32();
-// _lagcount = reader.ReadInt32();
+ _lagcount = reader.ReadInt32();
SF2MapperLatch = reader.ReadByte();
IOBuffer = reader.ReadByte();
Cpu.LoadStateBinary(reader);
@@ -275,7 +297,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} else {
Ram = reader.ReadBytes(0x8000);
Frame = reader.ReadInt32();
-// _lagcount = reader.ReadInt32();
+ _lagcount = reader.ReadInt32();
IOBuffer = reader.ReadByte();
Cpu.LoadStateBinary(reader);
VCE.LoadStateBinary(reader);
@@ -288,8 +310,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public byte[] SaveStateBinary()
{
- int buflen = SuperGrafx ? 166552 : 75854;
+ int buflen = SuperGrafx ? 166556 : 75858;
if (BramEnabled) buflen += 2048;
+ if (PopulousRAM != null) buflen += 0x8000;
var buf = new byte[buflen];
var stream = new MemoryStream(buf);
diff --git a/BizHawk.Emulation/Consoles/PC Engine/ScsiCD.cs b/BizHawk.Emulation/Consoles/PC Engine/ScsiCD.cs
new file mode 100644
index 0000000000..bc16e2888d
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/PC Engine/ScsiCD.cs
@@ -0,0 +1,192 @@
+using System;
+
+namespace BizHawk.Emulation
+{
+ public sealed class ScsiCD
+ {
+ private bool bsy, sel, cd, io, msg, req, ack, atn, rst;
+ private bool lagBSY, lagSEL, lagCD, lagIO, lagMSG, lagREQ, lagACK, lagATN, lagRST;
+
+ public bool BSY {
+ get { return bsy; }
+ set {
+ if (value != lagBSY) signalsChanged = true;
+ lagBSY = bsy;
+ bsy = value;
+ }
+ }
+ public bool SEL
+ {
+ get { return sel; }
+ set
+ {
+ if (value != lagSEL) signalsChanged = true;
+ lagSEL = sel;
+ sel = value;
+ }
+ }
+ public bool CD // false=data, true=control
+ {
+ get { return cd; }
+ set
+ {
+ if (value != lagCD) signalsChanged = true;
+ lagCD = cd;
+ cd = value;
+ }
+ }
+ public bool IO
+ {
+ get { return io; }
+ set
+ {
+ if (value != lagIO) signalsChanged = true;
+ lagIO = io;
+ io = value;
+ }
+ }
+ public bool MSG
+ {
+ get { return msg; }
+ set
+ {
+ if (value != lagMSG) signalsChanged = true;
+ lagMSG = msg;
+ msg = value;
+ }
+ }
+ public bool REQ
+ {
+ get { return req; }
+ set
+ {
+ if (value != lagREQ) signalsChanged = true;
+ lagREQ = req;
+ req = value;
+ }
+ }
+ public bool ACK
+ {
+ get { return ack; }
+ set
+ {
+ if (value != lagACK) signalsChanged = true;
+ lagACK = ack;
+ ack = value;
+ }
+ }
+ public bool ATN
+ {
+ get { return atn; }
+ set
+ {
+ if (value != lagATN) signalsChanged = true;
+ lagATN = atn;
+ atn = value;
+ }
+ }
+ public bool RST
+ {
+ get { return rst; }
+ set
+ {
+ if (value != lagRST) signalsChanged = true;
+ lagRST = rst;
+ rst = value;
+ }
+ }
+ public byte DB { get; set; } // data bits
+
+ private bool signalsChanged;
+ private bool driveSelected;
+
+ public void Think()
+ {
+ if (BSY == false && SEL == false)
+ {
+ Console.WriteLine("BUS FREE!");
+ // zap the rest of the signals
+ CD = false;
+ IO = false;
+ MSG = false;
+ REQ = false;
+ ACK = false;
+ ATN = false;
+ DB = 0;
+ }
+
+ if (SEL && lagSEL == false)
+ {
+ driveSelected = true;
+ CD = true;
+ BSY = true;
+ MSG = false;
+ IO = false;
+ REQ = true;
+ }
+
+ if (RST && lagRST == false)
+ {
+ // reset buffers and CDDA and stuff.
+ CD = false;
+ IO = false;
+ MSG = false;
+ REQ = false;
+ ACK = false;
+ ATN = false;
+ DB = 0;
+ }
+ }
+
+ /* SCSI BUS SIGNALS
+
+ BSY (BUSY). An "OR-tied" signal that indicates that the bus is being used.
+
+ SEL (SELECT). A signal used by an initiator to select a target or by a target
+ to reselect an initiator.
+
+ C/D (CONTROL/DATA). A signal driven by a target that indicates whether
+ CONTROL or DATA information is on the DATA BUS. True indicates CONTROL.
+
+ I/O (INPUT/OUTPUT). A signal driven by a target that controls the direction
+ of data movement on the DATA BUS with respect to an initiator. True indicates
+ input to the initiator. This signal is also used to distinguish between
+ SELECTION and RESELECTION phases.
+
+ MSG (MESSAGE). A signal driven by a target during the MESSAGE phase.
+
+ REQ (REQUEST). A signal driven by a target to indicate a request for a
+ REQ/ACK data transfer handshake.
+
+ ACK (ACKNOWLEDGE). A signal driven by an initiator to indicate an
+ acknowledgment for a REQ/ACK data transfer handshake.
+
+ ATN (ATTENTION). A signal driven by an initiator to indicate the ATTENTION
+ condition.
+
+ RST (RESET). An "OR-tied" signal that indicates the RESET condition.
+
+ Plus 8 data bits (DB7-0) and parity (P).
+
+ ==============================================================================
+ Signals
+ ----------------------------------------------------------
+ C/D, I/O,
+ Bus Phase BSY SEL MSG, REQ ACK/ATN DB(7-0,P)
+ ------------------------------------------------------------------------------
+ BUS FREE None None None None None
+ ARBITRATION All Winner None None SCSI ID
+ SELECTION I&T Initiator None Initiator Initiator
+ RESELECTION I&T Target Target Initiator Target
+ COMMAND Target None Target Initiator Initiator
+ DATA IN Target None Target Initiator Target
+ DATA OUT Target None Target Initiator Initiator
+ STATUS Target None Target Initiator Target
+ MESSAGE IN Target None Target Initiator Target
+ MESSAGE OUT Target None Target Initiator Initiator
+ ==============================================================================
+
+ */
+
+ }
+}
diff --git a/BizHawk.Emulation/Consoles/PC Engine/TurboCD.cs b/BizHawk.Emulation/Consoles/PC Engine/TurboCD.cs
index f9c562e823..a902c71c9b 100644
--- a/BizHawk.Emulation/Consoles/PC Engine/TurboCD.cs
+++ b/BizHawk.Emulation/Consoles/PC Engine/TurboCD.cs
@@ -5,17 +5,49 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public partial class PCEngine
{
private byte[] CdIoPorts = new byte[16];
+ private ScsiCD scsi = new ScsiCD();
private void WriteCD(int addr, byte value)
{
+ Console.WriteLine("Write to reg[{0:X4}] {1:X2}", addr&0x1FFF, value);
switch (addr & 0x1FFF)
{
- case 0x1802: // ADPCM / CD Control
+ case 0x1800: // SCSI Drive Control Line
+ CdIoPorts[0] = value;
+ // Console.WriteLine("Write to CDC Status [0] {0:X2}", value);
+
+ scsi.SEL = true;
+ scsi.Think();
+ scsi.SEL = false;
+ scsi.Think();
+
+ // this probably does some things
+ // possibly clear irq line or trigger or who knows
+ break;
+
+ case 0x1801: // CDC Command
+ CdIoPorts[1] = value;
+ scsi.DB = value;
+ scsi.Think();
+// Console.WriteLine("Write to CDC Command [1] {0:X2}", value);
+ break;
+
+ case 0x1802: // ACK and Interrupt Control
CdIoPorts[2] = value;
+ scsi.ACK = ((value & 0x80) != 0);
+ 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 0x1807: // BRAM Unlock
@@ -28,23 +60,23 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x180B: // ADPCM DMA Control
CdIoPorts[0x0B] = value;
- Console.WriteLine("Write to ADPCM DMA Control [B]");
+ // Console.WriteLine("Write to ADPCM DMA Control [B]");
// TODO... there is DMA to be done
break;
case 0x180D: // ADPCM Address Control
CdIoPorts[0x0D] = value;
- Console.WriteLine("Write to ADPCM Address Control [D]");
+ // Console.WriteLine("Write to ADPCM Address Control [D]");
break;
case 0x180E: // ADPCM Playback Rate
CdIoPorts[0x0E] = value;
- Console.WriteLine("Write to ADPCM Address Control [E]");
+ // Console.WriteLine("Write to ADPCM Address Control [E]");
break;
case 0x180F: // Audio Fade Timer
CdIoPorts[0x0F] = value;
- Console.WriteLine("Write to CD Audio fade timer [F]");
+// Console.WriteLine("Write to CD Audio fade timer [F]");
// TODO: hook this up to audio system);
break;
@@ -56,29 +88,58 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public byte ReadCD(int addr)
{
+ byte returnValue = 0;
switch (addr & 0x1FFF)
{
+ case 0x1800: // SCSI Drive Control Line
+ scsi.Think();
+ 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;
+ //if (returnValue != 0) returnValue = 0x40;
+ Console.WriteLine("Read SCSI Drive Control Line [0]: {0:X2} btw, pc={1:X4} ", returnValue,this.Cpu.PC);
+ return returnValue;
+
case 0x1802: // ADPCM / CD Control
+ Console.WriteLine("Read 1802 {0:X2}", CdIoPorts[2]);
return CdIoPorts[2];
case 0x1803: // BRAM Lock
if (BramEnabled)
{
- Console.WriteLine("LOCKED BRAM!");
+ Console.WriteLine("LOCKED BRAM! (read 1803)");
BramLocked = true;
}
return CdIoPorts[3];
case 0x1804: // CD Reset
+ Console.WriteLine("Read 1804 {0:X2}", CdIoPorts[4]);
return CdIoPorts[4];
case 0x180F: // Audio Fade Timer
+ Console.WriteLine("Read 180F {0:X2}", CdIoPorts[0xF]);
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;
+
default:
Console.WriteLine("unknown read to {0:X4}", addr);
return 0xFF;
}
}
+
+ private void RefreshIRQ2()
+ {
+ int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C;
+ Cpu.IRQ2Assert = (mask != 0);
+ }
}
}
diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt
index aeb2f4c38c..adaafdbeed 100644
--- a/BizHawk.MultiClient/output/gamedb.txt
+++ b/BizHawk.MultiClient/output/gamedb.txt
@@ -2174,7 +2174,7 @@ BB4429B6 Paranoia PCE
E6458212 Parasol Stars PCE
647718F9 Parodius PCE
740491C2 PC Denjin - Punkic Cyborgs PCE
-4938B8BB Populous PCE BRAM
+4938B8BB Populous PCE BRAM;PopulousSRAM
25E0F6E9 Power Drift PCE
BE8B6E3B Power Gate PCE
04A85769 Power League PCE