[PCE] ADPCM playback more or less working correctly now

plus some cleanup
This commit is contained in:
beirich 2011-09-05 17:45:01 +00:00
parent 08ec88319f
commit a8aaaef45e
32 changed files with 452 additions and 405 deletions

View File

@ -1,4 +1,5 @@
using System; using System;
using BizHawk.Emulation.Consoles.TurboGrafx;
// Do not modify this file directly! This is GENERATED code. // Do not modify this file directly! This is GENERATED code.
// Please open the CpuCoreGenerator solution and make your modifications there. // 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) 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 >> 8));
WriteMemory((ushort)(S-- + 0x2100), (byte)PC); WriteMemory((ushort)(S-- + 0x2100), (byte)PC);
WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10))); WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));
@ -2307,7 +2313,7 @@ namespace BizHawk.Emulation.CPUs.H6280
} }
} }
} }
ThinkAction(); ThinkAction(delta);
} }
} }
} }

View File

@ -237,7 +237,7 @@ namespace BizHawk.Emulation.CPUs.H6280
public byte ReadIrqStatus() public byte ReadIrqStatus()
{ {
byte status = 0; byte status = 0;
if (IRQ2Assert) status |= 1; if (IRQ2Assert) status |= 1;
if (IRQ1Assert) status |= 2; if (IRQ1Assert) status |= 2;
if (TimerAssert) status |= 4; if (TimerAssert) status |= 4;
return status; return status;
@ -333,7 +333,7 @@ namespace BizHawk.Emulation.CPUs.H6280
public Func<int, byte> ReadMemory21; public Func<int, byte> ReadMemory21;
public Action<int, byte> WriteMemory21; public Action<int, byte> WriteMemory21;
public Action<int, byte> WriteVDC; public Action<int, byte> WriteVDC;
public Action ThinkAction = delegate { }; public Action<int> ThinkAction = delegate { };
public byte ReadMemory(ushort address) public byte ReadMemory(ushort address)
{ {

View File

@ -5,20 +5,19 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
public sealed class ADPCM public sealed class ADPCM
{ {
public ushort adpcm_io_address; public ushort IOAddress;
public ushort adpcm_read_address; public ushort ReadAddress;
public ushort adpcm_write_address; public ushort WriteAddress;
public ushort adpcm_length; public ushort AdpcmLength;
public int adpcm_read_timer, adpcm_write_timer; public int ReadTimer, WriteTimer;
public byte adpcm_read_buffer, adpcm_write_buffer; public byte ReadBuffer, WriteBuffer;
public bool adpcm_read_pending, adpcm_write_pending; public bool ReadPending, WritePending;
public byte[] RAM = new byte[0x10000]; public byte[] RAM = new byte[0x10000];
public MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V); public MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
long LastThink; float Playback44khzTimer;
float adpcm_playback_timer;
ScsiCDBus SCSI; ScsiCDBus SCSI;
PCEngine pce; PCEngine pce;
@ -29,59 +28,40 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SCSI = scsi; 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) 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) if ((Port180D & 0x80) != 0 && (value & 0x80) == 0)
{ {
Log.Note("CD", "Reset ADPCM!"); Log.Note("CD", "Reset ADPCM!");
adpcm_read_address = 0; ReadAddress = 0;
adpcm_write_address = 0; WriteAddress = 0;
adpcm_io_address = 0; IOAddress = 0;
nibble = false; nibble = false;
playingSample = 0; playingSample = 0;
adpcm_playback_timer = 0; Playback44khzTimer = 0;
magnitude = 0; magnitude = 0;
AdpcmIsPlaying = false; AdpcmIsPlaying = false;
} }
if ((value & 8) != 0) if ((value & 8) != 0)
{ {
adpcm_read_address = adpcm_io_address; ReadAddress = IOAddress;
if ((value & 4) == 0) if ((value & 4) == 0)
adpcm_read_address--; ReadAddress--;
} }
if ((Port180D & 2) == 0 && (value & 2) != 0) if ((Port180D & 2) == 0 && (value & 2) != 0)
{ {
adpcm_write_address = adpcm_io_address; WriteAddress = IOAddress;
if ((value & 1) == 0) if ((value & 1) == 0)
adpcm_write_address--; WriteAddress--;
} }
if ((value & 0x10) != 0) if ((value & 0x10) != 0)
{ {
adpcm_length = adpcm_io_address; AdpcmLength = IOAddress;
Console.WriteLine("SET LENGTH={0:X4}", adpcm_length); //Console.WriteLine("SET LENGTH={0:X4}", adpcm_length);
} }
if (AdpcmIsPlaying && (value & 0x20) == 0) if (AdpcmIsPlaying && (value & 0x20) == 0)
@ -89,12 +69,15 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (AdpcmIsPlaying == false && (value & 0x20) != 0) 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; AdpcmIsPlaying = true;
nibble = false; // nibble = true;
playingSample = 0; playingSample = 2048;
adpcm_playback_timer = 0;
magnitude = 0; magnitude = 0;
Playback44khzTimer = 0;
} }
Port180D = value; Port180D = value;
@ -102,98 +85,34 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public bool AdpcmIsPlaying { get; private set; } public bool AdpcmIsPlaying { get; private set; }
public bool AdpcmBusyWriting { get { return AdpcmCdDmaRequested; } } public bool AdpcmBusyWriting { get { return AdpcmCdDmaRequested; } }
public bool AdpcmBusyReading { get { return adpcm_read_pending; } } public bool AdpcmBusyReading { get { return ReadPending; } }
Random rnd = new Random();
int playingSample; public void Think(int cycles)
int nextSampleTimer = 0;
bool nibble;
int magnitude;
void DecodeAdpcmSample()
{ {
// get sample. it's one nibble. Playback44khzTimer -= cycles;
byte sample; if (Playback44khzTimer < 0)
if (nibble == false)
{ {
sample = (byte) (RAM[adpcm_read_address] >> 4); Playback44khzTimer += 162.81f; // # of CPU cycles that translate to one 44100hz sample.
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.
AdpcmEmitSample(); AdpcmEmitSample();
} }
if (adpcm_read_timer > 0) adpcm_read_timer -= cycles; if (ReadTimer > 0) ReadTimer -= cycles;
if (adpcm_write_timer > 0) adpcm_write_timer -= 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++]; ReadBuffer = RAM[ReadAddress++];
adpcm_read_pending = false; ReadPending = false;
if (adpcm_length > ushort.MinValue) if (AdpcmLength > ushort.MinValue)
adpcm_length--; AdpcmLength--;
} }
if (adpcm_write_pending && adpcm_write_timer <= 0) if (WritePending && WriteTimer <= 0)
{ {
RAM[adpcm_write_address++] = adpcm_write_buffer; RAM[WriteAddress++] = WriteBuffer;
adpcm_write_pending = false; WritePending = false;
if (adpcm_length < ushort.MaxValue) if (AdpcmLength < ushort.MaxValue)
adpcm_length++; AdpcmLength++;
} }
if (AdpcmCdDmaRequested) if (AdpcmCdDmaRequested)
@ -201,7 +120,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (SCSI.REQ && SCSI.IO && !SCSI.CD && !SCSI.ACK) if (SCSI.REQ && SCSI.IO && !SCSI.CD && !SCSI.ACK)
{ {
byte dmaByte = SCSI.DataBits; byte dmaByte = SCSI.DataBits;
RAM[adpcm_write_address++] = dmaByte; RAM[WriteAddress++] = dmaByte;
SCSI.ACK = false; SCSI.ACK = false;
SCSI.REQ = false; SCSI.REQ = false;
@ -226,21 +145,121 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
set set
{ {
adpcm_write_buffer = value; WriteBuffer = value;
adpcm_write_timer = 24; WriteTimer = 24;
adpcm_write_pending = true; WritePending = true;
} }
get get
{ {
adpcm_read_pending = true; ReadPending = true;
adpcm_read_timer = 24; ReadTimer = 24;
return adpcm_read_buffer; return ReadBuffer;
} }
} }
public byte Port180B; public byte Port180B;
public byte Port180D; 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);
}
}
} }
} }

