2012-11-01 16:48:32 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2012-11-03 06:03:58 +00:00
|
|
|
|
using System.IO;
|
2012-11-01 16:48:32 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using BizHawk.Emulation.CPUs.M6502;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Computers.Commodore64
|
|
|
|
|
{
|
|
|
|
|
public partial class C64 : IEmulator
|
|
|
|
|
{
|
2012-11-08 21:12:33 +00:00
|
|
|
|
// input
|
|
|
|
|
private IController controller;
|
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// source
|
|
|
|
|
public Cartridge cart;
|
2012-11-06 05:49:42 +00:00
|
|
|
|
public string extension;
|
2012-11-03 06:03:58 +00:00
|
|
|
|
public byte[] inputFile;
|
2012-11-07 17:52:16 +00:00
|
|
|
|
public List<IMedia> mediaAttached = new List<IMedia>();
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// chipset
|
2012-11-05 16:56:58 +00:00
|
|
|
|
public Cia cia0;
|
2012-11-03 17:57:14 +00:00
|
|
|
|
public Cia cia1;
|
2012-11-08 21:12:33 +00:00
|
|
|
|
public byte cia0portAData;
|
|
|
|
|
public byte cia0portBData;
|
2012-11-01 16:48:32 +00:00
|
|
|
|
public MOS6502X cpu;
|
2012-11-03 17:57:14 +00:00
|
|
|
|
public Memory mem;
|
|
|
|
|
public Sid sid;
|
|
|
|
|
public VicII vic;
|
2012-11-05 14:24:01 +00:00
|
|
|
|
public ChipSignals signal;
|
2012-11-01 16:48:32 +00:00
|
|
|
|
|
2012-11-06 06:19:27 +00:00
|
|
|
|
public void HardReset()
|
2012-11-01 16:48:32 +00:00
|
|
|
|
{
|
|
|
|
|
cpu = new MOS6502X();
|
|
|
|
|
cpu.ReadMemory = ReadMemory;
|
|
|
|
|
cpu.WriteMemory = WriteMemory;
|
2012-11-03 06:03:58 +00:00
|
|
|
|
cpu.DummyReadMemory = PeekMemory;
|
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// initialize cia timers
|
2012-11-05 16:56:58 +00:00
|
|
|
|
cia0 = new Cia(signal);
|
2012-11-05 19:05:25 +00:00
|
|
|
|
cia0.ports[0] = new DirectionalDataPort(0x00, 0x00);
|
|
|
|
|
cia0.ports[1] = new DirectionalDataPort(0x00, 0x00);
|
2012-11-05 16:56:58 +00:00
|
|
|
|
cia1 = new Cia(signal);
|
2012-11-05 19:05:25 +00:00
|
|
|
|
cia1.ports[0] = new DirectionalDataPort(0x00, 0x00);
|
|
|
|
|
cia1.ports[1] = new DirectionalDataPort(0x00, 0x00);
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// initialize vic
|
2012-11-05 14:24:01 +00:00
|
|
|
|
signal = new ChipSignals();
|
|
|
|
|
vic = new VicII(signal, VicIIMode.NTSC);
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// initialize sid
|
|
|
|
|
sid = new Sid();
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// initialize memory (this must be done AFTER all other chips are initialized)
|
2012-11-06 06:19:27 +00:00
|
|
|
|
string romPath = CoreInputComm.C64_FirmwaresPath;
|
2012-11-05 16:56:58 +00:00
|
|
|
|
mem = new Memory(romPath, vic, sid, cia0, cia1);
|
2012-11-03 17:57:14 +00:00
|
|
|
|
vic.mem = mem;
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-06 05:49:42 +00:00
|
|
|
|
// initialize cpu (hard reset vector)
|
|
|
|
|
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
|
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
// initialize media
|
2012-11-06 05:49:42 +00:00
|
|
|
|
switch (extension.ToUpper())
|
2012-11-03 17:57:14 +00:00
|
|
|
|
{
|
2012-11-06 05:49:42 +00:00
|
|
|
|
case @".PRG":
|
|
|
|
|
if (inputFile.Length > 2)
|
2012-11-07 17:52:16 +00:00
|
|
|
|
mediaAttached.Add(new PRGFile(inputFile, mem, cpu));
|
2012-11-06 05:49:42 +00:00
|
|
|
|
break;
|
|
|
|
|
case @".CRT":
|
2012-11-08 19:57:22 +00:00
|
|
|
|
Cartridge newCart = new Cartridge(inputFile, mem);
|
|
|
|
|
if (newCart.valid)
|
|
|
|
|
{
|
|
|
|
|
cart = newCart;
|
2012-11-07 17:52:16 +00:00
|
|
|
|
mediaAttached.Add(cart);
|
2012-11-08 19:57:22 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cart = null;
|
|
|
|
|
}
|
2012-11-06 05:49:42 +00:00
|
|
|
|
break;
|
2012-11-03 17:57:14 +00:00
|
|
|
|
}
|
2012-11-06 06:19:27 +00:00
|
|
|
|
|
|
|
|
|
videoProvider = new MyVideoProvider(vic);
|
2012-11-01 16:48:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
public byte PeekMemory(ushort addr)
|
|
|
|
|
{
|
|
|
|
|
return mem.Peek(addr);
|
|
|
|
|
}
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
public byte PeekMemoryInt(int addr)
|
|
|
|
|
{
|
|
|
|
|
return mem.Peek((ushort)(addr & 0xFFFF));
|
|
|
|
|
}
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-03 17:57:14 +00:00
|
|
|
|
public void PokeMemoryInt(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
// todo
|
|
|
|
|
}
|
2012-11-03 06:03:58 +00:00
|
|
|
|
|
2012-11-08 21:12:33 +00:00
|
|
|
|
public void PollInput()
|
|
|
|
|
{
|
|
|
|
|
cia0portAData = 0xFF;
|
|
|
|
|
cia0portBData = 0xFF;
|
|
|
|
|
|
|
|
|
|
if (Controller["P1 Up"]) cia0portBData &= 0xFE;
|
|
|
|
|
if (Controller["P1 Down"]) cia0portBData &= 0xFD;
|
|
|
|
|
if (Controller["P1 Left"]) cia0portBData &= 0xFB;
|
|
|
|
|
if (Controller["P1 Right"]) cia0portBData &= 0xF7;
|
|
|
|
|
if (Controller["P1 Button"]) cia0portBData &= 0xEF;
|
|
|
|
|
if (Controller["P2 Up"]) cia0portAData &= 0xFE;
|
|
|
|
|
if (Controller["P2 Down"]) cia0portAData &= 0xFD;
|
|
|
|
|
if (Controller["P2 Left"]) cia0portAData &= 0xFB;
|
|
|
|
|
if (Controller["P2 Right"]) cia0portAData &= 0xF7;
|
|
|
|
|
if (Controller["P2 Button"]) cia0portAData &= 0xEF;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-01 16:48:32 +00:00
|
|
|
|
public byte ReadMemory(ushort addr)
|
|
|
|
|
{
|
2012-11-03 06:03:58 +00:00
|
|
|
|
return mem.Read(addr);
|
2012-11-01 16:48:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteMemory(ushort addr, byte value)
|
|
|
|
|
{
|
2012-11-03 17:57:14 +00:00
|
|
|
|
mem.Write(addr, value);
|
2012-11-01 16:48:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-05 14:24:01 +00:00
|
|
|
|
|
|
|
|
|
public class ChipSignals
|
|
|
|
|
{
|
2012-11-05 16:56:58 +00:00
|
|
|
|
private bool[] _CiaSerialInput = new bool[2];
|
2012-11-05 14:24:01 +00:00
|
|
|
|
private bool[] _CiaIRQOutput = new bool[2];
|
|
|
|
|
private bool _VicAECOutput;
|
|
|
|
|
private bool _VicBAOutput;
|
|
|
|
|
private bool _VicIRQOutput;
|
|
|
|
|
private bool _VicLPInput;
|
|
|
|
|
|
2012-11-05 16:56:58 +00:00
|
|
|
|
public bool CiaIRQ0 { get { return _CiaIRQOutput[0]; } set { _CiaIRQOutput[0] = value; } }
|
|
|
|
|
public bool CiaIRQ1 { get { return _CiaIRQOutput[1]; } set { _CiaIRQOutput[1] = value; } }
|
|
|
|
|
public bool CiaSerial0 { get { return _CiaSerialInput[0]; } }
|
|
|
|
|
public bool CiaSerial1 { get { return _CiaSerialInput[1]; } }
|
2012-11-05 14:24:01 +00:00
|
|
|
|
public bool CpuAEC { get { return _VicAECOutput; } }
|
2012-11-06 15:15:37 +00:00
|
|
|
|
public bool CpuIRQ { get { return _VicIRQOutput | _CiaIRQOutput[0]; } }
|
|
|
|
|
public bool CpuNMI { get { return _CiaIRQOutput[1]; } }
|
2012-11-05 14:24:01 +00:00
|
|
|
|
public bool CpuRDY { get { return _VicBAOutput; } }
|
2012-11-05 19:05:25 +00:00
|
|
|
|
public bool LPOutput { get { return _VicLPInput; } set { _VicLPInput = value; } }
|
2012-11-05 14:24:01 +00:00
|
|
|
|
public bool VicAEC { get { return _VicAECOutput; } set { _VicAECOutput = value; } }
|
|
|
|
|
public bool VicIRQ { get { return _VicIRQOutput; } set { _VicIRQOutput = value; } }
|
|
|
|
|
public bool VicLP { get { return _VicLPInput; } }
|
|
|
|
|
}
|
2012-11-01 16:48:32 +00:00
|
|
|
|
}
|