2011-06-19 01:37:09 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|
|
|
|
{
|
2011-08-14 18:20:13 +00:00
|
|
|
|
public partial class PCEngine
|
|
|
|
|
{
|
2011-09-05 17:45:01 +00:00
|
|
|
|
public static byte[] CdIoPorts = new byte[16];
|
2011-08-14 18:20:13 +00:00
|
|
|
|
|
2011-09-04 04:38:11 +00:00
|
|
|
|
public byte IRQ2Control { get { return CdIoPorts[2]; } set { CdIoPorts[2] = value; } }
|
|
|
|
|
public byte IRQ2Monitor { get { return CdIoPorts[3]; } set { CdIoPorts[3] = value; } }
|
|
|
|
|
|
2011-09-15 05:10:23 +00:00
|
|
|
|
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)); }
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 17:45:01 +00:00
|
|
|
|
public byte Port1803
|
|
|
|
|
{
|
|
|
|
|
get { return CdIoPorts[3]; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (value != CdIoPorts[3])
|
|
|
|
|
Console.WriteLine("UPDATE 1803: From {0:X2} to {1:X2}", CdIoPorts[3], value);
|
|
|
|
|
CdIoPorts[3] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-15 05:10:23 +00:00
|
|
|
|
void SetCDAudioCallback()
|
2011-08-14 18:20:13 +00:00
|
|
|
|
{
|
2011-09-15 05:10:23 +00:00
|
|
|
|
CDAudio.CallbackAction = () =>
|
2011-08-14 18:20:13 +00:00
|
|
|
|
{
|
2011-09-15 05:10:23 +00:00
|
|
|
|
Console.WriteLine("FIRING CD-AUDIO STOP IRQ MAYBE!");
|
|
|
|
|
IntDataTransferReady = false;
|
|
|
|
|
IntDataTransferComplete = true;
|
2011-08-14 18:20:13 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-04 04:38:11 +00:00
|
|
|
|
void WriteCD(int addr, byte value)
|
2011-08-14 18:20:13 +00:00
|
|
|
|
{
|
2011-08-29 02:47:03 +00:00
|
|
|
|
//Log.Error("CD","Write: {0:X4} {1:X2} (PC={2:X4})", addr & 0x1FFF, value, Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
switch (addr & 0x1FFF)
|
|
|
|
|
{
|
|
|
|
|
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.DataBits = 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);
|
|
|
|
|
|
2011-08-29 02:47:03 +00:00
|
|
|
|
if ((CdIoPorts[2] & 0x04) != 0) Log.Error("CD", "INTA enable");
|
|
|
|
|
if ((CdIoPorts[2] & 0x08) != 0) Log.Error("CD", "INTSTOP enable");
|
|
|
|
|
if ((CdIoPorts[2] & 0x10) != 0) Log.Error("CD", "INTSUB enable");
|
|
|
|
|
if ((CdIoPorts[2] & 0x20) != 0) Log.Error("CD", "INTM enable");
|
|
|
|
|
if ((CdIoPorts[2] & 0x40) != 0) Log.Error("CD", "INTD enable");
|
2011-09-05 17:45:01 +00:00
|
|
|
|
if ((Cpu.IRQControlByte & 0x01) == 0 &&
|
|
|
|
|
(CdIoPorts[2] & 0x7C) != 0) Log.Error("CD", "BTW, IRQ2 is not masked");
|
2011-08-14 18:20:13 +00:00
|
|
|
|
|
|
|
|
|
SCSI.Think();
|
|
|
|
|
RefreshIRQ2();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x1804: // CD Reset Command
|
|
|
|
|
CdIoPorts[4] = value;
|
|
|
|
|
SCSI.RST = ((value & 0x02) != 0);
|
|
|
|
|
SCSI.Think();
|
|
|
|
|
if (SCSI.RST)
|
|
|
|
|
{
|
2011-09-05 17:45:01 +00:00
|
|
|
|
Port1803 &= 0x8F; // Clear interrupt control bits
|
2011-08-14 18:20:13 +00:00
|
|
|
|
RefreshIRQ2();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x1805:
|
|
|
|
|
case 0x1806:
|
|
|
|
|
// Latch CDDA data... no action needed for us
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x1807: // BRAM Unlock
|
|
|
|
|
if (BramEnabled && (value & 0x80) != 0)
|
|
|
|
|
BramLocked = false;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-08-29 02:47:03 +00:00
|
|
|
|
case 0x1808: // ADPCM address LSB
|
2011-09-05 17:45:01 +00:00
|
|
|
|
ADPCM.IOAddress &= 0xFF00;
|
|
|
|
|
ADPCM.IOAddress |= value;
|
2011-08-31 04:06:54 +00:00
|
|
|
|
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("doing silly thing");
|
2011-09-05 17:45:01 +00:00
|
|
|
|
ADPCM.AdpcmLength = ADPCM.IOAddress;
|
2011-08-31 04:06:54 +00:00
|
|
|
|
}
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
2011-08-29 02:47:03 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x1809: // ADPCM address MSB
|
2011-09-05 17:45:01 +00:00
|
|
|
|
ADPCM.IOAddress &= 0x00FF;
|
|
|
|
|
ADPCM.IOAddress |= (ushort)(value << 8);
|
2011-08-31 04:06:54 +00:00
|
|
|
|
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("doing silly thing");
|
2011-09-05 17:45:01 +00:00
|
|
|
|
ADPCM.AdpcmLength = ADPCM.IOAddress;
|
2011-08-31 04:06:54 +00:00
|
|
|
|
}
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
2011-08-29 02:47:03 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x180A: // ADPCM Memory Read/Write Port
|
2011-09-04 04:38:11 +00:00
|
|
|
|
ADPCM.Port180A = value;
|
2011-08-29 02:47:03 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-08-14 18:20:13 +00:00
|
|
|
|
case 0x180B: // ADPCM DMA Control
|
2011-09-04 04:38:11 +00:00
|
|
|
|
ADPCM.Port180B = value;
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "Write to ADPCM DMA Control [B] {0:X2}", value);
|
2011-09-04 04:38:11 +00:00
|
|
|
|
if (ADPCM.AdpcmCdDmaRequested)
|
2011-08-30 04:02:52 +00:00
|
|
|
|
Console.WriteLine(" ADPCM DMA REQUESTED");
|
2011-08-14 18:20:13 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x180D: // ADPCM Address Control
|
2011-09-04 04:38:11 +00:00
|
|
|
|
ADPCM.AdpcmControlWrite(value);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x180E: // ADPCM Playback Rate
|
2011-09-04 04:38:11 +00:00
|
|
|
|
ADPCM.Port180E = value;
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "Write to ADPCM Sample Rate [E] {0:X2}", value);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x180F: // Audio Fade Timer
|
|
|
|
|
CdIoPorts[0x0F] = value;
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "Write to CD Audio fade timer [F] {0:X2}", value);
|
2011-08-30 04:02:52 +00:00
|
|
|
|
// 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 12:
|
|
|
|
|
case 13:
|
|
|
|
|
if (CDAudio.FadeOutFramesRemaining == 0)
|
|
|
|
|
CDAudio.FadeOut(120); // 2 seconds
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-08-14 18:20:13 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2011-08-29 02:47:03 +00:00
|
|
|
|
Log.Error("CD", "unknown write to {0:X4}:{1:X2} pc={2:X4}", addr, value, Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte ReadCD(int addr)
|
|
|
|
|
{
|
|
|
|
|
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;
|
2011-08-29 02:47:03 +00:00
|
|
|
|
//Log.Error("CD", "Read: 1800 {0:X2} (PC={1:X4})", returnValue, Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
return returnValue;
|
|
|
|
|
|
|
|
|
|
case 0x1801: // Read data bus
|
2011-08-29 02:47:03 +00:00
|
|
|
|
//Log.Error("CD", "Read: 1801 {0:X2} (PC={1:X4})", SCSI.DataBits, Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
return SCSI.DataBits;
|
|
|
|
|
|
|
|
|
|
case 0x1802: // ADPCM / CD Control
|
2011-08-29 02:47:03 +00:00
|
|
|
|
//Log.Error("CD", "Read: 1802 {0:X2} (PC={1:X4})", CdIoPorts[2], Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
return CdIoPorts[2];
|
|
|
|
|
|
|
|
|
|
case 0x1803: // BRAM Lock
|
|
|
|
|
if (BramEnabled)
|
|
|
|
|
BramLocked = true;
|
|
|
|
|
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC);
|
|
|
|
|
returnValue = Port1803;
|
2011-08-14 18:20:13 +00:00
|
|
|
|
CdIoPorts[3] ^= 2;
|
|
|
|
|
return returnValue;
|
|
|
|
|
|
|
|
|
|
case 0x1804: // CD Reset
|
2011-08-29 02:47:03 +00:00
|
|
|
|
//Log.Error("CD", "Read: 1804 {0:X2} (PC={1:X4})", CdIoPorts[4], Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
return CdIoPorts[4];
|
|
|
|
|
|
|
|
|
|
case 0x1805: // CD audio data Low
|
2011-09-05 17:45:01 +00:00
|
|
|
|
if ((Port1803 & 0x2) == 0)
|
2011-08-14 18:20:13 +00:00
|
|
|
|
sample = CDAudio.VolumeLeft;
|
|
|
|
|
else
|
|
|
|
|
sample = CDAudio.VolumeRight;
|
|
|
|
|
return (byte) sample;
|
|
|
|
|
|
|
|
|
|
case 0x1806: // CD audio data High
|
2011-09-05 17:45:01 +00:00
|
|
|
|
if ((Port1803 & 0x2) == 0)
|
2011-08-14 18:20:13 +00:00
|
|
|
|
sample = CDAudio.VolumeLeft;
|
|
|
|
|
else
|
|
|
|
|
sample = CDAudio.VolumeRight;
|
|
|
|
|
return (byte) (sample >> 8);
|
|
|
|
|
|
2011-09-05 17:45:01 +00:00
|
|
|
|
// wow, nothing ever reads 1807 yet
|
|
|
|
|
|
2011-08-29 02:47:03 +00:00
|
|
|
|
case 0x1808: // Auto Handshake Data Input
|
|
|
|
|
returnValue = SCSI.DataBits;
|
2011-08-14 18:20:13 +00:00
|
|
|
|
if (SCSI.REQ && SCSI.IO && !SCSI.CD)
|
|
|
|
|
{
|
|
|
|
|
SCSI.ACK = false;
|
|
|
|
|
SCSI.REQ = false;
|
|
|
|
|
SCSI.Think();
|
|
|
|
|
}
|
2011-08-29 02:47:03 +00:00
|
|
|
|
return returnValue;
|
|
|
|
|
|
|
|
|
|
case 0x180A: // ADPCM Memory Read/Write Port
|
2011-09-04 04:38:11 +00:00
|
|
|
|
return ADPCM.Port180A;
|
2011-08-29 02:47:03 +00:00
|
|
|
|
|
|
|
|
|
case 0x180B: // ADPCM Data Transfer Control
|
|
|
|
|
//Log.Error("CD", "Read ADPCM Data Transfer Control");
|
2011-09-04 04:38:11 +00:00
|
|
|
|
return ADPCM.Port180B;
|
2011-08-29 02:47:03 +00:00
|
|
|
|
|
|
|
|
|
case 0x180C: // ADPCM Status
|
|
|
|
|
returnValue = 0;
|
2011-09-09 03:40:58 +00:00
|
|
|
|
if (ADPCM.EndReached)
|
|
|
|
|
returnValue |= 0x01;
|
2011-09-04 04:38:11 +00:00
|
|
|
|
if (ADPCM.AdpcmIsPlaying)
|
2011-08-29 02:47:03 +00:00
|
|
|
|
returnValue |= 0x08;
|
2011-09-04 04:38:11 +00:00
|
|
|
|
if (ADPCM.AdpcmBusyWriting)
|
2011-08-29 02:47:03 +00:00
|
|
|
|
returnValue |= 0x04;
|
2011-09-04 04:38:11 +00:00
|
|
|
|
if (ADPCM.AdpcmBusyReading)
|
2011-08-29 02:47:03 +00:00
|
|
|
|
returnValue |= 0x80;
|
|
|
|
|
|
|
|
|
|
//Log.Error("CD", "Read ADPCM Status {0:X2}", returnValue);
|
|
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
|
|
|
|
|
|
case 0x180D: // ADPCM Play Control
|
|
|
|
|
//Log.Error("CD", "Read ADPCM Play Control");
|
|
|
|
|
return CdIoPorts[0x0D];
|
2011-08-14 18:20:13 +00:00
|
|
|
|
|
|
|
|
|
case 0x180F: // Audio Fade Timer
|
2011-09-05 17:45:01 +00:00
|
|
|
|
//Log.Error("CD", "Read: 180F {0:X2} (PC={1:X4})", CdIoPorts[0xF], Cpu.PC);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
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:
|
2011-08-29 02:47:03 +00:00
|
|
|
|
Log.Error("CD", "unknown read to {0:X4}", addr);
|
2011-08-14 18:20:13 +00:00
|
|
|
|
return 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-04 04:38:11 +00:00
|
|
|
|
public void RefreshIRQ2()
|
2011-08-14 18:20:13 +00:00
|
|
|
|
{
|
2011-09-05 17:45:01 +00:00
|
|
|
|
int mask = CdIoPorts[2] & Port1803 & 0x7C;
|
2011-08-14 18:20:13 +00:00
|
|
|
|
Cpu.IRQ2Assert = (mask != 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|