View File

@ -11,13 +11,14 @@
- Exile II .. seems to reset itself after playing the unskippable intro. :( - Exile II .. seems to reset itself after playing the unskippable intro. :(
- Macross 2036.. seems impossible to start/play the game. :( - 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 - rtype, end of level 4 dies with unrecognized scsi command ff
- Startling Odyssey does the reset-at-new-game-screen thats rather odd :( - Startling Odyssey does the reset-at-new-game-screen thats rather odd :(
- Super Darius II : at 1st Boss, game freezes waiting for adpcm - 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 ======= ======= TurboGrafx compatibility issues =======

View File

@ -19,12 +19,13 @@
public ControllerDefinition ControllerDefinition { get { return PCEngineController; } } public ControllerDefinition ControllerDefinition { get { return PCEngineController; } }
public IController Controller { get; set; } public IController Controller { get; set; }
private int SelectedController; int SelectedController;
private byte InputByte; byte InputByte;
public bool SEL { get { return ((InputByte & 1) != 0) ;} } public bool SEL { get { return ((InputByte & 1) != 0) ;} }
public bool CLR { get { return ((InputByte & 2) != 0); } } public bool CLR { get { return ((InputByte & 2) != 0); } }
private void WriteInput(byte value) void WriteInput(byte value)
{ {
bool prevSEL = SEL; bool prevSEL = SEL;
InputByte = value; InputByte = value;
@ -36,7 +37,7 @@
SelectedController = (SelectedController + 1); SelectedController = (SelectedController + 1);
} }
private byte ReadInput() byte ReadInput()
{ {
byte value = 0x3F; byte value = 0x3F;

View File

@ -5,9 +5,9 @@
// The Populous HuCard is the only traditional HuCard to have battery-backed saveRAM // 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. // 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) if (addr >= 0x80000 && addr < 0x88000)
return PopulousRAM[addr & 0x7FFF]; return PopulousRAM[addr & 0x7FFF];
@ -35,7 +35,7 @@
return 0xFF; return 0xFF;
} }
private void WriteMemoryPopulous(int addr, byte value) void WriteMemoryPopulous(int addr, byte value)
{ {
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x1FFF] = value; Ram[addr & 0x1FFF] = value;

View File

@ -5,9 +5,9 @@
// Street Fighter 2 was a 20-megabit HuCard. The PCE has a maximum 8-megabit addressable ROM space. // 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. // 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 if (addr < 0x7FFFF) // read ROM
return RomData[addr]; return RomData[addr];
@ -35,7 +35,7 @@
return 0xFF; return 0xFF;
} }
private void WriteMemorySF2(int addr, byte value) void WriteMemorySF2(int addr, byte value)
{ {
if ((addr & 0x1FFC) == 0x1FF0) if ((addr & 0x1FFC) == 0x1FF0)
{ {

View File

@ -5,7 +5,7 @@
// The SuperGrafx has 32K of RAM and a different port configuration to allow // The SuperGrafx has 32K of RAM and a different port configuration to allow
// I/O access to VDC1, VDC2, and the VPC. // I/O access to VDC1, VDC2, and the VPC.
private byte ReadMemorySGX(int addr) byte ReadMemorySGX(int addr)
{ {
if (addr < 0xFFFFF) // read ROM if (addr < 0xFFFFF) // read ROM
return RomData[addr % RomLength]; return RomData[addr % RomLength];
@ -38,7 +38,7 @@
return 0xFF; return 0xFF;
} }
private void WriteMemorySGX(int addr, byte value) void WriteMemorySGX(int addr, byte value)
{ {
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x7FFF] = value; Ram[addr & 0x7FFF] = value;

View File

@ -2,7 +2,7 @@
{ {
public partial class PCEngine public partial class PCEngine
{ {
private byte ReadMemoryCD(int addr) byte ReadMemoryCD(int addr)
{ {
if (addr < 0xD0000) // read ROM if (addr < 0xD0000) // read ROM
return RomData[addr % RomLength]; return RomData[addr % RomLength];
@ -41,7 +41,7 @@
return 0xFF; return 0xFF;
} }
private void WriteMemoryCD(int addr, byte value) void WriteMemoryCD(int addr, byte value)
{ {
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x1FFF] = value; Ram[addr & 0x1FFF] = value;

View File

@ -2,9 +2,9 @@
{ {
public partial class PCEngine public partial class PCEngine
{ {
private byte IOBuffer; byte IOBuffer;
private byte ReadMemory(int addr) byte ReadMemory(int addr)
{ {
if (addr < 0xFFFFF) // read ROM if (addr < 0xFFFFF) // read ROM
return RomData[addr % RomLength]; return RomData[addr % RomLength];
@ -37,7 +37,7 @@
return 0xFF; return 0xFF;
} }
private void WriteMemory(int addr, byte value) void WriteMemory(int addr, byte value)
{ {
if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM.
Ram[addr & 0x1FFF] = value; Ram[addr & 0x1FFF] = value;

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// ROM // ROM
public byte[] RomData; public byte[] RomData;
public int RomLength; public int RomLength;
private Disc disc; Disc disc;
// Machine // Machine
public NecSystemType Type; public NecSystemType Type;
@ -31,14 +31,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public SoundMixer SoundMixer; public SoundMixer SoundMixer;
public MetaspuSoundProvider SoundSynchronizer; public MetaspuSoundProvider SoundSynchronizer;
private bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } } bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
private bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } } bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
private bool TurboCD { get { return Type == NecSystemType.TurboCD; } } bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
// BRAM // BRAM
private bool BramEnabled = false; bool BramEnabled = false;
private bool BramLocked = true; bool BramLocked = true;
private byte[] BRAM; byte[] BRAM;
// Memory system // Memory system
public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram
@ -69,7 +69,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Init(game, rom); Init(game, rom);
} }
private void Init(GameInfo game, byte[] rom) void Init(GameInfo game, byte[] rom)
{ {
Controller = NullController.GetNullController(); Controller = NullController.GetNullController();
Cpu = new HuC6280(); Cpu = new HuC6280();
@ -113,7 +113,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM.SoundProvider); SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM.SoundProvider);
SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V); SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
soundProvider = SoundSynchronizer; soundProvider = SoundSynchronizer;
Cpu.ThinkAction = () => { SCSI.Think(); ADPCM.Think(); }; Cpu.ThinkAction = (cycles) => { SCSI.Think(); ADPCM.Think(cycles); };
} }
if (rom.Length == 0x60000) if (rom.Length == 0x60000)
@ -143,9 +143,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
BramEnabled = true; BramEnabled = true;
BRAM = new byte[2048]; 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[0] = 0x48; BRAM[1] = 0x55; BRAM[2] = 0x42; BRAM[3] = 0x4D;
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80; BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
} }
@ -199,9 +198,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SetupMemoryDomains(); SetupMemoryDomains();
} }
private int _lagcount = 0; int _lagcount = 0;
private bool lagged = true; bool lagged = true;
private bool islag = false; bool islag = false;
public int Frame { get; set; } public int Frame { get; set; }
public int LagCount { get { return _lagcount; } set { _lagcount = value; } } public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
public bool IsLagFrame { get { return islag; } } public bool IsLagFrame { get { return islag; } }
@ -245,7 +244,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
get { return (IVideoProvider) VPC ?? VDC1; } get { return (IVideoProvider) VPC ?? VDC1; }
} }
private ISoundProvider soundProvider; ISoundProvider soundProvider;
public ISoundProvider SoundProvider public ISoundProvider SoundProvider
{ {
get { return soundProvider; } get { return soundProvider; }
@ -305,6 +304,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.Write("SuperRAM "); writer.Write("SuperRAM ");
SuperRam.SaveAsHex(writer); SuperRam.SaveAsHex(writer);
} }
writer.Write("ADPCM_TEMP ");
ADPCM.RAM.SaveAsHex(writer);
} }
writer.WriteLine("[/PCEngine]"); writer.WriteLine("[/PCEngine]");
} }
@ -331,6 +332,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
CDRam.ReadFromHex(args[1]); CDRam.ReadFromHex(args[1]);
else if (args[0] == "SuperRAM") else if (args[0] == "SuperRAM")
SuperRam.ReadFromHex(args[1]); SuperRam.ReadFromHex(args[1]);
else if (args[0] == "ADPCM_TEMP")
ADPCM.RAM.ReadFromHex(args[1]);
else if (args[0] == "PopulousRAM" && PopulousRAM != null) else if (args[0] == "PopulousRAM" && PopulousRAM != null)
PopulousRAM.ReadFromHex(args[1]); PopulousRAM.ReadFromHex(args[1]);
else if (args[0] == "[HuC6280]") else if (args[0] == "[HuC6280]")
@ -455,7 +458,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
return buf; return buf;
} }
private void SetupMemoryDomains() void SetupMemoryDomains()
{ {
var domains = new List<MemoryDomain>(10); var domains = new List<MemoryDomain>(10);
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little, var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
@ -500,7 +503,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
memoryDomains = domains.AsReadOnly(); memoryDomains = domains.AsReadOnly();
} }
private IList<MemoryDomain> memoryDomains; IList<MemoryDomain> memoryDomains;
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } } public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
public MemoryDomain MainMemory { get { return memoryDomains[0]; } } public MemoryDomain MainMemory { get { return memoryDomains[0]; } }

