[PCE] ADPCM playback more or less working correctly now
plus some cleanup
This commit is contained in:
parent
08ec88319f
commit
a8aaaef45e
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Consoles.TurboGrafx;
|
||||
|
||||
// Do not modify this file directly! This is GENERATED code.
|
||||
// Please open the CpuCoreGenerator solution and make your modifications there.
|
||||
|
@ -43,6 +44,11 @@ namespace BizHawk.Emulation.CPUs.H6280
|
|||
|
||||
if (IRQ2Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ2Selector) == 0 && InBlockTransfer == false)
|
||||
{
|
||||
Console.WriteLine("============================================================");
|
||||
Console.WriteLine(" ENTERING IRQ2");
|
||||
Console.WriteLine(" 1802: {0:X2}, 1803: {1:X2}, && {2:X2}",PCEngine.CdIoPorts[2], PCEngine.CdIoPorts[3], PCEngine.CdIoPorts[2] & PCEngine.CdIoPorts[3]);
|
||||
Console.WriteLine("============================================================");
|
||||
|
||||
WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));
|
||||
WriteMemory((ushort)(S-- + 0x2100), (byte)PC);
|
||||
WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));
|
||||
|
@ -2307,7 +2313,7 @@ namespace BizHawk.Emulation.CPUs.H6280
|
|||
}
|
||||
}
|
||||
}
|
||||
ThinkAction();
|
||||
ThinkAction(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,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;
|
||||
|
@ -333,7 +333,7 @@ namespace BizHawk.Emulation.CPUs.H6280
|
|||
public Func<int, byte> ReadMemory21;
|
||||
public Action<int, byte> WriteMemory21;
|
||||
public Action<int, byte> WriteVDC;
|
||||
public Action ThinkAction = delegate { };
|
||||
public Action<int> ThinkAction = delegate { };
|
||||
|
||||
public byte ReadMemory(ushort address)
|
||||
{
|
||||
|
|
|
@ -5,20 +5,19 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
public sealed class ADPCM
|
||||
{
|
||||
public ushort adpcm_io_address;
|
||||
public ushort adpcm_read_address;
|
||||
public ushort adpcm_write_address;
|
||||
public ushort adpcm_length;
|
||||
public ushort IOAddress;
|
||||
public ushort ReadAddress;
|
||||
public ushort WriteAddress;
|
||||
public ushort AdpcmLength;
|
||||
|
||||
public int adpcm_read_timer, adpcm_write_timer;
|
||||
public byte adpcm_read_buffer, adpcm_write_buffer;
|
||||
public bool adpcm_read_pending, adpcm_write_pending;
|
||||
public int ReadTimer, WriteTimer;
|
||||
public byte ReadBuffer, WriteBuffer;
|
||||
public bool ReadPending, WritePending;
|
||||
|
||||
public byte[] RAM = new byte[0x10000];
|
||||
public MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
|
||||
|
||||
long LastThink;
|
||||
float adpcm_playback_timer;
|
||||
float Playback44khzTimer;
|
||||
|
||||
ScsiCDBus SCSI;
|
||||
PCEngine pce;
|
||||
|
@ -29,59 +28,40 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
SCSI = scsi;
|
||||
}
|
||||
|
||||
static readonly int[] StepSize =
|
||||
{
|
||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 140, 143,
|
||||
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449,
|
||||
494, 544, 598, 658, 724, 796, 876, 963,1060,1166,1282,1411,
|
||||
1552
|
||||
};
|
||||
|
||||
static readonly int[] StepFactor = { -1, -1, -1, -1, 2, 4, 6, 8 };
|
||||
|
||||
int AddClamped(int num1, int num2, int min, int max)
|
||||
{
|
||||
int result = num1 + num2;
|
||||
if (result < min) return min;
|
||||
if (result > max) return max;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void AdpcmControlWrite(byte value)
|
||||
{
|
||||
Log.Error("CD","ADPCM CONTROL WRITE {0:X2}",value);
|
||||
//Log.Error("CD","ADPCM CONTROL WRITE {0:X2}",value);
|
||||
if ((Port180D & 0x80) != 0 && (value & 0x80) == 0)
|
||||
{
|
||||
Log.Note("CD", "Reset ADPCM!");
|
||||
adpcm_read_address = 0;
|
||||
adpcm_write_address = 0;
|
||||
adpcm_io_address = 0;
|
||||
ReadAddress = 0;
|
||||
WriteAddress = 0;
|
||||
IOAddress = 0;
|
||||
nibble = false;
|
||||
playingSample = 0;
|
||||
adpcm_playback_timer = 0;
|
||||
Playback44khzTimer = 0;
|
||||
magnitude = 0;
|
||||
AdpcmIsPlaying = false;
|
||||
}
|
||||
|
||||
if ((value & 8) != 0)
|
||||
{
|
||||
adpcm_read_address = adpcm_io_address;
|
||||
ReadAddress = IOAddress;
|
||||
if ((value & 4) == 0)
|
||||
adpcm_read_address--;
|
||||
ReadAddress--;
|
||||
}
|
||||
|
||||
if ((Port180D & 2) == 0 && (value & 2) != 0)
|
||||
{
|
||||
adpcm_write_address = adpcm_io_address;
|
||||
WriteAddress = IOAddress;
|
||||
if ((value & 1) == 0)
|
||||
adpcm_write_address--;
|
||||
WriteAddress--;
|
||||
}
|
||||
|
||||
if ((value & 0x10) != 0)
|
||||
{
|
||||
adpcm_length = adpcm_io_address;
|
||||
Console.WriteLine("SET LENGTH={0:X4}", adpcm_length);
|
||||
AdpcmLength = IOAddress;
|
||||
//Console.WriteLine("SET LENGTH={0:X4}", adpcm_length);
|
||||
}
|
||||
|
||||
if (AdpcmIsPlaying && (value & 0x20) == 0)
|
||||
|
@ -89,12 +69,15 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
if (AdpcmIsPlaying == false && (value & 0x20) != 0)
|
||||
{
|
||||
Console.WriteLine("Start playing!");
|
||||
if ((value & 0x40) == 0)
|
||||
Console.WriteLine("a thing thats normally set is not set");
|
||||
|
||||
Console.WriteLine("Start playing! READ {0:X4} LENGTH {1:X4}", ReadAddress, AdpcmLength);
|
||||
AdpcmIsPlaying = true;
|
||||
nibble = false;
|
||||
playingSample = 0;
|
||||
adpcm_playback_timer = 0;
|
||||
// nibble = true;
|
||||
playingSample = 2048;
|
||||
magnitude = 0;
|
||||
Playback44khzTimer = 0;
|
||||
}
|
||||
|
||||
Port180D = value;
|
||||
|
@ -102,98 +85,34 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
public bool AdpcmIsPlaying { get; private set; }
|
||||
public bool AdpcmBusyWriting { get { return AdpcmCdDmaRequested; } }
|
||||
public bool AdpcmBusyReading { get { return adpcm_read_pending; } }
|
||||
|
||||
Random rnd = new Random();
|
||||
public bool AdpcmBusyReading { get { return ReadPending; } }
|
||||
|
||||
int playingSample;
|
||||
int nextSampleTimer = 0;
|
||||
bool nibble;
|
||||
|
||||
int magnitude;
|
||||
|
||||
void DecodeAdpcmSample()
|
||||
public void Think(int cycles)
|
||||
{
|
||||
// get sample. it's one nibble.
|
||||
byte sample;
|
||||
if (nibble == false)
|
||||
Playback44khzTimer -= cycles;
|
||||
if (Playback44khzTimer < 0)
|
||||
{
|
||||
sample = (byte) (RAM[adpcm_read_address] >> 4);
|
||||
nibble = true;
|
||||
} else {
|
||||
sample = (byte)(RAM[adpcm_read_address] & 0xF);
|
||||
nibble = false;
|
||||
adpcm_length--;
|
||||
adpcm_read_address++;
|
||||
}
|
||||
|
||||
bool positive = (sample & 8) == 0;
|
||||
int mag = sample & 7;
|
||||
int m = StepFactor[mag];
|
||||
|
||||
magnitude = AddClamped(magnitude, m, 0, 48);
|
||||
int adjustment = StepSize[magnitude];
|
||||
if (positive == false) adjustment *= -1;
|
||||
playingSample = AddClamped(playingSample, adjustment, 0, 4095);
|
||||
|
||||
adpcm_length--;
|
||||
}
|
||||
|
||||
void AdpcmEmitSample()
|
||||
{
|
||||
if (AdpcmIsPlaying == false)
|
||||
SoundProvider.buffer.enqueue_sample(0, 0);
|
||||
else
|
||||
{
|
||||
int rate = 16 - (Port180E & 0x0F);
|
||||
float khz = 32 / rate;
|
||||
|
||||
if (nextSampleTimer == 0)
|
||||
{
|
||||
DecodeAdpcmSample();
|
||||
nextSampleTimer = 4;
|
||||
}
|
||||
nextSampleTimer--;
|
||||
|
||||
if (adpcm_length == 0)
|
||||
{
|
||||
AdpcmIsPlaying = false;
|
||||
}
|
||||
|
||||
short adjustedSample = (short)((playingSample - 2048) << 3);
|
||||
SoundProvider.buffer.enqueue_sample(adjustedSample, adjustedSample);
|
||||
}
|
||||
}
|
||||
|
||||
public void Think()
|
||||
{
|
||||
int cycles = (int) (pce.Cpu.TotalExecutedCycles - LastThink);
|
||||
LastThink = pce.Cpu.TotalExecutedCycles;
|
||||
|
||||
adpcm_playback_timer -= cycles;
|
||||
if (adpcm_playback_timer < 0)
|
||||
{
|
||||
adpcm_playback_timer += 162.81f; // # of CPU cycles that translate to one 44100hz sample.
|
||||
Playback44khzTimer += 162.81f; // # of CPU cycles that translate to one 44100hz sample.
|
||||
AdpcmEmitSample();
|
||||
}
|
||||
|
||||
if (adpcm_read_timer > 0) adpcm_read_timer -= cycles;
|
||||
if (adpcm_write_timer > 0) adpcm_write_timer -= cycles;
|
||||
if (ReadTimer > 0) ReadTimer -= cycles;
|
||||
if (WriteTimer > 0) WriteTimer -= cycles;
|
||||
|
||||
if (adpcm_read_pending && adpcm_read_timer <= 0)
|
||||
if (ReadPending && ReadTimer <= 0)
|
||||
{
|
||||
adpcm_read_buffer = RAM[adpcm_read_address++];
|
||||
adpcm_read_pending = false;
|
||||
if (adpcm_length > ushort.MinValue)
|
||||
adpcm_length--;
|
||||
ReadBuffer = RAM[ReadAddress++];
|
||||
ReadPending = false;
|
||||
if (AdpcmLength > ushort.MinValue)
|
||||
AdpcmLength--;
|
||||
}
|
||||
|
||||
if (adpcm_write_pending && adpcm_write_timer <= 0)
|
||||
if (WritePending && WriteTimer <= 0)
|
||||
{
|
||||
RAM[adpcm_write_address++] = adpcm_write_buffer;
|
||||
adpcm_write_pending = false;
|
||||
if (adpcm_length < ushort.MaxValue)
|
||||
adpcm_length++;
|
||||
RAM[WriteAddress++] = WriteBuffer;
|
||||
WritePending = false;
|
||||
if (AdpcmLength < ushort.MaxValue)
|
||||
AdpcmLength++;
|
||||
}
|
||||
|
||||
if (AdpcmCdDmaRequested)
|
||||
|
@ -201,7 +120,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
if (SCSI.REQ && SCSI.IO && !SCSI.CD && !SCSI.ACK)
|
||||
{
|
||||
byte dmaByte = SCSI.DataBits;
|
||||
RAM[adpcm_write_address++] = dmaByte;
|
||||
RAM[WriteAddress++] = dmaByte;
|
||||
|
||||
SCSI.ACK = false;
|
||||
SCSI.REQ = false;
|
||||
|
@ -226,21 +145,121 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
set
|
||||
{
|
||||
adpcm_write_buffer = value;
|
||||
adpcm_write_timer = 24;
|
||||
adpcm_write_pending = true;
|
||||
WriteBuffer = value;
|
||||
WriteTimer = 24;
|
||||
WritePending = true;
|
||||
}
|
||||
|
||||
get
|
||||
{
|
||||
adpcm_read_pending = true;
|
||||
adpcm_read_timer = 24;
|
||||
return adpcm_read_buffer;
|
||||
ReadPending = true;
|
||||
ReadTimer = 24;
|
||||
return ReadBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
public byte Port180B;
|
||||
public byte Port180D;
|
||||
public byte Port180E;
|
||||
|
||||
byte port180E;
|
||||
public byte Port180E
|
||||
{
|
||||
get { return port180E; }
|
||||
set
|
||||
{
|
||||
port180E = value;
|
||||
float khz = 32 / (16 - (Port180E & 0x0F));
|
||||
destSamplesPerSourceSample = 44.1f / khz;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Playback Functions
|
||||
// ***************************************************************************
|
||||
|
||||
static readonly int[] StepSize =
|
||||
{
|
||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 140, 143,
|
||||
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449,
|
||||
494, 544, 598, 658, 724, 796, 876, 963,1060,1166,1282,1411,
|
||||
1552
|
||||
};
|
||||
|
||||
static readonly int[] StepFactor = { -1, -1, -1, -1, 2, 4, 6, 8 };
|
||||
|
||||
int playingSample;
|
||||
float nextSampleTimer = 0;
|
||||
float destSamplesPerSourceSample;
|
||||
bool nibble;
|
||||
int magnitude;
|
||||
|
||||
int AddClamped(int num1, int num2, int min, int max)
|
||||
{
|
||||
int result = num1 + num2;
|
||||
if (result < min) return min;
|
||||
if (result > max) return max;
|
||||
return result;
|
||||
}
|
||||
|
||||
byte ReadNibble()
|
||||
{
|
||||
byte value;
|
||||
if (nibble == false)
|
||||
value = (byte)(RAM[ReadAddress] >> 4);
|
||||
else
|
||||
{
|
||||
value = (byte)(RAM[ReadAddress] & 0xF);
|
||||
AdpcmLength--;
|
||||
ReadAddress++;
|
||||
}
|
||||
|
||||
nibble ^= true;
|
||||
return value;
|
||||
}
|
||||
|
||||
void DecodeAdpcmSample()
|
||||
{
|
||||
// get sample. it's one nibble.
|
||||
byte sample = ReadNibble();
|
||||
|
||||
bool positive = (sample & 8) == 0;
|
||||
int mag = sample & 7;
|
||||
int m = StepFactor[mag];
|
||||
|
||||
magnitude = AddClamped(magnitude, m, 0, 48);
|
||||
int adjustment = StepSize[magnitude];
|
||||
if (positive == false) adjustment *= -1;
|
||||
playingSample = AddClamped(playingSample, adjustment, 0, 4095);
|
||||
|
||||
//Console.WriteLine("decode: {0:X} sample: {1} ad_ref_index: {2}", sample,playingSample, magnitude);
|
||||
}
|
||||
|
||||
void AdpcmEmitSample()
|
||||
{
|
||||
if (AdpcmIsPlaying == false)
|
||||
SoundProvider.buffer.enqueue_sample(0, 0);
|
||||
else
|
||||
{
|
||||
int rate = 16 - (Port180E & 0x0F);
|
||||
float khz = 32 / rate;
|
||||
|
||||
if (nextSampleTimer <= 0)
|
||||
{
|
||||
DecodeAdpcmSample();
|
||||
nextSampleTimer += destSamplesPerSourceSample;
|
||||
}
|
||||
nextSampleTimer--;
|
||||
|
||||
if (AdpcmLength == 0)
|
||||
{
|
||||
AdpcmIsPlaying = false;
|
||||
}
|
||||
|
||||
short adjustedSample = (short)((playingSample - 2048) << 3);
|
||||
SoundProvider.buffer.enqueue_sample(adjustedSample, adjustedSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
- Exile II .. seems to reset itself after playing the unskippable intro. :(
|
||||
- Macross 2036.. seems impossible to start/play the game. :(
|
||||
|
||||
- Rayxanber 2 weird issues at the end of first level with cd audio player
|
||||
- rtype, end of level 4 dies with unrecognized scsi command ff
|
||||
- Startling Odyssey does the reset-at-new-game-screen thats rather odd :(
|
||||
- Super Darius II : at 1st Boss, game freezes waiting for adpcm
|
||||
- Ys 1, start new game, death by adpcm probably
|
||||
|
||||
- Ys 1, start new game, death by adpcm probably ** shit it works now.
|
||||
|
||||
|
||||
card angels does poll subcode...
|
||||
|
||||
|
||||
======= TurboGrafx compatibility issues =======
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
public ControllerDefinition ControllerDefinition { get { return PCEngineController; } }
|
||||
public IController Controller { get; set; }
|
||||
|
||||
private int SelectedController;
|
||||
private byte InputByte;
|
||||
int SelectedController;
|
||||
byte InputByte;
|
||||
|
||||
public bool SEL { get { return ((InputByte & 1) != 0) ;} }
|
||||
public bool CLR { get { return ((InputByte & 2) != 0); } }
|
||||
|
||||
private void WriteInput(byte value)
|
||||
void WriteInput(byte value)
|
||||
{
|
||||
bool prevSEL = SEL;
|
||||
InputByte = value;
|
||||
|
@ -36,7 +37,7 @@
|
|||
SelectedController = (SelectedController + 1);
|
||||
}
|
||||
|
||||
private byte ReadInput()
|
||||
byte ReadInput()
|
||||
{
|
||||
byte value = 0x3F;
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
// 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.
|
||||
|
||||
private byte[] PopulousRAM;
|
||||
byte[] PopulousRAM;
|
||||
|
||||
private byte ReadMemoryPopulous(int addr)
|
||||
byte ReadMemoryPopulous(int addr)
|
||||
{
|
||||
if (addr >= 0x80000 && addr < 0x88000)
|
||||
return PopulousRAM[addr & 0x7FFF];
|
||||
|
@ -35,7 +35,7 @@
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
private void WriteMemoryPopulous(int addr, byte value)
|
||||
void WriteMemoryPopulous(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
// 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.
|
||||
|
||||
private byte SF2MapperLatch;
|
||||
byte SF2MapperLatch;
|
||||
|
||||
private byte ReadMemorySF2(int addr)
|
||||
byte ReadMemorySF2(int addr)
|
||||
{
|
||||
if (addr < 0x7FFFF) // read ROM
|
||||
return RomData[addr];
|
||||
|
@ -35,7 +35,7 @@
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
private void WriteMemorySF2(int addr, byte value)
|
||||
void WriteMemorySF2(int addr, byte value)
|
||||
{
|
||||
if ((addr & 0x1FFC) == 0x1FF0)
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// The SuperGrafx has 32K of RAM and a different port configuration to allow
|
||||
// I/O access to VDC1, VDC2, and the VPC.
|
||||
|
||||
private byte ReadMemorySGX(int addr)
|
||||
byte ReadMemorySGX(int addr)
|
||||
{
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
@ -38,7 +38,7 @@
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
private void WriteMemorySGX(int addr, byte value)
|
||||
void WriteMemorySGX(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x7FFF] = value;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
private byte ReadMemoryCD(int addr)
|
||||
byte ReadMemoryCD(int addr)
|
||||
{
|
||||
if (addr < 0xD0000) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
@ -41,7 +41,7 @@
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
private void WriteMemoryCD(int addr, byte value)
|
||||
void WriteMemoryCD(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
private byte IOBuffer;
|
||||
byte IOBuffer;
|
||||
|
||||
private byte ReadMemory(int addr)
|
||||
byte ReadMemory(int addr)
|
||||
{
|
||||
if (addr < 0xFFFFF) // read ROM
|
||||
return RomData[addr % RomLength];
|
||||
|
@ -37,7 +37,7 @@
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
private void WriteMemory(int addr, byte value)
|
||||
void WriteMemory(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
|
||||
Ram[addr & 0x1FFF] = value;
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
// ROM
|
||||
public byte[] RomData;
|
||||
public int RomLength;
|
||||
private Disc disc;
|
||||
Disc disc;
|
||||
|
||||
// Machine
|
||||
public NecSystemType Type;
|
||||
|
@ -31,14 +31,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public SoundMixer SoundMixer;
|
||||
public MetaspuSoundProvider SoundSynchronizer;
|
||||
|
||||
private bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
|
||||
private bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
|
||||
private bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
|
||||
bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
|
||||
bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
|
||||
bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
|
||||
|
||||
// BRAM
|
||||
private bool BramEnabled = false;
|
||||
private bool BramLocked = true;
|
||||
private byte[] BRAM;
|
||||
bool BramEnabled = false;
|
||||
bool BramLocked = true;
|
||||
byte[] BRAM;
|
||||
|
||||
// Memory system
|
||||
public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram
|
||||
|
@ -69,7 +69,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
Init(game, rom);
|
||||
}
|
||||
|
||||
private void Init(GameInfo game, byte[] rom)
|
||||
void Init(GameInfo game, byte[] rom)
|
||||
{
|
||||
Controller = NullController.GetNullController();
|
||||
Cpu = new HuC6280();
|
||||
|
@ -113,7 +113,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM.SoundProvider);
|
||||
SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
|
||||
soundProvider = SoundSynchronizer;
|
||||
Cpu.ThinkAction = () => { SCSI.Think(); ADPCM.Think(); };
|
||||
Cpu.ThinkAction = (cycles) => { SCSI.Think(); ADPCM.Think(cycles); };
|
||||
}
|
||||
|
||||
if (rom.Length == 0x60000)
|
||||
|
@ -143,9 +143,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
BramEnabled = true;
|
||||
BRAM = new byte[2048];
|
||||
Console.WriteLine("ENABLE BRAM!");
|
||||
|
||||
// pre-format BRAM
|
||||
// pre-format BRAM. damn are we helpful.
|
||||
BRAM[0] = 0x48; BRAM[1] = 0x55; BRAM[2] = 0x42; BRAM[3] = 0x4D;
|
||||
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
|
||||
}
|
||||
|
@ -199,9 +198,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
SetupMemoryDomains();
|
||||
}
|
||||
|
||||
private int _lagcount = 0;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
int _lagcount = 0;
|
||||
bool lagged = true;
|
||||
bool islag = false;
|
||||
public int Frame { get; set; }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
|
@ -245,7 +244,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
get { return (IVideoProvider) VPC ?? VDC1; }
|
||||
}
|
||||
|
||||
private ISoundProvider soundProvider;
|
||||
ISoundProvider soundProvider;
|
||||
public ISoundProvider SoundProvider
|
||||
{
|
||||
get { return soundProvider; }
|
||||
|
@ -305,6 +304,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
writer.Write("SuperRAM ");
|
||||
SuperRam.SaveAsHex(writer);
|
||||
}
|
||||
writer.Write("ADPCM_TEMP ");
|
||||
ADPCM.RAM.SaveAsHex(writer);
|
||||
}
|
||||
writer.WriteLine("[/PCEngine]");
|
||||
}
|
||||
|
@ -331,6 +332,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
CDRam.ReadFromHex(args[1]);
|
||||
else if (args[0] == "SuperRAM")
|
||||
SuperRam.ReadFromHex(args[1]);
|
||||
else if (args[0] == "ADPCM_TEMP")
|
||||
ADPCM.RAM.ReadFromHex(args[1]);
|
||||
else if (args[0] == "PopulousRAM" && PopulousRAM != null)
|
||||
PopulousRAM.ReadFromHex(args[1]);
|
||||
else if (args[0] == "[HuC6280]")
|
||||
|
@ -455,7 +458,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
return buf;
|
||||
}
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>(10);
|
||||
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
|
||||
|
@ -500,7 +503,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
IList<MemoryDomain> memoryDomains;
|
||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||
|
||||
|
|
|
@ -6,23 +6,23 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
public sealed class ScsiCDBus
|
||||
{
|
||||
private const int STATUS_GOOD = 0;
|
||||
private const int STATUS_CHECK_CONDITION = 1;
|
||||
private const int STATUS_CONDITION_MET = 2;
|
||||
private const int STATUS_BUSY = 4;
|
||||
private const int STATUS_INTERMEDIATE = 8;
|
||||
const int STATUS_GOOD = 0;
|
||||
const int STATUS_CHECK_CONDITION = 1;
|
||||
const int STATUS_CONDITION_MET = 2;
|
||||
const int STATUS_BUSY = 4;
|
||||
const int STATUS_INTERMEDIATE = 8;
|
||||
|
||||
private const int SCSI_TEST_UNIT_READY = 0x00;
|
||||
private const int SCSI_REQUEST_SENSE = 0x03;
|
||||
private const int SCSI_READ = 0x08;
|
||||
private const int SCSI_AUDIO_START_POS = 0xD8;
|
||||
private const int SCSI_AUDIO_END_POS = 0xD9;
|
||||
private const int SCSI_PAUSE = 0xDA;
|
||||
private const int SCSI_READ_SUBCODE_Q = 0xDD;
|
||||
private const int SCSI_READ_TOC = 0xDE;
|
||||
const int SCSI_TEST_UNIT_READY = 0x00;
|
||||
const int SCSI_REQUEST_SENSE = 0x03;
|
||||
const int SCSI_READ = 0x08;
|
||||
const int SCSI_AUDIO_START_POS = 0xD8;
|
||||
const int SCSI_AUDIO_END_POS = 0xD9;
|
||||
const int SCSI_PAUSE = 0xDA;
|
||||
const int SCSI_READ_SUBCODE_Q = 0xDD;
|
||||
const int SCSI_READ_TOC = 0xDE;
|
||||
|
||||
private bool bsy, sel, cd, io, msg, req, ack, atn, rst;
|
||||
private bool signalsChanged;
|
||||
bool bsy, sel, cd, io, msg, req, ack, atn, rst;
|
||||
bool signalsChanged;
|
||||
|
||||
public bool BSY
|
||||
{
|
||||
|
@ -106,7 +106,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
public byte DataBits { get; set; } // data bits
|
||||
|
||||
private enum BusPhase
|
||||
enum BusPhase
|
||||
{
|
||||
BusFree,
|
||||
Command,
|
||||
|
@ -117,14 +117,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
Status
|
||||
}
|
||||
|
||||
private bool busPhaseChanged;
|
||||
private BusPhase Phase = BusPhase.BusFree;
|
||||
bool busPhaseChanged;
|
||||
BusPhase Phase = BusPhase.BusFree;
|
||||
|
||||
private bool MessageCompleted;
|
||||
private bool StatusCompleted;
|
||||
private byte MessageValue;
|
||||
bool MessageCompleted;
|
||||
bool StatusCompleted;
|
||||
byte MessageValue;
|
||||
|
||||
private QuickList<byte> CommandBuffer = new QuickList<byte>(10); // 10 = biggest command
|
||||
QuickList<byte> CommandBuffer = new QuickList<byte>(10); // 10 = biggest command
|
||||
public QuickQueue<byte> DataIn = new QuickQueue<byte>(2048); // one data sector
|
||||
|
||||
// ******** Data Transfer / READ command support ********
|
||||
|
@ -138,7 +138,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
// ******** Resources ********
|
||||
|
||||
private PCEngine pce;
|
||||
PCEngine pce;
|
||||
public Disc disc;
|
||||
|
||||
// ******** Events ********
|
||||
|
@ -218,7 +218,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
} while (signalsChanged || busPhaseChanged);
|
||||
}
|
||||
|
||||
private void ResetDevice()
|
||||
void ResetDevice()
|
||||
{
|
||||
CD = false;
|
||||
IO = false;
|
||||
|
@ -235,7 +235,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
pce.CDAudio.Stop();
|
||||
}
|
||||
|
||||
private void ThinkCommandPhase()
|
||||
void ThinkCommandPhase()
|
||||
{
|
||||
if (REQ && ACK)
|
||||
{
|
||||
|
@ -258,7 +258,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void ThinkDataInPhase()
|
||||
void ThinkDataInPhase()
|
||||
{
|
||||
if (REQ && ACK)
|
||||
{
|
||||
|
@ -286,13 +286,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void ThinkDataOutPhase()
|
||||
void ThinkDataOutPhase()
|
||||
{
|
||||
Console.WriteLine("*********** DATA OUT PHASE, DOES THIS HAPPEN? ****************");
|
||||
SetPhase(BusPhase.BusFree);
|
||||
}
|
||||
|
||||
private void ThinkMessageInPhase()
|
||||
void ThinkMessageInPhase()
|
||||
{
|
||||
if (REQ && ACK)
|
||||
{
|
||||
|
@ -307,13 +307,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void ThinkMessageOutPhase()
|
||||
void ThinkMessageOutPhase()
|
||||
{
|
||||
Console.WriteLine("******* IN MESSAGE OUT PHASE. DOES THIS EVER HAPPEN? ********");
|
||||
SetPhase(BusPhase.BusFree);
|
||||
}
|
||||
|
||||
private void ThinkStatusPhase()
|
||||
void ThinkStatusPhase()
|
||||
{
|
||||
if (REQ && ACK)
|
||||
{
|
||||
|
@ -329,13 +329,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
|
||||
// returns true if command completed, false if more data bytes needed
|
||||
private bool CheckCommandBuffer()
|
||||
bool CheckCommandBuffer()
|
||||
{
|
||||
switch (CommandBuffer[0])
|
||||
{
|
||||
case SCSI_TEST_UNIT_READY:
|
||||
if (CommandBuffer.Count < 6) return false;
|
||||
Log.Note("CD", "Execute TEST_UNIT_READY");
|
||||
SetStatusMessage(STATUS_GOOD, 0);
|
||||
return true;
|
||||
|
||||
|
@ -371,12 +370,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
default:
|
||||
Console.WriteLine("UNRECOGNIZED SCSI COMMAND! {0:X2}", CommandBuffer[0]);
|
||||
SetStatusMessage(STATUS_GOOD, 0);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CommandRead()
|
||||
void CommandRead()
|
||||
{
|
||||
int sector = (CommandBuffer[1] & 0x1f) << 16;
|
||||
sector |= CommandBuffer[2] << 8;
|
||||
|
@ -395,16 +395,16 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
pce.CDAudio.Stop();
|
||||
}
|
||||
|
||||
private int audioStartLBA;
|
||||
private int audioEndLBA;
|
||||
int audioStartLBA;
|
||||
int audioEndLBA;
|
||||
|
||||
private void CommandAudioStartPos()
|
||||
void CommandAudioStartPos()
|
||||
{
|
||||
switch (CommandBuffer[9] & 0xC0)
|
||||
{
|
||||
case 0x00: // Set start offset in LBA units
|
||||
audioStartLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5];
|
||||
Console.WriteLine("Set Start LBA: "+audioStartLBA);
|
||||
//Console.WriteLine("Set Start LBA: "+audioStartLBA);
|
||||
break;
|
||||
|
||||
case 0x40: // Set start offset in MSF units
|
||||
|
@ -412,13 +412,13 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
byte s = CommandBuffer[3].BCDtoBin();
|
||||
byte f = CommandBuffer[4].BCDtoBin();
|
||||
audioStartLBA = Disc.ConvertMSFtoLBA(m, s, f);
|
||||
Console.WriteLine("Set Start MSF: {0} {1} {2} lba={3}",m,s,f,audioStartLBA);
|
||||
//Console.WriteLine("Set Start MSF: {0} {1} {2} lba={3}",m,s,f,audioStartLBA);
|
||||
break;
|
||||
|
||||
case 0x80: // Set start offset in track units
|
||||
byte trackNo = CommandBuffer[2].BCDtoBin();
|
||||
audioStartLBA = disc.TOC.Sessions[0].Tracks[trackNo - 1].Indexes[1].aba - 150;
|
||||
Console.WriteLine("Set Start track: {0} lba={1}", trackNo, audioStartLBA);
|
||||
//Console.WriteLine("Set Start track: {0} lba={1}", trackNo, audioStartLBA);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -438,13 +438,13 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
// irq callback?
|
||||
}
|
||||
|
||||
private void CommandAudioEndPos()
|
||||
void CommandAudioEndPos()
|
||||
{
|
||||
switch (CommandBuffer[9] & 0xC0)
|
||||
{
|
||||
case 0x00: // Set end offset in LBA units
|
||||
audioEndLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5];
|
||||
Console.WriteLine("Set End LBA: " + audioEndLBA);
|
||||
//Console.WriteLine("Set End LBA: " + audioEndLBA);
|
||||
break;
|
||||
|
||||
case 0x40: // Set end offset in MSF units
|
||||
|
@ -452,7 +452,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
byte s = CommandBuffer[3].BCDtoBin();
|
||||
byte f = CommandBuffer[4].BCDtoBin();
|
||||
audioEndLBA = Disc.ConvertMSFtoLBA(m, s, f);
|
||||
Console.WriteLine("Set End MSF: {0} {1} {2} lba={3}", m, s, f, audioEndLBA);
|
||||
//Console.WriteLine("Set End MSF: {0} {1} {2} lba={3}", m, s, f, audioEndLBA);
|
||||
break;
|
||||
|
||||
case 0x80: // Set end offset in track units
|
||||
|
@ -461,7 +461,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
audioEndLBA = disc.LBACount;
|
||||
else
|
||||
audioEndLBA = disc.TOC.Sessions[0].Tracks[trackNo - 1].Indexes[1].aba - 150;
|
||||
Console.WriteLine("Set End track: {0} lba={1}", trackNo, audioEndLBA);
|
||||
//Console.WriteLine("Set End track: {0} lba={1}", trackNo, audioEndLBA);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -471,7 +471,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
pce.CDAudio.Stop();
|
||||
break;
|
||||
case 1: // play in loop mode. I guess this constitues A-B looping
|
||||
Console.WriteLine("DOING A-B LOOP. NOT SURE IF RIGHT.");
|
||||
//Console.WriteLine("DOING A-B LOOP. NOT SURE IF RIGHT.");
|
||||
pce.CDAudio.PlayStartingAtLba(audioStartLBA);
|
||||
pce.CDAudio.EndLBA = audioEndLBA;
|
||||
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.LoopOnCompletion;
|
||||
|
@ -483,7 +483,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.CallbackOnCompletion;
|
||||
break;
|
||||
case 3: // Play normal
|
||||
Console.WriteLine("*** SET END POS, IN PLAY NORMAL MODE? STARTING AT _START_ POS. IS THAT RIGHT?");
|
||||
//Console.WriteLine("*** SET END POS, IN PLAY NORMAL MODE? STARTING AT _START_ POS. IS THAT RIGHT?");
|
||||
pce.CDAudio.PlayStartingAtLba(audioStartLBA);
|
||||
pce.CDAudio.EndLBA = audioEndLBA;
|
||||
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.StopOnCompletion;
|
||||
|
@ -492,7 +492,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
SetStatusMessage(STATUS_GOOD, 0);
|
||||
}
|
||||
|
||||
private void CommandPause()
|
||||
void CommandPause()
|
||||
{
|
||||
// apparently pause means stop? I guess? Idunno.
|
||||
pce.CDAudio.Stop();
|
||||
|
@ -500,9 +500,12 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
// TODO send error if already stopped.. or paused... or something.
|
||||
}
|
||||
|
||||
private void CommandReadSubcodeQ()
|
||||
void CommandReadSubcodeQ()
|
||||
{
|
||||
Console.WriteLine("poll subcode");
|
||||
// TODO we are lacking some various things here. But we know when it gets used and it doesnt
|
||||
// seem to be used that often.
|
||||
|
||||
var sectorEntry = disc.ReadLBA_SectorEntry(pce.CDAudio.CurrentSector);
|
||||
|
||||
DataIn.Clear();
|
||||
|
@ -526,13 +529,13 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
SetPhase(BusPhase.DataIn);
|
||||
}
|
||||
|
||||
private void CommandReadTOC()
|
||||
void CommandReadTOC()
|
||||
{
|
||||
switch (CommandBuffer[1])
|
||||
{
|
||||
case 0: // return number of tracks
|
||||
{
|
||||
Log.Error("CD","Execute READ_TOC : num of tracks");
|
||||
//Log.Error("CD","Execute READ_TOC : num of tracks");
|
||||
DataIn.Clear();
|
||||
DataIn.Enqueue(0x01);
|
||||
DataIn.Enqueue(((byte) disc.TOC.Sessions[0].Tracks.Count).BinToBCD());
|
||||
|
@ -552,8 +555,8 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
DataIn.Enqueue(f.BinToBCD());
|
||||
SetPhase(BusPhase.DataIn);
|
||||
|
||||
Log.Error("CD","EXECUTE READ_TOC : length of disc, LBA {0}, m:{1},s:{2},f:{3}",
|
||||
totalLbaLength, m, s, f);
|
||||
//Log.Error("CD","EXECUTE READ_TOC : length of disc, LBA {0}, m:{1},s:{2},f:{3}",
|
||||
//totalLbaLength, m, s, f);
|
||||
break;
|
||||
}
|
||||
case 2: // Return starting position of specified track in MSF format
|
||||
|
@ -581,8 +584,8 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
DataIn.Enqueue(4);
|
||||
SetPhase(BusPhase.DataIn);
|
||||
|
||||
Log.Error("CD", "EXECUTE READ_TOC : start pos of TRACK {4}, LBA {0}, m:{1},s:{2},f:{3}",
|
||||
lbaPos, m, s, f, track);
|
||||
//Log.Error("CD", "EXECUTE READ_TOC : start pos of TRACK {4}, LBA {0}, m:{1},s:{2},f:{3}",
|
||||
//lbaPos, m, s, f, track);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -592,7 +595,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
}
|
||||
}
|
||||
|
||||
private void SetStatusMessage(byte status, byte message)
|
||||
void SetStatusMessage(byte status, byte message)
|
||||
{
|
||||
MessageValue = message;
|
||||
StatusCompleted = false;
|
||||
|
@ -601,7 +604,7 @@ throw new Exception("requesting 0 sectors read.............................");
|
|||
SetPhase(BusPhase.Status);
|
||||
}
|
||||
|
||||
private void SetPhase(BusPhase phase)
|
||||
void SetPhase(BusPhase phase)
|
||||
{
|
||||
if (Phase == phase)
|
||||
return;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// IRQ2 interrupts:
|
||||
// 0x04 - INTA - ADPCM interrupt
|
||||
// 0x08 - INTSTOP - Fire when end of CD-Audio playback reached when in STOP MODE 2.
|
||||
// 0x10 - INTSUB - no idea yet
|
||||
// 0x10 - INTSUB - something with subchannel
|
||||
// 0x20 - INTM - Fires when data transfer is complete
|
||||
// 0x40 - INTD - Fires when data transfer is ready
|
||||
|
||||
|
@ -11,11 +11,22 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
public partial class PCEngine
|
||||
{
|
||||
byte[] CdIoPorts = new byte[16];
|
||||
public static byte[] CdIoPorts = new byte[16];
|
||||
|
||||
public byte IRQ2Control { get { return CdIoPorts[2]; } set { CdIoPorts[2] = value; } }
|
||||
public byte IRQ2Monitor { get { return CdIoPorts[3]; } set { CdIoPorts[3] = value; } }
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void InitScsiBus()
|
||||
{
|
||||
SCSI = new ScsiCDBus(this, disc);
|
||||
|
@ -24,18 +35,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
// set or clear Ready Bit
|
||||
if (yes)
|
||||
CdIoPorts[3] |= 0x40;
|
||||
Port1803 |= 0x40;
|
||||
else
|
||||
CdIoPorts[3] &= 0xBF;
|
||||
Port1803 &= 0xBF;
|
||||
};
|
||||
SCSI.DataTransferComplete = yes =>
|
||||
{
|
||||
if (yes)
|
||||
CdIoPorts[3] |= 0x20; // Set "Complete"
|
||||
Port1803 |= 0x20; // Set "Complete"
|
||||
else
|
||||
{
|
||||
CdIoPorts[3] &= 0xBF; // Clear "ready"
|
||||
|
||||
Port1803 &= 0xBF; // Clear "ready"
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -75,7 +85,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
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");
|
||||
if ((Cpu.IRQControlByte & 0x01) != 0) Log.Error("CD", "BTW, IRQ2 is not masked");
|
||||
if ((Cpu.IRQControlByte & 0x01) == 0 &&
|
||||
(CdIoPorts[2] & 0x7C) != 0) Log.Error("CD", "BTW, IRQ2 is not masked");
|
||||
|
||||
SCSI.Think();
|
||||
RefreshIRQ2();
|
||||
|
@ -87,7 +98,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
SCSI.Think();
|
||||
if (SCSI.RST)
|
||||
{
|
||||
CdIoPorts[3] &= 0x8F; // Clear interrupt control bits
|
||||
Port1803 &= 0x8F; // Clear interrupt control bits
|
||||
RefreshIRQ2();
|
||||
}
|
||||
break;
|
||||
|
@ -99,32 +110,29 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
case 0x1807: // BRAM Unlock
|
||||
if (BramEnabled && (value & 0x80) != 0)
|
||||
{
|
||||
//Console.WriteLine("UNLOCK BRAM!");
|
||||
BramLocked = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1808: // ADPCM address LSB
|
||||
ADPCM.adpcm_io_address &= 0xFF00;
|
||||
ADPCM.adpcm_io_address |= value;
|
||||
ADPCM.IOAddress &= 0xFF00;
|
||||
ADPCM.IOAddress |= value;
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
{
|
||||
Console.WriteLine("doing silly thing");
|
||||
ADPCM.adpcm_length = ADPCM.adpcm_io_address;
|
||||
ADPCM.AdpcmLength = ADPCM.IOAddress;
|
||||
}
|
||||
Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
||||
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
||||
break;
|
||||
|
||||
case 0x1809: // ADPCM address MSB
|
||||
ADPCM.adpcm_io_address &= 0x00FF;
|
||||
ADPCM.adpcm_io_address |= (ushort)(value << 8);
|
||||
ADPCM.IOAddress &= 0x00FF;
|
||||
ADPCM.IOAddress |= (ushort)(value << 8);
|
||||
if ((CdIoPorts[0x0D] & 0x10) != 0)
|
||||
{
|
||||
Console.WriteLine("doing silly thing");
|
||||
ADPCM.adpcm_length = ADPCM.adpcm_io_address;
|
||||
ADPCM.AdpcmLength = ADPCM.IOAddress;
|
||||
}
|
||||
Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
||||
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
|
||||
break;
|
||||
|
||||
case 0x180A: // ADPCM Memory Read/Write Port
|
||||
|
@ -133,7 +141,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
case 0x180B: // ADPCM DMA Control
|
||||
ADPCM.Port180B = value;
|
||||
Log.Error("CD", "Write to ADPCM DMA Control [B] {0:X2}", value);
|
||||
//Log.Error("CD", "Write to ADPCM DMA Control [B] {0:X2}", value);
|
||||
if (ADPCM.AdpcmCdDmaRequested)
|
||||
Console.WriteLine(" ADPCM DMA REQUESTED");
|
||||
break;
|
||||
|
@ -144,12 +152,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
case 0x180E: // ADPCM Playback Rate
|
||||
ADPCM.Port180E = value;
|
||||
Log.Error("CD", "Write to ADPCM Sample Rate [E] {0:X2}", value);
|
||||
//Log.Error("CD", "Write to ADPCM Sample Rate [E] {0:X2}", value);
|
||||
break;
|
||||
|
||||
case 0x180F: // Audio Fade Timer
|
||||
CdIoPorts[0x0F] = value;
|
||||
Log.Error("CD", "Write to CD Audio fade timer [F] {0:X2}", value);
|
||||
//Log.Error("CD", "Write to CD Audio fade timer [F] {0:X2}", value);
|
||||
// TODO ADPCM fades/vol control also.
|
||||
|
||||
switch (value)
|
||||
|
@ -206,8 +214,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
if (BramEnabled)
|
||||
BramLocked = true;
|
||||
|
||||
Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC);
|
||||
returnValue = CdIoPorts[3];
|
||||
//Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC);
|
||||
returnValue = Port1803;
|
||||
CdIoPorts[3] ^= 2;
|
||||
return returnValue;
|
||||
|
||||
|
@ -216,19 +224,21 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
return CdIoPorts[4];
|
||||
|
||||
case 0x1805: // CD audio data Low
|
||||
if ((CdIoPorts[0x3] & 0x2) == 0)
|
||||
if ((Port1803 & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte) sample;
|
||||
|
||||
case 0x1806: // CD audio data High
|
||||
if ((CdIoPorts[0x3] & 0x2) == 0)
|
||||
if ((Port1803 & 0x2) == 0)
|
||||
sample = CDAudio.VolumeLeft;
|
||||
else
|
||||
sample = CDAudio.VolumeRight;
|
||||
return (byte) (sample >> 8);
|
||||
|
||||
// wow, nothing ever reads 1807 yet
|
||||
|
||||
case 0x1808: // Auto Handshake Data Input
|
||||
returnValue = SCSI.DataBits;
|
||||
if (SCSI.REQ && SCSI.IO && !SCSI.CD)
|
||||
|
@ -266,7 +276,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
return CdIoPorts[0x0D];
|
||||
|
||||
case 0x180F: // Audio Fade Timer
|
||||
Log.Error("CD", "Read: 180F {0:X2} (PC={1:X4})", CdIoPorts[0xF], Cpu.PC);
|
||||
//Log.Error("CD", "Read: 180F {0:X2} (PC={1:X4})", CdIoPorts[0xF], Cpu.PC);
|
||||
return CdIoPorts[0x0F];
|
||||
|
||||
// These are some retarded version check
|
||||
|
@ -285,7 +295,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
public void RefreshIRQ2()
|
||||
{
|
||||
int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C;
|
||||
int mask = CdIoPorts[2] & Port1803 & 0x7C;
|
||||
Cpu.IRQ2Assert = (mask != 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly byte[] PalConvert = {0, 36, 72, 109, 145, 182, 218, 255};
|
||||
static readonly byte[] PalConvert = {0, 36, 72, 109, 145, 182, 218, 255};
|
||||
|
||||
public void PrecomputePalette(int slot)
|
||||
{
|
||||
|
|
|
@ -23,11 +23,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public int RCRCounter;
|
||||
public int ActiveLine;
|
||||
|
||||
private byte[] PriorityBuffer = new byte[512];
|
||||
private byte[] InterSpritePriorityBuffer = new byte[512];
|
||||
public int HBlankCycles = 79;
|
||||
public bool PerformSpriteLimit;
|
||||
|
||||
byte[] PriorityBuffer = new byte[512];
|
||||
byte[] InterSpritePriorityBuffer = new byte[512];
|
||||
|
||||
public void ExecFrame(bool render)
|
||||
{
|
||||
if (MultiResHack > 0 && render)
|
||||
|
@ -111,7 +112,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
RenderSpritesScanline();
|
||||
}
|
||||
|
||||
private void RenderBackgroundScanline()
|
||||
void RenderBackgroundScanline()
|
||||
{
|
||||
Array.Clear(PriorityBuffer, 0, FrameWidth);
|
||||
|
||||
|
@ -151,7 +152,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] heightTable = { 16, 32, 64, 64 };
|
||||
byte[] heightTable = { 16, 32, 64, 64 };
|
||||
|
||||
public void RenderSpritesScanline()
|
||||
{
|
||||
|
@ -337,10 +338,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private int FramePitch = 256;
|
||||
private int FrameWidth = 256;
|
||||
private int FrameHeight = 240;
|
||||
private int[] FrameBuffer = new int[256 * 240];
|
||||
int FramePitch = 256;
|
||||
int FrameWidth = 256;
|
||||
int FrameHeight = 240;
|
||||
int[] FrameBuffer = new int[256 * 240];
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
|
|
|
@ -52,29 +52,29 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
public int DisplayStartLine { get { return (Registers[VPR] >> 8) + (Registers[VPR] & 0x1F); } }
|
||||
|
||||
private const int MAWR = 0; // Memory Address Write Register
|
||||
private const int MARR = 1; // Memory Address Read Register
|
||||
private const int VRR = 2; // VRAM Read Register
|
||||
private const int VWR = 2; // VRAM Write Register
|
||||
private const int CR = 5; // Control Register
|
||||
private const int RCR = 6; // Raster Compare Register
|
||||
private const int BXR = 7; // Background X-scroll Register
|
||||
private const int BYR = 8; // Background Y-scroll Register
|
||||
private const int MWR = 9; // Memory-access Width Register
|
||||
private const int HSR = 10; // Horizontal Sync Register
|
||||
private const int HDR = 11; // Horizontal Display Register
|
||||
private const int VPR = 12; // Vertical synchronous register
|
||||
private const int VDW = 13; // Vertical display register
|
||||
private const int VCR = 14; // Vertical display END position register;
|
||||
private const int DCR = 15; // DMA Control Register
|
||||
private const int SOUR = 16; // Source address for DMA
|
||||
private const int DESR = 17; // Destination address for DMA
|
||||
private const int LENR = 18; // Length of DMA transfer. Writing this will initiate DMA.
|
||||
private const int SATB = 19; // Sprite Attribute Table base location in VRAM
|
||||
const int MAWR = 0; // Memory Address Write Register
|
||||
const int MARR = 1; // Memory Address Read Register
|
||||
const int VRR = 2; // VRAM Read Register
|
||||
const int VWR = 2; // VRAM Write Register
|
||||
const int CR = 5; // Control Register
|
||||
const int RCR = 6; // Raster Compare Register
|
||||
const int BXR = 7; // Background X-scroll Register
|
||||
const int BYR = 8; // Background Y-scroll Register
|
||||
const int MWR = 9; // Memory-access Width Register
|
||||
const int HSR = 10; // Horizontal Sync Register
|
||||
const int HDR = 11; // Horizontal Display Register
|
||||
const int VPR = 12; // Vertical synchronous register
|
||||
const int VDW = 13; // Vertical display register
|
||||
const int VCR = 14; // Vertical display END position register;
|
||||
const int DCR = 15; // DMA Control Register
|
||||
const int SOUR = 16; // Source address for DMA
|
||||
const int DESR = 17; // Destination address for DMA
|
||||
const int LENR = 18; // Length of DMA transfer. Writing this will initiate DMA.
|
||||
const int SATB = 19; // Sprite Attribute Table base location in VRAM
|
||||
|
||||
private const int RegisterSelect = 0;
|
||||
private const int LSB = 2;
|
||||
private const int MSB = 3;
|
||||
const int RegisterSelect = 0;
|
||||
const int LSB = 2;
|
||||
const int MSB = 3;
|
||||
|
||||
public const byte StatusVerticalBlanking = 0x20;
|
||||
public const byte StatusVramVramDmaComplete = 0x10;
|
||||
|
@ -83,10 +83,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public const byte StatusSpriteOverflow = 0x02;
|
||||
public const byte StatusSprite0Collision = 0x01;
|
||||
|
||||
private const int VramSize = 0x8000;
|
||||
const int VramSize = 0x8000;
|
||||
|
||||
private HuC6280 cpu;
|
||||
private VCE vce;
|
||||
HuC6280 cpu;
|
||||
VCE vce;
|
||||
|
||||
public int MultiResHack = 0;
|
||||
|
||||
|
@ -126,7 +126,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void CompleteMSBWrite(int register)
|
||||
void CompleteMSBWrite(int register)
|
||||
{
|
||||
switch (register)
|
||||
{
|
||||
|
@ -206,7 +206,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
internal void RunDmaForScanline()
|
||||
{
|
||||
// TODO: dont do this all in one scanline. I guess it can do about 227 words per scanline.
|
||||
//Console.WriteLine("Doing some dma");
|
||||
// TODO: to be honest, dont do it in a block per scanline. put it in the CPU think function.
|
||||
Console.WriteLine("******************************* Doing some dma ******************************");
|
||||
int advanceSource = (Registers[DCR] & 4) == 0 ? +1 : -1;
|
||||
int advanceDest = (Registers[DCR] & 8) == 0 ? +1 : -1;
|
||||
int wordsDone = 0;
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public VDC VDC1;
|
||||
public VDC VDC2;
|
||||
public VCE VCE;
|
||||
private HuC6280 CPU;
|
||||
public HuC6280 CPU;
|
||||
|
||||
public byte[] Registers = {0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
|
@ -114,20 +114,20 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
// And there are no homebrew SGX games I know of.
|
||||
// Maybe we'll emulate it in the native-code version.
|
||||
|
||||
private const int RCR = 6;
|
||||
private const int BXR = 7;
|
||||
private const int BYR = 8;
|
||||
private const int VDW = 13;
|
||||
private const int DCR = 15;
|
||||
const int RCR = 6;
|
||||
const int BXR = 7;
|
||||
const int BYR = 8;
|
||||
const int VDW = 13;
|
||||
const int DCR = 15;
|
||||
|
||||
private int EffectivePriorityMode = 0;
|
||||
int EffectivePriorityMode = 0;
|
||||
|
||||
private int FrameHeight;
|
||||
private int FrameWidth;
|
||||
private int[] FrameBuffer;
|
||||
int FrameHeight;
|
||||
int FrameWidth;
|
||||
int[] FrameBuffer;
|
||||
|
||||
private byte[] PriorityBuffer = new byte[512];
|
||||
private byte[] InterSpritePriorityBuffer = new byte[512];
|
||||
byte[] PriorityBuffer = new byte[512];
|
||||
byte[] InterSpritePriorityBuffer = new byte[512];
|
||||
|
||||
public void ExecFrame(bool render)
|
||||
{
|
||||
|
@ -255,7 +255,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void RenderScanLine()
|
||||
void RenderScanLine()
|
||||
{
|
||||
if (VDC1.ActiveLine >= FrameHeight)
|
||||
return;
|
||||
|
@ -279,7 +279,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private void InitializeScanLine(int scanline)
|
||||
void InitializeScanLine(int scanline)
|
||||
{
|
||||
// Clear priority buffer
|
||||
Array.Clear(PriorityBuffer, 0, FrameWidth);
|
||||
|
@ -289,7 +289,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
FrameBuffer[(scanline * FrameWidth) + i] = VCE.Palette[0];
|
||||
}
|
||||
|
||||
private void RenderBackgroundScanline(VDC vdc, byte priority)
|
||||
void RenderBackgroundScanline(VDC vdc, byte priority)
|
||||
{
|
||||
if (vdc.BackgroundEnabled == false)
|
||||
return;
|
||||
|
@ -318,9 +318,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
private static byte[] heightTable = { 16, 32, 64, 64 };
|
||||
static byte[] heightTable = { 16, 32, 64, 64 };
|
||||
|
||||
private void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority)
|
||||
void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority)
|
||||
{
|
||||
if (vdc.SpritesEnabled == false)
|
||||
return;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
public ControllerDefinition ControllerDefinition { get { return SmsController; } }
|
||||
public IController Controller { get; set; }
|
||||
|
||||
private byte ReadControls1()
|
||||
byte ReadControls1()
|
||||
{
|
||||
lagged = false;
|
||||
byte value = 0xFF;
|
||||
|
@ -34,7 +34,7 @@
|
|||
return value;
|
||||
}
|
||||
|
||||
private byte ReadControls2()
|
||||
byte ReadControls2()
|
||||
{
|
||||
lagged = false;
|
||||
byte value = 0xFF;
|
||||
|
@ -64,7 +64,7 @@
|
|||
return value;
|
||||
}
|
||||
|
||||
private byte ReadPort0()
|
||||
byte ReadPort0()
|
||||
{
|
||||
if (IsGameGear == false)
|
||||
return 0xFF;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// Bank 2: Control Address $8000 - Maps $8000 - $BFFF
|
||||
// System RAM is at $C000+ as in the Sega mapper.
|
||||
|
||||
private byte ReadMemoryCM(ushort address)
|
||||
byte ReadMemoryCM(ushort address)
|
||||
{
|
||||
if (address < BankSize * 1) return RomData[(RomBank0 * BankSize) + address];
|
||||
if (address < BankSize * 2) return RomData[(RomBank1 * BankSize) + (address & BankSizeMask)];
|
||||
|
@ -18,7 +18,7 @@
|
|||
return SystemRam[address & RamSizeMask];
|
||||
}
|
||||
|
||||
private void WriteMemoryCM(ushort address, byte value)
|
||||
void WriteMemoryCM(ushort address, byte value)
|
||||
{
|
||||
if (address >= 0xC000)
|
||||
SystemRam[address & RamSizeMask] = value;
|
||||
|
@ -28,7 +28,7 @@
|
|||
else if (address == 0x8000) RomBank2 = (byte)(value % RomBanks);
|
||||
}
|
||||
|
||||
private void InitCodeMastersMapper()
|
||||
void InitCodeMastersMapper()
|
||||
{
|
||||
Cpu.ReadMemory = ReadMemoryCM;
|
||||
Cpu.WriteMemory = WriteMemoryCM;
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
// $FFFE - Mapper slot 1 control
|
||||
// $FFFF - Mapper slot 2 control
|
||||
|
||||
private const ushort BankSizeMask = 0x3FFF;
|
||||
private const ushort RamSizeMask = 0x1FFF;
|
||||
const ushort BankSizeMask = 0x3FFF;
|
||||
const ushort RamSizeMask = 0x1FFF;
|
||||
|
||||
private byte ReadMemory(ushort address)
|
||||
byte ReadMemory(ushort address)
|
||||
{
|
||||
if (address < 1024)
|
||||
return RomData[address];
|
||||
|
@ -37,7 +37,7 @@
|
|||
return SystemRam[address & RamSizeMask];
|
||||
}
|
||||
|
||||
private void WriteMemory(ushort address, byte value)
|
||||
void WriteMemory(ushort address, byte value)
|
||||
{
|
||||
if (address >= 0xC000)
|
||||
SystemRam[address & RamSizeMask] = value;
|
||||
|
@ -68,7 +68,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void InitSegaMapper()
|
||||
void InitSegaMapper()
|
||||
{
|
||||
Cpu.ReadMemory = ReadMemory;
|
||||
Cpu.WriteMemory = WriteMemory;
|
||||
|
@ -80,9 +80,9 @@
|
|||
|
||||
// Mapper when loading a BIOS as a ROM
|
||||
|
||||
private bool BiosMapped { get { return (Port3E & 0x08) == 0; } }
|
||||
bool BiosMapped { get { return (Port3E & 0x08) == 0; } }
|
||||
|
||||
private byte ReadMemoryBIOS(ushort address)
|
||||
byte ReadMemoryBIOS(ushort address)
|
||||
{
|
||||
if (BiosMapped == false && address < BankSize * 3)
|
||||
return 0x00;
|
||||
|
@ -99,7 +99,7 @@
|
|||
return SystemRam[address & RamSizeMask];
|
||||
}
|
||||
|
||||
private void WriteMemoryBIOS(ushort address, byte value)
|
||||
void WriteMemoryBIOS(ushort address, byte value)
|
||||
{
|
||||
if (address >= 0xC000)
|
||||
SystemRam[address & RamSizeMask] = value;
|
||||
|
@ -113,7 +113,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void InitBiosMapper()
|
||||
void InitBiosMapper()
|
||||
{
|
||||
Cpu.ReadMemory = ReadMemoryBIOS;
|
||||
Cpu.WriteMemory = WriteMemoryBIOS;
|
||||
|
@ -123,4 +123,4 @@
|
|||
WriteMemory(0xFFFF, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,9 +43,9 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
public bool IsGameGear = false;
|
||||
public bool HasYM2413 = false;
|
||||
|
||||
private int _lagcount = 0;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
int _lagcount = 0;
|
||||
bool lagged = true;
|
||||
bool islag = false;
|
||||
public int Frame { get; set; }
|
||||
|
||||
public void ResetFrameCounter()
|
||||
|
@ -55,10 +55,10 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
private byte Port01 = 0xFF;
|
||||
private byte Port02 = 0xFF;
|
||||
private byte Port3E = 0xAF;
|
||||
private byte Port3F = 0xFF;
|
||||
byte Port01 = 0xFF;
|
||||
byte Port02 = 0xFF;
|
||||
byte Port3E = 0xAF;
|
||||
byte Port3F = 0xFF;
|
||||
|
||||
public DisplayType DisplayType { get; set; }
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
@ -325,12 +325,12 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
public CoreInputComm CoreInputComm { get; set; }
|
||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||
|
||||
private ISoundProvider ActiveSoundProvider;
|
||||
ISoundProvider ActiveSoundProvider;
|
||||
public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } }
|
||||
|
||||
public string SystemId { get { return "SMS"; } }
|
||||
|
||||
private string region = "Export";
|
||||
string region = "Export";
|
||||
public string Region
|
||||
{
|
||||
get { return region; }
|
||||
|
@ -342,11 +342,11 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private readonly string[] validRegions = { "Export", "Japan" };
|
||||
readonly string[] validRegions = { "Export", "Japan" };
|
||||
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
IList<MemoryDomain> memoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>(3);
|
||||
var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, Endian.Little,
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
{
|
||||
public partial class VDP
|
||||
{
|
||||
private int[] PaletteTMS9918 = new int[]
|
||||
int[] PaletteTMS9918 = new int[]
|
||||
{
|
||||
unchecked((int)0x00000000),
|
||||
unchecked((int)0xFF000000),
|
||||
|
@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
unchecked((int)0xFFFFFFFF)
|
||||
};
|
||||
|
||||
private void RenderBackgroundM0()
|
||||
void RenderBackgroundM0()
|
||||
{
|
||||
if (DisplayOn == false)
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private void RenderBackgroundM2()
|
||||
void RenderBackgroundM2()
|
||||
{
|
||||
if (DisplayOn == false)
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private void RenderTmsSprites()
|
||||
void RenderTmsSprites()
|
||||
{
|
||||
if (DisplayOn == false) return;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
public partial class VDP
|
||||
{
|
||||
// TODO: HCounter
|
||||
private readonly byte[] VLineCounterTableNTSC192 =
|
||||
readonly byte[] VLineCounterTableNTSC192 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
@ -24,7 +24,7 @@
|
|||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
private readonly byte[] VLineCounterTableNTSC224 =
|
||||
readonly byte[] VLineCounterTableNTSC224 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
@ -45,7 +45,7 @@
|
|||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
private readonly byte[] VLineCounterTableNTSC240 =
|
||||
readonly byte[] VLineCounterTableNTSC240 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
@ -66,7 +66,7 @@
|
|||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
|
||||
};
|
||||
|
||||
private readonly byte[] VLineCounterTablePAL192 =
|
||||
readonly byte[] VLineCounterTablePAL192 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
@ -91,7 +91,7 @@
|
|||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
private readonly byte[] VLineCounterTablePAL224 =
|
||||
readonly byte[] VLineCounterTablePAL224 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
@ -116,7 +116,7 @@
|
|||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
private readonly byte[] VLineCounterTablePAL240 =
|
||||
readonly byte[] VLineCounterTablePAL240 =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
|
|
|
@ -18,24 +18,24 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
public byte[] Registers = new byte[] { 0x06, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
public byte StatusByte;
|
||||
|
||||
private bool VdpWaitingForLatchByte = true;
|
||||
private byte VdpLatch;
|
||||
private byte VdpBuffer;
|
||||
private ushort VdpAddress;
|
||||
private VdpCommand vdpCommand;
|
||||
private int TmsMode = 4;
|
||||
bool VdpWaitingForLatchByte = true;
|
||||
byte VdpLatch;
|
||||
byte VdpBuffer;
|
||||
ushort VdpAddress;
|
||||
VdpCommand vdpCommand;
|
||||
int TmsMode = 4;
|
||||
|
||||
private bool VIntPending;
|
||||
private bool HIntPending;
|
||||
bool VIntPending;
|
||||
bool HIntPending;
|
||||
|
||||
private VdpMode mode;
|
||||
public VdpMode VdpMode { get { return mode; } }
|
||||
private DisplayType DisplayType = DisplayType.NTSC;
|
||||
private Z80A Cpu;
|
||||
VdpMode mode;
|
||||
DisplayType DisplayType = DisplayType.NTSC;
|
||||
Z80A Cpu;
|
||||
public int IPeriod = 228;
|
||||
public VdpMode VdpMode { get { return mode; } }
|
||||
|
||||
int FrameHeight = 192;
|
||||
public int ScanLine;
|
||||
private int FrameHeight = 192;
|
||||
public int[] FrameBuffer = new int[256*192];
|
||||
public int[] GameGearFrameBuffer = new int[160*144];
|
||||
|
||||
|
@ -56,22 +56,22 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
public int SpriteTileBase { get { return (Registers[6] & 4) > 0 ? 256: 0; } }
|
||||
public byte BackdropColor { get { return (byte)(16 + (Registers[7] & 15)); } }
|
||||
|
||||
private int NameTableBase;
|
||||
private int ColorTableBase;
|
||||
private int PatternGeneratorBase;
|
||||
private int SpritePatternGeneratorBase;
|
||||
private int TmsPatternNameTableBase;
|
||||
private int TmsSpriteAttributeBase;
|
||||
int NameTableBase;
|
||||
int ColorTableBase;
|
||||
int PatternGeneratorBase;
|
||||
int SpritePatternGeneratorBase;
|
||||
int TmsPatternNameTableBase;
|
||||
int TmsSpriteAttributeBase;
|
||||
|
||||
// preprocessed state assist stuff.
|
||||
public int[] Palette = new int[32];
|
||||
public byte[] PatternBuffer = new byte[0x8000];
|
||||
|
||||
private byte[] ScanlinePriorityBuffer = new byte[256];
|
||||
private byte[] SpriteCollisionBuffer = new byte[256];
|
||||
byte[] ScanlinePriorityBuffer = new byte[256];
|
||||
byte[] SpriteCollisionBuffer = new byte[256];
|
||||
|
||||
private static readonly byte[] SMSPalXlatTable = { 0, 85, 170, 255 };
|
||||
private static readonly byte[] GGPalXlatTable = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 };
|
||||
static readonly byte[] SMSPalXlatTable = { 0, 85, 170, 255 };
|
||||
static readonly byte[] GGPalXlatTable = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 };
|
||||
|
||||
public VDP(Z80A cpu, VdpMode mode, DisplayType displayType)
|
||||
{
|
||||
|
@ -205,7 +205,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
return (1024 * (Registers[2] & 0x0C)) + 0x0700;
|
||||
}
|
||||
|
||||
private void CheckVideoMode()
|
||||
void CheckVideoMode()
|
||||
{
|
||||
if (Mode4Bit == false) // check old TMS modes
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private void WriteRegister(int reg, byte data)
|
||||
void WriteRegister(int reg, byte data)
|
||||
{
|
||||
Registers[reg] = data;
|
||||
switch(reg)
|
||||
|
@ -292,9 +292,9 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly byte[] pow2 = {1, 2, 4, 8, 16, 32, 64, 128};
|
||||
static readonly byte[] pow2 = {1, 2, 4, 8, 16, 32, 64, 128};
|
||||
|
||||
private void UpdatePatternBuffer(ushort address, byte value)
|
||||
void UpdatePatternBuffer(ushort address, byte value)
|
||||
{
|
||||
// writing one byte affects 8 pixels due to stupid planar storage.
|
||||
for (int i=0; i<8; i++)
|
||||
|
@ -309,9 +309,9 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
private int lineIntLinesRemaining;
|
||||
int lineIntLinesRemaining;
|
||||
|
||||
private void ProcessFrameInterrupt()
|
||||
void ProcessFrameInterrupt()
|
||||
{
|
||||
if (ScanLine == FrameHeight + 1)
|
||||
{
|
||||
|
@ -323,7 +323,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
Cpu.Interrupt = true;
|
||||
}
|
||||
|
||||
private void ProcessLineInterrupt()
|
||||
void ProcessLineInterrupt()
|
||||
{
|
||||
if (ScanLine <= FrameHeight)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace BizHawk
|
|||
// There is less overhead by not being dynamically resizable and stuff.
|
||||
public sealed class QuickList<T> where T : struct
|
||||
{
|
||||
private T[] buffer;
|
||||
T[] buffer;
|
||||
public int Position;
|
||||
|
||||
public QuickList(int capacity)
|
||||
|
@ -43,10 +43,10 @@ namespace BizHawk
|
|||
// only intended to be used with value types. If used on references you may get GC issues.
|
||||
public class QuickQueue<T> where T : struct
|
||||
{
|
||||
private T[] buffer;
|
||||
private int head;
|
||||
private int tail;
|
||||
private int size;
|
||||
T[] buffer;
|
||||
int head;
|
||||
int tail;
|
||||
int size;
|
||||
|
||||
public QuickQueue(int capacity)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ namespace BizHawk
|
|||
// .net has no built-in read only dictionary
|
||||
public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey,TValue>
|
||||
{
|
||||
private IDictionary<TKey, TValue> dict;
|
||||
IDictionary<TKey, TValue> dict;
|
||||
|
||||
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
|
|
|
@ -39,8 +39,8 @@ namespace BizHawk.Emulation.Sound
|
|||
public int PlayingTrack;
|
||||
|
||||
public int CurrentSector, SectorOffset; // Offset is in SAMPLES, not bytes. Sector is 588 samples long.
|
||||
private int CachedSector;
|
||||
private byte[] SectorCache = new byte[2352];
|
||||
int CachedSector;
|
||||
byte[] SectorCache = new byte[2352];
|
||||
|
||||
public int FadeOutOverFrames = 0;
|
||||
public int FadeOutFramesRemaining = 0;
|
||||
|
@ -70,6 +70,8 @@ namespace BizHawk.Emulation.Sound
|
|||
public void PlayStartingAtLba(int lba)
|
||||
{
|
||||
var point = Disc.TOC.SeekPoint(lba);
|
||||
if (point == null) return;
|
||||
|
||||
PlayingTrack = point.TrackNum;
|
||||
StartLBA = lba;
|
||||
EndLBA = point.Track.Indexes[1].aba + point.Track.length_aba - 150;
|
||||
|
@ -120,7 +122,7 @@ namespace BizHawk.Emulation.Sound
|
|||
FadeOutFramesRemaining = frames;
|
||||
}
|
||||
|
||||
private void EnsureSector()
|
||||
void EnsureSector()
|
||||
{
|
||||
if (CachedSector != CurrentSector)
|
||||
{
|
||||
|
|
|
@ -147,13 +147,13 @@ namespace BizHawk.Emulation.Sound
|
|||
MixSamples(samples, start, samples.Length - start);
|
||||
}
|
||||
|
||||
private void MixSamples(short[] samples, int start, int len)
|
||||
void MixSamples(short[] samples, int start, int len)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
MixChannel(samples, start, len, Channels[i]);
|
||||
}
|
||||
|
||||
private void MixChannel(short[] samples, int start, int len, PSGChannel channel)
|
||||
void MixChannel(short[] samples, int start, int len, PSGChannel channel)
|
||||
{
|
||||
if (channel.Enabled == false) return;
|
||||
if (channel.DDA == false && channel.Volume == 0) return;
|
||||
|
@ -268,7 +268,7 @@ namespace BizHawk.Emulation.Sound
|
|||
}
|
||||
}
|
||||
|
||||
private void LoadChannelStateText(TextReader reader, int channel)
|
||||
void LoadChannelStateText(TextReader reader, int channel)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace BizHawk.Emulation.Sound
|
|||
public bool Left = true;
|
||||
public bool Right = true;
|
||||
|
||||
private const int SampleRate = 44100;
|
||||
private static byte[] LogScale = { 0, 10, 13, 16, 20, 26, 32, 40, 51, 64, 81, 102, 128, 161, 203, 255 };
|
||||
const int SampleRate = 44100;
|
||||
static byte[] LogScale = { 0, 10, 13, 16, 20, 26, 32, 40, 51, 64, 81, 102, 128, 161, 203, 255 };
|
||||
|
||||
public void Mix(short[] samples, int start, int len, int maxVolume)
|
||||
{
|
||||
|
@ -48,10 +48,10 @@ namespace BizHawk.Emulation.Sound
|
|||
public Channel[] Channels = new Channel[4];
|
||||
public byte PsgLatch;
|
||||
|
||||
private Queue<QueuedCommand> commands = new Queue<QueuedCommand>(256);
|
||||
private int frameStartTime, frameStopTime;
|
||||
Queue<QueuedCommand> commands = new Queue<QueuedCommand>(256);
|
||||
int frameStartTime, frameStopTime;
|
||||
|
||||
private const int PsgBase = 111861;
|
||||
const int PsgBase = 111861;
|
||||
|
||||
public SN76489()
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ namespace BizHawk.Emulation.Sound
|
|||
commands.Enqueue(new QueuedCommand {Value = value, Time = cycles-frameStartTime});
|
||||
}
|
||||
|
||||
private void UpdateNoiseType(int value)
|
||||
void UpdateNoiseType(int value)
|
||||
{
|
||||
Channels[3].NoiseType = (byte)(value & 0x07);
|
||||
switch (Channels[3].NoiseType & 3)
|
||||
|
@ -125,7 +125,7 @@ namespace BizHawk.Emulation.Sound
|
|||
}
|
||||
}
|
||||
|
||||
private void WritePsgDataImmediate(byte value)
|
||||
void WritePsgDataImmediate(byte value)
|
||||
{
|
||||
switch (value & 0xF0)
|
||||
{
|
||||
|
@ -309,7 +309,7 @@ namespace BizHawk.Emulation.Sound
|
|||
// Next step from A4 is A#4. A#4 = (440.00 * 1.05946...) = 466.163...
|
||||
// Note that because frequencies must be integers, SMS games will be slightly out of pitch to a normally tuned instrument, especially at the low end.
|
||||
|
||||
private static readonly int[] frequencies =
|
||||
static readonly int[] frequencies =
|
||||
{
|
||||
27, // A0
|
||||
29, // A#0
|
||||
|
@ -402,7 +402,7 @@ namespace BizHawk.Emulation.Sound
|
|||
4435 // C#8
|
||||
};
|
||||
|
||||
private static readonly string[] notes =
|
||||
static readonly string[] notes =
|
||||
{
|
||||
"A0","A#0","B0",
|
||||
"C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1",
|
||||
|
|
|
@ -17,11 +17,11 @@ namespace BizHawk.Emulation.Sound
|
|||
{
|
||||
public ISoundProvider BaseSoundProvider;
|
||||
|
||||
private Queue<short> buffer = new Queue<short>(4096);
|
||||
Queue<short> buffer = new Queue<short>(4096);
|
||||
|
||||
private const int SamplesInOneFrame = 1470;
|
||||
private const int TargetExtraSamples = 882;
|
||||
private const int MaxExcessSamples = 4096;
|
||||
const int SamplesInOneFrame = 1470;
|
||||
const int TargetExtraSamples = 882;
|
||||
const int MaxExcessSamples = 4096;
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Sound
|
|||
{
|
||||
}
|
||||
|
||||
private short[] pullBuffer = new short[1470];
|
||||
short[] pullBuffer = new short[1470];
|
||||
public void PullSamples(ISoundProvider source)
|
||||
{
|
||||
Array.Clear(pullBuffer, 0, 1470);
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Sound
|
|||
|
||||
public sealed class SoundMixer : ISoundProvider
|
||||
{
|
||||
private List<ISoundProvider> SoundProviders;
|
||||
List<ISoundProvider> SoundProviders;
|
||||
|
||||
public SoundMixer(params ISoundProvider[] soundProviders)
|
||||
{
|
||||
|
|
|
@ -11,8 +11,8 @@ namespace BizHawk
|
|||
{
|
||||
public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>>
|
||||
{
|
||||
private readonly T1 first;
|
||||
private readonly T2 second;
|
||||
readonly T1 first;
|
||||
readonly T2 second;
|
||||
public T1 First { get { return first; } }
|
||||
public T2 Second { get { return second; } }
|
||||
|
||||
|
|
Loading…
Reference in New Issue