BizHawk/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6510.cs

208 lines
4.6 KiB
C#
Raw Normal View History

using BizHawk.Emulation.CPUs.M6502;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// an extension of the 6502 processor
public class MOS6510 : IStandardIO
{
// ------------------------------------
private C64Chips chips;
private MOS6502X cpu;
private bool freezeCpu;
private bool pinCassetteButton;
private bool pinCassetteMotor;
private bool pinCassetteOutput;
private bool pinCharen;
private bool pinLoram;
private bool pinHiram;
private byte portDir;
private bool unusedPin0;
private bool unusedPin1;
private uint unusedPinTTL0;
private uint unusedPinTTL1;
private uint unusedPinTTLCycles;
// ------------------------------------
public MOS6510(C64Chips newChips)
{
chips = newChips;
cpu = new MOS6502X();
// configure cpu r/w
cpu.DummyReadMemory = Read;
cpu.ReadMemory = Read;
cpu.WriteMemory = Write;
// configure data port defaults
portDir = 0x2F;
SetPortData(0x37);
// todo: verify this value (I only know that unconnected bits fade after a number of cycles)
unusedPinTTLCycles = 40;
unusedPinTTL0 = 0;
unusedPinTTL1 = 0;
}
public void HardReset()
{
cpu.Reset();
cpu.FlagI = true;
cpu.BCD_Enabled = true;
cpu.PC = (ushort)(chips.pla.Read(0xFFFC) | (chips.pla.Read(0xFFFD) << 8));
}
// ------------------------------------
public void ExecutePhase1()
{
}
public void ExecutePhase2()
{
if (chips.vic.BA)
freezeCpu = false;
if (chips.vic.AEC && !freezeCpu)
{
// the 6502 core expects active high
// so we reverse the polarity here
cpu.NMI = !(chips.cia1.IRQ & chips.cartPort.NMI);
cpu.IRQ = !(chips.vic.IRQ && chips.cia0.IRQ && chips.cartPort.IRQ);
cpu.ExecuteOne();
}
// process unused pin TTL
if (unusedPinTTL0 == 0)
unusedPin0 = false;
else
unusedPinTTL0--;
if (unusedPinTTL1 == 0)
unusedPin1 = false;
else
unusedPinTTL1--;
}
// ------------------------------------
public byte Peek(int addr)
{
if (addr == 0x0000)
return PortDirection;
else if (addr == 0x0001)
return PortData;
else
return chips.pla.Peek(addr);
}
public void Poke(int addr, byte val)
{
if (addr == 0x0000)
portDir = val;
else if (addr == 0x0001)
SetPortData(val);
else
chips.pla.Poke(addr, val);
}
public byte Read(ushort addr)
{
// cpu freezes after first read when RDY is low
if (!chips.vic.BA)
freezeCpu = true;
if (addr == 0x0000)
return PortDirection;
else if (addr == 0x0001)
return PortData;
else
return chips.pla.Read(addr);
}
public void Write(ushort addr, byte val)
{
if (addr == 0x0000)
PortDirection = val;
else if (addr == 0x0001)
PortData = val;
chips.pla.Write(addr, val);
}
// ------------------------------------
public bool Charen
{
get { return pinCharen; }
}
public bool HiRam
{
get { return pinHiram; }
}
public bool LoRam
{
get { return pinLoram; }
}
public byte PortData
{
get
{
byte result = 0x00;
result |= pinLoram ? (byte)0x01 : (byte)0x00;
result |= pinHiram ? (byte)0x02 : (byte)0x00;
result |= pinCharen ? (byte)0x04 : (byte)0x00;
result |= pinCassetteOutput ? (byte)0x08 : (byte)0x00;
result |= pinCassetteButton ? (byte)0x10 : (byte)0x00;
result |= pinCassetteMotor ? (byte)0x20 : (byte)0x00;
result |= unusedPin0 ? (byte)0x40 : (byte)0x00;
result |= unusedPin1 ? (byte)0x80 : (byte)0x00;
return result;
}
set
{
byte val = Port.CPUWrite(PortData, value, portDir);
Console.WriteLine("CPU write DTA: val=" + C64Util.ToBinary(value, 8) + " dir=" + C64Util.ToBinary(portDir, 8) + " new=" + C64Util.ToBinary(val, 8));
SetPortData(val);
}
}
public byte PortDirection
{
get { return portDir; }
set
{
Console.WriteLine("CPU write DIR: val=" + C64Util.ToBinary(value, 8));
portDir = value;
}
}
private void SetPortData(byte val)
{
pinCassetteOutput = ((val & 0x08) != 0);
pinCassetteButton = ((val & 0x10) != 0);
pinCassetteMotor = ((val & 0x20) != 0);
pinLoram = ((val & 0x01) != 0);
pinHiram = ((val & 0x02) != 0);
pinCharen = ((val & 0x04) != 0);
unusedPin0 = ((val & 0x40) != 0);
unusedPin1 = ((val & 0x80) != 0);
unusedPinTTL0 = unusedPinTTLCycles;
unusedPinTTL1 = unusedPinTTLCycles;
}
// ------------------------------------
}
}