commodore64: input added back, this method is closer to the circuitry itself
This commit is contained in:
parent
8e55810161
commit
e490d1be04
|
@ -82,6 +82,7 @@
|
||||||
<Compile Include="Computers\Commodore64\C64.Core.cs" />
|
<Compile Include="Computers\Commodore64\C64.Core.cs" />
|
||||||
<Compile Include="Computers\Commodore64\C64.cs" />
|
<Compile Include="Computers\Commodore64\C64.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Cartridges\Mapper0000.cs" />
|
<Compile Include="Computers\Commodore64\Cartridges\Mapper0000.cs" />
|
||||||
|
<Compile Include="Computers\Commodore64\C64.Input.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Memory.cs" />
|
<Compile Include="Computers\Commodore64\Memory.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Cartridges\Cartridge.cs" />
|
<Compile Include="Computers\Commodore64\Cartridges\Cartridge.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\CartridgePort.cs" />
|
<Compile Include="Computers\Commodore64\MOS\CartridgePort.cs" />
|
||||||
|
|
|
@ -44,6 +44,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
// configure video
|
// configure video
|
||||||
CoreOutputComm.VsyncDen = chips.vic.CyclesPerFrame;
|
CoreOutputComm.VsyncDen = chips.vic.CyclesPerFrame;
|
||||||
CoreOutputComm.VsyncNum = chips.vic.CyclesPerSecond;
|
CoreOutputComm.VsyncNum = chips.vic.CyclesPerSecond;
|
||||||
|
|
||||||
|
// configure input
|
||||||
|
InitInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitMedia()
|
private void InitMedia()
|
||||||
|
@ -103,6 +106,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
for (; count > 0; count--)
|
for (; count > 0; count--)
|
||||||
{
|
{
|
||||||
|
WriteInputPort();
|
||||||
chips.ExecutePhase1();
|
chips.ExecutePhase1();
|
||||||
chips.ExecutePhase2();
|
chips.ExecutePhase2();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
using BizHawk.Emulation.Computers.Commodore64.MOS;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
|
{
|
||||||
|
public partial class C64 : IEmulator
|
||||||
|
{
|
||||||
|
private PortAdapter inputAdapter0;
|
||||||
|
private PortAdapter inputAdapter1;
|
||||||
|
private byte[] joystickMatrix = new byte[2];
|
||||||
|
private byte[] keyboardMatrix = new byte[8];
|
||||||
|
|
||||||
|
private void InitInput()
|
||||||
|
{
|
||||||
|
inputAdapter0 = chips.cia0.Adapter0;
|
||||||
|
inputAdapter1 = chips.cia0.Adapter1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PollInput()
|
||||||
|
{
|
||||||
|
joystickMatrix[0] = 0xFF;
|
||||||
|
joystickMatrix[0] &= controller["P1 Up"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
joystickMatrix[0] &= controller["P1 Down"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
joystickMatrix[0] &= controller["P1 Left"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
joystickMatrix[0] &= controller["P1 Right"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
joystickMatrix[0] &= controller["P1 Button"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
|
||||||
|
joystickMatrix[1] = 0xFF;
|
||||||
|
joystickMatrix[1] &= controller["P2 Up"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
joystickMatrix[1] &= controller["P2 Down"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
joystickMatrix[1] &= controller["P2 Left"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
joystickMatrix[1] &= controller["P2 Right"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
joystickMatrix[1] &= controller["P2 Button"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[0] = 0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key Insert/Delete"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key Return"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key Cursor Left/Right"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key F7"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key F1"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key F3"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key F5"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[0] &= controller["Key Cursor Up/Down"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[1] = 0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key 3"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key W"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key A"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key 4"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key Z"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key S"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key E"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[1] &= controller["Key Left Shift"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[2] = 0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key 5"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key R"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key D"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key 6"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key C"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key F"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key T"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[2] &= controller["Key X"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[3] = 0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key 7"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key Y"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key G"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key 8"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key B"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key H"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key U"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[3] &= controller["Key V"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[4] = 0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key 9"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key I"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key J"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key 0"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key M"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key K"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key O"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[4] &= controller["Key N"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[5] = 0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key Plus"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key P"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key L"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key Minus"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key Period"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key Colon"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key At"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[5] &= controller["Key Comma"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[6] = 0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Pound"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Asterisk"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Semicolon"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Clear/Home"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Right Shift"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Equal"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Up Arrow"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[6] &= controller["Key Slash"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
|
||||||
|
keyboardMatrix[7] = 0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key 1"] ? (byte)0xFE : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Left Arrow"] ? (byte)0xFD : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Control"] ? (byte)0xFB : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key 2"] ? (byte)0xF7 : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Space"] ? (byte)0xEF : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Commodore"] ? (byte)0xDF : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Q"] ? (byte)0xBF : (byte)0xFF;
|
||||||
|
keyboardMatrix[7] &= controller["Key Run/Stop"] ? (byte)0x7F : (byte)0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteInputPort()
|
||||||
|
{
|
||||||
|
inputAdapter0.Data = 0xFF;
|
||||||
|
inputAdapter1.Data = 0xFF;
|
||||||
|
|
||||||
|
byte portA = inputAdapter0.Data;
|
||||||
|
byte portB = inputAdapter1.Data;
|
||||||
|
|
||||||
|
if ((portA & 0x01) == 0)
|
||||||
|
portB &= keyboardMatrix[0];
|
||||||
|
if ((portA & 0x02) == 0)
|
||||||
|
portB &= keyboardMatrix[1];
|
||||||
|
if ((portA & 0x04) == 0)
|
||||||
|
portB &= keyboardMatrix[2];
|
||||||
|
if ((portA & 0x08) == 0)
|
||||||
|
portB &= keyboardMatrix[3];
|
||||||
|
if ((portA & 0x10) == 0)
|
||||||
|
portB &= keyboardMatrix[4];
|
||||||
|
if ((portA & 0x20) == 0)
|
||||||
|
portB &= keyboardMatrix[5];
|
||||||
|
if ((portA & 0x40) == 0)
|
||||||
|
portB &= keyboardMatrix[6];
|
||||||
|
if ((portA & 0x80) == 0)
|
||||||
|
portB &= keyboardMatrix[7];
|
||||||
|
|
||||||
|
portA &= joystickMatrix[1];
|
||||||
|
portB &= joystickMatrix[0];
|
||||||
|
|
||||||
|
inputAdapter0.Data = portA;
|
||||||
|
inputAdapter1.Data = portB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
public partial class C64 : IEmulator
|
public partial class C64 : IEmulator
|
||||||
{
|
{
|
||||||
|
private IController controller;
|
||||||
private uint cyclesPerFrame;
|
private uint cyclesPerFrame;
|
||||||
private string extension;
|
private string extension;
|
||||||
private byte[] inputFile;
|
private byte[] inputFile;
|
||||||
|
@ -64,7 +65,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
|
|
||||||
// controller
|
// controller
|
||||||
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
|
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
|
||||||
public IController Controller { get { return null; } set { } }
|
public IController Controller { get { return controller; } set { controller = value; } }
|
||||||
public static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition
|
public static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition
|
||||||
{
|
{
|
||||||
Name = "Commodore 64 Controller", //TODO
|
Name = "Commodore 64 Controller", //TODO
|
||||||
|
@ -89,6 +90,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
// process frame
|
// process frame
|
||||||
public void FrameAdvance(bool render, bool rendersound)
|
public void FrameAdvance(bool render, bool rendersound)
|
||||||
{
|
{
|
||||||
|
PollInput();
|
||||||
chips.pla.InputWasRead = false;
|
chips.pla.InputWasRead = false;
|
||||||
Execute(cyclesPerFrame);
|
Execute(cyclesPerFrame);
|
||||||
_islag = !chips.pla.InputWasRead;
|
_islag = !chips.pla.InputWasRead;
|
||||||
|
|
|
@ -41,8 +41,18 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
Output
|
Output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] PBOnBit = new byte[] { 0x40, 0x80 };
|
||||||
|
private static byte[] PBOnMask = new byte[] { 0xBF, 0x7F };
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
|
private bool alarmSelect;
|
||||||
|
private Region chipRegion;
|
||||||
|
private bool cntPos;
|
||||||
|
private bool enableIntAlarm;
|
||||||
|
private bool enableIntFlag;
|
||||||
|
private bool enableIntSP;
|
||||||
|
private bool[] enableIntTimer;
|
||||||
private bool intAlarm;
|
private bool intAlarm;
|
||||||
private bool intFlag;
|
private bool intFlag;
|
||||||
private bool intSP;
|
private bool intSP;
|
||||||
|
@ -50,35 +60,37 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
private bool pinCnt;
|
private bool pinCnt;
|
||||||
private bool pinFlag;
|
private bool pinFlag;
|
||||||
private bool pinPC;
|
private bool pinPC;
|
||||||
|
private byte sr;
|
||||||
private InMode[] timerInMode;
|
private InMode[] timerInMode;
|
||||||
private OutMode[] timerOutMode;
|
private OutMode[] timerOutMode;
|
||||||
private bool[] timerPortEnable;
|
private bool[] timerPortEnable;
|
||||||
|
private bool[] timerPulse;
|
||||||
|
private RunMode[] timerRunMode;
|
||||||
|
private SPMode timerSPMode;
|
||||||
private byte[] tod;
|
private byte[] tod;
|
||||||
private byte[] todAlarm;
|
private byte[] todAlarm;
|
||||||
private bool todAlarmPM;
|
private bool todAlarmPM;
|
||||||
private bool todPM;
|
|
||||||
private uint todCounter;
|
private uint todCounter;
|
||||||
private uint todCounterLatch;
|
private uint todCounterLatch;
|
||||||
|
private bool todIn;
|
||||||
|
private bool todPM;
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
public MOS6526(Region region)
|
public MOS6526(Region region)
|
||||||
{
|
{
|
||||||
|
chipRegion = region;
|
||||||
|
enableIntTimer = new bool[2];
|
||||||
intTimer = new bool[2];
|
intTimer = new bool[2];
|
||||||
timerInMode = new InMode[2];
|
timerInMode = new InMode[2];
|
||||||
timerOutMode = new OutMode[2];
|
timerOutMode = new OutMode[2];
|
||||||
timerPortEnable = new bool[2];
|
timerPortEnable = new bool[2];
|
||||||
|
timerPulse = new bool[2];
|
||||||
|
timerRunMode = new RunMode[2];
|
||||||
tod = new byte[4];
|
tod = new byte[4];
|
||||||
todAlarm = new byte[4];
|
todAlarm = new byte[4];
|
||||||
switch (region)
|
|
||||||
{
|
SetTodIn(chipRegion);
|
||||||
case Region.NTSC:
|
|
||||||
todCounterLatch = 14318181 / 140;
|
|
||||||
break;
|
|
||||||
case Region.PAL:
|
|
||||||
todCounterLatch = 17734472 / 180;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
HardReset();
|
HardReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,15 +104,51 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
public void ExecutePhase2()
|
public void ExecutePhase2()
|
||||||
{
|
{
|
||||||
pinPC = true;
|
pinPC = true;
|
||||||
|
TODRun();
|
||||||
|
|
||||||
|
if (timerPulse[0])
|
||||||
|
portData[0] &= PBOnMask[0];
|
||||||
|
if (timerPulse[1])
|
||||||
|
portData[1] &= PBOnMask[0];
|
||||||
|
|
||||||
TimerRun(0);
|
TimerRun(0);
|
||||||
TimerRun(1);
|
TimerRun(1);
|
||||||
|
intAlarm |= (
|
||||||
|
tod[0] == todAlarm[0] &&
|
||||||
|
tod[1] == todAlarm[1] &&
|
||||||
|
tod[2] == todAlarm[2] &&
|
||||||
|
tod[3] == todAlarm[3] &&
|
||||||
|
todPM == todAlarmPM);
|
||||||
|
|
||||||
|
cntPos = false;
|
||||||
|
underflow[0] = false;
|
||||||
|
underflow[1] = false;
|
||||||
|
|
||||||
|
pinIRQ = !(
|
||||||
|
(intTimer[0] && enableIntTimer[0]) ||
|
||||||
|
(intTimer[1] && enableIntTimer[1]) ||
|
||||||
|
(intAlarm && enableIntAlarm) ||
|
||||||
|
(intSP && enableIntSP) ||
|
||||||
|
(intFlag && enableIntFlag)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
{
|
{
|
||||||
HardResetInternal();
|
HardResetInternal();
|
||||||
|
alarmSelect = false;
|
||||||
|
cntPos = false;
|
||||||
|
enableIntAlarm = false;
|
||||||
|
enableIntFlag = false;
|
||||||
|
enableIntSP = false;
|
||||||
|
enableIntTimer[0] = false;
|
||||||
|
enableIntTimer[1] = false;
|
||||||
|
intAlarm = false;
|
||||||
|
intFlag = false;
|
||||||
|
intSP = false;
|
||||||
intTimer[0] = false;
|
intTimer[0] = false;
|
||||||
intTimer[1] = false;
|
intTimer[1] = false;
|
||||||
|
sr = 0;
|
||||||
timerPortEnable[0] = false;
|
timerPortEnable[0] = false;
|
||||||
timerPortEnable[1] = false;
|
timerPortEnable[1] = false;
|
||||||
timerInMode[0] = InMode.Phase2;
|
timerInMode[0] = InMode.Phase2;
|
||||||
|
@ -109,6 +157,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
timerOn[1] = false;
|
timerOn[1] = false;
|
||||||
timerOutMode[0] = OutMode.Pulse;
|
timerOutMode[0] = OutMode.Pulse;
|
||||||
timerOutMode[1] = OutMode.Pulse;
|
timerOutMode[1] = OutMode.Pulse;
|
||||||
|
timerPortEnable[0] = false;
|
||||||
|
timerPortEnable[1] = false;
|
||||||
|
timerPulse[0] = false;
|
||||||
|
timerPulse[1] = false;
|
||||||
|
timerRunMode[0] = RunMode.Continuous;
|
||||||
|
timerRunMode[1] = RunMode.Continuous;
|
||||||
|
timerSPMode = SPMode.Input;
|
||||||
tod[0] = 0;
|
tod[0] = 0;
|
||||||
tod[1] = 0;
|
tod[1] = 0;
|
||||||
tod[2] = 0;
|
tod[2] = 0;
|
||||||
|
@ -118,11 +173,29 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
todAlarm[2] = 0;
|
todAlarm[2] = 0;
|
||||||
todAlarm[3] = 0;
|
todAlarm[3] = 0;
|
||||||
todCounter = todCounterLatch;
|
todCounter = todCounterLatch;
|
||||||
|
todIn = (chipRegion == Region.PAL);
|
||||||
|
todPM = false;
|
||||||
|
|
||||||
pinCnt = false;
|
pinCnt = false;
|
||||||
pinFlag = true;
|
pinFlag = true;
|
||||||
pinPC = true;
|
pinPC = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetTodIn(Region region)
|
||||||
|
{
|
||||||
|
switch (region)
|
||||||
|
{
|
||||||
|
case Region.NTSC:
|
||||||
|
todCounterLatch = 14318181 / 140;
|
||||||
|
todIn = false;
|
||||||
|
break;
|
||||||
|
case Region.PAL:
|
||||||
|
todCounterLatch = 17734472 / 180;
|
||||||
|
todIn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
private byte BCDAdd(byte i, byte j, out bool overflow)
|
private byte BCDAdd(byte i, byte j, out bool overflow)
|
||||||
|
@ -149,7 +222,76 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
private void TimerRun(uint index)
|
private void TimerRun(uint index)
|
||||||
{
|
{
|
||||||
|
if (timerOn[index])
|
||||||
|
{
|
||||||
|
uint t = timer[index];
|
||||||
|
bool u = false;
|
||||||
|
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
switch (timerInMode[index])
|
||||||
|
{
|
||||||
|
case InMode.CNT:
|
||||||
|
// CNT positive
|
||||||
|
if (cntPos)
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InMode.Phase2:
|
||||||
|
// every clock
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflow:
|
||||||
|
// every underflow[0]
|
||||||
|
if (underflow[0])
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflowCNT:
|
||||||
|
// every underflow[0] while CNT high
|
||||||
|
if (underflow[0] && pinCnt)
|
||||||
|
{
|
||||||
|
u = (t == 0);
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// underflow?
|
||||||
|
if (u)
|
||||||
|
{
|
||||||
|
t = timerLatch[index];
|
||||||
|
if (timerRunMode[index] == RunMode.Oneshot)
|
||||||
|
timerOn[index] = false;
|
||||||
|
|
||||||
|
if (timerPortEnable[index])
|
||||||
|
{
|
||||||
|
// force port B bit to output
|
||||||
|
portDir[index] |= PBOnBit[index];
|
||||||
|
switch (timerOutMode[index])
|
||||||
|
{
|
||||||
|
case OutMode.Pulse:
|
||||||
|
timerPulse[index] = true;
|
||||||
|
portData[index] |= PBOnBit[index];
|
||||||
|
break;
|
||||||
|
case OutMode.Toggle:
|
||||||
|
portData[index] ^= PBOnBit[index];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
intTimer[index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
underflow[index] = u;
|
||||||
|
timer[index] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TODRun()
|
private void TODRun()
|
||||||
|
@ -184,6 +326,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
todCounter--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
@ -191,7 +334,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
public bool CNT
|
public bool CNT
|
||||||
{
|
{
|
||||||
get { return pinCnt; }
|
get { return pinCnt; }
|
||||||
set { pinCnt = value; }
|
set { cntPos |= (!pinCnt && value); pinCnt = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FLAG
|
public bool FLAG
|
||||||
|
@ -236,6 +379,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
val = ReadRegister(addr);
|
val = ReadRegister(addr);
|
||||||
pinPC = false;
|
pinPC = false;
|
||||||
break;
|
break;
|
||||||
|
case 0x0D:
|
||||||
|
val = ReadRegister(addr);
|
||||||
|
intTimer[0] = false;
|
||||||
|
intTimer[1] = false;
|
||||||
|
intAlarm = false;
|
||||||
|
intSP = false;
|
||||||
|
intFlag = false;
|
||||||
|
pinIRQ = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
val = ReadRegister(addr);
|
val = ReadRegister(addr);
|
||||||
break;
|
break;
|
||||||
|
@ -264,28 +416,77 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
val = portDir[1];
|
val = portDir[1];
|
||||||
break;
|
break;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
|
val = (byte)(timer[0] & 0xFF);
|
||||||
break;
|
break;
|
||||||
case 0x5:
|
case 0x5:
|
||||||
|
val = (byte)(timer[0] >> 8);
|
||||||
break;
|
break;
|
||||||
case 0x6:
|
case 0x6:
|
||||||
|
val = (byte)(timer[1] & 0xFF);
|
||||||
break;
|
break;
|
||||||
case 0x7:
|
case 0x7:
|
||||||
|
val = (byte)(timer[1] >> 8);
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
|
val = tod[0];
|
||||||
break;
|
break;
|
||||||
case 0x9:
|
case 0x9:
|
||||||
|
val = tod[1];
|
||||||
break;
|
break;
|
||||||
case 0xA:
|
case 0xA:
|
||||||
|
val = tod[2];
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
|
val = tod[3];
|
||||||
break;
|
break;
|
||||||
case 0xC:
|
case 0xC:
|
||||||
|
val = sr;
|
||||||
break;
|
break;
|
||||||
case 0xD:
|
case 0xD:
|
||||||
|
val = (byte)(
|
||||||
|
(intTimer[0] ? 0x01 : 0x00) |
|
||||||
|
(intTimer[1] ? 0x02 : 0x00) |
|
||||||
|
(intAlarm ? 0x04 : 0x00) |
|
||||||
|
(intSP ? 0x08 : 0x00) |
|
||||||
|
(intFlag ? 0x10 : 0x00) |
|
||||||
|
(!pinIRQ ? 0x80 : 0x00)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 0xE:
|
case 0xE:
|
||||||
|
val = (byte)(
|
||||||
|
(timerOn[0] ? 0x01 : 0x00) |
|
||||||
|
(timerPortEnable[0] ? 0x02 : 0x00) |
|
||||||
|
(todIn ? 0x80 : 0x00));
|
||||||
|
if (timerOutMode[0] == OutMode.Toggle)
|
||||||
|
val |= 0x04;
|
||||||
|
if (timerRunMode[0] == RunMode.Oneshot)
|
||||||
|
val |= 0x08;
|
||||||
|
if (timerInMode[0] == InMode.CNT)
|
||||||
|
val |= 0x20;
|
||||||
|
if (timerSPMode == SPMode.Output)
|
||||||
|
val |= 0x40;
|
||||||
break;
|
break;
|
||||||
case 0xF:
|
case 0xF:
|
||||||
|
val = (byte)(
|
||||||
|
(timerOn[1] ? 0x01 : 0x00) |
|
||||||
|
(timerPortEnable[1] ? 0x02 : 0x00) |
|
||||||
|
(alarmSelect ? 0x80 : 0x00));
|
||||||
|
if (timerOutMode[1] == OutMode.Toggle)
|
||||||
|
val |= 0x04;
|
||||||
|
if (timerRunMode[1] == RunMode.Oneshot)
|
||||||
|
val |= 0x08;
|
||||||
|
switch (timerInMode[1])
|
||||||
|
{
|
||||||
|
case InMode.CNT:
|
||||||
|
val |= 0x20;
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflow:
|
||||||
|
val |= 0x40;
|
||||||
|
break;
|
||||||
|
case InMode.TimerAUnderflowCNT:
|
||||||
|
val |= 0x60;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,9 +500,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void Write(ushort addr, byte val, byte mask)
|
public void Write(ushort addr, byte val, byte mask)
|
||||||
{
|
{
|
||||||
|
addr &= 0xF;
|
||||||
val &= mask;
|
val &= mask;
|
||||||
val |= (byte)(ReadRegister(addr) & ~mask);
|
val |= (byte)(ReadRegister(addr) & ~mask);
|
||||||
addr &= 0xF;
|
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
|
@ -312,6 +513,26 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
WritePort1(val);
|
WritePort1(val);
|
||||||
pinPC = false;
|
pinPC = false;
|
||||||
break;
|
break;
|
||||||
|
case 0x5:
|
||||||
|
WriteRegister(addr, val);
|
||||||
|
if (!timerOn[0])
|
||||||
|
timer[0] = timerLatch[0];
|
||||||
|
break;
|
||||||
|
case 0x7:
|
||||||
|
WriteRegister(addr, val);
|
||||||
|
if (!timerOn[1])
|
||||||
|
timer[1] = timerLatch[1];
|
||||||
|
break;
|
||||||
|
case 0xE:
|
||||||
|
WriteRegister(addr, val);
|
||||||
|
if ((val & 0x10) != 0)
|
||||||
|
timer[0] = timerLatch[0];
|
||||||
|
break;
|
||||||
|
case 0xF:
|
||||||
|
WriteRegister(addr, val);
|
||||||
|
if ((val & 0x10) != 0)
|
||||||
|
timer[1] = timerLatch[1];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WriteRegister(addr, val);
|
WriteRegister(addr, val);
|
||||||
break;
|
break;
|
||||||
|
@ -320,6 +541,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void WriteRegister(ushort addr, byte val)
|
public void WriteRegister(ushort addr, byte val)
|
||||||
{
|
{
|
||||||
|
bool intReg;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
|
@ -335,28 +558,89 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
portDir[1] = val;
|
portDir[1] = val;
|
||||||
break;
|
break;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
|
timerLatch[0] &= 0xFF00;
|
||||||
|
timerLatch[0] |= val;
|
||||||
break;
|
break;
|
||||||
case 0x5:
|
case 0x5:
|
||||||
|
timerLatch[0] &= 0x00FF;
|
||||||
|
timerLatch[0] |= (uint)val << 8;
|
||||||
break;
|
break;
|
||||||
case 0x6:
|
case 0x6:
|
||||||
|
timerLatch[1] &= 0xFF00;
|
||||||
|
timerLatch[1] |= val;
|
||||||
break;
|
break;
|
||||||
case 0x7:
|
case 0x7:
|
||||||
|
timerLatch[1] &= 0x00FF;
|
||||||
|
timerLatch[1] |= (uint)val << 8;
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
|
if (alarmSelect)
|
||||||
|
todAlarm[0] = (byte)(val & 0xF);
|
||||||
|
else
|
||||||
|
tod[0] = (byte)(val & 0xF);
|
||||||
break;
|
break;
|
||||||
case 0x9:
|
case 0x9:
|
||||||
|
if (alarmSelect)
|
||||||
|
todAlarm[1] = (byte)(val & 0x7F);
|
||||||
|
else
|
||||||
|
tod[1] = (byte)(val & 0x7F);
|
||||||
break;
|
break;
|
||||||
case 0xA:
|
case 0xA:
|
||||||
|
if (alarmSelect)
|
||||||
|
todAlarm[2] = (byte)(val & 0x7F);
|
||||||
|
else
|
||||||
|
tod[2] = (byte)(val & 0x7F);
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
|
if (alarmSelect)
|
||||||
|
{
|
||||||
|
todAlarm[3] = (byte)(val & 0x1F);
|
||||||
|
todAlarmPM = ((val & 0x80) != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tod[3] = (byte)(val & 0x1F);
|
||||||
|
todPM = ((val & 0x80) != 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC:
|
case 0xC:
|
||||||
|
sr = val;
|
||||||
break;
|
break;
|
||||||
case 0xD:
|
case 0xD:
|
||||||
|
intReg = ((val & 0x80) != 0);
|
||||||
|
if ((val & 0x01) != 0)
|
||||||
|
enableIntTimer[0] = intReg;
|
||||||
|
if ((val & 0x02) != 0)
|
||||||
|
enableIntTimer[1] = intReg;
|
||||||
|
if ((val & 0x04) != 0)
|
||||||
|
enableIntAlarm = intReg;
|
||||||
|
if ((val & 0x08) != 0)
|
||||||
|
enableIntSP = intReg;
|
||||||
|
if ((val & 0x10) != 0)
|
||||||
|
enableIntFlag = intReg;
|
||||||
break;
|
break;
|
||||||
case 0xE:
|
case 0xE:
|
||||||
|
timerOn[0] = ((val & 0x01) != 0);
|
||||||
|
timerPortEnable[0] = ((val & 0x02) != 0);
|
||||||
|
timerOutMode[0] = ((val & 0x04) != 0) ? OutMode.Toggle : OutMode.Pulse;
|
||||||
|
timerRunMode[0] = ((val & 0x08) != 0) ? RunMode.Oneshot : RunMode.Continuous;
|
||||||
|
timerInMode[0] = ((val & 0x20) != 0) ? InMode.CNT : InMode.Phase2;
|
||||||
|
timerSPMode = ((val & 0x40) != 0) ? SPMode.Output : SPMode.Input;
|
||||||
|
todIn = ((val & 0x80) != 0);
|
||||||
break;
|
break;
|
||||||
case 0xF:
|
case 0xF:
|
||||||
|
timerOn[1] = ((val & 0x01) != 0);
|
||||||
|
timerPortEnable[1] = ((val & 0x02) != 0);
|
||||||
|
timerOutMode[1] = ((val & 0x04) != 0) ? OutMode.Toggle : OutMode.Pulse;
|
||||||
|
timerRunMode[1] = ((val & 0x08) != 0) ? RunMode.Oneshot : RunMode.Continuous;
|
||||||
|
switch (val & 0x60)
|
||||||
|
{
|
||||||
|
case 0x00: timerInMode[1] = InMode.Phase2; break;
|
||||||
|
case 0x20: timerInMode[1] = InMode.CNT; break;
|
||||||
|
case 0x40: timerInMode[1] = InMode.TimerAUnderflow; break;
|
||||||
|
case 0x60: timerInMode[1] = InMode.TimerAUnderflowCNT; break;
|
||||||
|
}
|
||||||
|
alarmSelect = ((val & 0x80) != 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
case PLABank.None:
|
case PLABank.None:
|
||||||
break;
|
break;
|
||||||
case PLABank.RAM:
|
case PLABank.RAM:
|
||||||
chips.ram.Write(addr, val);
|
|
||||||
break;
|
break;
|
||||||
case PLABank.Sid:
|
case PLABank.Sid:
|
||||||
chips.sid.Write(addr, val);
|
chips.sid.Write(addr, val);
|
||||||
|
@ -564,6 +563,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
chips.vic.Write(addr, val);
|
chips.vic.Write(addr, val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
chips.ram.Write(addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
protected uint[] timer;
|
protected uint[] timer;
|
||||||
protected uint[] timerLatch;
|
protected uint[] timerLatch;
|
||||||
protected bool[] timerOn;
|
protected bool[] timerOn;
|
||||||
|
protected bool[] underflow;
|
||||||
|
|
||||||
public Timer()
|
public Timer()
|
||||||
{
|
{
|
||||||
|
@ -23,17 +24,24 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
timer = new uint[2];
|
timer = new uint[2];
|
||||||
timerLatch = new uint[2];
|
timerLatch = new uint[2];
|
||||||
timerOn = new bool[2];
|
timerOn = new bool[2];
|
||||||
|
underflow = new bool[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
public PortAdapter Adapter0()
|
public PortAdapter Adapter0
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
return Port.GetAdapter(ReadPort0, ExternalWritePort0);
|
return Port.GetAdapter(ReadPort0, ExternalWritePort0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PortAdapter Adapter1()
|
public PortAdapter Adapter1
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
return Port.GetAdapter(ReadPort1, ExternalWritePort1);
|
return Port.GetAdapter(ReadPort1, ExternalWritePort1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ExternalWritePort(uint index, byte data)
|
private void ExternalWritePort(uint index, byte data)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue