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:
adelikat 2014-04-05 14:13:05 +00:00
parent 43d58e3441
commit 27daa82464
32 changed files with 621 additions and 1142 deletions

View File

@ -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>

View File

@ -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,47 +280,64 @@ 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;
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;
}
//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; }
public byte ReadConsoleSwitches(bool peek)
{
byte value = 0xFF;
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() { }
}
}

View File

@ -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)
{
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) => { })
};
memoryDomains = new MemoryDomainList(domains);
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) => 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);
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 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
}
}
}
}

View File

@ -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
{

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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)))
{

View File

@ -9,7 +9,7 @@
return base.ReadMemory(addr);
}
return core.rom[addr & 0xFFF];
return Core.Rom[addr & 0xFFF];
}
public override byte PeekMemory(ushort addr)

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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();
}
}
}

View File

@ -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)

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}
}