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":