2012-03-25 01:33:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
2012-05-06 02:48:39 +00:00
|
|
|
|
using BizHawk.Emulation.CPUs.Z80;
|
|
|
|
|
using BizHawk.Emulation.Sound;
|
2012-03-25 01:33:05 +00:00
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Consoles.Coleco
|
|
|
|
|
{
|
2012-11-17 17:39:33 +00:00
|
|
|
|
public sealed partial class ColecoVision : IEmulator
|
2012-03-25 01:33:05 +00:00
|
|
|
|
{
|
2012-11-17 21:12:51 +00:00
|
|
|
|
// ROM
|
|
|
|
|
public byte[] RomData;
|
|
|
|
|
public int RomLength;
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public byte[] BiosRom;
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
// Machine
|
|
|
|
|
public Z80A Cpu;
|
|
|
|
|
public TMS9918A VDP;
|
|
|
|
|
public SN76489 PSG;
|
|
|
|
|
public byte[] Ram = new byte[1024];
|
2012-05-06 02:48:39 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public ColecoVision(GameInfo game, byte[] rom, string biosPath)
|
2012-03-25 01:33:05 +00:00
|
|
|
|
{
|
2012-11-17 21:12:51 +00:00
|
|
|
|
Cpu = new Z80A();
|
|
|
|
|
Cpu.ReadMemory = ReadMemory;
|
|
|
|
|
Cpu.WriteMemory = WriteMemory;
|
|
|
|
|
Cpu.ReadHardware = ReadPort;
|
|
|
|
|
Cpu.WriteHardware = WritePort;
|
|
|
|
|
Cpu.Logger = (s) => Console.WriteLine(s);
|
|
|
|
|
//Cpu.Debug = true;
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
VDP = new TMS9918A(Cpu);
|
|
|
|
|
PSG = new SN76489();
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
// TODO: hack to allow bios-less operation would be nice, no idea if its feasible
|
2012-11-17 21:28:09 +00:00
|
|
|
|
BiosRom = File.ReadAllBytes(biosPath);
|
2012-05-06 02:48:39 +00:00
|
|
|
|
|
2012-03-25 01:33:05 +00:00
|
|
|
|
CoreOutputComm = new CoreOutputComm();
|
|
|
|
|
CoreInputComm = new CoreInputComm();
|
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
LoadRom(rom);
|
|
|
|
|
this.game = game;
|
2012-03-25 01:33:05 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
Reset();
|
2012-03-25 01:33:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public void FrameAdvance(bool render, bool renderSound)
|
|
|
|
|
{
|
|
|
|
|
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
|
|
|
|
VDP.ExecuteFrame();
|
|
|
|
|
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LoadRom(byte[] rom)
|
|
|
|
|
{
|
|
|
|
|
RomData = new byte[0x8000];
|
|
|
|
|
for (int i = 0; i < 0x8000; i++)
|
|
|
|
|
RomData[i] = rom[i % rom.Length];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
|
{
|
|
|
|
|
/*Cpu.RegisterPC = Cpu.ReadWord(0x800A);
|
|
|
|
|
Console.WriteLine("code start vector = {0:X4}", Cpu.RegisterPC);*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte ReadPort(ushort port)
|
|
|
|
|
{
|
|
|
|
|
port &= 0xFF;
|
|
|
|
|
//Console.WriteLine("Read port {0:X2}", port);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2012-03-25 01:33:05 +00:00
|
|
|
|
|
2012-09-14 22:28:38 +00:00
|
|
|
|
public byte[] ReadSaveRam() { return null; }
|
|
|
|
|
public void StoreSaveRam(byte[] data) { }
|
|
|
|
|
public void ClearSaveRam() { }
|
2012-03-25 01:33:05 +00:00
|
|
|
|
public bool SaveRamModified { get; set; }
|
2012-09-14 22:28:38 +00:00
|
|
|
|
|
2012-10-03 15:31:04 +00:00
|
|
|
|
public bool DeterministicEmulation { get { return true; } }
|
2012-11-17 17:39:33 +00:00
|
|
|
|
public void SaveStateText(TextWriter writer) { }
|
|
|
|
|
public void LoadStateText(TextReader reader) { }
|
|
|
|
|
public void SaveStateBinary(BinaryWriter bw) { }
|
|
|
|
|
public void LoadStateBinary(BinaryReader br) { }
|
2012-03-25 01:33:05 +00:00
|
|
|
|
|
|
|
|
|
public byte[] SaveStateBinary()
|
|
|
|
|
{
|
2012-11-17 21:12:51 +00:00
|
|
|
|
return new byte[0];
|
2012-03-25 01:33:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public void Dispose() { }
|
|
|
|
|
public void ResetFrameCounter() { }
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public string SystemId { get { return "Coleco"; } }
|
|
|
|
|
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; } }
|
2012-11-17 17:39:33 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public ISyncSoundProvider SyncSoundProvider { get { return null; } }
|
|
|
|
|
public bool StartAsyncSound() { return true; }
|
|
|
|
|
public void EndAsyncSound() { }
|
2012-03-25 01:33:05 +00:00
|
|
|
|
|
2012-11-17 21:12:51 +00:00
|
|
|
|
public IList<MemoryDomain> MemoryDomains { get { return null; } }
|
|
|
|
|
public MemoryDomain MainMemory { get { return null; } }
|
2012-03-25 01:33:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|