Atari 2600 - a round of code cleanup and check in some files I neglected to in the past few commits, remove oldTIA.cs
This commit is contained in:
parent
43d58e3441
commit
27daa82464
|
@ -206,7 +206,6 @@
|
|||
<Compile Include="Consoles\Atari\2600\Mappers\mUA.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\Mappers\Multicart.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\Mappers\mX07.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\oldTIA.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\M6532.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\TIA.cs">
|
||||
<SubType>Code</SubType>
|
||||
|
|
|
@ -4,75 +4,33 @@ using BizHawk.Common;
|
|||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.M6502;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
partial class Atari2600
|
||||
public partial class Atari2600
|
||||
{
|
||||
public byte[] rom;
|
||||
public MOS6502X cpu;
|
||||
public M6532 m6532;
|
||||
public TIA tia;
|
||||
public DCFilter dcfilter;
|
||||
public byte[] ram = new byte[128];
|
||||
public MapperBase mapper;
|
||||
private TIA _tia;
|
||||
private DCFilter _dcfilter;
|
||||
private MapperBase _mapper;
|
||||
public byte[] Ram;
|
||||
|
||||
// The Atari 2600 memory mapper looks something like this...usually
|
||||
public byte[] Rom { get; private set; }
|
||||
public MOS6502X Cpu { get; private set; }
|
||||
public M6532 M6532 { get; private set; }
|
||||
|
||||
// N/A Page #
|
||||
// 000 0000000 000000
|
||||
|
||||
// 0x0000-0x003F - TIA Registers
|
||||
// 0x0040-0x007F - TIA Registers (mirror)
|
||||
// 0x0080-0x00FF - 6532 RAM
|
||||
|
||||
// 0x0100-0x01FF - Mirror of 0x00FF
|
||||
|
||||
// 0x0200-0x023F - TIA Registers (mirror)
|
||||
// 0x0240-0x027F - TIA Registers (mirror)
|
||||
|
||||
// 0x0280-0x029F - 6532 Registers
|
||||
// 0x02A0-0x02BF - 6532 Registers (mirror)
|
||||
// 0x02C0-0x02DF - 6532 Registers (mirror)
|
||||
// 0x02E0-0x02FF - 6532 Registers (mirror)
|
||||
|
||||
// 0x0300-0x033F - TIA Registers (mirror)
|
||||
// 0x0340-0x037F - TIA Registers (mirror)
|
||||
|
||||
// 0x0380-0x039F - 6532 Registers (mirror)
|
||||
// 0x03A0-0x03BF - 6532 Registers (mirror)
|
||||
// 0x03C0-0x03DF - 6532 Registers (mirror)
|
||||
// 0x03E0-0x03FF - 6532 Registers (mirror)
|
||||
|
||||
// 0x0400-0x07FF - Mirror of 0x0000-0x03FF
|
||||
// 0x0800-0x0BFF - Mirror of 0x0000-0x03FF
|
||||
// 0x0C00-0x0FFF - Mirror of 0x0000-0x03FF
|
||||
|
||||
// 0x1000-0x1FFF - ROM
|
||||
|
||||
// If page# % 4 == 0 or 1, TIA
|
||||
// If page# % 4 == 2 or 3, 6532
|
||||
// if (addr & 0x0200 == 0x0000 && addr & 0x1080 == 0x0080)
|
||||
// RAM
|
||||
// else
|
||||
// registers
|
||||
// else
|
||||
// ROM
|
||||
public byte BaseReadMemory(ushort addr)
|
||||
{
|
||||
addr = (ushort)(addr & 0x1FFF);
|
||||
if ((addr & 0x1080) == 0)
|
||||
{
|
||||
return tia.ReadMemory(addr, false);
|
||||
return _tia.ReadMemory(addr, false);
|
||||
}
|
||||
else if ((addr & 0x1080) == 0x0080)
|
||||
|
||||
if ((addr & 0x1080) == 0x0080)
|
||||
{
|
||||
return m6532.ReadMemory(addr, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return rom[addr & 0x0FFF];
|
||||
return M6532.ReadMemory(addr, false);
|
||||
}
|
||||
|
||||
return Rom[addr & 0x0FFF];
|
||||
}
|
||||
|
||||
public byte BasePeekMemory(ushort addr)
|
||||
|
@ -80,16 +38,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
addr = (ushort)(addr & 0x1FFF);
|
||||
if ((addr & 0x1080) == 0)
|
||||
{
|
||||
return tia.ReadMemory(addr, true);
|
||||
return _tia.ReadMemory(addr, true);
|
||||
}
|
||||
else if ((addr & 0x1080) == 0x0080)
|
||||
|
||||
if ((addr & 0x1080) == 0x0080)
|
||||
{
|
||||
return m6532.ReadMemory(addr, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return rom[addr & 0x0FFF];
|
||||
return M6532.ReadMemory(addr, true);
|
||||
}
|
||||
|
||||
return Rom[addr & 0x0FFF];
|
||||
}
|
||||
|
||||
public void BaseWriteMemory(ushort addr, byte value)
|
||||
|
@ -97,11 +54,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
addr = (ushort)(addr & 0x1FFF);
|
||||
if ((addr & 0x1080) == 0)
|
||||
{
|
||||
tia.WriteMemory(addr, value);
|
||||
_tia.WriteMemory(addr, value);
|
||||
}
|
||||
else if ((addr & 0x1080) == 0x0080)
|
||||
{
|
||||
m6532.WriteMemory(addr, value);
|
||||
M6532.WriteMemory(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -111,7 +68,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
byte temp = mapper.ReadMemory((ushort)(addr&0x1FFF));
|
||||
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
|
||||
|
||||
CoreComm.MemoryCallbackSystem.CallRead(addr);
|
||||
|
||||
|
@ -120,16 +77,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public byte PeekMemory(ushort addr)
|
||||
{
|
||||
byte temp = mapper.ReadMemory((ushort)(addr & 0x1FFF));
|
||||
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
|
||||
_mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
|
||||
|
||||
CoreComm.MemoryCallbackSystem.CallWrite((uint)addr);
|
||||
CoreComm.MemoryCallbackSystem.CallWrite(addr);
|
||||
}
|
||||
|
||||
public void ExecFetch(ushort addr)
|
||||
|
@ -139,166 +96,164 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public void HardReset()
|
||||
{
|
||||
//regenerate mapper here to make sure its state is entirely clean
|
||||
switch (game.GetOptionsDict()["m"])
|
||||
// Regenerate mapper here to make sure its state is entirely clean
|
||||
switch (this._game.GetOptionsDict()["m"])
|
||||
{
|
||||
case "2IN1":
|
||||
case "4IN1":
|
||||
case "8IN1":
|
||||
case "16IN1":
|
||||
case "32IN1":
|
||||
mapper = new Multicart();
|
||||
_mapper = new Multicart();
|
||||
break;
|
||||
case "AR":
|
||||
mapper = new mAR();
|
||||
_mapper = new mAR();
|
||||
break;
|
||||
case "4K":
|
||||
mapper = new m4K();
|
||||
_mapper = new m4K();
|
||||
break;
|
||||
case "2K":
|
||||
mapper = new m2K();
|
||||
_mapper = new m2K();
|
||||
break;
|
||||
case "CV":
|
||||
mapper = new mCV();
|
||||
_mapper = new mCV();
|
||||
break;
|
||||
case "DPC":
|
||||
mapper = new mDPC();
|
||||
_mapper = new mDPC();
|
||||
break;
|
||||
case "DPC+":
|
||||
mapper = new mDPCPlus();
|
||||
_mapper = new mDPCPlus();
|
||||
break;
|
||||
case "F8":
|
||||
mapper = new mF8();
|
||||
_mapper = new mF8();
|
||||
break;
|
||||
case "F8SC":
|
||||
mapper = new mF8SC();
|
||||
_mapper = new mF8SC();
|
||||
break;
|
||||
case "F6":
|
||||
mapper = new mF6();
|
||||
_mapper = new mF6();
|
||||
break;
|
||||
case "F6SC":
|
||||
mapper = new mF6SC();
|
||||
_mapper = new mF6SC();
|
||||
break;
|
||||
case "F4":
|
||||
mapper = new mF4();
|
||||
_mapper = new mF4();
|
||||
break;
|
||||
case "F4SC":
|
||||
mapper = new mF4SC();
|
||||
_mapper = new mF4SC();
|
||||
break;
|
||||
case "FE":
|
||||
mapper = new mFE();
|
||||
_mapper = new mFE();
|
||||
break;
|
||||
case "E0":
|
||||
mapper = new mE0();
|
||||
_mapper = new mE0();
|
||||
break;
|
||||
case "3F":
|
||||
mapper = new m3F();
|
||||
_mapper = new m3F();
|
||||
break;
|
||||
case "FA":
|
||||
mapper = new mFA();
|
||||
_mapper = new mFA();
|
||||
break;
|
||||
case "FA2":
|
||||
mapper = new mFA2();
|
||||
_mapper = new mFA2();
|
||||
break;
|
||||
case "E7":
|
||||
mapper = new mE7();
|
||||
_mapper = new mE7();
|
||||
break;
|
||||
case "F0":
|
||||
mapper = new mF0();
|
||||
_mapper = new mF0();
|
||||
break;
|
||||
case "UA":
|
||||
mapper = new mUA();
|
||||
_mapper = new mUA();
|
||||
break;
|
||||
|
||||
//Homebrew mappers
|
||||
// Homebrew mappers
|
||||
case "3E":
|
||||
mapper = new m3E();
|
||||
_mapper = new m3E();
|
||||
break;
|
||||
case "0840":
|
||||
mapper = new m0840();
|
||||
_mapper = new m0840();
|
||||
break;
|
||||
case "MC":
|
||||
mapper = new mMC();
|
||||
_mapper = new mMC();
|
||||
break;
|
||||
case "EF":
|
||||
mapper = new mEF();
|
||||
_mapper = new mEF();
|
||||
break;
|
||||
case "EFSC":
|
||||
mapper = new mEFSC();
|
||||
_mapper = new mEFSC();
|
||||
break;
|
||||
case "X07":
|
||||
mapper = new mX07();
|
||||
_mapper = new mX07();
|
||||
break;
|
||||
case "4A50":
|
||||
mapper = new m4A50();
|
||||
_mapper = new m4A50();
|
||||
break;
|
||||
case "SB":
|
||||
mapper = new mSB();
|
||||
_mapper = new mSB();
|
||||
break;
|
||||
|
||||
default: throw new InvalidOperationException("mapper not supported: " + game.GetOptionsDict()["m"]);
|
||||
default: throw new InvalidOperationException("mapper not supported: " + this._game.GetOptionsDict()["m"]);
|
||||
}
|
||||
mapper.core = this;
|
||||
|
||||
_mapper.Core = this;
|
||||
|
||||
_lagcount = 0;
|
||||
cpu = new MOS6502X();
|
||||
//cpu.debug = true;
|
||||
cpu.ReadMemory = ReadMemory;
|
||||
cpu.WriteMemory = WriteMemory;
|
||||
cpu.PeekMemory = PeekMemory;
|
||||
cpu.DummyReadMemory = ReadMemory;
|
||||
cpu.OnExecFetch = ExecFetch;
|
||||
// Setup TIA
|
||||
//tia = new TIA(this, frameBuffer);
|
||||
tia = new TIA(this);
|
||||
Cpu = new MOS6502X
|
||||
{
|
||||
ReadMemory = this.ReadMemory,
|
||||
WriteMemory = this.WriteMemory,
|
||||
PeekMemory = this.PeekMemory,
|
||||
DummyReadMemory = this.ReadMemory,
|
||||
OnExecFetch = this.ExecFetch
|
||||
};
|
||||
|
||||
_tia = new TIA(this);
|
||||
|
||||
// dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
|
||||
dcfilter = DCFilter.AsISoundProvider(tia, 256);
|
||||
// Setup 6532
|
||||
m6532 = new M6532(this);
|
||||
_dcfilter = DCFilter.AsISoundProvider(_tia, 256);
|
||||
|
||||
//setup the system state here. for instance..
|
||||
M6532 = new M6532(this);
|
||||
|
||||
// Set up the system state here. for instance..
|
||||
// Read from the reset vector for where to start
|
||||
cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8)); //set the initial PC
|
||||
//cpu.PC = 0x0000; //set the initial PC
|
||||
Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8)); // set the initial PC
|
||||
|
||||
// show mapper class on romstatusdetails
|
||||
// Show mapper class on romstatusdetails
|
||||
CoreComm.RomStatusDetails =
|
||||
string.Format("{0}\r\nSHA1:{1}\r\nMD5:{2}\r\nMapper Impl \"{3}\"",
|
||||
game.Name,
|
||||
Util.Hash_SHA1(rom), Util.Hash_MD5(rom),
|
||||
mapper.GetType());
|
||||
string.Format(
|
||||
"{0}\r\nSHA1:{1}\r\nMD5:{2}\r\nMapper Impl \"{3}\"",
|
||||
this._game.Name,
|
||||
Util.Hash_SHA1(Rom),
|
||||
Util.Hash_MD5(Rom),
|
||||
_mapper.GetType());
|
||||
}
|
||||
|
||||
public void FrameAdvance(bool render, bool rendersound)
|
||||
{
|
||||
_frame++;
|
||||
_islag = true;
|
||||
tia.frameComplete = false;
|
||||
while (tia.frameComplete == false)
|
||||
_tia.FrameComplete = false;
|
||||
while (_tia.FrameComplete == false)
|
||||
{
|
||||
tia.execute(1);
|
||||
tia.execute(1);
|
||||
tia.execute(1);
|
||||
_tia.Execute(1);
|
||||
_tia.Execute(1);
|
||||
_tia.Execute(1);
|
||||
|
||||
m6532.timer.tick();
|
||||
M6532.timer.tick();
|
||||
if (CoreComm.Tracer.Enabled)
|
||||
CoreComm.Tracer.Put(cpu.TraceState());
|
||||
cpu.ExecuteOne();
|
||||
mapper.ClockCpu();
|
||||
//if (cpu.PendingCycles <= 0)
|
||||
//{
|
||||
// //Console.WriteLine("Tia clocks: " + tia.scanlinePos + " CPU pending: " + cpu.PendingCycles);
|
||||
//}
|
||||
//if (cpu.PendingCycles < 0)
|
||||
//{
|
||||
// Console.WriteLine("------------Something went wrong------------");
|
||||
//}
|
||||
{
|
||||
CoreComm.Tracer.Put(Cpu.TraceState());
|
||||
}
|
||||
|
||||
Cpu.ExecuteOne();
|
||||
_mapper.ClockCpu();
|
||||
}
|
||||
|
||||
if (_islag)
|
||||
{
|
||||
LagCount++;
|
||||
//if (render == false) return;
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadControls1(bool peek)
|
||||
|
@ -306,12 +261,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
CoreComm.InputCallback.Call();
|
||||
byte value = 0xFF;
|
||||
|
||||
if (Controller["P1 Up"]) value &= 0xEF;
|
||||
if (Controller["P1 Down"]) value &= 0xDF;
|
||||
if (Controller["P1 Left"]) value &= 0xBF;
|
||||
if (Controller["P1 Right"]) value &= 0x7F;
|
||||
if (Controller["P1 Button"]) value &= 0xF7;
|
||||
if(!peek) _islag = false;
|
||||
if (Controller["P1 Up"]) { value &= 0xEF; }
|
||||
if (Controller["P1 Down"]) { value &= 0xDF; }
|
||||
if (Controller["P1 Left"]) { value &= 0xBF; }
|
||||
if (Controller["P1 Right"]) { value &= 0x7F; }
|
||||
if (Controller["P1 Button"]) { value &= 0xF7; }
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -320,22 +280,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
CoreComm.InputCallback.Call();
|
||||
byte value = 0xFF;
|
||||
|
||||
if (Controller["P2 Up"]) value &= 0xEF;
|
||||
if (Controller["P2 Down"]) value &= 0xDF;
|
||||
if (Controller["P2 Left"]) value &= 0xBF;
|
||||
if (Controller["P2 Right"]) value &= 0x7F;
|
||||
if (Controller["P2 Button"]) value &= 0xF7;
|
||||
if (!peek) _islag = false;
|
||||
return value;
|
||||
if (Controller["P2 Up"]) { value &= 0xEF; }
|
||||
if (Controller["P2 Down"]) { value &= 0xDF; }
|
||||
if (Controller["P2 Left"]) { value &= 0xBF; }
|
||||
if (Controller["P2 Right"]) { value &= 0x7F; }
|
||||
if (Controller["P2 Button"]) { value &= 0xF7; }
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
//private bool bw;
|
||||
//private bool p0difficulty = true;
|
||||
//private bool p1difficulty = true;
|
||||
|
||||
//public void SetBw(bool setting) { bw = setting; }
|
||||
//public void SetP0Diff(bool setting) { p0difficulty = setting; }
|
||||
//public void SetP1Diff(bool setting) { p1difficulty = setting; }
|
||||
return value;
|
||||
}
|
||||
|
||||
public byte ReadConsoleSwitches(bool peek)
|
||||
{
|
||||
|
@ -343,24 +300,44 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
bool select = Controller["Select"];
|
||||
bool reset = Controller["Reset"];
|
||||
|
||||
if (reset) value &= 0xFE;
|
||||
if (select) value &= 0xFD;
|
||||
if (SyncSettings.BW) value &= 0xF7;
|
||||
if (SyncSettings.LeftDifficulty) value &= 0xBF;
|
||||
if (SyncSettings.RightDifficulty) value &= 0x7F;
|
||||
if(!peek) _islag = false;
|
||||
if (reset) { value &= 0xFE; }
|
||||
if (select) { value &= 0xFD; }
|
||||
if (SyncSettings.BW) { value &= 0xF7; }
|
||||
if (SyncSettings.LeftDifficulty) { value &= 0xBF; }
|
||||
if (SyncSettings.RightDifficulty) { value &= 0x7F; }
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public class MapperBase
|
||||
{
|
||||
public Atari2600 core;
|
||||
public virtual byte ReadMemory(ushort addr) { return core.BaseReadMemory(addr); }
|
||||
public virtual byte PeekMemory(ushort addr) { return core.BasePeekMemory(addr); }
|
||||
public virtual void WriteMemory(ushort addr, byte value) { core.BaseWriteMemory(addr, value); }
|
||||
public Atari2600 Core { get; set; }
|
||||
|
||||
public virtual byte ReadMemory(ushort addr)
|
||||
{
|
||||
return Core.BaseReadMemory(addr);
|
||||
}
|
||||
|
||||
public virtual byte PeekMemory(ushort addr)
|
||||
{
|
||||
return Core.BasePeekMemory(addr);
|
||||
}
|
||||
|
||||
public virtual void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
Core.BaseWriteMemory(addr, value);
|
||||
}
|
||||
|
||||
public virtual void SyncState(Serializer ser) { }
|
||||
|
||||
public virtual void Dispose() { }
|
||||
|
||||
public virtual void ClockCpu() { }
|
||||
}
|
||||
}
|
|
@ -1,46 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
public partial class Atari2600 : IEmulator
|
||||
{
|
||||
public string SystemId { get { return "A26"; } }
|
||||
public GameInfo game;
|
||||
private readonly GameInfo _game;
|
||||
private bool _islag = true;
|
||||
private int _lagcount;
|
||||
private int _frame;
|
||||
|
||||
public string BoardName { get { return mapper.GetType().Name; } }
|
||||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
public IVideoProvider VideoProvider { get { return tia; } }
|
||||
public ISoundProvider SoundProvider { get { return dcfilter; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(dcfilter, 735); } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public Atari2600(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings)
|
||||
public Atari2600(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
|
||||
{
|
||||
Ram = new byte[128];
|
||||
CoreComm = comm;
|
||||
this.Settings = (A2600Settings)Settings ?? A2600Settings.GetDefaults();
|
||||
this.SyncSettings = (A2600SyncSettings)SyncSettings ?? A2600SyncSettings.GetDefaults();
|
||||
Settings = (A2600Settings)settings ?? A2600Settings.GetDefaults();
|
||||
SyncSettings = (A2600SyncSettings)syncSettings ?? A2600SyncSettings.GetDefaults();
|
||||
|
||||
var domains = new List<MemoryDomain>(1)
|
||||
var domains = new List<MemoryDomain>
|
||||
{
|
||||
new MemoryDomain("Main RAM", 128, MemoryDomain.Endian.Little, addr => ram[addr], (addr, value) => ram[addr] = value),
|
||||
new MemoryDomain("TIA", 16, MemoryDomain.Endian.Little, addr => tia.ReadMemory((ushort) addr, true),
|
||||
(addr, value) => tia.WriteMemory((ushort) addr, value)),
|
||||
new MemoryDomain("PIA", 1024, MemoryDomain.Endian.Little, addr => m6532.ReadMemory((ushort) addr, true),
|
||||
(addr, value) => m6532.WriteMemory((ushort) addr, value)),
|
||||
new MemoryDomain("System Bus", 8192, MemoryDomain.Endian.Little, addr => mapper.PeekMemory((ushort) addr), (addr, value) => { })
|
||||
new MemoryDomain(
|
||||
"Main RAM",
|
||||
128,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => Ram[addr],
|
||||
(addr, value) => Ram[addr] = value),
|
||||
new MemoryDomain(
|
||||
"TIA",
|
||||
16,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => _tia.ReadMemory((ushort)addr, true),
|
||||
(addr, value) => this._tia.WriteMemory((ushort)addr, value)),
|
||||
new MemoryDomain(
|
||||
"PIA",
|
||||
1024,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => M6532.ReadMemory((ushort)addr, true),
|
||||
(addr, value) => M6532.WriteMemory((ushort)addr, value)),
|
||||
new MemoryDomain(
|
||||
"System Bus",
|
||||
8192,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => _mapper.PeekMemory((ushort) addr),
|
||||
(addr, value) => { })
|
||||
};
|
||||
memoryDomains = new MemoryDomainList(domains);
|
||||
MemoryDomains = new MemoryDomainList(domains);
|
||||
CoreComm.CpuTraceAvailable = true;
|
||||
this.rom = rom;
|
||||
this.game = game;
|
||||
Rom = rom;
|
||||
_game = game;
|
||||
|
||||
if (!game.GetOptionsDict().ContainsKey("m"))
|
||||
{
|
||||
|
@ -51,32 +63,39 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
HardReset();
|
||||
}
|
||||
|
||||
public List<KeyValuePair<string, int>> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new List<KeyValuePair<string, int>>
|
||||
{
|
||||
new KeyValuePair<string, int>("A", cpu.A),
|
||||
new KeyValuePair<string, int>("X", cpu.X),
|
||||
new KeyValuePair<string, int>("Y", cpu.Y),
|
||||
new KeyValuePair<string, int>("S", cpu.S),
|
||||
new KeyValuePair<string, int>("PC", cpu.PC),
|
||||
new KeyValuePair<string, int>("Flag C", cpu.FlagC ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag Z", cpu.FlagZ ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag I", cpu.FlagI ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag D", cpu.FlagD ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag B", cpu.FlagB ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag V", cpu.FlagV ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag N", cpu.FlagN ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag T", cpu.FlagT ? 1 : 0)
|
||||
};
|
||||
}
|
||||
public string SystemId { get { return "A26"; } }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
_lagcount = 0;
|
||||
_islag = false;
|
||||
}
|
||||
public string BoardName { get { return _mapper.GetType().Name; } }
|
||||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
public IVideoProvider VideoProvider { get { return _tia; } }
|
||||
|
||||
public ISoundProvider SoundProvider { get { return _dcfilter; } }
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(_dcfilter, 735); } }
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get { return Atari2600ControllerDefinition; } }
|
||||
|
||||
public IController Controller { get; set; }
|
||||
|
||||
public int Frame { get { return _frame; } set { _frame = value; } }
|
||||
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
|
||||
public bool IsLagFrame { get { return _islag; } }
|
||||
|
||||
public bool SaveRamModified { get; set; }
|
||||
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
public bool BinarySaveStatesPreferred { get { return false; } }
|
||||
|
||||
public A2600Settings Settings { get; private set; }
|
||||
|
||||
public A2600SyncSettings SyncSettings { get; private set; }
|
||||
|
||||
public MemoryDomainList MemoryDomains { get; private set; }
|
||||
|
||||
public static readonly ControllerDefinition Atari2600ControllerDefinition = new ControllerDefinition
|
||||
{
|
||||
|
@ -89,65 +108,114 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
};
|
||||
|
||||
void SyncState(Serializer ser)
|
||||
public List<KeyValuePair<string, int>> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new List<KeyValuePair<string, int>>
|
||||
{
|
||||
new KeyValuePair<string, int>("A", Cpu.A),
|
||||
new KeyValuePair<string, int>("X", Cpu.X),
|
||||
new KeyValuePair<string, int>("Y", Cpu.Y),
|
||||
new KeyValuePair<string, int>("S", Cpu.S),
|
||||
new KeyValuePair<string, int>("PC", Cpu.PC),
|
||||
new KeyValuePair<string, int>("Flag C", Cpu.FlagC ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag Z", Cpu.FlagZ ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag I", Cpu.FlagI ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag D", Cpu.FlagD ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag B", Cpu.FlagB ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag V", Cpu.FlagV ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag N", Cpu.FlagN ? 1 : 0),
|
||||
new KeyValuePair<string, int>("Flag T", Cpu.FlagT ? 1 : 0)
|
||||
};
|
||||
}
|
||||
|
||||
public bool StartAsyncSound() { return true; }
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
_lagcount = 0;
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("A2600");
|
||||
cpu.SyncState(ser);
|
||||
ser.Sync("ram", ref ram, false);
|
||||
Cpu.SyncState(ser);
|
||||
ser.Sync("ram", ref this.Ram, false);
|
||||
ser.Sync("Lag", ref _lagcount);
|
||||
ser.Sync("Frame", ref _frame);
|
||||
ser.Sync("IsLag", ref _islag);
|
||||
tia.SyncState(ser);
|
||||
m6532.SyncState(ser);
|
||||
_tia.SyncState(ser);
|
||||
M6532.SyncState(ser);
|
||||
ser.BeginSection("Mapper");
|
||||
mapper.SyncState(ser);
|
||||
_mapper.SyncState(ser);
|
||||
ser.EndSection();
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get { return Atari2600ControllerDefinition; } }
|
||||
public IController Controller { get; set; }
|
||||
public byte[] ReadSaveRam()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public int Frame { get { return _frame; } set { _frame = value; } }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return _islag; } }
|
||||
private bool _islag = true;
|
||||
private int _lagcount;
|
||||
private int _frame;
|
||||
|
||||
public byte[] ReadSaveRam() { return null; }
|
||||
public void StoreSaveRam(byte[] data) { }
|
||||
public void ClearSaveRam() { }
|
||||
public bool SaveRamModified { get; set; }
|
||||
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); }
|
||||
public void LoadStateText(TextReader reader) { SyncState(Serializer.CreateTextReader(reader)); }
|
||||
public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); }
|
||||
public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); }
|
||||
public void ClearSaveRam() { }
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
SyncState(Serializer.CreateTextWriter(writer));
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
SyncState(Serializer.CreateTextReader(reader));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
SyncState(Serializer.CreateBinaryWriter(bw));
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
{
|
||||
SyncState(Serializer.CreateBinaryReader(br));
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
var ms = new MemoryStream();
|
||||
var bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public bool BinarySaveStatesPreferred { get { return false; } }
|
||||
|
||||
private readonly MemoryDomainList memoryDomains;
|
||||
public MemoryDomainList MemoryDomains { get { return memoryDomains; } }
|
||||
public void Dispose() { }
|
||||
|
||||
public object GetSettings() { return Settings.Clone(); }
|
||||
public object GetSyncSettings() { return SyncSettings.Clone(); }
|
||||
public bool PutSettings(object o) { Settings = (A2600Settings)o; return false; }
|
||||
public bool PutSyncSettings(object o) { SyncSettings = (A2600SyncSettings)o; return false; }
|
||||
public object GetSettings()
|
||||
{
|
||||
return Settings.Clone();
|
||||
}
|
||||
|
||||
public A2600Settings Settings { get; private set; }
|
||||
public A2600SyncSettings SyncSettings { get; private set; }
|
||||
public object GetSyncSettings()
|
||||
{
|
||||
return SyncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(object o)
|
||||
{
|
||||
Settings = (A2600Settings)o;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(object o)
|
||||
{
|
||||
SyncSettings = (A2600SyncSettings)o;
|
||||
return false;
|
||||
}
|
||||
|
||||
public class A2600Settings
|
||||
{
|
||||
|
@ -164,6 +232,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
return (A2600Settings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static A2600Settings GetDefaults()
|
||||
{
|
||||
return new A2600Settings
|
||||
|
@ -183,8 +252,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
[Description("Set the TV Type switch on the console to B&W or Color")]
|
||||
public bool BW { get; set; }
|
||||
|
||||
[Description("Set the Left Difficulty switch on the console")]
|
||||
public bool LeftDifficulty { get; set; }
|
||||
|
||||
[Description("Set the Right Difficulty switch on the console")]
|
||||
public bool RightDifficulty { get; set; }
|
||||
|
||||
|
@ -192,6 +263,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
return (A2600SyncSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static A2600SyncSettings GetDefaults()
|
||||
{
|
||||
return new A2600SyncSettings
|
||||
|
@ -203,5 +275,4 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
// Read Ram
|
||||
ushort maskedAddr = (ushort)(addr & 0x007f);
|
||||
return core.ram[maskedAddr];
|
||||
return core.Ram[maskedAddr];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (!RS)
|
||||
{
|
||||
ushort maskedAddr = (ushort)(addr & 0x007f);
|
||||
core.ram[maskedAddr] = value;
|
||||
core.Ram[maskedAddr] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
/*
|
||||
Mapper used for multi-cart mappers
|
||||
*/
|
||||
internal class Multicart : MapperBase
|
||||
{
|
||||
public Multicart()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
{
|
||||
if (addr < 0x1000)
|
||||
{
|
||||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return Core.Rom[addr & 0xFFF];
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
{
|
||||
return ReadMemory(addr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_bank4K << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[addr & 0x7FF];
|
||||
return this.Core.Rom[addr & 0x7FF];
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
|
|
|
@ -61,12 +61,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x03FF) + (_rambank_1K << 10)] = 0xFF; // Reading from the write port triggers an unwanted write
|
||||
}
|
||||
|
||||
return core.rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
return Core.Rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x2000) // High bank fixed to last 2k of ROM
|
||||
{
|
||||
return core.rom[(core.rom.Length - 2048) + (addr & 0x07FF)];
|
||||
return Core.Rom[(Core.Rom.Length - 2048) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
return base.ReadMemory(addr);
|
||||
|
@ -91,12 +91,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x03FF) + (_rambank_1K << 10)]; // Reading from the write port triggers an unwanted write
|
||||
}
|
||||
|
||||
return core.rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
return Core.Rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x2000) // High bank fixed to last 2k of ROM
|
||||
{
|
||||
return core.rom[(core.rom.Length - 2048) + (addr & 0x07FF)];
|
||||
return Core.Rom[(Core.Rom.Length - 2048) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
return base.ReadMemory(addr);
|
||||
|
@ -114,13 +114,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
else if (addr == 0x003F)
|
||||
{
|
||||
_hasRam = false;
|
||||
if ((value << 11) < core.rom.Length)
|
||||
if ((value << 11) < Core.Rom.Length)
|
||||
{
|
||||
_lowbank_2K = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lowbank_2K = value & (core.rom.Length >> 11);
|
||||
_lowbank_2K = value & (Core.Rom.Length >> 11);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if (addr < 0x17FF) // Low 2k Bank
|
||||
{
|
||||
return core.rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
return Core.Rom[(_lowbank_2K << 11) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x2000) // High bank fixed to last 2k of ROM
|
||||
{
|
||||
return core.rom[(core.rom.Length - 2048) + (addr & 0x07FF)];
|
||||
return Core.Rom[(Core.Rom.Length - 2048) + (addr & 0x07FF)];
|
||||
}
|
||||
|
||||
return base.ReadMemory(addr);
|
||||
|
@ -60,13 +60,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
if (addr < 0x0040)
|
||||
{
|
||||
if ((value << 11) < core.rom.Length)
|
||||
if ((value << 11) < Core.Rom.Length)
|
||||
{
|
||||
_lowbank_2K = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lowbank_2K = value & (core.rom.Length >> 11);
|
||||
_lowbank_2K = value & (Core.Rom.Length >> 11);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,23 +54,23 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
if ((addr & 0x1800) == 0x1000) // 2K region from 0x1000 - 0x17ff
|
||||
{
|
||||
val = _myIsRomLow ? core.rom[(addr & 0x7ff) + _mySliceLow]
|
||||
val = _myIsRomLow ? Core.Rom[(addr & 0x7ff) + _mySliceLow]
|
||||
: _myRam[(addr & 0x7ff) + _mySliceLow];
|
||||
}
|
||||
else if (((addr & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff
|
||||
((addr & 0x1fff) <= 0x1dff))
|
||||
{
|
||||
val = _myIsRomMiddle ? core.rom[(addr & 0x7ff) + _mySliceMiddle]
|
||||
val = _myIsRomMiddle ? Core.Rom[(addr & 0x7ff) + _mySliceMiddle]
|
||||
: _myRam[(addr & 0x7ff) + _mySliceMiddle];
|
||||
}
|
||||
else if ((addr & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff
|
||||
{
|
||||
val = _myIsRomHigh ? core.rom[(addr & 0xff) + _mySliceHigh]
|
||||
val = _myIsRomHigh ? Core.Rom[(addr & 0xff) + _mySliceHigh]
|
||||
: _myRam[(addr & 0xff) + _mySliceHigh];
|
||||
}
|
||||
else if ((addr & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff
|
||||
{
|
||||
val = core.rom[(addr & 0xff) + (core.rom.Length - 256)];
|
||||
val = Core.Rom[(addr & 0xff) + (Core.Rom.Length - 256)];
|
||||
if (((_myLastData & 0xe0) == 0x60) && ((_myLastAddress >= 0x1000) ||
|
||||
(_myLastAddress < 0x200)))
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[addr & 0xFFF];
|
||||
return Core.Rom[addr & 0xFFF];
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if (addr >= 0x1800 && addr < 0x2000)
|
||||
{
|
||||
return core.rom[(addr & 0x7FF)];
|
||||
return Core.Rom[(addr & 0x7FF)];
|
||||
}
|
||||
|
||||
return base.ReadMemory(addr);
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
|
||||
Address(addr);
|
||||
return core.rom[(bank_4k << 12) + addr];
|
||||
return Core.Rom[(bank_4k << 12) + addr];
|
||||
}
|
||||
|
||||
public override void WriteMemory(ushort addr, byte value)
|
||||
|
|
|
@ -43,20 +43,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if (addr < 0x1400)
|
||||
{
|
||||
return core.rom[(_toggle1 << 10) + (addr & 0x3FF)];
|
||||
return Core.Rom[(_toggle1 << 10) + (addr & 0x3FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x1800)
|
||||
{
|
||||
return core.rom[(_toggle2 << 10) + (addr & 0x3FF)];
|
||||
return Core.Rom[(_toggle2 << 10) + (addr & 0x3FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x1C00)
|
||||
{
|
||||
return core.rom[(_toggle3 << 10) + (addr & 0x3FF)];
|
||||
return Core.Rom[(_toggle3 << 10) + (addr & 0x3FF)];
|
||||
}
|
||||
|
||||
return core.rom[(7 * 1024) + (addr & 0x3FF)]; // 7 because final bank is always set to last
|
||||
return Core.Rom[(7 * 1024) + (addr & 0x3FF)]; // 7 because final bank is always set to last
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _rambank0[addr & 0x3FF];
|
||||
}
|
||||
|
||||
return core.rom[(_rombank_1K * 0x800) + (addr & 0x7FF)];
|
||||
return Core.Rom[(_rombank_1K * 0x800) + (addr & 0x7FF)];
|
||||
}
|
||||
|
||||
if (addr < 0x1900) // Ram 1 Read port
|
||||
|
@ -76,8 +76,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
addr -= 0x1800;
|
||||
addr &= 0x7FF;
|
||||
int offset = core.rom.Length - 0x0800;
|
||||
return core.rom[offset + addr]; // Fixed to last 1.5K
|
||||
int offset = Core.Rom.Length - 0x0800;
|
||||
return Core.Rom[offset + addr]; // Fixed to last 1.5K
|
||||
}
|
||||
|
||||
return base.ReadMemory(addr);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x7F)];
|
||||
}
|
||||
|
||||
return core.rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_bank << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x7F)];
|
||||
}
|
||||
|
||||
return core.rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x7F)];
|
||||
}
|
||||
|
||||
return core.rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_bank_4K << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank_4K << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _ram[(addr & 0x7F)];
|
||||
}
|
||||
|
||||
return core.rom[(_bank_4K << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank_4K << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _auxRam[addr & 0xFF];
|
||||
}
|
||||
|
||||
return core.rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return _auxRam[addr & 0xFF];
|
||||
}
|
||||
|
||||
return core.rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
@ -82,7 +82,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (addr == 0x1FF8) _bank4k = 3;
|
||||
if (addr == 0x1FF9) _bank4k = 4;
|
||||
if (addr == 0x1FFA) _bank4k = 5;
|
||||
if (addr == 0x1FFB && core.rom.Length == 28 * 1024) // Only available on 28k Roms
|
||||
if (addr == 0x1FFB && Core.Rom.Length == 28 * 1024) // Only available on 28k Roms
|
||||
{
|
||||
_bank4k = 6;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
/*
|
||||
Cartridge class used for SB "SUPERbanking" 128k-256k bankswitched games.
|
||||
There are either 32 or 64 4K banks.
|
||||
*/
|
||||
internal class mSB : MapperBase
|
||||
{
|
||||
public mSB()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return base.ReadMemory(addr);
|
||||
}
|
||||
|
||||
return core.rom[(_rombank_2K << 12) + (addr & 0xFFF)];
|
||||
return Core.Rom[(_rombank_2K << 12) + (addr & 0xFFF)];
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
|
@ -9,13 +9,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
// Emulates the TIA
|
||||
public class TIA : IVideoProvider, ISoundProvider
|
||||
{
|
||||
public bool frameComplete;
|
||||
|
||||
private readonly Atari2600 core;
|
||||
private byte hsyncCnt;
|
||||
private int capChargeStart;
|
||||
private bool capCharging;
|
||||
|
||||
private const byte CXP0 = 0x01;
|
||||
private const byte CXP1 = 0x02;
|
||||
private const byte CXM0 = 0x04;
|
||||
|
@ -23,7 +16,32 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
private const byte CXPF = 0x10;
|
||||
private const byte CXBL = 0x20;
|
||||
|
||||
struct missileData
|
||||
private readonly Atari2600 _core;
|
||||
private byte _hsyncCnt;
|
||||
private int _capChargeStart;
|
||||
private bool _capCharging;
|
||||
|
||||
private PlayerData player0;
|
||||
private PlayerData player1;
|
||||
private PlayfieldData playField;
|
||||
private HmoveData hmove;
|
||||
private BallData ball;
|
||||
|
||||
private bool vblankEnabled;
|
||||
private bool vsyncEnabled;
|
||||
|
||||
private uint[] scanline = new uint[160];
|
||||
|
||||
public TIA(Atari2600 core)
|
||||
{
|
||||
_core = core;
|
||||
player0.scanCnt = 8;
|
||||
player1.scanCnt = 8;
|
||||
}
|
||||
|
||||
public bool FrameComplete { get; set; }
|
||||
|
||||
private struct MissileData
|
||||
{
|
||||
public bool Enabled;
|
||||
public bool ResetToPlayer;
|
||||
|
@ -35,7 +53,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public bool Tick()
|
||||
{
|
||||
bool result = false;
|
||||
var result = false;
|
||||
|
||||
// At hPosCnt == 0, start drawing the missile, if enabled
|
||||
if (HPosCnt < (1 << Size))
|
||||
|
@ -59,7 +77,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
}
|
||||
|
||||
if (((Number & 0x07) == 0x02 || ((Number & 0x07) == 0x03) || ((Number & 0x07) == 0x06)))
|
||||
if ((Number & 0x07) == 0x02 || ((Number & 0x07) == 0x03) || ((Number & 0x07) == 0x06))
|
||||
{
|
||||
if (HPosCnt >= 32 && HPosCnt <= (32 + (1 << Size) - 1) )
|
||||
{
|
||||
|
@ -85,6 +103,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
// Increment the counter
|
||||
HPosCnt++;
|
||||
|
||||
// Counter loops at 160
|
||||
HPosCnt %= 160;
|
||||
|
||||
|
@ -105,9 +124,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
}
|
||||
|
||||
struct playerData
|
||||
private struct PlayerData
|
||||
{
|
||||
public missileData missile;
|
||||
public MissileData Missile;
|
||||
public byte grp;
|
||||
public byte dgrp;
|
||||
public byte color;
|
||||
|
@ -122,9 +141,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
public byte resetCnt;
|
||||
public byte collisions;
|
||||
|
||||
public bool tick()
|
||||
public bool Tick()
|
||||
{
|
||||
bool result = false;
|
||||
var result = false;
|
||||
if (scanCnt < 8)
|
||||
{
|
||||
// Make the mask to check the graphic
|
||||
|
@ -133,7 +152,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
// Reflect it if needed
|
||||
if (reflect)
|
||||
{
|
||||
playerMask = (byte)reverseBits(playerMask, 8);
|
||||
playerMask = (byte)ReverseBits(playerMask, 8);
|
||||
}
|
||||
|
||||
// Check the graphic (depending on delay)
|
||||
|
@ -153,9 +172,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
|
||||
// Reset missile, if desired
|
||||
if (scanCnt == 0x04 && hPosCnt <= 16 && missile.ResetToPlayer)
|
||||
if (scanCnt == 0x04 && hPosCnt <= 16 && Missile.ResetToPlayer)
|
||||
{
|
||||
missile.HPosCnt = 0;
|
||||
Missile.HPosCnt = 0;
|
||||
}
|
||||
|
||||
// Increment counter
|
||||
|
@ -170,12 +189,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
scanStrchCnt++;
|
||||
scanStrchCnt %= 2;
|
||||
}
|
||||
|
||||
// Quad size player
|
||||
else if ((nusiz & 0x07) == 0x07)
|
||||
{
|
||||
scanStrchCnt++;
|
||||
scanStrchCnt %= 4;
|
||||
}
|
||||
|
||||
// Single size player
|
||||
else
|
||||
{
|
||||
|
@ -186,7 +207,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
scanCnt++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// At counter position 0 we should start drawing, a pixel late
|
||||
|
@ -217,8 +237,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
// Reset is no longer in effect
|
||||
reset = false;
|
||||
|
||||
// Increment the counter
|
||||
hPosCnt++;
|
||||
|
||||
// Counter loops at 160
|
||||
hPosCnt %= 160;
|
||||
|
||||
|
@ -239,7 +261,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
missile.SyncState(ser);
|
||||
Missile.SyncState(ser);
|
||||
ser.Sync("grp", ref grp);
|
||||
ser.Sync("dgrp", ref dgrp);
|
||||
ser.Sync("color", ref color);
|
||||
|
@ -254,9 +276,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ser.Sync("resetCnt", ref resetCnt);
|
||||
ser.Sync("collisions", ref collisions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct ballData
|
||||
private struct BallData
|
||||
{
|
||||
public bool enabled;
|
||||
public bool denabled;
|
||||
|
@ -264,10 +286,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
public byte size;
|
||||
public byte HM;
|
||||
public byte hPosCnt;
|
||||
|
||||
public byte collisions;
|
||||
|
||||
public bool tick()
|
||||
public bool Tick()
|
||||
{
|
||||
bool result = false;
|
||||
if (hPosCnt < (1 << size))
|
||||
|
@ -286,6 +307,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
// Increment the counter
|
||||
hPosCnt++;
|
||||
|
||||
// Counter loops at 160
|
||||
hPosCnt %= 160;
|
||||
|
||||
|
@ -304,12 +326,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ser.Sync("collisions", ref collisions);
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct playfieldData
|
||||
private struct PlayfieldData
|
||||
{
|
||||
public UInt32 grp;
|
||||
public uint grp;
|
||||
public byte pfColor;
|
||||
public byte bkColor;
|
||||
public bool reflect;
|
||||
|
@ -326,9 +347,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ser.Sync("priority", ref priority);
|
||||
ser.EndSection();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct hmoveData
|
||||
private struct HmoveData
|
||||
{
|
||||
public bool hmoveEnabled;
|
||||
public bool hmoveJustStarted;
|
||||
|
@ -374,20 +395,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
};
|
||||
|
||||
playerData player0;
|
||||
playerData player1;
|
||||
playfieldData playField;
|
||||
hmoveData hmove;
|
||||
ballData ball;
|
||||
|
||||
|
||||
bool vblankEnabled;
|
||||
bool vsyncEnabled;
|
||||
|
||||
private readonly List<uint[]> scanlinesBuffer = new List<uint[]>();
|
||||
uint[] scanline = new uint[160];
|
||||
|
||||
private readonly UInt32[] palette = new UInt32[]{
|
||||
private readonly uint[] palette = new uint[]
|
||||
{
|
||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
|
||||
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
|
||||
|
@ -422,13 +433,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
|
||||
};
|
||||
|
||||
public TIA(Atari2600 core)
|
||||
{
|
||||
this.core = core;
|
||||
player0.scanCnt = 8;
|
||||
player1.scanCnt = 8;
|
||||
}
|
||||
|
||||
public int[] frameBuffer = new int[320 * 262];
|
||||
public int[] GetVideoBuffer() { return frameBuffer; }
|
||||
public int VirtualWidth { get { return 320; } }
|
||||
|
@ -436,31 +440,37 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
public int BufferHeight { get { return 262; } }
|
||||
public int BackgroundColor { get { return 0; } }
|
||||
|
||||
public class audio
|
||||
public class Audio
|
||||
{
|
||||
/// <summary>noise/division control</summary>
|
||||
|
||||
// noise/division control
|
||||
public byte AUDC = 0;
|
||||
/// <summary>frequency divider</summary>
|
||||
|
||||
// frequency divider
|
||||
public byte AUDF = 1;
|
||||
/// <summary>volume</summary>
|
||||
|
||||
// volume
|
||||
public byte AUDV = 0;
|
||||
|
||||
/// <summary>2 state counter</summary>
|
||||
// 2 state counter
|
||||
bool sr1 = true;
|
||||
/// <summary>4 bit shift register</summary>
|
||||
|
||||
// 4 bit shift register
|
||||
int sr4 = 0x0f;
|
||||
/// <summary>5 bit shift register</summary>
|
||||
|
||||
// 5 bit shift register
|
||||
int sr5 = 0x1f;
|
||||
/// <summary>3 state counter</summary>
|
||||
|
||||
// 3 state counter
|
||||
int sr3 = 2;
|
||||
|
||||
/// <summary>counter based off AUDF</summary>
|
||||
// counter based off AUDF
|
||||
byte freqcnt;
|
||||
|
||||
/// <summary>latched audio value</summary>
|
||||
bool on = true;
|
||||
// latched audio value
|
||||
private bool on = true;
|
||||
|
||||
bool run_3()
|
||||
private bool run_3()
|
||||
{
|
||||
sr3++;
|
||||
if (sr3 == 3)
|
||||
|
@ -468,10 +478,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
sr3 = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool run_4()
|
||||
private bool run_4()
|
||||
{
|
||||
bool ret = (sr4 & 1) != 0;
|
||||
bool c = (sr4 & 1) != 0 ^ (sr4 & 2) != 0;
|
||||
|
@ -479,7 +490,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool run_5()
|
||||
private bool run_5()
|
||||
{
|
||||
bool ret = (sr5 & 1) != 0;
|
||||
bool c = (sr5 & 1) != 0 ^ (sr5 & 4) != 0;
|
||||
|
@ -487,26 +498,27 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool one_4()
|
||||
private bool one_4()
|
||||
{
|
||||
bool ret = (sr4 & 1) != 0;
|
||||
sr4 = (sr4 >> 1) | 8;
|
||||
return ret;
|
||||
}
|
||||
bool one_5()
|
||||
|
||||
private bool one_5()
|
||||
{
|
||||
bool ret = (sr5 & 1) != 0;
|
||||
sr5 = (sr5 >> 1) | 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool run_1()
|
||||
private bool run_1()
|
||||
{
|
||||
sr1 = !sr1;
|
||||
return !sr1;
|
||||
}
|
||||
|
||||
bool run_9()
|
||||
private bool run_9()
|
||||
{
|
||||
bool ret = (sr4 & 1) != 0;
|
||||
bool c = (sr5 & 1) != 0 ^ (sr4 & 1) != 0;
|
||||
|
@ -519,7 +531,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
/// call me approx 31k times a second
|
||||
/// </summary>
|
||||
/// <returns>16 bit audio sample</returns>
|
||||
public short cycle()
|
||||
public short Cycle()
|
||||
{
|
||||
if (++freqcnt == AUDF)
|
||||
{
|
||||
|
@ -618,32 +630,23 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
}
|
||||
|
||||
public audio[] AUD = { new audio(), new audio() };
|
||||
public Audio[] AUD = { new Audio(), new Audio() };
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
short[] moreSamples = new short[523];
|
||||
var moreSamples = new short[523];
|
||||
for (int i = 0; i < moreSamples.Length; i++)
|
||||
{
|
||||
for (int snd = 0; snd < 2; snd++)
|
||||
{
|
||||
moreSamples[i] += AUD[snd].cycle();
|
||||
//moreSamples[i] += (short)(((AUD[snd].sr4 & 0x08) != 0) ? AUD[snd].AUDV * 1092 : 0);
|
||||
moreSamples[i] += AUD[snd].Cycle();
|
||||
}
|
||||
/*if (++freqDiv == (audioFreqDiv * 2))
|
||||
{
|
||||
freqDiv = 0;
|
||||
myP4 = (byte)(((myP4 & 0x0f) != 0) ? ((myP4 << 1) | ((((myP4 & 0x08) != 0) ? 1 : 0) ^ (((myP4 & 0x04) != 0) ? 1 : 0))) : 1);
|
||||
}
|
||||
|
||||
moreSamples[i] = (short)(((myP4 & 0x08) != 0) ? 32767 : 0);
|
||||
*/
|
||||
}
|
||||
|
||||
for (int i = 0; i < samples.Length / 2; i++)
|
||||
{
|
||||
samples[i * 2] = moreSamples[(int)(((double)moreSamples.Length / (double)(samples.Length / 2)) * i)];
|
||||
samples[i * 2 + 1] = samples[i * 2];
|
||||
samples[(i * 2) + 1] = samples[i * 2];
|
||||
}
|
||||
}
|
||||
public void DiscardSamples() { }
|
||||
|
@ -651,7 +654,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
|
||||
// Execute TIA cycles
|
||||
public void execute(int cycles)
|
||||
public void Execute(int cycles)
|
||||
{
|
||||
// Still ignoring cycles...
|
||||
|
||||
|
@ -660,16 +663,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
// ---- Things that happen only in the drawing section ----
|
||||
// TODO: Remove this magic number (17). It depends on the HMOVE
|
||||
if ((hsyncCnt / 4) >= (hmove.lateHBlankReset ? 19 : 17))
|
||||
if ((_hsyncCnt / 4) >= (hmove.lateHBlankReset ? 19 : 17))
|
||||
{
|
||||
// TODO: Remove this magic number
|
||||
if ((hsyncCnt / 4) >= 37)
|
||||
if ((_hsyncCnt / 4) >= 37)
|
||||
{
|
||||
rightSide = true;
|
||||
}
|
||||
|
||||
// The bit number of the PF data which we want
|
||||
int pfBit = ((hsyncCnt / 4) - 17) % 20;
|
||||
int pfBit = ((_hsyncCnt / 4) - 17) % 20;
|
||||
|
||||
// Create the mask for the bit we want
|
||||
// Note that bits are arranged 0 1 2 3 4 .. 19
|
||||
|
@ -678,7 +681,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
// Reverse the mask if on the right and playfield is reflected
|
||||
if (rightSide && playField.reflect)
|
||||
{
|
||||
pfMask = reverseBits(pfMask, 20);
|
||||
pfMask = ReverseBits(pfMask, 20);
|
||||
}
|
||||
|
||||
// Calculate collisions
|
||||
|
@ -691,29 +694,29 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
|
||||
// ---- Player 0 ----
|
||||
collisions |= (player0.tick() ? CXP0 : (byte)0x00);
|
||||
collisions |= (player0.Tick() ? CXP0 : (byte)0x00);
|
||||
|
||||
// ---- Missile 0 ----
|
||||
collisions |= (player0.missile.Tick() ? CXM0 : (byte)0x00);
|
||||
collisions |= (player0.Missile.Tick() ? CXM0 : (byte)0x00);
|
||||
|
||||
// ---- Player 1 ----
|
||||
collisions |= (player1.tick() ? CXP1 : (byte)0x00);
|
||||
collisions |= (player1.Tick() ? CXP1 : (byte)0x00);
|
||||
|
||||
// ---- Missile 0 ----
|
||||
collisions |= (player1.missile.Tick() ? CXM1 : (byte)0x00);
|
||||
collisions |= (player1.Missile.Tick() ? CXM1 : (byte)0x00);
|
||||
|
||||
// ---- Ball ----
|
||||
collisions |= (ball.tick() ? CXBL : (byte)0x00);
|
||||
collisions |= (ball.Tick() ? CXBL : (byte)0x00);
|
||||
|
||||
|
||||
// Pick the pixel color from collisions
|
||||
uint pixelColor = 0x000000;
|
||||
if (core.Settings.ShowBG)
|
||||
if (_core.Settings.ShowBG)
|
||||
{
|
||||
pixelColor = palette[playField.bkColor];
|
||||
}
|
||||
|
||||
if ((collisions & CXPF) != 0 && core.Settings.ShowPlayfield)
|
||||
if ((collisions & CXPF) != 0 && _core.Settings.ShowPlayfield)
|
||||
{
|
||||
if (playField.score)
|
||||
{
|
||||
|
@ -735,7 +738,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if ((collisions & CXBL) != 0)
|
||||
{
|
||||
ball.collisions |= collisions;
|
||||
if (core.Settings.ShowBall)
|
||||
if (_core.Settings.ShowBall)
|
||||
{
|
||||
pixelColor = palette[playField.pfColor];
|
||||
}
|
||||
|
@ -743,8 +746,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if ((collisions & CXM1) != 0)
|
||||
{
|
||||
player1.missile.Collisions |= collisions;
|
||||
if (core.Settings.ShowMissle2)
|
||||
player1.Missile.Collisions |= collisions;
|
||||
if (_core.Settings.ShowMissle2)
|
||||
{
|
||||
pixelColor = palette[player1.color];
|
||||
}
|
||||
|
@ -753,7 +756,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if ((collisions & CXP1) != 0)
|
||||
{
|
||||
player1.collisions |= collisions;
|
||||
if (core.Settings.ShowPlayer2)
|
||||
if (_core.Settings.ShowPlayer2)
|
||||
{
|
||||
pixelColor = palette[player1.color];
|
||||
}
|
||||
|
@ -761,8 +764,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if ((collisions & CXM0) != 0)
|
||||
{
|
||||
player0.missile.Collisions |= collisions;
|
||||
if (core.Settings.ShowMissle1)
|
||||
player0.Missile.Collisions |= collisions;
|
||||
if (_core.Settings.ShowMissle1)
|
||||
{
|
||||
pixelColor = palette[player0.color];
|
||||
}
|
||||
|
@ -771,24 +774,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if ((collisions & CXP0) != 0)
|
||||
{
|
||||
player0.collisions |= collisions;
|
||||
if (core.Settings.ShowPlayer1)
|
||||
if (_core.Settings.ShowPlayer1)
|
||||
{
|
||||
pixelColor = palette[player0.color];
|
||||
}
|
||||
}
|
||||
|
||||
if (playField.priority && (collisions & CXPF) != 0 && core.Settings.ShowPlayfield)
|
||||
if (playField.priority && (collisions & CXPF) != 0 && _core.Settings.ShowPlayfield)
|
||||
{
|
||||
if (playField.score)
|
||||
{
|
||||
if (!rightSide)
|
||||
{
|
||||
pixelColor = palette[player0.color];
|
||||
}
|
||||
else
|
||||
{
|
||||
pixelColor = palette[player1.color];
|
||||
}
|
||||
pixelColor = !rightSide ? palette[player0.color] : palette[player1.color];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -804,7 +800,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
// Add the pixel to the scanline
|
||||
// TODO: Remove this magic number (68)
|
||||
scanline[hsyncCnt - 68] = pixelColor;
|
||||
scanline[_hsyncCnt - 68] = pixelColor;
|
||||
}
|
||||
|
||||
|
||||
|
@ -833,7 +829,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
hmove.hmoveCnt = 0;
|
||||
|
||||
//hmove.hmoveCnt++;
|
||||
hmove.hmoveJustStarted = false;
|
||||
hmove.lateHBlankReset = true;
|
||||
hmove.decCntEnabled = false;
|
||||
|
@ -851,7 +846,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (((15 - hmove.player0Cnt) ^ ((player0.HM & 0x07) | ((~(player0.HM & 0x08)) & 0x08))) != 0x0F)
|
||||
{
|
||||
// "Clock-Stuffing"
|
||||
player0.tick();
|
||||
player0.Tick();
|
||||
|
||||
// Increase by 1, max of 15
|
||||
hmove.player0Cnt++;
|
||||
|
@ -869,10 +864,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{ }
|
||||
|
||||
// If the move counter still has a bit in common with the HM register
|
||||
if (((15 - hmove.missile0Cnt) ^ ((player0.missile.Hm & 0x07) | ((~(player0.missile.Hm & 0x08)) & 0x08))) != 0x0F)
|
||||
if (((15 - hmove.missile0Cnt) ^ ((player0.Missile.Hm & 0x07) | ((~(player0.Missile.Hm & 0x08)) & 0x08))) != 0x0F)
|
||||
{
|
||||
// "Clock-Stuffing"
|
||||
player0.missile.Tick();
|
||||
player0.Missile.Tick();
|
||||
|
||||
// Increase by 1, max of 15
|
||||
hmove.missile0Cnt++;
|
||||
|
@ -891,7 +886,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (((15 - hmove.player1Cnt) ^ ((player1.HM & 0x07) | ((~(player1.HM & 0x08)) & 0x08))) != 0x0F)
|
||||
{
|
||||
// "Clock-Stuffing"
|
||||
player1.tick();
|
||||
player1.Tick();
|
||||
|
||||
// Increase by 1, max of 15
|
||||
hmove.player1Cnt++;
|
||||
|
@ -906,10 +901,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (hmove.missile1Latch)
|
||||
{
|
||||
// If the move counter still has a bit in common with the HM register
|
||||
if (((15 - hmove.missile1Cnt) ^ ((player1.missile.Hm & 0x07) | ((~(player1.missile.Hm & 0x08)) & 0x08))) != 0x0F)
|
||||
if (((15 - hmove.missile1Cnt) ^ ((player1.Missile.Hm & 0x07) | ((~(player1.Missile.Hm & 0x08)) & 0x08))) != 0x0F)
|
||||
{
|
||||
// "Clock-Stuffing"
|
||||
player1.missile.Tick();
|
||||
player1.Missile.Tick();
|
||||
|
||||
// Increase by 1, max of 15
|
||||
hmove.missile1Cnt++;
|
||||
|
@ -927,7 +922,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (((15 - hmove.ballCnt) ^ ((ball.HM & 0x07) | ((~(ball.HM & 0x08)) & 0x08))) != 0x0F)
|
||||
{
|
||||
// "Clock-Stuffing"
|
||||
ball.tick();
|
||||
ball.Tick();
|
||||
|
||||
// Increase by 1, max of 15
|
||||
hmove.ballCnt++;
|
||||
|
@ -946,7 +941,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
hmove.hmoveDelayCnt = 0;
|
||||
}
|
||||
}
|
||||
//hmove.hmoveJustStarted = false;
|
||||
|
||||
hmove.hmoveCnt++;
|
||||
hmove.hmoveCnt %= 4;
|
||||
}
|
||||
|
@ -964,14 +959,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Increment the hsync counter
|
||||
hsyncCnt++;
|
||||
hsyncCnt %= 228;
|
||||
_hsyncCnt++;
|
||||
_hsyncCnt %= 228;
|
||||
|
||||
// End of the line? Add it to the buffer!
|
||||
if (hsyncCnt == 0)
|
||||
if (_hsyncCnt == 0)
|
||||
{
|
||||
hmove.lateHBlankReset = false;
|
||||
scanlinesBuffer.Add(scanline);
|
||||
|
@ -984,14 +977,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
* that need to be fixed; but it's preferable to not crash the emulator
|
||||
* in such situations
|
||||
*/
|
||||
outputFrame();
|
||||
OutputFrame();
|
||||
scanlinesBuffer.Clear();
|
||||
frameComplete = true;
|
||||
FrameComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove the magic numbers from this function to allow for a variable height screen
|
||||
public void outputFrame()
|
||||
public void OutputFrame()
|
||||
{
|
||||
for (int row = 0; row < 262; row++)
|
||||
{
|
||||
|
@ -999,11 +992,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
if (scanlinesBuffer.Count > row)
|
||||
{
|
||||
frameBuffer[row * 320 + col] = (int)(scanlinesBuffer[row][col / 2] | 0xFF000000);
|
||||
frameBuffer[(row * 320) + col] = (int)(scanlinesBuffer[row][col / 2] | 0xFF000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
frameBuffer[row * 320 + col] = unchecked((int)0xFF000000);
|
||||
frameBuffer[(row * 320) + col] = unchecked((int)0xFF000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1014,41 +1007,49 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ushort maskedAddr = (ushort)(addr & 0x000F);
|
||||
if (maskedAddr == 0x00) // CXM0P
|
||||
{
|
||||
return (byte)((((player0.missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((player0.missile.Collisions & CXP0) != 0) ? 0x40 : 0x00));
|
||||
return (byte)((((player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x01) // CXM1P
|
||||
|
||||
if (maskedAddr == 0x01) // CXM1P
|
||||
{
|
||||
return (byte)((((player1.missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((player1.missile.Collisions & CXP1) != 0) ? 0x40 : 0x00));
|
||||
return (byte)((((player1.Missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((player1.Missile.Collisions & CXP1) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x02) // CXP0FB
|
||||
|
||||
if (maskedAddr == 0x02) // CXP0FB
|
||||
{
|
||||
return (byte)((((player0.collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player0.collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x03) // CXP1FB
|
||||
|
||||
if (maskedAddr == 0x03) // CXP1FB
|
||||
{
|
||||
return (byte)((((player1.collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player1.collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x04) // CXM0FB
|
||||
|
||||
if (maskedAddr == 0x04) // CXM0FB
|
||||
{
|
||||
return (byte)((((player0.missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player0.missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
return (byte)((((player0.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player0.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x05) // CXM1FB
|
||||
|
||||
if (maskedAddr == 0x05) // CXM1FB
|
||||
{
|
||||
return (byte)((((player1.missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player1.missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
return (byte)((((player1.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((player1.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x06) // CXBLPF
|
||||
|
||||
if (maskedAddr == 0x06) // CXBLPF
|
||||
{
|
||||
return (byte)(((ball.collisions & CXPF) != 0) ? 0x80 : 0x00);
|
||||
}
|
||||
else if (maskedAddr == 0x07) // CXPPMM
|
||||
|
||||
if (maskedAddr == 0x07) // CXPPMM
|
||||
{
|
||||
return (byte)((((player0.collisions & CXP1) != 0) ? 0x80 : 0x00) | (((player0.missile.Collisions & CXM1) != 0) ? 0x40 : 0x00));
|
||||
return (byte)((((player0.collisions & CXP1) != 0) ? 0x80 : 0x00) | (((player0.Missile.Collisions & CXM1) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x08) // INPT0
|
||||
|
||||
if (maskedAddr == 0x08) // INPT0
|
||||
{
|
||||
// Changing the hard coded value will change the paddle position. The range seems to be roughly 0-56000 according to values from stella
|
||||
// 6105 roughly centers the paddle in Breakout
|
||||
if (capCharging && core.cpu.TotalExecutedCycles - capChargeStart >= 6105)
|
||||
if (_capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= 6105)
|
||||
{
|
||||
return 0x80;
|
||||
}
|
||||
|
@ -1057,13 +1058,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
return 0x00;
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x0C) // INPT4
|
||||
|
||||
if (maskedAddr == 0x0C) // INPT4
|
||||
{
|
||||
return (byte)((core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00);
|
||||
return (byte)((_core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00);
|
||||
}
|
||||
else if (maskedAddr == 0x0D) // INPT5
|
||||
|
||||
if (maskedAddr == 0x0D) // INPT5
|
||||
{
|
||||
return (byte)((core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00);
|
||||
return (byte)((_core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00);
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
|
@ -1085,53 +1088,55 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
// When VSYNC is disabled, this will be the first line of the new frame
|
||||
|
||||
// write to frame buffer
|
||||
outputFrame();
|
||||
OutputFrame();
|
||||
|
||||
// Clear all from last frame
|
||||
scanlinesBuffer.Clear();
|
||||
//Frame is done
|
||||
frameComplete = true;
|
||||
|
||||
// Frame is done
|
||||
FrameComplete = true;
|
||||
|
||||
vsyncEnabled = false;
|
||||
|
||||
// Do not reset hsync, since we're on the first line of the new frame
|
||||
//hsyncCnt = 0;
|
||||
// hsyncCnt = 0;
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x01) // VBLANK
|
||||
{
|
||||
vblankEnabled = (value & 0x02) != 0;
|
||||
capCharging = (value & 0x80) == 0;
|
||||
_capCharging = (value & 0x80) == 0;
|
||||
if ((value & 0x80) == 0)
|
||||
{
|
||||
capChargeStart = core.cpu.TotalExecutedCycles;
|
||||
_capChargeStart = _core.Cpu.TotalExecutedCycles;
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x02) // WSYNC
|
||||
{
|
||||
int count = 0;
|
||||
while (hsyncCnt > 0)
|
||||
while (_hsyncCnt > 0)
|
||||
{
|
||||
count++;
|
||||
execute(1);
|
||||
Execute(1);
|
||||
|
||||
// Add a cycle to the cpu every 3 TIA clocks (corrects timer error in M6532)
|
||||
if (count % 3 == 0)
|
||||
{
|
||||
core.m6532.timer.tick();
|
||||
_core.M6532.timer.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x04) // NUSIZ0
|
||||
{
|
||||
player0.nusiz = (byte)(value & 0x37);
|
||||
player0.missile.Size = (byte)((value & 0x30) >> 4);
|
||||
player0.missile.Number = (byte)(value & 0x07);
|
||||
player0.Missile.Size = (byte)((value & 0x30) >> 4);
|
||||
player0.Missile.Number = (byte)(value & 0x07);
|
||||
}
|
||||
else if (maskedAddr == 0x05) // NUSIZ1
|
||||
{
|
||||
player1.nusiz = (byte)(value & 0x37);
|
||||
player1.missile.Size = (byte)((value & 0x30) >> 4);
|
||||
player1.missile.Number = (byte)(value & 0x07);
|
||||
player1.Missile.Size = (byte)((value & 0x30) >> 4);
|
||||
player1.Missile.Number = (byte)(value & 0x07);
|
||||
}
|
||||
else if (maskedAddr == 0x06) // COLUP0
|
||||
{
|
||||
|
@ -1158,42 +1163,42 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
else if (maskedAddr == 0x0B) // REFP0
|
||||
{
|
||||
player0.reflect = ((value & 0x08) != 0);
|
||||
player0.reflect = (value & 0x08) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x0C) // REFP1
|
||||
{
|
||||
player1.reflect = ((value & 0x08) != 0);
|
||||
player1.reflect = (value & 0x08) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x0D) // PF0
|
||||
{
|
||||
playField.grp = (UInt32)((playField.grp & 0x0FFFF) + ((reverseBits(value,8) & 0x0F) << 16));
|
||||
playField.grp = (uint)((playField.grp & 0x0FFFF) + ((ReverseBits(value, 8) & 0x0F) << 16));
|
||||
}
|
||||
else if (maskedAddr == 0x0E) // PF1
|
||||
{
|
||||
playField.grp = (UInt32)((playField.grp & 0xF00FF) + (value << 8));
|
||||
playField.grp = (uint)((playField.grp & 0xF00FF) + (value << 8));
|
||||
}
|
||||
else if (maskedAddr == 0x0F) // PF2
|
||||
{
|
||||
playField.grp = (UInt32)((playField.grp & 0xFFF00) + reverseBits(value,8));
|
||||
playField.grp = (uint)((playField.grp & 0xFFF00) + ReverseBits(value,8));
|
||||
}
|
||||
else if (maskedAddr == 0x10) // RESP0
|
||||
{
|
||||
// Borrowed from EMU7800. Apparently resetting between 68 and 76 has strange results.
|
||||
if (hsyncCnt < 69)
|
||||
if (_hsyncCnt < 69)
|
||||
{
|
||||
player0.hPosCnt = 0;
|
||||
player0.resetCnt = 0;
|
||||
player0.reset = true;
|
||||
}
|
||||
else if (hsyncCnt == 69)
|
||||
else if (_hsyncCnt == 69)
|
||||
{
|
||||
player0.resetCnt = 3;
|
||||
}
|
||||
else if (hsyncCnt == 72)
|
||||
else if (_hsyncCnt == 72)
|
||||
{
|
||||
player0.resetCnt = 2;
|
||||
}
|
||||
else if (hsyncCnt == 75)
|
||||
else if (_hsyncCnt == 75)
|
||||
{
|
||||
player0.resetCnt = 1;
|
||||
}
|
||||
|
@ -1201,27 +1206,26 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
player0.resetCnt = 0;
|
||||
}
|
||||
//player0.resetCnt = 0;
|
||||
}
|
||||
else if (maskedAddr == 0x11) // RESP1
|
||||
{
|
||||
// Borrowed from EMU7800. Apparently resetting between 68 and 76 has strange results.
|
||||
// This fixes some graphic glitches with Frostbite
|
||||
if (hsyncCnt < 69)
|
||||
if (_hsyncCnt < 69)
|
||||
{
|
||||
player1.hPosCnt = 0;
|
||||
player1.resetCnt = 0;
|
||||
player1.reset = true;
|
||||
}
|
||||
else if (hsyncCnt == 69)
|
||||
else if (_hsyncCnt == 69)
|
||||
{
|
||||
player1.resetCnt = 3;
|
||||
}
|
||||
else if (hsyncCnt == 72)
|
||||
else if (_hsyncCnt == 72)
|
||||
{
|
||||
player1.resetCnt = 2;
|
||||
}
|
||||
else if (hsyncCnt == 75)
|
||||
else if (_hsyncCnt == 75)
|
||||
{
|
||||
player1.resetCnt = 1;
|
||||
}
|
||||
|
@ -1229,19 +1233,18 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
player1.resetCnt = 0;
|
||||
}
|
||||
//player1.resetCnt = 0;
|
||||
}
|
||||
else if (maskedAddr == 0x12) // RESM0
|
||||
{
|
||||
player0.missile.HPosCnt = (byte)(hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
player0.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
}
|
||||
else if (maskedAddr == 0x13) // RESM1
|
||||
{
|
||||
player1.missile.HPosCnt = (byte)(hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
player1.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
}
|
||||
else if (maskedAddr == 0x14) // RESBL
|
||||
{
|
||||
ball.hPosCnt = (byte)(hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
ball.hPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
|
||||
}
|
||||
else if (maskedAddr == 0x15) // AUDC0
|
||||
{
|
||||
|
@ -1282,11 +1285,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
else if (maskedAddr == 0x1D) // ENAM0
|
||||
{
|
||||
player0.missile.Enabled = (value & 0x02) != 0;
|
||||
player0.Missile.Enabled = (value & 0x02) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x1E) // ENAM1
|
||||
{
|
||||
player1.missile.Enabled = (value & 0x02) != 0;
|
||||
player1.Missile.Enabled = (value & 0x02) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x1F) // ENABL
|
||||
{
|
||||
|
@ -1302,11 +1305,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
else if (maskedAddr == 0x22) // HMM0
|
||||
{
|
||||
player0.missile.Hm = (byte)((value & 0xF0) >> 4);
|
||||
player0.Missile.Hm = (byte)((value & 0xF0) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x23) // HMM1
|
||||
{
|
||||
player1.missile.Hm = (byte)((value & 0xF0) >> 4);
|
||||
player1.Missile.Hm = (byte)((value & 0xF0) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x24) // HMBL
|
||||
{
|
||||
|
@ -1326,11 +1329,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
else if (maskedAddr == 0x28) // RESMP0
|
||||
{
|
||||
player0.missile.ResetToPlayer = (value & 0x02) != 0;
|
||||
player0.Missile.ResetToPlayer = (value & 0x02) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x29) // RESMP1
|
||||
{
|
||||
player1.missile.ResetToPlayer = (value & 0x02) != 0;
|
||||
player1.Missile.ResetToPlayer = (value & 0x02) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x2A) // HMOVE
|
||||
{
|
||||
|
@ -1341,22 +1344,22 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
else if (maskedAddr == 0x2B) // HMCLR
|
||||
{
|
||||
player0.HM = 0;
|
||||
player0.missile.Hm = 0;
|
||||
player0.Missile.Hm = 0;
|
||||
player1.HM = 0;
|
||||
player1.missile.Hm = 0;
|
||||
player1.Missile.Hm = 0;
|
||||
ball.HM = 0;
|
||||
}
|
||||
else if (maskedAddr == 0x2C) // CXCLR
|
||||
{
|
||||
player0.collisions = 0;
|
||||
player0.missile.Collisions = 0;
|
||||
player0.Missile.Collisions = 0;
|
||||
player1.collisions = 0;
|
||||
player1.missile.Collisions = 0;
|
||||
player1.Missile.Collisions = 0;
|
||||
ball.collisions = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int reverseBits(int value, int bits)
|
||||
private static int ReverseBits(int value, int bits)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
|
@ -1371,7 +1374,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ser.BeginSection("TIA");
|
||||
ball.SyncState(ser);
|
||||
hmove.SyncState(ser);
|
||||
ser.Sync("hsyncCnt", ref hsyncCnt);
|
||||
ser.Sync("hsyncCnt", ref _hsyncCnt);
|
||||
ser.BeginSection("Player0");
|
||||
player0.SyncState(ser);
|
||||
ser.EndSection();
|
||||
|
@ -1379,7 +1382,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
player1.SyncState(ser);
|
||||
ser.EndSection();
|
||||
playField.SyncState(ser);
|
||||
//ser.Sync("scanline", ref scanline);
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,616 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
// Emulates the TIA
|
||||
public class oldTIA
|
||||
{
|
||||
private readonly Atari2600 core;
|
||||
|
||||
public bool audioEnabled = false;
|
||||
public byte audioFreqDiv = 0;
|
||||
|
||||
UInt32 PF; // PlayField data
|
||||
byte BKcolor, PFcolor;
|
||||
bool PFpriority;
|
||||
bool PFreflect;
|
||||
bool PFscore;
|
||||
bool inpt_latching;
|
||||
bool inpt4;
|
||||
bool hmoveHappened;
|
||||
|
||||
struct playerData
|
||||
{
|
||||
public byte grp;
|
||||
public byte dgrp;
|
||||
public byte color;
|
||||
public byte pos;
|
||||
public byte HM;
|
||||
public bool reflect;
|
||||
public bool delay;
|
||||
/*
|
||||
public byte nusiz;
|
||||
*/
|
||||
};
|
||||
struct ballMissileData
|
||||
{
|
||||
public bool enabled;
|
||||
public byte pos;
|
||||
public byte HM;
|
||||
public byte size;
|
||||
/*
|
||||
public bool reset;
|
||||
public bool delay;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
ballMissileData ball;
|
||||
|
||||
playerData player0;
|
||||
playerData player1;
|
||||
|
||||
byte player0copies;
|
||||
byte player0copy1;
|
||||
byte player0copy2;
|
||||
byte player1copies;
|
||||
byte player1copy1;
|
||||
byte player1copy2;
|
||||
|
||||
byte P0_collisions;
|
||||
byte P1_collisions;
|
||||
byte M0_collisions;
|
||||
byte M1_collisions;
|
||||
byte BL_collisions;
|
||||
|
||||
const byte COLP0 = 0x01;
|
||||
const byte COLP1 = 0x02;
|
||||
const byte COLM0 = 0x04;
|
||||
const byte COLM1 = 0x08;
|
||||
const byte COLPF = 0x10;
|
||||
const byte COLBL = 0x20;
|
||||
|
||||
bool vblankEnabled;
|
||||
|
||||
readonly int[] frameBuffer;
|
||||
public bool frameComplete;
|
||||
|
||||
readonly List<uint[]> scanlinesBuffer = new List<uint[]> ();
|
||||
uint[] scanline = new uint[160];
|
||||
public int scanlinePos;
|
||||
|
||||
readonly int[] hmove = new int[] { 0,-1,-2,-3,-4,-5,-6,-7,-8,7,6,5,4,3,2,1 };
|
||||
|
||||
UInt32[] palette = new UInt32[]{
|
||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
|
||||
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
|
||||
0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0,
|
||||
0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0,
|
||||
0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0,
|
||||
0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0,
|
||||
0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0,
|
||||
0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0,
|
||||
0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0,
|
||||
0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0,
|
||||
0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0,
|
||||
0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0,
|
||||
0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0,
|
||||
0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0,
|
||||
0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0,
|
||||
0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0,
|
||||
0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0,
|
||||
0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0,
|
||||
0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0,
|
||||
0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0,
|
||||
0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0,
|
||||
0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0,
|
||||
0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0,
|
||||
0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0,
|
||||
0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0,
|
||||
0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0,
|
||||
0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0,
|
||||
0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0,
|
||||
0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0,
|
||||
0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0,
|
||||
0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
|
||||
};
|
||||
|
||||
public oldTIA(Atari2600 core, int[] frameBuffer)
|
||||
{
|
||||
player1copy2 = 0;
|
||||
player0copy2 = 0;
|
||||
this.core = core;
|
||||
BKcolor = 0x00;
|
||||
this.frameBuffer = frameBuffer;
|
||||
scanlinePos = 0;
|
||||
frameComplete = false;
|
||||
}
|
||||
|
||||
public void execute(int cycles)
|
||||
{
|
||||
// Ignore cycles for now, just do one cycle (three color counts/pixels)
|
||||
|
||||
if (scanlinePos < 68)
|
||||
{
|
||||
scanlinePos ++;
|
||||
// HBLANK
|
||||
return;
|
||||
}
|
||||
|
||||
UInt32 PFmask;
|
||||
|
||||
int pixelPos = scanlinePos - 68;
|
||||
|
||||
// First half of screen
|
||||
if (pixelPos < 80)
|
||||
{
|
||||
PFmask = (UInt32)(1 << ((20-1) - (byte)((pixelPos % 80) / 4)));
|
||||
}
|
||||
// Second half
|
||||
else
|
||||
{
|
||||
if (PFreflect)
|
||||
{
|
||||
PFmask = (UInt32)(1 << ((byte)((pixelPos % 80) / 4)));
|
||||
}
|
||||
else
|
||||
{
|
||||
PFmask = (UInt32)(1 << ((20 - 1) - (byte)((pixelPos % 80) / 4)));
|
||||
}
|
||||
}
|
||||
|
||||
uint color = palette[BKcolor];
|
||||
byte collisions = 0;
|
||||
|
||||
if ((PF & PFmask) != 0)
|
||||
{
|
||||
color = palette[PFcolor];
|
||||
if (PFscore)
|
||||
{
|
||||
if (pixelPos < 80)
|
||||
{
|
||||
color = palette[player0.color];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = palette[player1.color];
|
||||
}
|
||||
}
|
||||
collisions |= COLPF;
|
||||
}
|
||||
|
||||
// Ball
|
||||
if (ball.enabled && pixelPos >= ball.pos && pixelPos < (ball.pos + (1 << ball.size)))
|
||||
{
|
||||
color = palette[PFcolor];
|
||||
collisions |= COLBL;
|
||||
}
|
||||
|
||||
// Player 1
|
||||
if (pixelPos >= player1.pos && pixelPos < (player1.pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - player1.pos));
|
||||
if (player1.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
|
||||
if (((player1.grp & mask) != 0 && !player1.delay) || ((player1.dgrp & mask) != 0 && player1.delay))
|
||||
{
|
||||
color = palette[player1.color];
|
||||
collisions |= COLP1;
|
||||
}
|
||||
}
|
||||
|
||||
byte pos = (byte)(player1.pos + player1copy1);
|
||||
// Player copy 1
|
||||
if (player1copies >= 1 && pixelPos >= pos && pixelPos < (pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - pos));
|
||||
if (player1.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
|
||||
if (((player1.grp & mask) != 0 && !player1.delay) || ((player1.dgrp & mask) != 0 && player1.delay))
|
||||
{
|
||||
color = palette[player1.color];
|
||||
collisions |= COLP1;
|
||||
}
|
||||
}
|
||||
|
||||
pos = (byte)(player1.pos + player1copy2);
|
||||
// Player copy 2
|
||||
if (player1copies >=2 && pixelPos >= pos && pixelPos < (pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - pos));
|
||||
if (player1.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
|
||||
if (((player1.grp & mask) != 0 && !player1.delay) || ((player1.dgrp & mask) != 0 && player1.delay))
|
||||
{
|
||||
color = palette[player1.color];
|
||||
collisions |= COLP1;
|
||||
}
|
||||
}
|
||||
|
||||
// Player 0
|
||||
if (pixelPos >= player0.pos && pixelPos < (player0.pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - player0.pos));
|
||||
if (player0.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
if (((player0.grp & mask) != 0 && !player0.delay) || ((player0.dgrp & mask) != 0 && player0.delay))
|
||||
{
|
||||
color = palette[player0.color];
|
||||
collisions |= COLP0;
|
||||
}
|
||||
}
|
||||
|
||||
pos = (byte)(player0.pos + player0copy1);
|
||||
// Player copy 1
|
||||
if (player0copies >= 1 && pixelPos >= pos && pixelPos < (pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - pos));
|
||||
if (player0.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
|
||||
if (((player0.grp & mask) != 0 && !player0.delay) || ((player0.dgrp & mask) != 0 && player0.delay))
|
||||
{
|
||||
color = palette[player0.color];
|
||||
collisions |= COLP0;
|
||||
}
|
||||
}
|
||||
|
||||
pos = (byte)(player0.pos + player0copy2);
|
||||
// Player copy 1
|
||||
if (player0copies >= 2 && pixelPos >= pos && pixelPos < (pos + 8))
|
||||
{
|
||||
byte mask = (byte)(0x80 >> (pixelPos - pos));
|
||||
if (player0.reflect)
|
||||
{
|
||||
mask = reverseBits(mask);
|
||||
}
|
||||
|
||||
if (((player0.grp & mask) != 0 && !player0.delay) || ((player0.dgrp & mask) != 0 && player0.delay))
|
||||
{
|
||||
color = palette[player0.color];
|
||||
collisions |= COLP0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((PF & PFmask) != 0 && PFpriority)
|
||||
{
|
||||
color = palette[PFcolor];
|
||||
if (PFscore)
|
||||
{
|
||||
if (pixelPos < 80)
|
||||
{
|
||||
color = palette[player0.color];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = palette[player1.color];
|
||||
}
|
||||
}
|
||||
collisions |= COLPF;
|
||||
}
|
||||
|
||||
if (vblankEnabled)
|
||||
{
|
||||
color = 0x000000;
|
||||
}
|
||||
|
||||
P0_collisions |= (((collisions & COLP0) != 0) ? collisions : P0_collisions);
|
||||
P1_collisions |= (((collisions & COLP1) != 0) ? collisions : P1_collisions);
|
||||
M0_collisions |= (((collisions & COLM0) != 0) ? collisions : M0_collisions);
|
||||
M1_collisions |= (((collisions & COLM1) != 0) ? collisions : M1_collisions);
|
||||
BL_collisions |= (((collisions & COLBL) != 0) ? collisions : BL_collisions);
|
||||
|
||||
if (hmoveHappened && pixelPos >= 0 && pixelPos < 8)
|
||||
{
|
||||
color = 0x000000;
|
||||
}
|
||||
if (pixelPos >= 8)
|
||||
{
|
||||
hmoveHappened = false;
|
||||
}
|
||||
scanline[pixelPos] = color;
|
||||
|
||||
scanlinePos++;
|
||||
if (scanlinePos >= 228)
|
||||
{
|
||||
scanlinesBuffer.Add(scanline);
|
||||
scanline = new uint[160];
|
||||
}
|
||||
scanlinePos %= 228;
|
||||
|
||||
}
|
||||
|
||||
public void outputFrame()
|
||||
{
|
||||
for (int row = 0; row < 262; row++)
|
||||
{
|
||||
for (int col = 0; col < 320; col++)
|
||||
{
|
||||
if (scanlinesBuffer.Count > row)
|
||||
{
|
||||
frameBuffer[row * 320 + col] = (int)(scanlinesBuffer[row][col / 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
frameBuffer[row * 320 + col] = 0x000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadMemory(ushort addr, bool peek)
|
||||
{
|
||||
ushort maskedAddr = (ushort)(addr & 0x000F);
|
||||
Console.WriteLine("TIA read: " + maskedAddr.ToString("x"));
|
||||
if (maskedAddr == 0x02) // CXP0FB
|
||||
{
|
||||
return (byte)((((P0_collisions & COLPF) != 0) ? 0x80 : 0x00) | (((P0_collisions & COLBL) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x07) // CXPPMM
|
||||
{
|
||||
return (byte)((((P0_collisions & COLP1) != 0) ? 0x80 : 0x00) | (((M0_collisions & COLM1) != 0) ? 0x40 : 0x00));
|
||||
}
|
||||
else if (maskedAddr == 0x0C) // INPT4
|
||||
{
|
||||
if (inpt_latching)
|
||||
{
|
||||
if (inpt4)
|
||||
{
|
||||
inpt4 = ((core.ReadControls1(peek) & 0x08) != 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
inpt4 = ((core.ReadControls1(peek) & 0x08) != 0);
|
||||
}
|
||||
return (byte)(inpt4 ? 0x80 : 0x00);
|
||||
|
||||
}
|
||||
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
ushort maskedAddr = (ushort)(addr & 0x3f);
|
||||
Console.WriteLine("TIA write: " + maskedAddr.ToString("x"));
|
||||
|
||||
if (maskedAddr == 0x00)
|
||||
{
|
||||
if ((value & 0x02) != 0)
|
||||
{
|
||||
Console.WriteLine("TIA VSYNC On");
|
||||
// Frame is complete, output to buffer
|
||||
outputFrame();
|
||||
scanlinesBuffer.Clear();
|
||||
frameComplete = true;
|
||||
scanlinePos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("TIA VSYNC Off");
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x01)
|
||||
{
|
||||
vblankEnabled = (value & 0x02) != 0;
|
||||
if ((value & 0x02) != 0)
|
||||
{
|
||||
Console.WriteLine("TIA Vblank On");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("TIA Vblank Off");
|
||||
}
|
||||
inpt_latching = (value & 0x40) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x02) // WSYNC
|
||||
{
|
||||
Console.WriteLine("TIA WSYNC");
|
||||
while (scanlinePos > 0)
|
||||
{
|
||||
execute(1);
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x04) // NUSIZ0
|
||||
{
|
||||
byte size = (byte)(value & 0x07);
|
||||
switch (size)
|
||||
{
|
||||
case 0x00:
|
||||
player0copies = 0;
|
||||
break;
|
||||
case 0x01:
|
||||
player0copies = 1;
|
||||
player0copy1 = 16;
|
||||
break;
|
||||
case 0x02:
|
||||
player0copies = 1;
|
||||
player0copy1 = 32;
|
||||
break;
|
||||
case 0x03:
|
||||
player0copies = 2;
|
||||
player0copy1 = 16;
|
||||
player0copy2 = 32;
|
||||
break;
|
||||
case 0x06:
|
||||
player0copies = 2;
|
||||
player0copy1 = 32;
|
||||
player0copy2 = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x05) // NUSIZ1
|
||||
{
|
||||
byte size = (byte)(value & 0x07);
|
||||
switch (size)
|
||||
{
|
||||
case 0x00:
|
||||
player1copies = 0;
|
||||
break;
|
||||
case 0x01:
|
||||
player1copies = 1;
|
||||
player1copy1 = 16;
|
||||
break;
|
||||
case 0x02:
|
||||
player1copies = 1;
|
||||
player1copy1 = 32;
|
||||
break;
|
||||
case 0x03:
|
||||
player1copies = 2;
|
||||
player1copy1 = 16;
|
||||
player1copy2 = 32;
|
||||
break;
|
||||
case 0x06:
|
||||
player1copies = 2;
|
||||
player1copy1 = 32;
|
||||
player1copy2 = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (maskedAddr == 0x06) // COLUP0
|
||||
{
|
||||
player0.color = (byte)(value & 0xFE);
|
||||
}
|
||||
else if (maskedAddr == 0x07) // COLUP1
|
||||
{
|
||||
player1.color = (byte)(value & 0xFE);
|
||||
}
|
||||
else if (maskedAddr == 0x08) // COLUPF
|
||||
{
|
||||
PFcolor = (byte)(value & 0xFE);
|
||||
}
|
||||
else if (maskedAddr == 0x09) // COLUBK
|
||||
{
|
||||
BKcolor = (byte)(value & 0xFE);
|
||||
}
|
||||
else if (maskedAddr == 0x0A) // CTRLPF
|
||||
{
|
||||
PFpriority = (value & 0x04) != 0;
|
||||
PFreflect = (value & 0x01) != 0;
|
||||
PFscore = (value & 0x02) != 0;
|
||||
|
||||
ball.size = (byte)((value & 0x30) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x0B) // REFP0
|
||||
{
|
||||
player0.reflect = ((value & 0x08) != 0);
|
||||
}
|
||||
else if (maskedAddr == 0x0C) // REFP1
|
||||
{
|
||||
player1.reflect = ((value & 0x08) != 0);
|
||||
}
|
||||
else if (maskedAddr == 0x0D) // PF0
|
||||
{
|
||||
PF = (UInt32)((PF & 0x0FFFF) + ((reverseBits(value) & 0x0F) << 16));
|
||||
}
|
||||
else if (maskedAddr == 0x0E) // PF1
|
||||
{
|
||||
PF = (UInt32)((PF & 0xF00FF) + (value << 8));
|
||||
}
|
||||
else if (maskedAddr == 0x0F) // PF2
|
||||
{
|
||||
PF = (PF & 0xFFF00) + reverseBits(value);
|
||||
}
|
||||
else if (maskedAddr == 0x10) // RESP0
|
||||
{
|
||||
player0.pos = (byte)(scanlinePos - 68 + 5);
|
||||
}
|
||||
else if (maskedAddr == 0x11) // RESP1
|
||||
{
|
||||
player1.pos = (byte)(scanlinePos - 68 + 5);
|
||||
}
|
||||
else if (maskedAddr == 0x14) // RESBL
|
||||
{
|
||||
ball.pos = (byte)(scanlinePos - 68 + 4);
|
||||
}
|
||||
else if (maskedAddr == 0x15) // AUDC0
|
||||
{
|
||||
audioEnabled = value != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x17) // AUDF0
|
||||
{
|
||||
audioFreqDiv = (byte)(value + 1);
|
||||
}
|
||||
else if (maskedAddr == 0x1B) // GRP0
|
||||
{
|
||||
player0.grp = value;
|
||||
player1.dgrp = player1.grp;
|
||||
}
|
||||
else if (maskedAddr == 0x1C) // GRP1
|
||||
{
|
||||
player1.grp = value;
|
||||
player0.dgrp = player0.grp;
|
||||
}
|
||||
else if (maskedAddr == 0x1F) // ENABL
|
||||
{
|
||||
ball.enabled = (value & 0x02) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x20) // HMP0
|
||||
{
|
||||
player0.HM = (byte)((value & 0xF0) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x21) // HMP1
|
||||
{
|
||||
player1.HM = (byte)((value & 0xF0) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x24) // HMBL
|
||||
{
|
||||
ball.HM = (byte)((value & 0xF0) >> 4);
|
||||
}
|
||||
else if (maskedAddr == 0x25) // VDELP0
|
||||
{
|
||||
player0.delay = (value & 0x01) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x26) // VDELP1
|
||||
{
|
||||
player1.delay = (value & 0x01) != 0;
|
||||
}
|
||||
else if (maskedAddr == 0x2A) // HMOVE
|
||||
{
|
||||
player0.pos = (byte)(player0.pos + hmove[player0.HM]);
|
||||
player1.pos = (byte)(player1.pos + hmove[player1.HM]);
|
||||
ball.pos = (byte)(ball.pos + hmove[ball.HM]);
|
||||
|
||||
player0.HM = 0;
|
||||
player1.HM = 0;
|
||||
ball.HM = 0;
|
||||
|
||||
hmoveHappened = true;
|
||||
}
|
||||
else if (maskedAddr == 0x2C) // CXCLR
|
||||
{
|
||||
P0_collisions = 0;
|
||||
P1_collisions = 0;
|
||||
M0_collisions = 0;
|
||||
M1_collisions = 0;
|
||||
BL_collisions = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public byte reverseBits(byte value)
|
||||
{
|
||||
byte result = 0x00;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
result = (byte)(result | (((value >> i) & 0x01 ) << (7-i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue