Fix PCE Populous by supporting its custom SaveRAM.
+ Unsubstantial TurboCD progress.
This commit is contained in:
parent
4b892cdfea
commit
3f27ac0b2a
|
@ -112,6 +112,8 @@
|
|||
<Compile Include="Consoles\Nintendo\NES\PPU.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\PPU.regs.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\PPU.run.cs" />
|
||||
<Compile Include="Consoles\PC Engine\MemoryMap.Populous.cs" />
|
||||
<Compile Include="Consoles\PC Engine\ScsiCD.cs" />
|
||||
<Compile Include="Consoles\PC Engine\TurboCD.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\MemoryMap.CodeMasters.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\MemoryMap.Sega.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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
==============================================================================
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue