diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index b95534ff48..d80fc2af92 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -203,12 +203,10 @@
-
-
-
-
-
+
+
+
diff --git a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.Core.cs b/BizHawk.Emulation/Consoles/Coleco/ColecoVision.Core.cs
deleted file mode 100644
index 69f94d7565..0000000000
--- a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.Core.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using BizHawk.Emulation.CPUs.Z80;
-using BizHawk.Emulation.Sound;
-using BizHawk.Emulation.Consoles.Sega;
-
-namespace BizHawk.Emulation.Consoles.Coleco
-{
- public partial class ColecoVision : IEmulator
- {
- public byte[] rom = new byte[2048];
- public byte[] expansion = new byte[0x4000];
- public byte[] cartridgeslot = new byte[0xFFFF]; //TODO: how big should this be?
- public Z80A cpu;
- public VDP Vdp; //adelikat: Using the SMS one for now
-
- public byte ReadMemory(ushort addr)
- {
- byte ret;
- if (addr < 0x2000)
- {
- ret = rom[addr];
- }
- else if (addr >= 0x2000 && addr < 0x6000)
- {
- ret = expansion[addr];
- }
- else if (addr >= 0x6000 && addr < 0x8000)
- {
- ret = ram[addr & 1023];
- }
- else if (addr >= 0x8000)
- {
- ret = cartridgeslot[addr];
- }
- else
- {
- ret = 0xFF;
- }
-
- if (CoreInputComm.MemoryCallbackSystem.HasRead)
- {
- CoreInputComm.MemoryCallbackSystem.TriggerRead(addr);
- }
-
- return ret;
- }
-
- public void WriteMemory(ushort addr, byte value)
- {
- if (addr >= 0x6000 && addr < 0x8000)
- {
- ram[addr] = value;
- }
-
- if (CoreInputComm.MemoryCallbackSystem.HasWrite)
- {
- CoreInputComm.MemoryCallbackSystem.TriggerWrite(addr);
- }
- }
-
- public void HardReset()
- {
- _lagcount = 0;
- cpu = new Z80A();
- Vdp = new VDP(this, cpu, VdpMode.SMS, DisplayType);
- cpu.ReadMemory = ReadMemory;
- cpu.WriteMemory = WriteMemory;
- }
-
- public void FrameAdvance(bool render, bool rendersound)
- {
- _frame++;
- _islag = true;
-
- Vdp.ExecFrame(render);
-
- //if (render == false) return;
- //for (int i = 0; i < 256 * 192; i++)
- // frameBuffer[i] = 0; //black
-
- if (_islag)
- _lagcount++;
- }
-
- public byte ReadControls()
- {
- if (CoreInputComm.InputCallback != null) CoreInputComm.InputCallback();
- byte value = 0xFF;
-
- if (Controller["P1 Up"]) value &= 0xFF; //TODO;
- if (Controller["P1 Down"]) value &= 0xFF; //TODO;
- if (Controller["P1 Left"]) value &= 0xFF; //TODO;
- if (Controller["P1 Right"]) value &= 0xFF; //TODO;
- //TODO: remaining buttons
-
- _islag = false;
- return value;
-
- }
- }
-}
diff --git a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs b/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs
index 346b8f76d2..029e44d658 100644
--- a/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs
+++ b/BizHawk.Emulation/Consoles/Coleco/ColecoVision.cs
@@ -1,77 +1,108 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.IO;
using BizHawk.Emulation.CPUs.Z80;
using BizHawk.Emulation.Sound;
-using BizHawk.Emulation.Consoles.Sega;
namespace BizHawk.Emulation.Consoles.Coleco
{
- public partial class ColecoVision : IEmulator, IVideoProvider, ISoundProvider
+ public sealed partial class ColecoVision : IEmulator
{
- public string SystemId { get { return "Coleco"; } }
- public GameInfo game;
- public int[] frameBuffer = new int[256 * 192];
- public CoreInputComm CoreInputComm { get; set; }
- public CoreOutputComm CoreOutputComm { get; private set; }
- public IVideoProvider VideoProvider { get { return this; } }
- public ISoundProvider SoundProvider { get { return this; } }
- public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(this, 735); } }
- public bool StartAsyncSound() { return true; }
- public void EndAsyncSound() { }
- public byte[] ram = new byte[2048];
+ // ROM
+ public byte[] RomData;
+ public int RomLength;
- public DisplayType DisplayType { get; set; } //TOOD: delete me
+ public byte[] BiosRom;
+
+ // Machine
+ public Z80A Cpu;
+ public TMS9918A VDP;
+ public SN76489 PSG;
+ public byte[] Ram = new byte[1024];
public ColecoVision(GameInfo game, byte[] rom)
{
- cpu = new Z80A();
- Vdp = new VDP(this, cpu, VdpMode.SMS, DisplayType);
+ Cpu = new Z80A();
+ Cpu.ReadMemory = ReadMemory;
+ Cpu.WriteMemory = WriteMemory;
+ Cpu.ReadHardware = ReadPort;
+ Cpu.WriteHardware = WritePort;
+Cpu.Logger = (s) => Console.WriteLine(s);
+//Cpu.Debug = true;
+
+ VDP = new TMS9918A(Cpu);
+ PSG = new SN76489();
+
+ // TODO: bios rom not hardcoded
+ // TODO: hack to allow bios-less operation would be nice, no idea if its feasible
+ BiosRom = File.ReadAllBytes("D:/coleco.rom");
- var domains = new List(1);
- domains.Add(new MemoryDomain("Main RAM", 1024, Endian.Little, addr => ram[1023], (addr, value) => ram[addr & 1023] = value));
- memoryDomains = domains.AsReadOnly();
CoreOutputComm = new CoreOutputComm();
CoreInputComm = new CoreInputComm();
- this.rom = rom;
- this.game = game;
- HardReset();
+
+ LoadRom(rom);
+ this.game = game;
+
+ Reset();
}
- public void ResetFrameCounter() { _frame = 0; }
+ public void FrameAdvance(bool render, bool renderSound)
+ {
+ PSG.BeginFrame(Cpu.TotalExecutedCycles);
+ VDP.ExecuteFrame();
+ PSG.EndFrame(Cpu.TotalExecutedCycles);
+ }
- public static readonly ControllerDefinition ColecoVisionControllerDefinition = new ControllerDefinition
- {
- Name = "ColecoVision Basic Controller",
- BoolButtons =
- {
- "P1 Up", "P1 Down", "P1 Left", "P1 Right",
- "P1 L1", "P1 L2", "P1 R1", "P1 R2",
- "P1 Key1", "P1 Key2", "P1 Key3", "P1 Key4", "P1 Key5",
- "P1 Key6", "P1 Key7", "P1 Key8", "P1 Key9", "P1 Star", "P1 Pound" //adelikat: TODO: can there be multiple controllers?
- }
- };
+ void LoadRom(byte[] rom)
+ {
+ RomData = new byte[0x8000];
+ for (int i = 0; i < 0x8000; i++)
+ RomData[i] = rom[i % rom.Length];
+ }
- void SyncState(Serializer ser)
- {
- //cpu.SyncState(ser); //TODO: z80 does not have this, do it the SMS way?
- ser.Sync("ram", ref ram, false);
- ser.Sync("Lag", ref _lagcount);
- ser.Sync("Frame", ref _frame);
- ser.Sync("IsLag", ref _islag);
- }
+ void Reset()
+ {
+ /*Cpu.RegisterPC = Cpu.ReadWord(0x800A);
+ Console.WriteLine("code start vector = {0:X4}", Cpu.RegisterPC);*/
+ }
- public ControllerDefinition ControllerDefinition { get { return ColecoVisionControllerDefinition; } }
- public IController Controller { get; set; }
+ byte ReadPort(ushort port)
+ {
+ port &= 0xFF;
+ //Console.WriteLine("Read port {0:X2}", port);
- public int Frame { get { return _frame; } set { _frame = value; } }
- public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
- public bool IsLagFrame { get { return _islag; } }
- private bool _islag = true;
- private int _lagcount = 0;
- private int _frame = 0;
+ if (port >= 0xA0 && port < 0xC0)
+ {
+ if ((port & 1) == 0)
+ return VDP.ReadData();
+ return VDP.ReadVdpStatus();
+ }
+
+ return 0xFF;
+ }
+
+ void WritePort(ushort port, byte value)
+ {
+ port &= 0xFF;
+
+ if (port >= 0xA0 && port < 0xC0)
+ {
+ if ((port & 1) == 0)
+ VDP.WriteVdpData(value);
+ else
+ VDP.WriteVdpControl(value);
+ return;
+ }
+
+ if (port >= 0xE0)
+ {
+ PSG.WritePsgData(value, Cpu.TotalExecutedCycles);
+ return;
+ }
+
+
+ //Console.WriteLine("Write port {0:X2}:{1:X2}", port, value);
+ }
public byte[] ReadSaveRam() { return null; }
public void StoreSaveRam(byte[] data) { }
@@ -79,34 +110,31 @@ namespace BizHawk.Emulation.Consoles.Coleco
public bool SaveRamModified { get; set; }
public bool DeterministicEmulation { get { return true; } }
- public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); }
- public void LoadStateText(TextReader reader) { SyncState(Serializer.CreateTextReader(reader)); }
- public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); }
- public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); }
+ public void SaveStateText(TextWriter writer) { }
+ public void LoadStateText(TextReader reader) { }
+ public void SaveStateBinary(BinaryWriter bw) { }
+ public void LoadStateBinary(BinaryReader br) { }
public byte[] SaveStateBinary()
{
- MemoryStream ms = new MemoryStream();
- BinaryWriter bw = new BinaryWriter(ms);
- SaveStateBinary(bw);
- bw.Flush();
- return ms.ToArray();
+ return new byte[0];
}
- public int[] GetVideoBuffer() { return frameBuffer; }
- public int VirtualWidth { get { return 256; } }
- public int BufferWidth { get { return 256; } }
- public int BufferHeight { get { return 192; } }
- public int BackgroundColor { get { return 0; } }
- public void GetSamples(short[] samples)
- {
- }
+ public void Dispose() { }
+ public void ResetFrameCounter() { }
- public void DiscardSamples() { }
- public int MaxVolume { get; set; }
- private IList memoryDomains;
- public IList MemoryDomains { get { return memoryDomains; } }
- public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
- public void Dispose() { }
+ public string SystemId { get { return "ColecoVision"; } }
+ public GameInfo game;
+ public CoreInputComm CoreInputComm { get; set; }
+ public CoreOutputComm CoreOutputComm { get; private set; }
+ public IVideoProvider VideoProvider { get { return VDP; } }
+ public ISoundProvider SoundProvider { get { return PSG; } }
+
+ public ISyncSoundProvider SyncSoundProvider { get { return null; } }
+ public bool StartAsyncSound() { return true; }
+ public void EndAsyncSound() { }
+
+ public IList MemoryDomains { get { return null; } }
+ public MemoryDomain MainMemory { get { return null; } }
}
}
diff --git a/BizHawk.Emulation/Consoles/Coleco/Input.cs b/BizHawk.Emulation/Consoles/Coleco/Input.cs
new file mode 100644
index 0000000000..2ae721926e
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Coleco/Input.cs
@@ -0,0 +1,32 @@
+namespace BizHawk.Emulation.Consoles.Coleco
+{
+ public partial class ColecoVision
+ {
+ public static readonly ControllerDefinition ColecoVisionControllerDefinition = new ControllerDefinition
+ {
+ Name = "ColecoVision Basic Controller",
+ BoolButtons =
+ {
+ "P1 Up", "P1 Down", "P1 Left", "P1 Right",
+ "P1 L1", "P1 L2", "P1 R1", "P1 R2",
+ "P1 Key1", "P1 Key2", "P1 Key3", "P1 Key4", "P1 Key5",
+ "P1 Key6", "P1 Key7", "P1 Key8", "P1 Key9", "P1 Star", "P1 Pound",
+
+ "P2 Up", "P2 Down", "P2 Left", "P2 Right",
+ "P2 L1", "P2 L2", "P2 R1", "P2 R2",
+ "P2 Key1", "P2 Key2", "P2 Key3", "P2 Key4", "P2 Key5",
+ "P2 Key6", "P2 Key7", "P2 Key8", "P2 Key9", "P2 Star", "P2 Pound"
+ }
+ };
+
+ public ControllerDefinition ControllerDefinition { get { return ColecoVisionControllerDefinition; } }
+ public IController Controller { get; set; }
+
+ public int Frame { get { return _frame; } /*set { _frame = value; }*/ }
+ public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
+ public bool IsLagFrame { get { return _islag; } }
+ private bool _islag = true;
+ private int _lagcount = 0;
+ private int _frame = 0;
+ }
+}
diff --git a/BizHawk.Emulation/Consoles/Coleco/MemoryMap.cs b/BizHawk.Emulation/Consoles/Coleco/MemoryMap.cs
new file mode 100644
index 0000000000..f44e495f28
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Coleco/MemoryMap.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+
+namespace BizHawk.Emulation.Consoles.Coleco
+{
+ public partial class ColecoVision
+ {
+ public byte ReadMemory(ushort addr)
+ {
+ if (addr >= 0x8000)
+ return RomData[addr & 0x7FFF];
+ if (addr >= 0x6000)
+ return Ram[addr & 1023];
+ if (addr < 0x2000)
+ return BiosRom[addr];
+
+ //Console.WriteLine("Unhandled read at {0:X4}", addr);
+ return 0xFF;
+ }
+
+ public void WriteMemory(ushort addr, byte value)
+ {
+ if (addr >= 0x6000 && addr < 0x8000)
+ {
+ Ram[addr & 1023] = value;
+ return;
+ }
+
+ //Console.WriteLine("Unhandled write at {0:X4}:{1:X2}", addr, value);
+ }
+ }
+}
diff --git a/BizHawk.Emulation/Consoles/Coleco/TMS9918A.cs b/BizHawk.Emulation/Consoles/Coleco/TMS9918A.cs
new file mode 100644
index 0000000000..e461b7aed9
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Coleco/TMS9918A.cs
@@ -0,0 +1,355 @@
+using System;
+using BizHawk.Emulation.CPUs.Z80;
+
+namespace BizHawk.Emulation.Consoles.Coleco
+{
+ public sealed class TMS9918A : IVideoProvider
+ {
+ byte[] VRAM = new byte[0x4000];
+ byte[] Registers = new byte[8];
+ byte StatusByte;
+
+ bool VdpWaitingForLatchByte;
+ byte VdpLatch;
+ ushort VdpAddress;
+ byte VdpBuffer;
+ VdpCommand vdpCommand; // TODO remove?
+
+ int TmsMode;
+
+ public bool Mode1Bit { get { return (Registers[1] & 16) > 0; } }
+ public bool Mode2Bit { get { return (Registers[0] & 2) > 0; } }
+ public bool Mode3Bit { get { return (Registers[1] & 8) > 0; } }
+
+ public bool EnableDoubledSprites { get { return (Registers[1] & 1) > 0; } }
+ public bool EnableLargeSprites { get { return (Registers[1] & 2) > 0; } }
+ public bool EnableInterrupts { get { return (Registers[1] & 32) > 0; } }
+ public bool DisplayOn { get { return (Registers[1] & 64) > 0; } }
+ // TODO, is 4/16K bit used?
+
+ //int NameTableBase;
+ int ColorTableBase;
+ int PatternGeneratorBase;
+ int SpritePatternGeneratorBase;
+ int TmsPatternNameTableBase;
+ int TmsSpriteAttributeBase;
+
+ public void ExecuteFrame()
+ {
+ for (int scanLine = 0; scanLine < 262; scanLine++)
+ {
+ RenderScanline(scanLine);
+
+ if (scanLine == 192)
+ {
+ // TODO interrupt pending thing
+ if (EnableInterrupts)
+ Cpu.NonMaskableInterrupt = true;
+ //Console.WriteLine("Set NMI / VSYNC");
+ }
+
+ Cpu.ExecuteCycles(228);
+ }
+
+ }
+
+ public void WriteVdpControl(byte value)
+ {
+ if (VdpWaitingForLatchByte)
+ {
+ VdpLatch = value;
+ VdpWaitingForLatchByte = false;
+ VdpAddress = (ushort)((VdpAddress & 0xFF00) | value);
+ return;
+ }
+
+ VdpWaitingForLatchByte = true;
+ VdpAddress = (ushort)(((value & 63) << 8) | VdpLatch);
+ switch (value & 0xC0)
+ {
+ case 0x00: // read VRAM
+ vdpCommand = VdpCommand.VramRead;
+ VdpBuffer = VRAM[VdpAddress & 0x3FFF];
+ VdpAddress++;
+ break;
+ case 0x40: // write VRAM
+ vdpCommand = VdpCommand.VramWrite;
+ break;
+ case 0x80: // VDP register write
+ vdpCommand = VdpCommand.RegisterWrite;
+ int reg = value & 0x0F;
+ WriteRegister(reg, VdpLatch);
+ break;
+ }
+ }
+
+ public void WriteVdpData(byte value)
+ {
+ VdpWaitingForLatchByte = true;
+ VdpBuffer = value;
+
+ // Write VRAM and update pre-computed pattern buffer.
+ //UpdatePatternBuffer((ushort)(VdpAddress & 0x3FFF), value);
+ //Console.WriteLine("VRAM[{0:X4}] = {1:X2}", VdpAddress & 0x3FFF, value);
+ VRAM[VdpAddress & 0x3FFF] = value;
+
+ VdpAddress++;
+ }
+
+ void WriteRegister(int reg, byte data)
+ {
+ if (reg >= 8) return;
+
+ Console.WriteLine("Write register {0} : {1:X2}", reg, data);
+ Registers[reg] = data;
+ switch (reg)
+ {
+ case 0: // Mode Control Register 1
+ CheckVideoMode();
+ break;
+ case 1: // Mode Control Register 2
+ CheckVideoMode();
+ //Cpu.NonMaskableInterrupt = (EnableInterrupts && VIntPending);
+ break;
+ case 2: // Name Table Base Address
+ //NameTableBase = CalcNameTableBase();
+ TmsPatternNameTableBase = (Registers[2] << 10) & 0x3C00;
+ break;
+ case 3: // Color Table Base Address
+ ColorTableBase = (Registers[3] << 6) & 0x3FC0;
+ break;
+ case 4: // Pattern Generator Base Address
+ PatternGeneratorBase = (Registers[4] << 11) & 0x3800;
+ break;
+ case 5: // Sprite Attribute Table Base Address
+ // ??? should I move from my property to precalculated?
+ TmsSpriteAttributeBase = (Registers[5] << 7) & 0x3F80;
+ break;
+ case 6: // Sprite Pattern Generator Base Adderss
+ SpritePatternGeneratorBase = (Registers[6] << 11) & 0x3800;
+ break;
+ }
+ }
+
+ public byte ReadVdpStatus()
+ {
+ VdpWaitingForLatchByte = true;
+ byte returnValue = StatusByte;
+ StatusByte &= 0x1F;
+ //VIntPending = false;
+ Cpu.NonMaskableInterrupt = false;
+
+ //Console.WriteLine("Clear NMI / read status");
+ return returnValue;
+ }
+
+ public byte ReadData()
+ {
+ VdpWaitingForLatchByte = true;
+ byte value = VdpBuffer;
+ VdpBuffer = VRAM[VdpAddress & 0x3FFF];
+ VdpAddress++;
+ return value;
+ }
+
+ void CheckVideoMode()
+ {
+ if (Mode1Bit) TmsMode = 1;
+ else if (Mode2Bit) TmsMode = 2;
+ else if (Mode3Bit) TmsMode = 3;
+ else TmsMode = 0;
+
+ Console.WriteLine("video mode {0}", TmsMode);
+ }
+
+ void RenderScanline(int scanLine)
+ {
+ if (scanLine >= 192)
+ return;
+
+ if (TmsMode == 2)
+ {
+ RenderBackgroundM2(scanLine);
+ RenderTmsSprites(scanLine);
+ }
+ else if (TmsMode == 0)
+ {
+ RenderBackgroundM0(scanLine);
+ RenderTmsSprites(scanLine);
+ }
+ }
+
+ void RenderBackgroundM0(int scanLine)
+ {
+ if (DisplayOn == false)
+ {
+ Array.Clear(FrameBuffer, scanLine * 256, 256);
+ return;
+ }
+
+ int yc = scanLine / 8;
+ int yofs = scanLine % 8;
+ int FrameBufferOffset = scanLine * 256;
+ int PatternNameOffset = TmsPatternNameTableBase + (yc * 32);
+ int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
+
+ for (int xc = 0; xc < 32; xc++)
+ {
+ int pn = VRAM[PatternNameOffset++];
+ int pv = VRAM[PatternGeneratorBase + (pn * 8) + yofs];
+ int colorEntry = VRAM[ColorTableBase + (pn / 8)];
+ int fgIndex = (colorEntry >> 4) & 0x0F;
+ int bgIndex = colorEntry & 0x0F;
+ int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
+ int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
+
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x80) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x40) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x20) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x10) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x08) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x04) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x02) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x01) > 0) ? fgColor : bgColor;
+ }
+ }
+
+ void RenderBackgroundM2(int scanLine)
+ {
+ if (DisplayOn == false)
+ {
+ Array.Clear(FrameBuffer, scanLine * 256, 256);
+ return;
+ }
+
+ int yrow = scanLine / 8;
+ int yofs = scanLine % 8;
+ int FrameBufferOffset = scanLine * 256;
+ int PatternNameOffset = TmsPatternNameTableBase + (yrow * 32);
+ int PatternGeneratorOffset = (((Registers[4] & 4) << 11) & 0x2000);// +((yrow / 8) * 0x100);
+ int ColorOffset = (ColorTableBase & 0x2000);// +((yrow / 8) * 0x100);
+ int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
+
+ for (int xc = 0; xc < 32; xc++)
+ {
+ int pn = VRAM[PatternNameOffset++] + ((yrow / 8) * 0x100);
+ int pv = VRAM[PatternGeneratorOffset + (pn * 8) + yofs];
+ int colorEntry = VRAM[ColorOffset + (pn * 8) + yofs];
+ int fgIndex = (colorEntry >> 4) & 0x0F;
+ int bgIndex = colorEntry & 0x0F;
+ int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
+ int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
+
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x80) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x40) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x20) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x10) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x08) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x04) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x02) > 0) ? fgColor : bgColor;
+ FrameBuffer[FrameBufferOffset++] = ((pv & 0x01) > 0) ? fgColor : bgColor;
+ }
+ }
+
+ byte[] ScanlinePriorityBuffer = new byte[256];
+ byte[] SpriteCollisionBuffer = new byte[256];
+
+ void RenderTmsSprites(int scanLine)
+ {
+ if (DisplayOn == false) return;
+
+ Array.Clear(ScanlinePriorityBuffer, 0, 256);
+ Array.Clear(SpriteCollisionBuffer, 0, 256);
+
+ bool Double = EnableDoubledSprites;
+ bool LargeSprites = EnableLargeSprites;
+
+ int SpriteSize = 8;
+ if (LargeSprites) SpriteSize *= 2;
+ if (Double) SpriteSize *= 2;
+ int OneCellSize = Double ? 16 : 8;
+
+ int NumSpritesOnScanline = 0;
+ for (int i = 0; i < 32; i++)
+ {
+ int SpriteBase = TmsSpriteAttributeBase + (i * 4);
+ int y = VRAM[SpriteBase++];
+ int x = VRAM[SpriteBase++];
+ int Pattern = VRAM[SpriteBase++];
+ int Color = VRAM[SpriteBase];
+
+ if (y == 208) break; // terminator sprite
+ if (y > 224) y -= 256; // sprite Y wrap
+ y++; // inexplicably, sprites start on Y+1
+ if (y > scanLine || y + SpriteSize <= scanLine) continue; // sprite is not on this scanline
+ if ((Color & 0x80) > 0) x -= 32; // Early Clock adjustment
+
+ if (++NumSpritesOnScanline == 5)
+ {
+ StatusByte |= (byte)i; // set 5th sprite index
+ StatusByte |= 0x40; // set overflow bit
+ break;
+ }
+
+ if (LargeSprites) Pattern &= 0xFC; // 16x16 sprites forced to 4-byte alignment
+ int SpriteLine = scanLine - y;
+ if (Double) SpriteLine /= 2;
+
+ byte pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine];
+
+ for (int xp = 0; xp < SpriteSize && x + xp < 256; xp++)
+ {
+ if (x + xp < 0) continue;
+ if (LargeSprites && xp == OneCellSize)
+ pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine + 16];
+
+ if ((pv & (1 << (7 - (xp & 7)))) > 0)
+ {
+ // todo sprite collision
+ if (Color != 0 && ScanlinePriorityBuffer[x + xp] == 0)
+ {
+ ScanlinePriorityBuffer[x + xp] = 1;
+ FrameBuffer[(scanLine * 256) + x + xp] = PaletteTMS9918[Color & 0x0F];
+ }
+ }
+ }
+ }
+ }
+
+ Z80A Cpu;
+ public TMS9918A(Z80A cpu)
+ {
+ this.Cpu = cpu;
+ }
+
+ public int[] FrameBuffer = new int[256 * 192];
+ public int[] GetVideoBuffer() { return FrameBuffer; }
+
+ public int VirtualWidth { get { return 256; } }
+ public int BufferWidth { get { return 256; } }
+ public int BufferHeight { get { return 192; } }
+ public int BackgroundColor { get { return 0; } }
+
+ enum VdpCommand { VramRead, VramWrite, RegisterWrite }
+
+ int[] PaletteTMS9918 = new int[]
+ {
+ unchecked((int)0x00000000),
+ unchecked((int)0xFF000000),
+ unchecked((int)0xFF47B73B),
+ unchecked((int)0xFF7CCF6F),
+ unchecked((int)0xFF5D4EFF),
+ unchecked((int)0xFF8072FF),
+ unchecked((int)0xFFB66247),
+ unchecked((int)0xFF5DC8ED),
+ unchecked((int)0xFFD76B48),
+ unchecked((int)0xFFFB8F6C),
+ unchecked((int)0xFFC3CD41),
+ unchecked((int)0xFFD3DA76),
+ unchecked((int)0xFF3E9F2F),
+ unchecked((int)0xFFB664C7),
+ unchecked((int)0xFFCCCCCC),
+ unchecked((int)0xFFFFFFFF)
+ };
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Coleco/VDP.Mode4.cs b/BizHawk.Emulation/Consoles/Coleco/VDP.Mode4.cs
deleted file mode 100644
index 20e82efb73..0000000000
--- a/BizHawk.Emulation/Consoles/Coleco/VDP.Mode4.cs
+++ /dev/null
@@ -1,299 +0,0 @@
-using System;
-
-// Contains rendering functions for TMS9918 Mode 4.
-
-namespace BizHawk.Emulation.Consoles.Coleco
-{
- public partial class VDP
- {
- internal void RenderBackgroundCurrentLine(bool show)
- {
- if (DisplayOn == false)
- {
- for (int x = 0; x < 256; x++)
- FrameBuffer[(ScanLine*256) + x] = Palette[BackdropColor];
- return;
- }
-
- // Clear the priority buffer for this scanline
- Array.Clear(ScanlinePriorityBuffer, 0, 256);
-
- int mapBase = NameTableBase;
-
- int vertOffset = ScanLine + Registers[9];
- if (FrameHeight == 192)
- {
- if (vertOffset >= 224)
- vertOffset -= 224;
- }
- else
- {
- if (vertOffset >= 256)
- vertOffset -= 256;
- }
- byte horzOffset = (HorizScrollLock && ScanLine < 16) ? (byte)0 : Registers[8];
-
- int yTile = vertOffset / 8;
-
- for (int xTile = 0; xTile < 32; xTile++)
- {
- if (xTile == 24 && VerticalScrollLock)
- {
- vertOffset = ScanLine;
- yTile = vertOffset / 8;
- }
-
- byte PaletteBase = 0;
- int tileInfo = VRAM[mapBase + ((yTile * 32) + xTile) * 2] | (VRAM[mapBase + (((yTile * 32) + xTile) * 2) + 1] << 8);
- int tileNo = tileInfo & 0x01FF;
- if ((tileInfo & 0x800) != 0)
- PaletteBase = 16;
- bool Priority = (tileInfo & 0x1000) != 0;
- bool VFlip = (tileInfo & 0x400) != 0;
- bool HFlip = (tileInfo & 0x200) != 0;
-
- int yOfs = vertOffset & 7;
- if (VFlip)
- yOfs = 7 - yOfs;
-
- if (HFlip == false)
- {
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 0] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 1] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 2] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 3] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 4] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 5] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 6] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 7] + PaletteBase] : Palette[BackdropColor];
-
- if (Priority)
- {
- horzOffset -= 8;
- for (int k = 0; k < 8; k++)
- {
- if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0)
- ScanlinePriorityBuffer[horzOffset] = 1;
- horzOffset++;
- }
- }
- }
- else // Flipped Horizontally
- {
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 7] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 6] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 5] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 4] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 3] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 2] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 1] + PaletteBase] : Palette[BackdropColor];
- FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 0] + PaletteBase] : Palette[BackdropColor];
-
- if (Priority)
- {
- horzOffset -= 8;
- for (int k = 7; k >= 0; k--)
- {
- if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0)
- ScanlinePriorityBuffer[horzOffset] = 1;
- horzOffset++;
- }
- }
- }
- }
- }
-
- internal void RenderSpritesCurrentLine(bool show)
- {
- if (DisplayOn == false) return;
- int SpriteBase = SpriteAttributeTableBase;
- int SpriteHeight = EnableLargeSprites ? 16 : 8;
-
- // Clear the sprite collision buffer for this scanline
- Array.Clear(SpriteCollisionBuffer, 0, 256);
-
- // Loop through these sprites and render the current scanline
- int SpritesDrawnThisScanline = 0;
- for (int i=0; i<64; i++)
- {
- if (SpritesDrawnThisScanline >= 8)
- {
- StatusByte |= 0x40; // Set Overflow bit
- if (SpriteLimit) break;
- }
-
- int x = VRAM[SpriteBase + 0x80 + (i * 2)];
- if (ShiftSpritesLeft8Pixels)
- x -= 8;
-
- int y = VRAM[SpriteBase + i] + 1;
- if (y == 209 && FrameHeight == 192) break; // 208 is special terminator sprite (in 192-line mode)
- if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256;
-
- if (y + SpriteHeight <= ScanLine || y > ScanLine)
- continue;
-
- int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
- if (EnableLargeSprites)
- tileNo &= 0xFE;
- tileNo += SpriteTileBase;
-
- int ys = ScanLine - y;
-
- for (int xs = 0; xs < 8 && x + xs < 256; xs++)
- {
- byte color = PatternBuffer[(tileNo * 64) + (ys * 8) + xs];
- if (color != 0 && x + xs >= 0)
- {
- if (SpriteCollisionBuffer[x + xs] != 0)
- StatusByte |= 0x20; // Set Collision bit
- else if (ScanlinePriorityBuffer[x + xs] == 0)
- {
- if (show) FrameBuffer[(ys + y) * 256 + x + xs] = Palette[(color + 16)];
- SpriteCollisionBuffer[x + xs] = 1;
- }
- }
- }
- SpritesDrawnThisScanline++;
- }
- }
-
- internal void RenderSpritesCurrentLineDoubleSize(bool show)
- {
- if (DisplayOn == false) return;
- int SpriteBase = SpriteAttributeTableBase;
- int SpriteHeight = EnableLargeSprites ? 16 : 8;
-
- // Clear the sprite collision buffer for this scanline
- Array.Clear(SpriteCollisionBuffer, 0, 256);
-
- // Loop through these sprites and render the current scanline
- int SpritesDrawnThisScanline = 0;
- for (int i = 0; i <64; i++)
- {
- if (SpritesDrawnThisScanline >= 8)
- {
- StatusByte |= 0x40; // Set Overflow bit
- if (SpriteLimit) break;
- }
-
- int x = VRAM[SpriteBase + 0x80 + (i * 2)];
- if (ShiftSpritesLeft8Pixels)
- x -= 8;
-
- int y = VRAM[SpriteBase + i] + 1;
- if (y == 209 && FrameHeight == 192) break; // terminator sprite
- if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256;
-
- if (y + (SpriteHeight*2) <= ScanLine || y > ScanLine)
- continue;
-
- int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
- if (EnableLargeSprites)
- tileNo &= 0xFE;
- tileNo += SpriteTileBase;
-
- int ys = ScanLine - y;
-
- for (int xs = 0; xs < 16 && x + xs < 256; xs++)
- {
- byte color = PatternBuffer[(tileNo * 64) + ((ys/2) * 8) + (xs/2)];
- if (color != 0 && x + xs >= 0 && ScanlinePriorityBuffer[x + xs] == 0)
- {
- if (SpriteCollisionBuffer[x + xs] != 0)
- StatusByte |= 0x20; // Set Collision bit
- else
- {
- if (show) FrameBuffer[(ys + y) * 256 + x + xs] = Palette[(color + 16)];
- SpriteCollisionBuffer[x + xs] = 1;
- }
- }
- }
- SpritesDrawnThisScanline++;
- }
- }
-
- internal void ProcessSpriteCollisionForFrameskip()
- {
- if (DisplayOn == false) return;
- int SpriteBase = SpriteAttributeTableBase;
- int SpriteHeight = EnableLargeSprites ? 16 : 8;
-
- // Clear the sprite collision buffer for this scanline
- Array.Clear(SpriteCollisionBuffer, 0, 256);
-
- // 208 is a special terminator sprite (in 192-line mode). Lets find it...
- int TerminalSprite = 64;
- if (FrameHeight == 192)
- for (int i = 0; i < 64; i++)
- {
- if (VRAM[SpriteBase + i] == 208)
- {
- TerminalSprite = i;
- break;
- }
- }
-
- // Loop through these sprites and render the current scanline
- int SpritesDrawnThisScanline = 0;
- for (int i = TerminalSprite - 1; i >= 0; i--)
- {
- if (SpritesDrawnThisScanline >= 8)
- StatusByte |= 0x40; // Set Overflow bit
-
- int x = VRAM[SpriteBase + 0x80 + (i * 2)];
- if (ShiftSpritesLeft8Pixels)
- x -= 8;
-
- int y = VRAM[SpriteBase + i] + 1;
- if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256;
-
- if (y + SpriteHeight <= ScanLine || y > ScanLine)
- continue;
-
- int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
- if (EnableLargeSprites)
- tileNo &= 0xFE;
- tileNo += SpriteTileBase;
-
- int ys = ScanLine - y;
-
- for (int xs = 0; xs < 8 && x + xs < 256; xs++)
- {
- byte color = PatternBuffer[(tileNo * 64) + (ys * 8) + xs];
- if (color != 0 && x + xs >= 0)
- {
- if (SpriteCollisionBuffer[x + xs] != 0)
- StatusByte |= 0x20; // Set Collision bit
- SpriteCollisionBuffer[x + xs] = 1;
- }
- }
- SpritesDrawnThisScanline++;
- }
- }
-
- // Performs render buffer blanking. This includes the left-column blanking as well as Game Gear blanking if requested.
- // Should be called at the end of the frame.
- internal void RenderBlankingRegions()
- {
- int blankingColor = Palette[BackdropColor];
-
- if (LeftBlanking)
- {
- for (int y = 0; y < FrameHeight; y++)
- {
- for (int x = 0; x < 8; x++)
- FrameBuffer[(y * 256) + x] = blankingColor;
- }
- }
-
- if (mode == VdpMode.GameGear)
- {
- int yStart = (FrameHeight - 144)/2;
- for (int y = 0; y < 144; y++)
- for (int x = 0; x < 160; x++)
- GameGearFrameBuffer[(y * 160) + x] = FrameBuffer[((y + yStart) * 256) + x + 48];
- }
- }
- }
-}
diff --git a/BizHawk.Emulation/Consoles/Coleco/VDP.ModeTMS.cs b/BizHawk.Emulation/Consoles/Coleco/VDP.ModeTMS.cs
deleted file mode 100644
index 0160d30f69..0000000000
--- a/BizHawk.Emulation/Consoles/Coleco/VDP.ModeTMS.cs
+++ /dev/null
@@ -1,163 +0,0 @@
-// Contains rendering functions for legacy TMS9918 modes.
-
-using System;
-
-namespace BizHawk.Emulation.Consoles.Coleco
-{
- public partial class VDP
- {
- int[] PaletteTMS9918 = new int[]
- {
- unchecked((int)0x00000000),
- unchecked((int)0xFF000000),
- unchecked((int)0xFF47B73B),
- unchecked((int)0xFF7CCF6F),
- unchecked((int)0xFF5D4EFF),
- unchecked((int)0xFF8072FF),
- unchecked((int)0xFFB66247),
- unchecked((int)0xFF5DC8ED),
- unchecked((int)0xFFD76B48),
- unchecked((int)0xFFFB8F6C),
- unchecked((int)0xFFC3CD41),
- unchecked((int)0xFFD3DA76),
- unchecked((int)0xFF3E9F2F),
- unchecked((int)0xFFB664C7),
- unchecked((int)0xFFCCCCCC),
- unchecked((int)0xFFFFFFFF)
- };
-
- void RenderBackgroundM0(bool show)
- {
- if (DisplayOn == false)
- {
- Array.Clear(FrameBuffer, ScanLine * 256, 256);
- return;
- }
-
- int yc = ScanLine/8;
- int yofs = ScanLine%8;
- int FrameBufferOffset = ScanLine*256;
- int PatternNameOffset = TmsPatternNameTableBase + (yc*32);
- int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
-
- for (int xc=0; xc<32; xc++)
- {
- int pn = VRAM[PatternNameOffset++];
- int pv = VRAM[PatternGeneratorBase + (pn*8) + yofs];
- int colorEntry = VRAM[ColorTableBase + (pn/8)];
- int fgIndex = (colorEntry >> 4) & 0x0F;
- int bgIndex = colorEntry & 0x0F;
- int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
- int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
-
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x80) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x40) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x20) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x10) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x08) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x04) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x02) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x01) > 0) ? fgColor : bgColor) : 0;
- }
- }
-
- void RenderBackgroundM2(bool show)
- {
- if (DisplayOn == false)
- {
- Array.Clear(FrameBuffer, ScanLine * 256, 256);
- return;
- }
-
- int yrow = ScanLine/8;
- int yofs = ScanLine%8;
- int FrameBufferOffset = ScanLine*256;
- int PatternNameOffset = TmsPatternNameTableBase + (yrow*32);
- int PatternGeneratorOffset = (((Registers[4] & 4) << 11) & 0x2000);// +((yrow / 8) * 0x100);
- int ColorOffset = (ColorTableBase & 0x2000);// +((yrow / 8) * 0x100);
- int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
-
- for (int xc=0; xc<32; xc++)
- {
- int pn = VRAM[PatternNameOffset++] + ((yrow/8)*0x100);
- int pv = VRAM[PatternGeneratorOffset + (pn * 8) + yofs];
- int colorEntry = VRAM[ColorOffset + (pn * 8) + yofs];
- int fgIndex = (colorEntry >> 4) & 0x0F;
- int bgIndex = colorEntry & 0x0F;
- int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
- int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
-
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x80) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x40) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x20) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x10) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x08) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x04) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x02) > 0) ? fgColor : bgColor) : 0;
- FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x01) > 0) ? fgColor : bgColor) : 0;
- }
- }
-
- void RenderTmsSprites(bool show)
- {
- if (DisplayOn == false) return;
-
- Array.Clear(ScanlinePriorityBuffer, 0, 256);
- Array.Clear(SpriteCollisionBuffer, 0, 256);
-
- bool Double = EnableDoubledSprites;
- bool LargeSprites = EnableLargeSprites;
-
- int SpriteSize = 8;
- if (LargeSprites) SpriteSize *= 2;
- if (Double) SpriteSize *= 2;
- int OneCellSize = Double ? 16 : 8;
-
- int NumSpritesOnScanline = 0;
- for (int i=0; i<32; i++)
- {
- int SpriteBase = TmsSpriteAttributeBase + (i*4);
- int y = VRAM[SpriteBase++];
- int x = VRAM[SpriteBase++];
- int Pattern = VRAM[SpriteBase++];
- int Color = VRAM[SpriteBase];
-
- if (y == 208) break; // terminator sprite
- if (y > 224) y -= 256; // sprite Y wrap
- y++; // inexplicably, sprites start on Y+1
- if (y > ScanLine || y + SpriteSize <= ScanLine) continue; // sprite is not on this scanline
- if ((Color & 0x80) > 0) x -= 32; // Early Clock adjustment
-
- if (++NumSpritesOnScanline == 5)
- {
- StatusByte |= (byte) i; // set 5th sprite index
- StatusByte |= 0x40; // set overflow bit
- break;
- }
-
- if (LargeSprites) Pattern &= 0xFC; // 16x16 sprites forced to 4-byte alignment
- int SpriteLine = ScanLine - y;
- if (Double) SpriteLine /= 2;
-
- byte pv = VRAM[SpritePatternGeneratorBase + (Pattern*8) + SpriteLine];
-
- for (int xp = 0; xp < SpriteSize && x + xp < 256; xp++)
- {
- if (x+xp < 0) continue;
- if (LargeSprites && xp == OneCellSize)
- pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine + 16];
-
- if ((pv & (1 << (7 - (xp & 7)))) > 0)
- {
- // todo sprite collision
- if (Color != 0 && ScanlinePriorityBuffer[x+xp] == 0)
- {
- ScanlinePriorityBuffer[x + xp] = 1;
- if (show) FrameBuffer[(ScanLine*256) + x + xp] = PaletteTMS9918[Color & 0x0F];
- }
- }
- }
- }
- }
- }
-}
diff --git a/BizHawk.Emulation/Consoles/Coleco/VDP.Tables.cs b/BizHawk.Emulation/Consoles/Coleco/VDP.Tables.cs
deleted file mode 100644
index 2b5f0bd1ef..0000000000
--- a/BizHawk.Emulation/Consoles/Coleco/VDP.Tables.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-namespace BizHawk.Emulation.Consoles.Coleco
-{
- public partial class VDP
- {
- // TODO: HCounter
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
- 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
- };
-
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
- 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
- };
-
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05
- };
-
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2,
- 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
- };
-
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
- 0x00, 0x01, 0x02,
- 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
- };
-
- 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,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
- 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
- 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
- 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
- 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
- 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
- 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
- };
- }
-}
diff --git a/BizHawk.Emulation/Consoles/Coleco/VDP.cs b/BizHawk.Emulation/Consoles/Coleco/VDP.cs
deleted file mode 100644
index e77f5af4d6..0000000000
--- a/BizHawk.Emulation/Consoles/Coleco/VDP.cs
+++ /dev/null
@@ -1,526 +0,0 @@
-using System;
-using System.Globalization;
-using System.IO;
-using BizHawk.Emulation.CPUs.Z80;
-
-namespace BizHawk.Emulation.Consoles.Coleco
-{
- public enum VdpMode { SMS, GameGear } //TODO: delete me
-
- // Emulates the Texas Instruments TMS9918 VDP.
- public sealed partial class VDP : IVideoProvider
- {
- // VDP State
- public byte[] VRAM = new byte[0x4000]; //16kb video RAM
- public byte[] CRAM; // SMS = 32 bytes, GG = 64 bytes CRAM
- public byte[] Registers = new byte[] { 0x06, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 };
- public byte StatusByte;
-
- bool VdpWaitingForLatchByte = true;
- byte VdpLatch;
- byte VdpBuffer;
- ushort VdpAddress;
- VdpCommand vdpCommand;
- int TmsMode = 4;
-
- bool VIntPending;
- bool HIntPending;
-
- ColecoVision Coleco;
- VdpMode mode;
- DisplayType DisplayType = DisplayType.NTSC;
- Z80A Cpu;
-
- public bool SpriteLimit;
- public int IPeriod = 228;
- public VdpMode VdpMode { get { return mode; } }
-
- int FrameHeight = 192;
- public int ScanLine;
- public int[] FrameBuffer = new int[256 * 192];
- public int[] GameGearFrameBuffer = new int[160 * 144];
-
- public bool Mode1Bit { get { return (Registers[1] & 16) > 0; } }
- public bool Mode2Bit { get { return (Registers[0] & 2) > 0; } }
- public bool Mode3Bit { get { return (Registers[1] & 8) > 0; } }
- public bool Mode4Bit { get { return (Registers[0] & 4) > 0; } }
- public bool ShiftSpritesLeft8Pixels { get { return (Registers[0] & 8) > 0; } }
- public bool EnableLineInterrupts { get { return (Registers[0] & 16) > 0; } }
- public bool LeftBlanking { get { return (Registers[0] & 32) > 0; } }
- public bool HorizScrollLock { get { return (Registers[0] & 64) > 0; } }
- public bool VerticalScrollLock { get { return (Registers[0] & 128) > 0; } }
- public bool EnableDoubledSprites { get { return (Registers[1] & 1) > 0; } }
- public bool EnableLargeSprites { get { return (Registers[1] & 2) > 0; } }
- public bool EnableFrameInterrupts { get { return (Registers[1] & 32) > 0; } }
- public bool DisplayOn { get { return (Registers[1] & 64) > 0; } }
- public int SpriteAttributeTableBase { get { return ((Registers[5] >> 1) << 8) & 0x3FFF; } }
- public int SpriteTileBase { get { return (Registers[6] & 4) > 0 ? 256 : 0; } }
- public byte BackdropColor { get { return (byte)(16 + (Registers[7] & 15)); } }
-
- 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];
-
- byte[] ScanlinePriorityBuffer = new byte[256];
- byte[] SpriteCollisionBuffer = new byte[256];
-
- 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(ColecoVision sms, Z80A cpu, VdpMode mode, DisplayType displayType)
- {
- Coleco = sms;
- Cpu = cpu;
- this.mode = mode;
- if (mode == VdpMode.SMS) CRAM = new byte[32];
- if (mode == VdpMode.GameGear) CRAM = new byte[64];
- DisplayType = displayType;
- NameTableBase = CalcNameTableBase();
- }
-
- public byte ReadData()
- {
- VdpWaitingForLatchByte = true;
- byte value = VdpBuffer;
- VdpBuffer = VRAM[VdpAddress & 0x3FFF];
- VdpAddress++;
- return value;
- }
-
- public byte ReadVdpStatus()
- {
- VdpWaitingForLatchByte = true;
- byte returnValue = StatusByte;
- StatusByte &= 0x1F;
- HIntPending = false;
- VIntPending = false;
- Cpu.Interrupt = false;
- return returnValue;
- }
-
- public byte ReadVLineCounter()
- {
- if (DisplayType == DisplayType.NTSC)
- {
- if (FrameHeight == 192)
- return VLineCounterTableNTSC192[ScanLine];
- if (FrameHeight == 224)
- return VLineCounterTableNTSC224[ScanLine];
- return VLineCounterTableNTSC240[ScanLine];
- }
- else
- { // PAL
- if (FrameHeight == 192)
- return VLineCounterTablePAL192[ScanLine];
- if (FrameHeight == 224)
- return VLineCounterTablePAL224[ScanLine];
- return VLineCounterTablePAL240[ScanLine];
- }
- }
-
- public void WriteVdpControl(byte value)
- {
- if (VdpWaitingForLatchByte)
- {
- VdpLatch = value;
- VdpWaitingForLatchByte = false;
- VdpAddress = (ushort)((VdpAddress & 0xFF00) | value);
- return;
- }
-
- VdpWaitingForLatchByte = true;
- VdpAddress = (ushort)(((value & 63) << 8) | VdpLatch);
- switch (value & 0xC0)
- {
- case 0x00: // read VRAM
- vdpCommand = VdpCommand.VramRead;
- VdpBuffer = VRAM[VdpAddress & 0x3FFF];
- VdpAddress++;
- break;
- case 0x40: // write VRAM
- vdpCommand = VdpCommand.VramWrite;
- break;
- case 0x80: // VDP register write
- vdpCommand = VdpCommand.RegisterWrite;
- int reg = value & 0x0F;
- WriteRegister(reg, VdpLatch);
- break;
- case 0xC0: // write CRAM / modify palette
- vdpCommand = VdpCommand.CramWrite;
- break;
- }
- }
-
- public void WriteVdpData(byte value)
- {
- VdpWaitingForLatchByte = true;
- VdpBuffer = value;
- if (vdpCommand == VdpCommand.CramWrite)
- {
- // Write Palette / CRAM
- int mask = VdpMode == VdpMode.SMS ? 0x1F : 0x3F;
- CRAM[VdpAddress & mask] = value;
- UpdatePrecomputedPalette();
- }
- else
- {
- // Write VRAM and update pre-computed pattern buffer.
- UpdatePatternBuffer((ushort)(VdpAddress & 0x3FFF), value);
- VRAM[VdpAddress & 0x3FFF] = value;
- }
- VdpAddress++;
- }
-
- public void UpdatePrecomputedPalette()
- {
- if (mode == VdpMode.SMS)
- {
- for (int i = 0; i < 32; i++)
- {
- byte value = CRAM[i];
- byte r = SMSPalXlatTable[(value & 0x03)];
- byte g = SMSPalXlatTable[(value & 0x0C) >> 2];
- byte b = SMSPalXlatTable[(value & 0x30) >> 4];
- Palette[i] = Colors.ARGB(r, g, b);
- }
- }
- else
- { // GameGear
- for (int i = 0; i < 32; i++)
- {
- ushort value = (ushort)((CRAM[(i * 2) + 1] << 8) | CRAM[(i * 2) + 0]);
- byte r = GGPalXlatTable[(value & 0x000F)];
- byte g = GGPalXlatTable[(value & 0x00F0) >> 4];
- byte b = GGPalXlatTable[(value & 0x0F00) >> 8];
- Palette[i] = Colors.ARGB(r, g, b);
- }
- }
- }
-
- public int CalcNameTableBase()
- {
- if (FrameHeight == 192)
- return 1024 * (Registers[2] & 0x0E);
- return (1024 * (Registers[2] & 0x0C)) + 0x0700;
- }
-
- void CheckVideoMode()
- {
- if (Mode4Bit == false) // check old TMS modes
- {
- if (Mode1Bit) TmsMode = 1;
- else if (Mode2Bit) TmsMode = 2;
- else if (Mode3Bit) TmsMode = 3;
- else TmsMode = 0;
- }
-
- else if (Mode4Bit && Mode2Bit) // if Mode4 and Mode2 set, then check extension modes
- {
- TmsMode = 4;
- switch (Registers[1] & 0x18)
- {
- case 0x00:
- case 0x18: // 192-line mode
- if (FrameHeight != 192)
- {
- FrameHeight = 192;
- FrameBuffer = new int[256 * 192];
- NameTableBase = CalcNameTableBase();
- }
- break;
- case 0x10: // 224-line mode
- if (FrameHeight != 224)
- {
- FrameHeight = 224;
- FrameBuffer = new int[256 * 224];
- NameTableBase = CalcNameTableBase();
- }
- break;
- case 0x08: // 240-line mode
- if (FrameHeight != 240)
- {
- FrameHeight = 240;
- FrameBuffer = new int[256 * 240];
- NameTableBase = CalcNameTableBase();
- }
- break;
- }
- }
-
- else
- { // default to standard 192-line mode4
- TmsMode = 4;
- if (FrameHeight != 192)
- {
- FrameHeight = 192;
- FrameBuffer = new int[256 * 192];
- NameTableBase = CalcNameTableBase();
- }
- }
- }
-
- void WriteRegister(int reg, byte data)
- {
- Registers[reg] = data;
- switch (reg)
- {
- case 0: // Mode Control Register 1
- CheckVideoMode();
- Cpu.Interrupt = (EnableLineInterrupts && HIntPending);
- break;
- case 1: // Mode Control Register 2
- CheckVideoMode();
- Cpu.Interrupt = (EnableFrameInterrupts && VIntPending);
- break;
- case 2: // Name Table Base Address
- NameTableBase = CalcNameTableBase();
- TmsPatternNameTableBase = (Registers[2] << 10) & 0x3C00;
- break;
- case 3: // Color Table Base Address
- ColorTableBase = (Registers[3] << 6) & 0x3FC0;
- break;
- case 4: // Pattern Generator Base Address
- PatternGeneratorBase = (Registers[4] << 11) & 0x3800;
- break;
- case 5: // Sprite Attribute Table Base Address
- // ??? should I move from my property to precalculated?
- TmsSpriteAttributeBase = (Registers[5] << 7) & 0x3F80;
- break;
- case 6: // Sprite Pattern Generator Base Adderss
- SpritePatternGeneratorBase = (Registers[6] << 11) & 0x3800;
- break;
- }
- }
-
- static readonly byte[] pow2 = { 1, 2, 4, 8, 16, 32, 64, 128 };
-
- void UpdatePatternBuffer(ushort address, byte value)
- {
- // writing one byte affects 8 pixels due to stupid planar storage.
- for (int i = 0; i < 8; i++)
- {
- byte colorBit = pow2[address % 4];
- byte sourceBit = pow2[7 - i];
- ushort dest = (ushort)(((address & 0xFFFC) * 2) + i);
- if ((value & sourceBit) > 0) // setting bit
- PatternBuffer[dest] |= colorBit;
- else // clearing bit
- PatternBuffer[dest] &= (byte)~colorBit;
- }
- }
-
- int lineIntLinesRemaining;
-
- void ProcessFrameInterrupt()
- {
- if (ScanLine == FrameHeight + 1)
- {
- StatusByte |= 0x80;
- VIntPending = true;
- }
-
- if (VIntPending && EnableFrameInterrupts)
- Cpu.Interrupt = true;
- }
-
- void ProcessLineInterrupt()
- {
- if (ScanLine <= FrameHeight)
- {
- if (lineIntLinesRemaining-- <= 0)
- {
- HIntPending = true;
- if (EnableLineInterrupts)
- Cpu.Interrupt = true;
- lineIntLinesRemaining = Registers[0x0A];
- }
- return;
- }
- // else we're outside the active display period
- lineIntLinesRemaining = Registers[0x0A];
- }
-
- public void ExecFrame(bool render)
- {
- int scanlinesPerFrame = DisplayType == DisplayType.NTSC ? 262 : 313;
- for (ScanLine = 0; ScanLine < scanlinesPerFrame; ScanLine++)
- {
- RenderCurrentScanline(render);
-
- ProcessFrameInterrupt();
- ProcessLineInterrupt();
-
- Cpu.ExecuteCycles(IPeriod);
-
- if (ScanLine == scanlinesPerFrame - 1)
- RenderBlankingRegions();
- }
- }
-
- internal void RenderCurrentScanline(bool render)
- {
- if (ScanLine >= FrameHeight)
- return;
-
- if (TmsMode == 4)
- {
- if (render == false)
- {
- ProcessSpriteCollisionForFrameskip();
- return;
- }
-
- RenderBackgroundCurrentLine(Coleco.CoreInputComm.SMS_ShowBG);
-
- if (EnableDoubledSprites)
- RenderSpritesCurrentLineDoubleSize(Coleco.CoreInputComm.SMS_ShowOBJ);
- else
- RenderSpritesCurrentLine(Coleco.CoreInputComm.SMS_ShowOBJ);
- }
- else if (TmsMode == 2)
- {
- if (render == false)
- return;
-
- RenderBackgroundM2(Coleco.CoreInputComm.SMS_ShowBG);
- RenderTmsSprites(Coleco.CoreInputComm.SMS_ShowOBJ);
- }
- else if (TmsMode == 0)
- {
- if (render == false)
- return;
-
- RenderBackgroundM0(Coleco.CoreInputComm.SMS_ShowBG);
- RenderTmsSprites(Coleco.CoreInputComm.SMS_ShowOBJ);
- }
- }
-
- public void SaveStateText(TextWriter writer)
- {
- writer.WriteLine("[VDP]");
- writer.WriteLine("StatusByte {0:X2}", StatusByte);
- writer.WriteLine("WaitingForLatchByte {0}", VdpWaitingForLatchByte);
- writer.WriteLine("Latch {0:X2}", VdpLatch);
- writer.WriteLine("ReadBuffer {0:X2}", VdpBuffer);
- writer.WriteLine("VdpAddress {0:X4}", VdpAddress);
- writer.WriteLine("Command " + Enum.GetName(typeof(VdpCommand), vdpCommand));
-
- writer.Write("Registers ");
- Registers.SaveAsHex(writer);
- writer.Write("CRAM ");
- CRAM.SaveAsHex(writer);
- writer.Write("VRAM ");
- VRAM.SaveAsHex(writer);
-
- writer.WriteLine("[/VDP]");
- writer.WriteLine();
- }
-
- public void LoadStateText(TextReader reader)
- {
- while (true)
- {
- string[] args = reader.ReadLine().Split(' ');
- if (args[0].Trim() == "") continue;
- if (args[0] == "[/VDP]") break;
- if (args[0] == "StatusByte")
- StatusByte = byte.Parse(args[1], NumberStyles.HexNumber);
- else if (args[0] == "WaitingForLatchByte")
- VdpWaitingForLatchByte = bool.Parse(args[1]);
- else if (args[0] == "Latch")
- VdpLatch = byte.Parse(args[1], NumberStyles.HexNumber);
- else if (args[0] == "ReadBuffer")
- VdpBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
- else if (args[0] == "VdpAddress")
- VdpAddress = ushort.Parse(args[1], NumberStyles.HexNumber);
- else if (args[0] == "Command")
- vdpCommand = (VdpCommand)Enum.Parse(typeof(VdpCommand), args[1]);
- else if (args[0] == "Registers")
- Registers.ReadFromHex(args[1]);
- else if (args[0] == "CRAM")
- {
- CRAM.ReadFromHex(args[1]);
- UpdatePrecomputedPalette();
- }
- else if (args[0] == "VRAM")
- {
- VRAM.ReadFromHex(args[1]);
- for (ushort i = 0; i < VRAM.Length; i++)
- UpdatePatternBuffer(i, VRAM[i]);
- }
-
- else
- Console.WriteLine("Skipping unrecognized identifier " + args[0]);
- }
- for (int i = 0; i < Registers.Length; i++)
- WriteRegister(i, Registers[i]);
- }
-
- public void SaveStateBinary(BinaryWriter writer)
- {
- writer.Write(StatusByte);
- writer.Write(VdpWaitingForLatchByte);
- writer.Write(VdpLatch);
- writer.Write(VdpBuffer);
- writer.Write(VdpAddress);
- writer.Write((byte)vdpCommand);
- writer.Write(Registers);
- writer.Write(CRAM);
- writer.Write(VRAM);
- }
-
- public void LoadStateBinary(BinaryReader reader)
- {
- StatusByte = reader.ReadByte();
- VdpWaitingForLatchByte = reader.ReadBoolean();
- VdpLatch = reader.ReadByte();
- VdpBuffer = reader.ReadByte();
- VdpAddress = reader.ReadUInt16();
- vdpCommand = (VdpCommand)Enum.ToObject(typeof(VdpCommand), reader.ReadByte());
- Registers = reader.ReadBytes(Registers.Length);
- CRAM = reader.ReadBytes(CRAM.Length);
- VRAM = reader.ReadBytes(VRAM.Length);
- UpdatePrecomputedPalette();
- for (ushort i = 0; i < VRAM.Length; i++)
- UpdatePatternBuffer(i, VRAM[i]);
- for (int i = 0; i < Registers.Length; i++)
- WriteRegister(i, Registers[i]);
- }
-
- public int[] GetVideoBuffer()
- {
- return mode == VdpMode.SMS ? FrameBuffer : GameGearFrameBuffer;
- }
-
- public int VirtualWidth { get { return BufferWidth; } }
- public int BufferWidth
- {
- get { return mode == VdpMode.SMS ? 256 : 160; }
- }
-
- public int BufferHeight
- {
- get { return mode == VdpMode.SMS ? FrameHeight : 144; }
- }
-
- public int BackgroundColor
- {
- get { return Palette[BackdropColor]; }
- }
-
- enum VdpCommand
- {
- VramRead,
- VramWrite,
- RegisterWrite,
- CramWrite
- }
- }
-}
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index e31833face..b58602b327 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -1486,7 +1486,7 @@ namespace BizHawk.MultiClient
if (path == null) return false;
using (var file = new HawkFile())
{
- string[] romExtensions = new string[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT" };
+ string[] romExtensions = new string[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL" };
//lets not use this unless we need to
//file.NonArchiveExtensions = romExtensions;
@@ -1758,7 +1758,7 @@ namespace BizHawk.MultiClient
}
break;
case "COLV":
- SMS c = new SMS(game, rom.RomData);//new ColecoVision(game, rom.FileData);
+ ColecoVision c = new ColecoVision(game, rom.RomData);
nextEmulator = c;
break;
case "INTV":