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.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\Cartridges\Cartridge.cs" />
|
||||
<Compile Include="Computers\Commodore64\MOS\CartridgePort.cs" />
|
||||
|
|
|
@ -44,6 +44,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
// configure video
|
||||
CoreOutputComm.VsyncDen = chips.vic.CyclesPerFrame;
|
||||
CoreOutputComm.VsyncNum = chips.vic.CyclesPerSecond;
|
||||
|
||||
// configure input
|
||||
InitInput();
|
||||
}
|
||||
|
||||
private void InitMedia()
|
||||
|
@ -103,6 +106,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
for (; count > 0; count--)
|
||||
{
|
||||
WriteInputPort();
|
||||
chips.ExecutePhase1();
|
||||
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
|
||||
{
|
||||
private IController controller;
|
||||
private uint cyclesPerFrame;
|
||||
private string extension;
|
||||
private byte[] inputFile;
|
||||
|
@ -64,7 +65,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
// controller
|
||||
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
|
||||
{
|
||||
Name = "Commodore 64 Controller", //TODO
|
||||
|
@ -89,6 +90,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
// process frame
|
||||
public void FrameAdvance(bool render, bool rendersound)
|
||||
{
|
||||
PollInput();
|
||||
chips.pla.InputWasRead = false;
|
||||
Execute(cyclesPerFrame);
|
||||
_islag = !chips.pla.InputWasRead;
|
||||
|
|
|
@ -41,8 +41,18 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
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 intFlag;
|
||||
private bool intSP;
|
||||
|
@ -50,35 +60,37 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
private bool pinCnt;
|
||||
private bool pinFlag;
|
||||
private bool pinPC;
|
||||
private byte sr;
|
||||
private InMode[] timerInMode;
|
||||
private OutMode[] timerOutMode;
|
||||
private bool[] timerPortEnable;
|
||||
private bool[] timerPulse;
|
||||
private RunMode[] timerRunMode;
|
||||
private SPMode timerSPMode;
|
||||
private byte[] tod;
|
||||
private byte[] todAlarm;
|
||||
private bool todAlarmPM;
|
||||
private bool todPM;
|
||||
private uint todCounter;
|
||||
private uint todCounterLatch;
|
||||
private bool todIn;
|
||||
private bool todPM;
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
public MOS6526(Region region)
|
||||
{
|
||||
chipRegion = region;
|
||||
enableIntTimer = new bool[2];
|
||||
intTimer = new bool[2];
|
||||
timerInMode = new InMode[2];
|
||||
timerOutMode = new OutMode[2];
|
||||
timerPortEnable = new bool[2];
|
||||
timerPulse = new bool[2];
|
||||
timerRunMode = new RunMode[2];
|
||||
tod = new byte[4];
|
||||
todAlarm = new byte[4];
|
||||
switch (region)
|
||||
{
|
||||
case Region.NTSC:
|
||||
todCounterLatch = 14318181 / 140;
|
||||
break;
|
||||
case Region.PAL:
|
||||
todCounterLatch = 17734472 / 180;
|
||||
break;
|
||||
}
|
||||
|
||||
SetTodIn(chipRegion);
|
||||
HardReset();
|
||||
}
|
||||
|
||||
|
@ -92,15 +104,51 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
public void ExecutePhase2()
|
||||
{
|
||||
pinPC = true;
|
||||
TODRun();
|
||||
|
||||
if (timerPulse[0])
|
||||
portData[0] &= PBOnMask[0];
|
||||
if (timerPulse[1])
|
||||
portData[1] &= PBOnMask[0];
|
||||
|
||||
TimerRun(0);
|
||||
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()
|
||||
{
|
||||
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[1] = false;
|
||||
sr = 0;
|
||||
timerPortEnable[0] = false;
|
||||
timerPortEnable[1] = false;
|
||||
timerInMode[0] = InMode.Phase2;
|
||||
|
@ -109,6 +157,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
timerOn[1] = false;
|
||||
timerOutMode[0] = 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[1] = 0;
|
||||
tod[2] = 0;
|
||||
|
@ -118,9 +173,27 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
todAlarm[2] = 0;
|
||||
todAlarm[3] = 0;
|
||||
todCounter = todCounterLatch;
|
||||
todIn = (chipRegion == Region.PAL);
|
||||
todPM = false;
|
||||
|
||||
pinCnt = false;
|
||||
pinFlag = 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;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
@ -149,7 +222,76 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
|
||||
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()
|
||||
|
@ -184,6 +326,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
}
|
||||
}
|
||||
}
|
||||
todCounter--;
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
@ -191,7 +334,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
public bool CNT
|
||||
{
|
||||
get { return pinCnt; }
|
||||
set { pinCnt = value; }
|
||||
set { cntPos |= (!pinCnt && value); pinCnt = value; }
|
||||
}
|
||||
|
||||
public bool FLAG
|
||||
|
@ -236,6 +379,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
val = ReadRegister(addr);
|
||||
pinPC = false;
|
||||
break;
|
||||
case 0x0D:
|
||||
val = ReadRegister(addr);
|
||||
intTimer[0] = false;
|
||||
intTimer[1] = false;
|
||||
intAlarm = false;
|
||||
intSP = false;
|
||||
intFlag = false;
|
||||
pinIRQ = true;
|
||||
break;
|
||||
default:
|
||||
val = ReadRegister(addr);
|
||||
break;
|
||||
|
@ -264,28 +416,77 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
val = portDir[1];
|
||||
break;
|
||||
case 0x4:
|
||||
val = (byte)(timer[0] & 0xFF);
|
||||
break;
|
||||
case 0x5:
|
||||
val = (byte)(timer[0] >> 8);
|
||||
break;
|
||||
case 0x6:
|
||||
val = (byte)(timer[1] & 0xFF);
|
||||
break;
|
||||
case 0x7:
|
||||
val = (byte)(timer[1] >> 8);
|
||||
break;
|
||||
case 0x8:
|
||||
val = tod[0];
|
||||
break;
|
||||
case 0x9:
|
||||
val = tod[1];
|
||||
break;
|
||||
case 0xA:
|
||||
val = tod[2];
|
||||
break;
|
||||
case 0xB:
|
||||
val = tod[3];
|
||||
break;
|
||||
case 0xC:
|
||||
val = sr;
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -299,9 +500,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
|
||||
public void Write(ushort addr, byte val, byte mask)
|
||||
{
|
||||
addr &= 0xF;
|
||||
val &= mask;
|
||||
val |= (byte)(ReadRegister(addr) & ~mask);
|
||||
addr &= 0xF;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -312,6 +513,26 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
WritePort1(val);
|
||||
pinPC = false;
|
||||
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:
|
||||
WriteRegister(addr, val);
|
||||
break;
|
||||
|
@ -320,6 +541,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
|
||||
public void WriteRegister(ushort addr, byte val)
|
||||
{
|
||||
bool intReg;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x0:
|
||||
|
@ -335,28 +558,89 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
portDir[1] = val;
|
||||
break;
|
||||
case 0x4:
|
||||
timerLatch[0] &= 0xFF00;
|
||||
timerLatch[0] |= val;
|
||||
break;
|
||||
case 0x5:
|
||||
timerLatch[0] &= 0x00FF;
|
||||
timerLatch[0] |= (uint)val << 8;
|
||||
break;
|
||||
case 0x6:
|
||||
timerLatch[1] &= 0xFF00;
|
||||
timerLatch[1] |= val;
|
||||
break;
|
||||
case 0x7:
|
||||
timerLatch[1] &= 0x00FF;
|
||||
timerLatch[1] |= (uint)val << 8;
|
||||
break;
|
||||
case 0x8:
|
||||
if (alarmSelect)
|
||||
todAlarm[0] = (byte)(val & 0xF);
|
||||
else
|
||||
tod[0] = (byte)(val & 0xF);
|
||||
break;
|
||||
case 0x9:
|
||||
if (alarmSelect)
|
||||
todAlarm[1] = (byte)(val & 0x7F);
|
||||
else
|
||||
tod[1] = (byte)(val & 0x7F);
|
||||
break;
|
||||
case 0xA:
|
||||
if (alarmSelect)
|
||||
todAlarm[2] = (byte)(val & 0x7F);
|
||||
else
|
||||
tod[2] = (byte)(val & 0x7F);
|
||||
break;
|
||||
case 0xB:
|
||||
if (alarmSelect)
|
||||
{
|
||||
todAlarm[3] = (byte)(val & 0x1F);
|
||||
todAlarmPM = ((val & 0x80) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tod[3] = (byte)(val & 0x1F);
|
||||
todPM = ((val & 0x80) != 0);
|
||||
}
|
||||
break;
|
||||
case 0xC:
|
||||
sr = val;
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -555,7 +555,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
case PLABank.None:
|
||||
break;
|
||||
case PLABank.RAM:
|
||||
chips.ram.Write(addr, val);
|
||||
break;
|
||||
case PLABank.Sid:
|
||||
chips.sid.Write(addr, val);
|
||||
|
@ -564,6 +563,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
chips.vic.Write(addr, val);
|
||||
break;
|
||||
}
|
||||
chips.ram.Write(addr, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
protected uint[] timer;
|
||||
protected uint[] timerLatch;
|
||||
protected bool[] timerOn;
|
||||
protected bool[] underflow;
|
||||
|
||||
public Timer()
|
||||
{
|
||||
|
@ -23,16 +24,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
timer = new uint[2];
|
||||
timerLatch = new uint[2];
|
||||
timerOn = new bool[2];
|
||||
underflow = new bool[2];
|
||||
}
|
||||
|
||||
public PortAdapter Adapter0()
|
||||
public PortAdapter Adapter0
|
||||
{
|
||||
return Port.GetAdapter(ReadPort0, ExternalWritePort0);
|
||||
get
|
||||
{
|
||||
return Port.GetAdapter(ReadPort0, ExternalWritePort0);
|
||||
}
|
||||
}
|
||||
|
||||
public PortAdapter Adapter1()
|
||||
public PortAdapter Adapter1
|
||||
{
|
||||
return Port.GetAdapter(ReadPort1, ExternalWritePort1);
|
||||
get
|
||||
{
|
||||
return Port.GetAdapter(ReadPort1, ExternalWritePort1);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExternalWritePort(uint index, byte data)
|
||||
|
|
Loading…
Reference in New Issue