View File

@ -6,23 +6,23 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
public sealed class ScsiCDBus public sealed class ScsiCDBus
{ {
private const int STATUS_GOOD = 0; const int STATUS_GOOD = 0;
private const int STATUS_CHECK_CONDITION = 1; const int STATUS_CHECK_CONDITION = 1;
private const int STATUS_CONDITION_MET = 2; const int STATUS_CONDITION_MET = 2;
private const int STATUS_BUSY = 4; const int STATUS_BUSY = 4;
private const int STATUS_INTERMEDIATE = 8; const int STATUS_INTERMEDIATE = 8;
private const int SCSI_TEST_UNIT_READY = 0x00; const int SCSI_TEST_UNIT_READY = 0x00;
private const int SCSI_REQUEST_SENSE = 0x03; const int SCSI_REQUEST_SENSE = 0x03;
private const int SCSI_READ = 0x08; const int SCSI_READ = 0x08;
private const int SCSI_AUDIO_START_POS = 0xD8; const int SCSI_AUDIO_START_POS = 0xD8;
private const int SCSI_AUDIO_END_POS = 0xD9; const int SCSI_AUDIO_END_POS = 0xD9;
private const int SCSI_PAUSE = 0xDA; const int SCSI_PAUSE = 0xDA;
private const int SCSI_READ_SUBCODE_Q = 0xDD; const int SCSI_READ_SUBCODE_Q = 0xDD;
private const int SCSI_READ_TOC = 0xDE; const int SCSI_READ_TOC = 0xDE;
private bool bsy, sel, cd, io, msg, req, ack, atn, rst; bool bsy, sel, cd, io, msg, req, ack, atn, rst;
private bool signalsChanged; bool signalsChanged;
public bool BSY public bool BSY
{ {
@ -106,7 +106,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
public byte DataBits { get; set; } // data bits public byte DataBits { get; set; } // data bits
private enum BusPhase enum BusPhase
{ {
BusFree, BusFree,
Command, Command,
@ -117,14 +117,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Status Status
} }
private bool busPhaseChanged; bool busPhaseChanged;
private BusPhase Phase = BusPhase.BusFree; BusPhase Phase = BusPhase.BusFree;
private bool MessageCompleted; bool MessageCompleted;
private bool StatusCompleted; bool StatusCompleted;
private byte MessageValue; 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 public QuickQueue<byte> DataIn = new QuickQueue<byte>(2048); // one data sector
// ******** Data Transfer / READ command support ******** // ******** Data Transfer / READ command support ********
@ -138,7 +138,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// ******** Resources ******** // ******** Resources ********
private PCEngine pce; PCEngine pce;
public Disc disc; public Disc disc;
// ******** Events ******** // ******** Events ********
@ -218,7 +218,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} while (signalsChanged || busPhaseChanged); } while (signalsChanged || busPhaseChanged);
} }
private void ResetDevice() void ResetDevice()
{ {
CD = false; CD = false;
IO = false; IO = false;
@ -235,7 +235,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
pce.CDAudio.Stop(); pce.CDAudio.Stop();
} }
private void ThinkCommandPhase() void ThinkCommandPhase()
{ {
if (REQ && ACK) if (REQ && ACK)
{ {
@ -258,7 +258,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
private void ThinkDataInPhase() void ThinkDataInPhase()
{ {
if (REQ && ACK) 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? ****************"); Console.WriteLine("*********** DATA OUT PHASE, DOES THIS HAPPEN? ****************");
SetPhase(BusPhase.BusFree); SetPhase(BusPhase.BusFree);
} }
private void ThinkMessageInPhase() void ThinkMessageInPhase()
{ {
if (REQ && ACK) 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? ********"); Console.WriteLine("******* IN MESSAGE OUT PHASE. DOES THIS EVER HAPPEN? ********");
SetPhase(BusPhase.BusFree); SetPhase(BusPhase.BusFree);
} }
private void ThinkStatusPhase() void ThinkStatusPhase()
{ {
if (REQ && ACK) if (REQ && ACK)
{ {
@ -329,13 +329,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
// returns true if command completed, false if more data bytes needed // returns true if command completed, false if more data bytes needed
private bool CheckCommandBuffer() bool CheckCommandBuffer()
{ {
switch (CommandBuffer[0]) switch (CommandBuffer[0])
{ {
case SCSI_TEST_UNIT_READY: case SCSI_TEST_UNIT_READY:
if (CommandBuffer.Count < 6) return false; if (CommandBuffer.Count < 6) return false;
Log.Note("CD", "Execute TEST_UNIT_READY");
SetStatusMessage(STATUS_GOOD, 0); SetStatusMessage(STATUS_GOOD, 0);
return true; return true;
@ -371,12 +370,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
default: default:
Console.WriteLine("UNRECOGNIZED SCSI COMMAND! {0:X2}", CommandBuffer[0]); Console.WriteLine("UNRECOGNIZED SCSI COMMAND! {0:X2}", CommandBuffer[0]);
SetStatusMessage(STATUS_GOOD, 0);
break; break;
} }
return false; return false;
} }
private void CommandRead() void CommandRead()
{ {
int sector = (CommandBuffer[1] & 0x1f) << 16; int sector = (CommandBuffer[1] & 0x1f) << 16;
sector |= CommandBuffer[2] << 8; sector |= CommandBuffer[2] << 8;
@ -395,16 +395,16 @@ throw new Exception("requesting 0 sectors read.............................");
pce.CDAudio.Stop(); pce.CDAudio.Stop();
} }
private int audioStartLBA; int audioStartLBA;
private int audioEndLBA; int audioEndLBA;
private void CommandAudioStartPos() void CommandAudioStartPos()
{ {
switch (CommandBuffer[9] & 0xC0) switch (CommandBuffer[9] & 0xC0)
{ {
case 0x00: // Set start offset in LBA units case 0x00: // Set start offset in LBA units
audioStartLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5]; audioStartLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5];
Console.WriteLine("Set Start LBA: "+audioStartLBA); //Console.WriteLine("Set Start LBA: "+audioStartLBA);
break; break;
case 0x40: // Set start offset in MSF units 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 s = CommandBuffer[3].BCDtoBin();
byte f = CommandBuffer[4].BCDtoBin(); byte f = CommandBuffer[4].BCDtoBin();
audioStartLBA = Disc.ConvertMSFtoLBA(m, s, f); 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; break;
case 0x80: // Set start offset in track units case 0x80: // Set start offset in track units
byte trackNo = CommandBuffer[2].BCDtoBin(); byte trackNo = CommandBuffer[2].BCDtoBin();
audioStartLBA = disc.TOC.Sessions[0].Tracks[trackNo - 1].Indexes[1].aba - 150; 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; break;
} }
@ -438,13 +438,13 @@ throw new Exception("requesting 0 sectors read.............................");
// irq callback? // irq callback?
} }
private void CommandAudioEndPos() void CommandAudioEndPos()
{ {
switch (CommandBuffer[9] & 0xC0) switch (CommandBuffer[9] & 0xC0)
{ {
case 0x00: // Set end offset in LBA units case 0x00: // Set end offset in LBA units
audioEndLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5]; audioEndLBA = (CommandBuffer[3] << 16) | (CommandBuffer[4] << 8) | CommandBuffer[5];
Console.WriteLine("Set End LBA: " + audioEndLBA); //Console.WriteLine("Set End LBA: " + audioEndLBA);
break; break;
case 0x40: // Set end offset in MSF units 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 s = CommandBuffer[3].BCDtoBin();
byte f = CommandBuffer[4].BCDtoBin(); byte f = CommandBuffer[4].BCDtoBin();
audioEndLBA = Disc.ConvertMSFtoLBA(m, s, f); 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; break;
case 0x80: // Set end offset in track units case 0x80: // Set end offset in track units
@ -461,7 +461,7 @@ throw new Exception("requesting 0 sectors read.............................");
audioEndLBA = disc.LBACount; audioEndLBA = disc.LBACount;
else else
audioEndLBA = disc.TOC.Sessions[0].Tracks[trackNo - 1].Indexes[1].aba - 150; 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; break;
} }
@ -471,7 +471,7 @@ throw new Exception("requesting 0 sectors read.............................");
pce.CDAudio.Stop(); pce.CDAudio.Stop();
break; break;
case 1: // play in loop mode. I guess this constitues A-B looping 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.PlayStartingAtLba(audioStartLBA);
pce.CDAudio.EndLBA = audioEndLBA; pce.CDAudio.EndLBA = audioEndLBA;
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.LoopOnCompletion; pce.CDAudio.PlayMode = CDAudio.PlaybackMode.LoopOnCompletion;
@ -483,7 +483,7 @@ throw new Exception("requesting 0 sectors read.............................");
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.CallbackOnCompletion; pce.CDAudio.PlayMode = CDAudio.PlaybackMode.CallbackOnCompletion;
break; break;
case 3: // Play normal 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.PlayStartingAtLba(audioStartLBA);
pce.CDAudio.EndLBA = audioEndLBA; pce.CDAudio.EndLBA = audioEndLBA;
pce.CDAudio.PlayMode = CDAudio.PlaybackMode.StopOnCompletion; pce.CDAudio.PlayMode = CDAudio.PlaybackMode.StopOnCompletion;
@ -492,7 +492,7 @@ throw new Exception("requesting 0 sectors read.............................");
SetStatusMessage(STATUS_GOOD, 0); SetStatusMessage(STATUS_GOOD, 0);
} }
private void CommandPause() void CommandPause()
{ {
// apparently pause means stop? I guess? Idunno. // apparently pause means stop? I guess? Idunno.
pce.CDAudio.Stop(); pce.CDAudio.Stop();
@ -500,9 +500,12 @@ throw new Exception("requesting 0 sectors read.............................");
// TODO send error if already stopped.. or paused... or something. // TODO send error if already stopped.. or paused... or something.
} }
private void CommandReadSubcodeQ() void CommandReadSubcodeQ()
{ {
Console.WriteLine("poll subcode"); 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); var sectorEntry = disc.ReadLBA_SectorEntry(pce.CDAudio.CurrentSector);
DataIn.Clear(); DataIn.Clear();
@ -526,13 +529,13 @@ throw new Exception("requesting 0 sectors read.............................");
SetPhase(BusPhase.DataIn); SetPhase(BusPhase.DataIn);
} }
private void CommandReadTOC() void CommandReadTOC()
{ {
switch (CommandBuffer[1]) switch (CommandBuffer[1])
{ {
case 0: // return number of tracks 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.Clear();
DataIn.Enqueue(0x01); DataIn.Enqueue(0x01);
DataIn.Enqueue(((byte) disc.TOC.Sessions[0].Tracks.Count).BinToBCD()); 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()); DataIn.Enqueue(f.BinToBCD());
SetPhase(BusPhase.DataIn); SetPhase(BusPhase.DataIn);
Log.Error("CD","EXECUTE READ_TOC : length of disc, LBA {0}, m:{1},s:{2},f:{3}", //Log.Error("CD","EXECUTE READ_TOC : length of disc, LBA {0}, m:{1},s:{2},f:{3}",
totalLbaLength, m, s, f); //totalLbaLength, m, s, f);
break; break;
} }
case 2: // Return starting position of specified track in MSF format 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); DataIn.Enqueue(4);
SetPhase(BusPhase.DataIn); SetPhase(BusPhase.DataIn);
Log.Error("CD", "EXECUTE READ_TOC : start pos of TRACK {4}, LBA {0}, m:{1},s:{2},f:{3}", //Log.Error("CD", "EXECUTE READ_TOC : start pos of TRACK {4}, LBA {0}, m:{1},s:{2},f:{3}",
lbaPos, m, s, f, track); //lbaPos, m, s, f, track);
break; 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; MessageValue = message;
StatusCompleted = false; StatusCompleted = false;
@ -601,7 +604,7 @@ throw new Exception("requesting 0 sectors read.............................");
SetPhase(BusPhase.Status); SetPhase(BusPhase.Status);
} }
private void SetPhase(BusPhase phase) void SetPhase(BusPhase phase)
{ {
if (Phase == phase) if (Phase == phase)
return; return;

View File

@ -3,7 +3,7 @@
// IRQ2 interrupts: // IRQ2 interrupts:
// 0x04 - INTA - ADPCM interrupt // 0x04 - INTA - ADPCM interrupt
// 0x08 - INTSTOP - Fire when end of CD-Audio playback reached when in STOP MODE 2. // 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 // 0x20 - INTM - Fires when data transfer is complete
// 0x40 - INTD - Fires when data transfer is ready // 0x40 - INTD - Fires when data transfer is ready
@ -11,11 +11,22 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
public partial class PCEngine 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 IRQ2Control { get { return CdIoPorts[2]; } set { CdIoPorts[2] = value; } }
public byte IRQ2Monitor { get { return CdIoPorts[3]; } set { CdIoPorts[3] = 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() void InitScsiBus()
{ {
SCSI = new ScsiCDBus(this, disc); SCSI = new ScsiCDBus(this, disc);
@ -24,18 +35,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{ {
// set or clear Ready Bit // set or clear Ready Bit
if (yes) if (yes)
CdIoPorts[3] |= 0x40; Port1803 |= 0x40;
else else
CdIoPorts[3] &= 0xBF; Port1803 &= 0xBF;
}; };
SCSI.DataTransferComplete = yes => SCSI.DataTransferComplete = yes =>
{ {
if (yes) if (yes)
CdIoPorts[3] |= 0x20; // Set "Complete" Port1803 |= 0x20; // Set "Complete"
else 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] & 0x10) != 0) Log.Error("CD", "INTSUB enable");
if ((CdIoPorts[2] & 0x20) != 0) Log.Error("CD", "INTM enable"); if ((CdIoPorts[2] & 0x20) != 0) Log.Error("CD", "INTM enable");
if ((CdIoPorts[2] & 0x40) != 0) Log.Error("CD", "INTD 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(); SCSI.Think();
RefreshIRQ2(); RefreshIRQ2();
@ -87,7 +98,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SCSI.Think(); SCSI.Think();
if (SCSI.RST) if (SCSI.RST)
{ {
CdIoPorts[3] &= 0x8F; // Clear interrupt control bits Port1803 &= 0x8F; // Clear interrupt control bits
RefreshIRQ2(); RefreshIRQ2();
} }
break; break;
@ -99,32 +110,29 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x1807: // BRAM Unlock case 0x1807: // BRAM Unlock
if (BramEnabled && (value & 0x80) != 0) if (BramEnabled && (value & 0x80) != 0)
{
//Console.WriteLine("UNLOCK BRAM!");
BramLocked = false; BramLocked = false;
}
break; break;
case 0x1808: // ADPCM address LSB case 0x1808: // ADPCM address LSB
ADPCM.adpcm_io_address &= 0xFF00; ADPCM.IOAddress &= 0xFF00;
ADPCM.adpcm_io_address |= value; ADPCM.IOAddress |= value;
if ((CdIoPorts[0x0D] & 0x10) != 0) if ((CdIoPorts[0x0D] & 0x10) != 0)
{ {
Console.WriteLine("doing silly thing"); 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; break;
case 0x1809: // ADPCM address MSB case 0x1809: // ADPCM address MSB
ADPCM.adpcm_io_address &= 0x00FF; ADPCM.IOAddress &= 0x00FF;
ADPCM.adpcm_io_address |= (ushort)(value << 8); ADPCM.IOAddress |= (ushort)(value << 8);
if ((CdIoPorts[0x0D] & 0x10) != 0) if ((CdIoPorts[0x0D] & 0x10) != 0)
{ {
Console.WriteLine("doing silly thing"); 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; break;
case 0x180A: // ADPCM Memory Read/Write Port case 0x180A: // ADPCM Memory Read/Write Port
@ -133,7 +141,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x180B: // ADPCM DMA Control case 0x180B: // ADPCM DMA Control
ADPCM.Port180B = value; 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) if (ADPCM.AdpcmCdDmaRequested)
Console.WriteLine(" ADPCM DMA REQUESTED"); Console.WriteLine(" ADPCM DMA REQUESTED");
break; break;
@ -144,12 +152,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x180E: // ADPCM Playback Rate case 0x180E: // ADPCM Playback Rate
ADPCM.Port180E = value; 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; break;
case 0x180F: // Audio Fade Timer case 0x180F: // Audio Fade Timer
CdIoPorts[0x0F] = value; 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. // TODO ADPCM fades/vol control also.
switch (value) switch (value)
@ -206,8 +214,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (BramEnabled) if (BramEnabled)
BramLocked = true; BramLocked = true;
Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC); //Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC);
returnValue = CdIoPorts[3]; returnValue = Port1803;
CdIoPorts[3] ^= 2; CdIoPorts[3] ^= 2;
return returnValue; return returnValue;
@ -216,19 +224,21 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
return CdIoPorts[4]; return CdIoPorts[4];
case 0x1805: // CD audio data Low case 0x1805: // CD audio data Low
if ((CdIoPorts[0x3] & 0x2) == 0) if ((Port1803 & 0x2) == 0)
sample = CDAudio.VolumeLeft; sample = CDAudio.VolumeLeft;
else else
sample = CDAudio.VolumeRight; sample = CDAudio.VolumeRight;
return (byte) sample; return (byte) sample;
case 0x1806: // CD audio data High case 0x1806: // CD audio data High
if ((CdIoPorts[0x3] & 0x2) == 0) if ((Port1803 & 0x2) == 0)
sample = CDAudio.VolumeLeft; sample = CDAudio.VolumeLeft;
else else
sample = CDAudio.VolumeRight; sample = CDAudio.VolumeRight;
return (byte) (sample >> 8); return (byte) (sample >> 8);
// wow, nothing ever reads 1807 yet
case 0x1808: // Auto Handshake Data Input case 0x1808: // Auto Handshake Data Input
returnValue = SCSI.DataBits; returnValue = SCSI.DataBits;
if (SCSI.REQ && SCSI.IO && !SCSI.CD) if (SCSI.REQ && SCSI.IO && !SCSI.CD)
@ -266,7 +276,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
return CdIoPorts[0x0D]; return CdIoPorts[0x0D];
case 0x180F: // Audio Fade Timer 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]; return CdIoPorts[0x0F];
// These are some retarded version check // These are some retarded version check
@ -285,7 +295,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public void RefreshIRQ2() public void RefreshIRQ2()
{ {
int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C; int mask = CdIoPorts[2] & Port1803 & 0x7C;
Cpu.IRQ2Assert = (mask != 0); Cpu.IRQ2Assert = (mask != 0);
} }
} }

View File

@ -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) public void PrecomputePalette(int slot)
{ {

View File

@ -23,11 +23,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public int RCRCounter; public int RCRCounter;
public int ActiveLine; public int ActiveLine;
private byte[] PriorityBuffer = new byte[512];
private byte[] InterSpritePriorityBuffer = new byte[512];
public int HBlankCycles = 79; public int HBlankCycles = 79;
public bool PerformSpriteLimit; public bool PerformSpriteLimit;
byte[] PriorityBuffer = new byte[512];
byte[] InterSpritePriorityBuffer = new byte[512];
public void ExecFrame(bool render) public void ExecFrame(bool render)
{ {
if (MultiResHack > 0 && render) if (MultiResHack > 0 && render)
@ -111,7 +112,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
RenderSpritesScanline(); RenderSpritesScanline();
} }
private void RenderBackgroundScanline() void RenderBackgroundScanline()
{ {
Array.Clear(PriorityBuffer, 0, FrameWidth); 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() public void RenderSpritesScanline()
{ {
@ -337,10 +338,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
private int FramePitch = 256; int FramePitch = 256;
private int FrameWidth = 256; int FrameWidth = 256;
private int FrameHeight = 240; int FrameHeight = 240;
private int[] FrameBuffer = new int[256 * 240]; int[] FrameBuffer = new int[256 * 240];
public int[] GetVideoBuffer() public int[] GetVideoBuffer()
{ {

View File

@ -52,29 +52,29 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public int DisplayStartLine { get { return (Registers[VPR] >> 8) + (Registers[VPR] & 0x1F); } } public int DisplayStartLine { get { return (Registers[VPR] >> 8) + (Registers[VPR] & 0x1F); } }
private const int MAWR = 0; // Memory Address Write Register const int MAWR = 0; // Memory Address Write Register
private const int MARR = 1; // Memory Address Read Register const int MARR = 1; // Memory Address Read Register
private const int VRR = 2; // VRAM Read Register const int VRR = 2; // VRAM Read Register
private const int VWR = 2; // VRAM Write Register const int VWR = 2; // VRAM Write Register
private const int CR = 5; // Control Register const int CR = 5; // Control Register
private const int RCR = 6; // Raster Compare Register const int RCR = 6; // Raster Compare Register
private const int BXR = 7; // Background X-scroll Register const int BXR = 7; // Background X-scroll Register
private const int BYR = 8; // Background Y-scroll Register const int BYR = 8; // Background Y-scroll Register
private const int MWR = 9; // Memory-access Width Register const int MWR = 9; // Memory-access Width Register
private const int HSR = 10; // Horizontal Sync Register const int HSR = 10; // Horizontal Sync Register
private const int HDR = 11; // Horizontal Display Register const int HDR = 11; // Horizontal Display Register
private const int VPR = 12; // Vertical synchronous register const int VPR = 12; // Vertical synchronous register
private const int VDW = 13; // Vertical display register const int VDW = 13; // Vertical display register
private const int VCR = 14; // Vertical display END position register; const int VCR = 14; // Vertical display END position register;
private const int DCR = 15; // DMA Control Register const int DCR = 15; // DMA Control Register
private const int SOUR = 16; // Source address for DMA const int SOUR = 16; // Source address for DMA
private const int DESR = 17; // Destination address for DMA const int DESR = 17; // Destination address for DMA
private const int LENR = 18; // Length of DMA transfer. Writing this will initiate DMA. 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 SATB = 19; // Sprite Attribute Table base location in VRAM
private const int RegisterSelect = 0; const int RegisterSelect = 0;
private const int LSB = 2; const int LSB = 2;
private const int MSB = 3; const int MSB = 3;
public const byte StatusVerticalBlanking = 0x20; public const byte StatusVerticalBlanking = 0x20;
public const byte StatusVramVramDmaComplete = 0x10; public const byte StatusVramVramDmaComplete = 0x10;
@ -83,10 +83,10 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public const byte StatusSpriteOverflow = 0x02; public const byte StatusSpriteOverflow = 0x02;
public const byte StatusSprite0Collision = 0x01; public const byte StatusSprite0Collision = 0x01;
private const int VramSize = 0x8000; const int VramSize = 0x8000;
private HuC6280 cpu; HuC6280 cpu;
private VCE vce; VCE vce;
public int MultiResHack = 0; public int MultiResHack = 0;
@ -126,7 +126,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
private void CompleteMSBWrite(int register) void CompleteMSBWrite(int register)
{ {
switch (register) switch (register)
{ {
@ -206,7 +206,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
internal void RunDmaForScanline() internal void RunDmaForScanline()
{ {
// TODO: dont do this all in one scanline. I guess it can do about 227 words per scanline. // 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 advanceSource = (Registers[DCR] & 4) == 0 ? +1 : -1;
int advanceDest = (Registers[DCR] & 8) == 0 ? +1 : -1; int advanceDest = (Registers[DCR] & 8) == 0 ? +1 : -1;
int wordsDone = 0; int wordsDone = 0;

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public VDC VDC1; public VDC VDC1;
public VDC VDC2; public VDC VDC2;
public VCE VCE; public VCE VCE;
private HuC6280 CPU; public HuC6280 CPU;
public byte[] Registers = {0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00}; 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. // And there are no homebrew SGX games I know of.
// Maybe we'll emulate it in the native-code version. // Maybe we'll emulate it in the native-code version.
private const int RCR = 6; const int RCR = 6;
private const int BXR = 7; const int BXR = 7;
private const int BYR = 8; const int BYR = 8;
private const int VDW = 13; const int VDW = 13;
private const int DCR = 15; const int DCR = 15;
private int EffectivePriorityMode = 0; int EffectivePriorityMode = 0;
private int FrameHeight; int FrameHeight;
private int FrameWidth; int FrameWidth;
private int[] FrameBuffer; int[] FrameBuffer;
private byte[] PriorityBuffer = new byte[512]; byte[] PriorityBuffer = new byte[512];
private byte[] InterSpritePriorityBuffer = new byte[512]; byte[] InterSpritePriorityBuffer = new byte[512];
public void ExecFrame(bool render) public void ExecFrame(bool render)
{ {
@ -255,7 +255,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
private void RenderScanLine() void RenderScanLine()
{ {
if (VDC1.ActiveLine >= FrameHeight) if (VDC1.ActiveLine >= FrameHeight)
return; return;
@ -279,7 +279,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
private void InitializeScanLine(int scanline) void InitializeScanLine(int scanline)
{ {
// Clear priority buffer // Clear priority buffer
Array.Clear(PriorityBuffer, 0, FrameWidth); Array.Clear(PriorityBuffer, 0, FrameWidth);
@ -289,7 +289,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
FrameBuffer[(scanline * FrameWidth) + i] = VCE.Palette[0]; FrameBuffer[(scanline * FrameWidth) + i] = VCE.Palette[0];
} }
private void RenderBackgroundScanline(VDC vdc, byte priority) void RenderBackgroundScanline(VDC vdc, byte priority)
{ {
if (vdc.BackgroundEnabled == false) if (vdc.BackgroundEnabled == false)
return; 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) if (vdc.SpritesEnabled == false)
return; return;

View File

@ -16,7 +16,7 @@
public ControllerDefinition ControllerDefinition { get { return SmsController; } } public ControllerDefinition ControllerDefinition { get { return SmsController; } }
public IController Controller { get; set; } public IController Controller { get; set; }
private byte ReadControls1() byte ReadControls1()
{ {
lagged = false; lagged = false;
byte value = 0xFF; byte value = 0xFF;
@ -34,7 +34,7 @@
return value; return value;
} }
private byte ReadControls2() byte ReadControls2()
{ {
lagged = false; lagged = false;
byte value = 0xFF; byte value = 0xFF;
@ -64,7 +64,7 @@
return value; return value;
} }
private byte ReadPort0() byte ReadPort0()
{ {
if (IsGameGear == false) if (IsGameGear == false)
return 0xFF; return 0xFF;

View File

@ -9,7 +9,7 @@
// Bank 2: Control Address $8000 - Maps $8000 - $BFFF // Bank 2: Control Address $8000 - Maps $8000 - $BFFF
// System RAM is at $C000+ as in the Sega mapper. // 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 * 1) return RomData[(RomBank0 * BankSize) + address];
if (address < BankSize * 2) return RomData[(RomBank1 * BankSize) + (address & BankSizeMask)]; if (address < BankSize * 2) return RomData[(RomBank1 * BankSize) + (address & BankSizeMask)];
@ -18,7 +18,7 @@
return SystemRam[address & RamSizeMask]; return SystemRam[address & RamSizeMask];
} }
private void WriteMemoryCM(ushort address, byte value) void WriteMemoryCM(ushort address, byte value)
{ {
if (address >= 0xC000) if (address >= 0xC000)
SystemRam[address & RamSizeMask] = value; SystemRam[address & RamSizeMask] = value;
@ -28,7 +28,7 @@
else if (address == 0x8000) RomBank2 = (byte)(value % RomBanks); else if (address == 0x8000) RomBank2 = (byte)(value % RomBanks);
} }
private void InitCodeMastersMapper() void InitCodeMastersMapper()
{ {
Cpu.ReadMemory = ReadMemoryCM; Cpu.ReadMemory = ReadMemoryCM;
Cpu.WriteMemory = WriteMemoryCM; Cpu.WriteMemory = WriteMemoryCM;

View File

@ -14,10 +14,10 @@
// $FFFE - Mapper slot 1 control // $FFFE - Mapper slot 1 control
// $FFFF - Mapper slot 2 control // $FFFF - Mapper slot 2 control
private const ushort BankSizeMask = 0x3FFF; const ushort BankSizeMask = 0x3FFF;
private const ushort RamSizeMask = 0x1FFF; const ushort RamSizeMask = 0x1FFF;
private byte ReadMemory(ushort address) byte ReadMemory(ushort address)
{ {
if (address < 1024) if (address < 1024)
return RomData[address]; return RomData[address];
@ -37,7 +37,7 @@
return SystemRam[address & RamSizeMask]; return SystemRam[address & RamSizeMask];
} }
private void WriteMemory(ushort address, byte value) void WriteMemory(ushort address, byte value)
{ {
if (address >= 0xC000) if (address >= 0xC000)
SystemRam[address & RamSizeMask] = value; SystemRam[address & RamSizeMask] = value;
@ -68,7 +68,7 @@
} }
} }
private void InitSegaMapper() void InitSegaMapper()
{ {
Cpu.ReadMemory = ReadMemory; Cpu.ReadMemory = ReadMemory;
Cpu.WriteMemory = WriteMemory; Cpu.WriteMemory = WriteMemory;
@ -80,9 +80,9 @@
// Mapper when loading a BIOS as a ROM // 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) if (BiosMapped == false && address < BankSize * 3)
return 0x00; return 0x00;
@ -99,7 +99,7 @@
return SystemRam[address & RamSizeMask]; return SystemRam[address & RamSizeMask];
} }
private void WriteMemoryBIOS(ushort address, byte value) void WriteMemoryBIOS(ushort address, byte value)
{ {
if (address >= 0xC000) if (address >= 0xC000)
SystemRam[address & RamSizeMask] = value; SystemRam[address & RamSizeMask] = value;
@ -113,7 +113,7 @@
} }
} }
private void InitBiosMapper() void InitBiosMapper()
{ {
Cpu.ReadMemory = ReadMemoryBIOS; Cpu.ReadMemory = ReadMemoryBIOS;
Cpu.WriteMemory = WriteMemoryBIOS; Cpu.WriteMemory = WriteMemoryBIOS;
@ -123,4 +123,4 @@
WriteMemory(0xFFFF, 2); WriteMemory(0xFFFF, 2);
} }
} }
} }

View File

@ -43,9 +43,9 @@ namespace BizHawk.Emulation.Consoles.Sega
public bool IsGameGear = false; public bool IsGameGear = false;
public bool HasYM2413 = false; public bool HasYM2413 = false;
private int _lagcount = 0; int _lagcount = 0;
private bool lagged = true; bool lagged = true;
private bool islag = false; bool islag = false;
public int Frame { get; set; } public int Frame { get; set; }
public void ResetFrameCounter() public void ResetFrameCounter()
@ -55,10 +55,10 @@ namespace BizHawk.Emulation.Consoles.Sega
public int LagCount { get { return _lagcount; } set { _lagcount = value; } } public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
public bool IsLagFrame { get { return islag; } } public bool IsLagFrame { get { return islag; } }
private byte Port01 = 0xFF; byte Port01 = 0xFF;
private byte Port02 = 0xFF; byte Port02 = 0xFF;
private byte Port3E = 0xAF; byte Port3E = 0xAF;
private byte Port3F = 0xFF; byte Port3F = 0xFF;
public DisplayType DisplayType { get; set; } public DisplayType DisplayType { get; set; }
public bool DeterministicEmulation { get; set; } public bool DeterministicEmulation { get; set; }
@ -325,12 +325,12 @@ namespace BizHawk.Emulation.Consoles.Sega
public CoreInputComm CoreInputComm { get; set; } public CoreInputComm CoreInputComm { get; set; }
public CoreOutputComm CoreOutputComm { get; private set; } public CoreOutputComm CoreOutputComm { get; private set; }
private ISoundProvider ActiveSoundProvider; ISoundProvider ActiveSoundProvider;
public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } } public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } }
public string SystemId { get { return "SMS"; } } public string SystemId { get { return "SMS"; } }
private string region = "Export"; string region = "Export";
public string Region public string Region
{ {
get { return 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 domains = new List<MemoryDomain>(3);
var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, Endian.Little, var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, Endian.Little,

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Consoles.Sega
{ {
public partial class VDP public partial class VDP
{ {
private int[] PaletteTMS9918 = new int[] int[] PaletteTMS9918 = new int[]
{ {
unchecked((int)0x00000000), unchecked((int)0x00000000),
unchecked((int)0xFF000000), unchecked((int)0xFF000000),
@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Consoles.Sega
unchecked((int)0xFFFFFFFF) unchecked((int)0xFFFFFFFF)
}; };
private void RenderBackgroundM0() void RenderBackgroundM0()
{ {
if (DisplayOn == false) if (DisplayOn == false)
{ {
@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Consoles.Sega
} }
} }
private void RenderBackgroundM2() void RenderBackgroundM2()
{ {
if (DisplayOn == false) if (DisplayOn == false)
{ {
@ -98,7 +98,7 @@ namespace BizHawk.Emulation.Consoles.Sega
} }
} }
private void RenderTmsSprites() void RenderTmsSprites()
{ {
if (DisplayOn == false) return; if (DisplayOn == false) return;

View File

@ -3,7 +3,7 @@
public partial class VDP public partial class VDP
{ {
// TODO: HCounter // 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, 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, 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, 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, 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, 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, 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, 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, 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 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, 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, 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 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, 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, 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 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, 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, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,

View File

@ -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[] Registers = new byte[] { 0x06, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 };
public byte StatusByte; public byte StatusByte;
private bool VdpWaitingForLatchByte = true; bool VdpWaitingForLatchByte = true;
private byte VdpLatch; byte VdpLatch;
private byte VdpBuffer; byte VdpBuffer;
private ushort VdpAddress; ushort VdpAddress;
private VdpCommand vdpCommand; VdpCommand vdpCommand;
private int TmsMode = 4; int TmsMode = 4;
private bool VIntPending; bool VIntPending;
private bool HIntPending; bool HIntPending;
private VdpMode mode; VdpMode mode;
public VdpMode VdpMode { get { return mode; } } DisplayType DisplayType = DisplayType.NTSC;
private DisplayType DisplayType = DisplayType.NTSC; Z80A Cpu;
private Z80A Cpu;
public int IPeriod = 228; public int IPeriod = 228;
public VdpMode VdpMode { get { return mode; } }
int FrameHeight = 192;
public int ScanLine; public int ScanLine;
private int FrameHeight = 192;
public int[] FrameBuffer = new int[256*192]; public int[] FrameBuffer = new int[256*192];
public int[] GameGearFrameBuffer = new int[160*144]; 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 int SpriteTileBase { get { return (Registers[6] & 4) > 0 ? 256: 0; } }
public byte BackdropColor { get { return (byte)(16 + (Registers[7] & 15)); } } public byte BackdropColor { get { return (byte)(16 + (Registers[7] & 15)); } }
private int NameTableBase; int NameTableBase;
private int ColorTableBase; int ColorTableBase;
private int PatternGeneratorBase; int PatternGeneratorBase;
private int SpritePatternGeneratorBase; int SpritePatternGeneratorBase;
private int TmsPatternNameTableBase; int TmsPatternNameTableBase;
private int TmsSpriteAttributeBase; int TmsSpriteAttributeBase;
// preprocessed state assist stuff. // preprocessed state assist stuff.
public int[] Palette = new int[32]; public int[] Palette = new int[32];
public byte[] PatternBuffer = new byte[0x8000]; public byte[] PatternBuffer = new byte[0x8000];
private byte[] ScanlinePriorityBuffer = new byte[256]; byte[] ScanlinePriorityBuffer = new byte[256];
private byte[] SpriteCollisionBuffer = new byte[256]; byte[] SpriteCollisionBuffer = new byte[256];
private static readonly byte[] SMSPalXlatTable = { 0, 85, 170, 255 }; 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[] 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) public VDP(Z80A cpu, VdpMode mode, DisplayType displayType)
{ {
@ -205,7 +205,7 @@ namespace BizHawk.Emulation.Consoles.Sega
return (1024 * (Registers[2] & 0x0C)) + 0x0700; return (1024 * (Registers[2] & 0x0C)) + 0x0700;
} }
private void CheckVideoMode() void CheckVideoMode()
{ {
if (Mode4Bit == false) // check old TMS modes 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; Registers[reg] = data;
switch(reg) 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. // writing one byte affects 8 pixels due to stupid planar storage.
for (int i=0; i<8; i++) 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) if (ScanLine == FrameHeight + 1)
{ {
@ -323,7 +323,7 @@ namespace BizHawk.Emulation.Consoles.Sega
Cpu.Interrupt = true; Cpu.Interrupt = true;
} }
private void ProcessLineInterrupt() void ProcessLineInterrupt()
{ {
if (ScanLine <= FrameHeight) if (ScanLine <= FrameHeight)
{ {

View File

@ -9,7 +9,7 @@ namespace BizHawk
// There is less overhead by not being dynamically resizable and stuff. // There is less overhead by not being dynamically resizable and stuff.
public sealed class QuickList<T> where T : struct public sealed class QuickList<T> where T : struct
{ {
private T[] buffer; T[] buffer;
public int Position; public int Position;
public QuickList(int capacity) 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. // only intended to be used with value types. If used on references you may get GC issues.
public class QuickQueue<T> where T : struct public class QuickQueue<T> where T : struct
{ {
private T[] buffer; T[] buffer;
private int head; int head;
private int tail; int tail;
private int size; int size;
public QuickQueue(int capacity) public QuickQueue(int capacity)
{ {
@ -101,7 +101,7 @@ namespace BizHawk
// .net has no built-in read only dictionary // .net has no built-in read only dictionary
public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey,TValue> public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey,TValue>
{ {
private IDictionary<TKey, TValue> dict; IDictionary<TKey, TValue> dict;
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary) public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{ {

View File

@ -39,8 +39,8 @@ namespace BizHawk.Emulation.Sound
public int PlayingTrack; public int PlayingTrack;
public int CurrentSector, SectorOffset; // Offset is in SAMPLES, not bytes. Sector is 588 samples long. public int CurrentSector, SectorOffset; // Offset is in SAMPLES, not bytes. Sector is 588 samples long.
private int CachedSector; int CachedSector;
private byte[] SectorCache = new byte[2352]; byte[] SectorCache = new byte[2352];
public int FadeOutOverFrames = 0; public int FadeOutOverFrames = 0;
public int FadeOutFramesRemaining = 0; public int FadeOutFramesRemaining = 0;
@ -70,6 +70,8 @@ namespace BizHawk.Emulation.Sound
public void PlayStartingAtLba(int lba) public void PlayStartingAtLba(int lba)
{ {
var point = Disc.TOC.SeekPoint(lba); var point = Disc.TOC.SeekPoint(lba);
if (point == null) return;
PlayingTrack = point.TrackNum; PlayingTrack = point.TrackNum;
StartLBA = lba; StartLBA = lba;
EndLBA = point.Track.Indexes[1].aba + point.Track.length_aba - 150; EndLBA = point.Track.Indexes[1].aba + point.Track.length_aba - 150;
@ -120,7 +122,7 @@ namespace BizHawk.Emulation.Sound
FadeOutFramesRemaining = frames; FadeOutFramesRemaining = frames;
} }
private void EnsureSector() void EnsureSector()
{ {
if (CachedSector != CurrentSector) if (CachedSector != CurrentSector)
{ {

View File

@ -147,13 +147,13 @@ namespace BizHawk.Emulation.Sound
MixSamples(samples, start, samples.Length - start); 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++) for (int i = 0; i < 6; i++)
MixChannel(samples, start, len, Channels[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.Enabled == false) return;
if (channel.DDA == false && channel.Volume == 0) 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) while (true)
{ {

View File

@ -21,8 +21,8 @@ namespace BizHawk.Emulation.Sound
public bool Left = true; public bool Left = true;
public bool Right = true; public bool Right = true;
private const int SampleRate = 44100; const int SampleRate = 44100;
private static byte[] LogScale = { 0, 10, 13, 16, 20, 26, 32, 40, 51, 64, 81, 102, 128, 161, 203, 255 }; 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) 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 Channel[] Channels = new Channel[4];
public byte PsgLatch; public byte PsgLatch;
private Queue<QueuedCommand> commands = new Queue<QueuedCommand>(256); Queue<QueuedCommand> commands = new Queue<QueuedCommand>(256);
private int frameStartTime, frameStopTime; int frameStartTime, frameStopTime;
private const int PsgBase = 111861; const int PsgBase = 111861;
public SN76489() public SN76489()
{ {
@ -107,7 +107,7 @@ namespace BizHawk.Emulation.Sound
commands.Enqueue(new QueuedCommand {Value = value, Time = cycles-frameStartTime}); commands.Enqueue(new QueuedCommand {Value = value, Time = cycles-frameStartTime});
} }
private void UpdateNoiseType(int value) void UpdateNoiseType(int value)
{ {
Channels[3].NoiseType = (byte)(value & 0x07); Channels[3].NoiseType = (byte)(value & 0x07);
switch (Channels[3].NoiseType & 3) 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) 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... // 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. // 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 27, // A0
29, // A#0 29, // A#0
@ -402,7 +402,7 @@ namespace BizHawk.Emulation.Sound
4435 // C#8 4435 // C#8
}; };
private static readonly string[] notes = static readonly string[] notes =
{ {
"A0","A#0","B0", "A0","A#0","B0",
"C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1", "C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1",

View File

@ -17,11 +17,11 @@ namespace BizHawk.Emulation.Sound
{ {
public ISoundProvider BaseSoundProvider; public ISoundProvider BaseSoundProvider;
private Queue<short> buffer = new Queue<short>(4096); Queue<short> buffer = new Queue<short>(4096);
private const int SamplesInOneFrame = 1470; const int SamplesInOneFrame = 1470;
private const int TargetExtraSamples = 882; const int TargetExtraSamples = 882;
private const int MaxExcessSamples = 4096; const int MaxExcessSamples = 4096;
public void DiscardSamples() public void DiscardSamples()
{ {

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Sound
{ {
} }
private short[] pullBuffer = new short[1470]; short[] pullBuffer = new short[1470];
public void PullSamples(ISoundProvider source) public void PullSamples(ISoundProvider source)
{ {
Array.Clear(pullBuffer, 0, 1470); Array.Clear(pullBuffer, 0, 1470);

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Sound
public sealed class SoundMixer : ISoundProvider public sealed class SoundMixer : ISoundProvider
{ {
private List<ISoundProvider> SoundProviders; List<ISoundProvider> SoundProviders;
public SoundMixer(params ISoundProvider[] soundProviders) public SoundMixer(params ISoundProvider[] soundProviders)
{ {

View File

@ -11,8 +11,8 @@ namespace BizHawk
{ {
public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>> public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>>
{ {
private readonly T1 first; readonly T1 first;
private readonly T2 second; readonly T2 second;
public T1 First { get { return first; } } public T1 First { get { return first; } }
public T2 Second { get { return second; } } public T2 Second { get { return second; } }