This commit is contained in:
parent
76e137378c
commit
73f625dee4
|
@ -78,6 +78,11 @@
|
|||
<Compile Include="Buffer.cs" />
|
||||
<Compile Include="Computers\Commodore64\C64.core.cs" />
|
||||
<Compile Include="Computers\Commodore64\C64.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridge.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cia.cs" />
|
||||
<Compile Include="Computers\Commodore64\MemBus.cs" />
|
||||
<Compile Include="Computers\Commodore64\Sid.cs" />
|
||||
<Compile Include="Computers\Commodore64\VicII.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\Atari2600.Core.cs" />
|
||||
<Compile Include="Consoles\Atari\2600\Mappers\m3Fe.cs" />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Emulation.CPUs.M6502;
|
||||
|
@ -8,25 +9,76 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
public partial class C64 : IEmulator
|
||||
{
|
||||
public byte[] rom;
|
||||
// source
|
||||
public Cartridge cart;
|
||||
public bool cartInserted;
|
||||
public byte[] inputFile;
|
||||
|
||||
// chipset
|
||||
public Cia cia1;
|
||||
public Cia cia2;
|
||||
public MOS6502X cpu;
|
||||
public MemoryBus mem;
|
||||
public Sid sid;
|
||||
public VicII vic;
|
||||
public VicSignals vicSignal;
|
||||
|
||||
private void HardReset()
|
||||
{
|
||||
cpu = new MOS6502X();
|
||||
cpu.ReadMemory = ReadMemory;
|
||||
cpu.WriteMemory = WriteMemory;
|
||||
cpu.DummyReadMemory = ReadMemory;
|
||||
cpu.DummyReadMemory = PeekMemory;
|
||||
|
||||
// initialize cia timers
|
||||
cia1 = new Cia();
|
||||
cia2 = new Cia();
|
||||
|
||||
// initialize vic
|
||||
vicSignal = new VicSignals();
|
||||
vic = new VicII(vicSignal, VicIIMode.NTSC);
|
||||
|
||||
// initialize sid
|
||||
sid = new Sid();
|
||||
|
||||
// initialize memory (this must be done AFTER all other chips are initialized)
|
||||
string romPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "C64Kernal");
|
||||
mem = new MemoryBus(romPath, vic, sid, cia1, cia2);
|
||||
|
||||
// initialize media
|
||||
Cartridge cart = new Cartridge(inputFile);
|
||||
if (cart.valid)
|
||||
{
|
||||
mem.ApplyCartridge(cart);
|
||||
}
|
||||
|
||||
// initialize cpu (hard reset vector)
|
||||
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
|
||||
}
|
||||
|
||||
public byte PeekMemory(ushort addr)
|
||||
{
|
||||
return mem.Peek(addr);
|
||||
}
|
||||
|
||||
public byte PeekMemoryInt(int addr)
|
||||
{
|
||||
return mem.Peek((ushort)(addr & 0xFFFF));
|
||||
}
|
||||
|
||||
public void PokeMemoryInt(int addr, byte val)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
return 0;
|
||||
return mem.Read(addr);
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
//TODO
|
||||
mem.Write(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
public C64(GameInfo game, byte[] rom, string romextension)
|
||||
{
|
||||
videoProvider = new MyVideoProvider(this);
|
||||
SetupMemoryDomains();
|
||||
CoreOutputComm = new CoreOutputComm();
|
||||
CoreInputComm = new CoreInputComm();
|
||||
HardReset();
|
||||
inputFile = rom;
|
||||
SetupMemoryDomains();
|
||||
CoreOutputComm = new CoreOutputComm();
|
||||
CoreInputComm = new CoreInputComm();
|
||||
HardReset();
|
||||
videoProvider = new MyVideoProvider(vic);
|
||||
}
|
||||
|
||||
public string SystemId { get { return "C64"; } }
|
||||
|
@ -45,7 +46,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
}
|
||||
|
||||
/*TODO*/
|
||||
public int[] frameBuffer = new int[256 * 192]; //TODO
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return null; } } //TODO
|
||||
public bool StartAsyncSound() { return true; } //TODO
|
||||
public void EndAsyncSound() { } //TODO
|
||||
|
@ -58,12 +58,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public IController Controller { get; set; }
|
||||
public static readonly ControllerDefinition Atari7800ControllerDefinition = new ControllerDefinition
|
||||
{
|
||||
Name = "Atari 7800 Basic Controller", //TODO
|
||||
Name = "Commodore 64 Controller", //TODO
|
||||
BoolButtons =
|
||||
{
|
||||
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button",
|
||||
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button",
|
||||
"Reset", "Select"
|
||||
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button",
|
||||
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button"
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -89,8 +88,23 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
_frame++;
|
||||
_islag = true;
|
||||
|
||||
//TODO
|
||||
//Do stuff here
|
||||
int cyclesPerSecond = (14318181 / 14 / 60);
|
||||
|
||||
for (int i = 0; i < cyclesPerSecond; i++)
|
||||
{
|
||||
if (vicSignal.Interrupt)
|
||||
{
|
||||
cpu.IRQ = true;
|
||||
}
|
||||
if (vicSignal.AllowCpu)
|
||||
{
|
||||
cpu.ExecuteOne();
|
||||
}
|
||||
vic.PerformCycle();
|
||||
sid.PerformCycle();
|
||||
cia1.PerformCycle();
|
||||
cia2.PerformCycle();
|
||||
}
|
||||
|
||||
if (_islag)
|
||||
{
|
||||
|
@ -104,27 +118,31 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
private MySoundProvider soundProvider;
|
||||
private MyVideoProvider videoProvider;
|
||||
|
||||
class MyVideoProvider : IVideoProvider
|
||||
{
|
||||
public int top = 0; //TODO
|
||||
public int bottom = 262; //TODO
|
||||
public int left = 0; //TODO
|
||||
public int right = 320; //TODO
|
||||
public int top;
|
||||
public int bottom;
|
||||
public int left;
|
||||
public int right;
|
||||
|
||||
C64 emu;
|
||||
public MyVideoProvider(C64 emu)
|
||||
VicII vic;
|
||||
public MyVideoProvider(VicII vic)
|
||||
{
|
||||
this.emu = emu;
|
||||
this.vic = vic;
|
||||
|
||||
buffer = new int[vic.rasterWidth * vic.rasterTotalLines];
|
||||
top = 0;
|
||||
bottom = vic.rasterTotalLines-1;
|
||||
left = 0;
|
||||
right = vic.rasterWidth-1;
|
||||
}
|
||||
|
||||
int[] buffer = new int[262 * 320];
|
||||
int[] buffer;
|
||||
|
||||
public void FillFrameBuffer()
|
||||
{
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = 0; //TODO
|
||||
}
|
||||
Array.Copy(vic.buffer, buffer, buffer.Length);
|
||||
}
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
|
@ -141,7 +159,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>(1);
|
||||
domains.Add(new MemoryDomain("Main RAM", 1, Endian.Little, addr => 0xFF, null)); //TODO
|
||||
domains.Add(new MemoryDomain("RAM", 0x10000, Endian.Little, new Func<int, byte>(PeekMemoryInt), new Action<int,byte>(PokeMemoryInt))); //TODO
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public class CartridgeChip
|
||||
{
|
||||
public int address;
|
||||
public int bank;
|
||||
public byte[] data;
|
||||
public ushort romMask;
|
||||
public int type;
|
||||
}
|
||||
|
||||
public class Cartridge
|
||||
{
|
||||
public List<CartridgeChip> chips;
|
||||
public bool exRomPin;
|
||||
public bool gamePin;
|
||||
public int type;
|
||||
public bool valid;
|
||||
public int version;
|
||||
|
||||
public Cartridge(byte[] rom)
|
||||
{
|
||||
chips = new List<CartridgeChip>();
|
||||
|
||||
if (rom.Length >= 0x50)
|
||||
{
|
||||
MemoryStream source = new MemoryStream(rom);
|
||||
BinaryReader reader = new BinaryReader(source);
|
||||
string idString;
|
||||
|
||||
// note: cartridge files store values big-endian.
|
||||
|
||||
idString = new string(reader.ReadChars(16));
|
||||
if (idString == "C64 CARTRIDGE ")
|
||||
{
|
||||
int headerLength = 0;
|
||||
headerLength = reader.ReadByte();
|
||||
headerLength <<= 8;
|
||||
headerLength |= reader.ReadByte();
|
||||
headerLength <<= 8;
|
||||
headerLength |= reader.ReadByte();
|
||||
headerLength <<= 8;
|
||||
headerLength |= reader.ReadByte();
|
||||
|
||||
version = reader.ReadByte();
|
||||
version <<= 8;
|
||||
version |= reader.ReadByte();
|
||||
|
||||
type = reader.ReadByte();
|
||||
type <<= 8;
|
||||
type |= reader.ReadByte();
|
||||
|
||||
exRomPin = (reader.ReadByte() == 1);
|
||||
gamePin = (reader.ReadByte() == 1);
|
||||
|
||||
reader.ReadBytes(6); // reserved
|
||||
reader.ReadBytes(32); // name
|
||||
|
||||
// skip the rest, don't need this info
|
||||
if (headerLength > 0x40)
|
||||
{
|
||||
reader.ReadBytes(headerLength - 0x40);
|
||||
}
|
||||
|
||||
while (source.Position < rom.Length)
|
||||
{
|
||||
string chipID = new string(reader.ReadChars(4));
|
||||
|
||||
if (chipID == "CHIP")
|
||||
{
|
||||
CartridgeChip chip = new CartridgeChip();
|
||||
|
||||
int packetLength;
|
||||
packetLength = reader.ReadByte();
|
||||
packetLength <<= 8;
|
||||
packetLength |= reader.ReadByte();
|
||||
packetLength <<= 8;
|
||||
packetLength |= reader.ReadByte();
|
||||
packetLength <<= 8;
|
||||
packetLength |= reader.ReadByte();
|
||||
packetLength -= 16;
|
||||
|
||||
chip.type = reader.ReadByte();
|
||||
chip.type <<= 8;
|
||||
chip.type |= reader.ReadByte();
|
||||
|
||||
chip.bank = reader.ReadByte();
|
||||
chip.bank <<= 8;
|
||||
chip.bank |= reader.ReadByte();
|
||||
|
||||
chip.address = reader.ReadByte();
|
||||
chip.address <<= 8;
|
||||
chip.address |= reader.ReadByte();
|
||||
|
||||
int size;
|
||||
size = reader.ReadByte();
|
||||
size <<= 8;
|
||||
size |= reader.ReadByte();
|
||||
|
||||
chip.data = reader.ReadBytes(size);
|
||||
chip.romMask = (ushort)(size - 1);
|
||||
|
||||
packetLength -= size;
|
||||
if (packetLength > 0)
|
||||
{
|
||||
// discard extra bytes
|
||||
reader.ReadBytes(packetLength);
|
||||
}
|
||||
|
||||
chips.Add(chip);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
valid = (chips.Count > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
CartridgeChip currentChip = chips[0];
|
||||
return currentChip.data[addr & currentChip.romMask];
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
// can't write to rom but we can process DE00/DF00 here
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public class Cia
|
||||
{
|
||||
public int cycles;
|
||||
public byte[] regs;
|
||||
|
||||
public Cia()
|
||||
{
|
||||
regs = new byte[0x10];
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
cycles++;
|
||||
}
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
byte result = 0;
|
||||
|
||||
switch (addr & 0x0F)
|
||||
{
|
||||
case 0x00:
|
||||
break;
|
||||
case 0x01:
|
||||
break;
|
||||
case 0x02:
|
||||
break;
|
||||
case 0x03:
|
||||
break;
|
||||
case 0x04:
|
||||
break;
|
||||
case 0x05:
|
||||
break;
|
||||
case 0x06:
|
||||
break;
|
||||
case 0x07:
|
||||
break;
|
||||
case 0x08:
|
||||
break;
|
||||
case 0x09:
|
||||
break;
|
||||
case 0x0A:
|
||||
break;
|
||||
case 0x0B:
|
||||
break;
|
||||
case 0x0C:
|
||||
break;
|
||||
case 0x0D:
|
||||
break;
|
||||
case 0x0E:
|
||||
break;
|
||||
case 0x0F:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
switch (addr & 0x0F)
|
||||
{
|
||||
case 0x00:
|
||||
break;
|
||||
case 0x01:
|
||||
break;
|
||||
case 0x02:
|
||||
break;
|
||||
case 0x03:
|
||||
break;
|
||||
case 0x04:
|
||||
break;
|
||||
case 0x05:
|
||||
break;
|
||||
case 0x06:
|
||||
break;
|
||||
case 0x07:
|
||||
break;
|
||||
case 0x08:
|
||||
break;
|
||||
case 0x09:
|
||||
break;
|
||||
case 0x0A:
|
||||
break;
|
||||
case 0x0B:
|
||||
break;
|
||||
case 0x0C:
|
||||
break;
|
||||
case 0x0D:
|
||||
break;
|
||||
case 0x0E:
|
||||
break;
|
||||
case 0x0F:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,451 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public enum MemoryBusDesignation
|
||||
{
|
||||
Disabled,
|
||||
RAM,
|
||||
Basic,
|
||||
Kernal,
|
||||
IO,
|
||||
Character,
|
||||
ROMLo,
|
||||
ROMHi,
|
||||
Vic,
|
||||
Sid,
|
||||
ColorRam,
|
||||
Cia1,
|
||||
Cia2,
|
||||
Expansion1,
|
||||
Expansion2
|
||||
}
|
||||
|
||||
public class MemoryBusLayout
|
||||
{
|
||||
public MemoryBusDesignation Mem1000 = MemoryBusDesignation.RAM;
|
||||
public MemoryBusDesignation Mem8000 = MemoryBusDesignation.RAM;
|
||||
public MemoryBusDesignation MemA000 = MemoryBusDesignation.RAM;
|
||||
public MemoryBusDesignation MemC000 = MemoryBusDesignation.RAM;
|
||||
public MemoryBusDesignation MemD000 = MemoryBusDesignation.RAM;
|
||||
public MemoryBusDesignation MemE000 = MemoryBusDesignation.RAM;
|
||||
}
|
||||
|
||||
public class MemoryBus
|
||||
{
|
||||
// chips
|
||||
public Cia cia1;
|
||||
public Cia cia2;
|
||||
public VicII vic;
|
||||
public Sid sid;
|
||||
|
||||
// storage
|
||||
public Cartridge cart;
|
||||
public bool cartInserted = false;
|
||||
|
||||
// roms
|
||||
public byte[] basicRom;
|
||||
public byte[] charRom;
|
||||
public bool exRomPin = true;
|
||||
public bool gamePin = true;
|
||||
public byte[] kernalRom;
|
||||
public MemoryBusLayout layout;
|
||||
|
||||
// ram
|
||||
public byte[] colorRam;
|
||||
public byte[] ram;
|
||||
|
||||
// registers
|
||||
public byte busData;
|
||||
public byte cpu00; // register $00
|
||||
public byte cpu01; // register $01
|
||||
public bool readTrigger = true;
|
||||
public bool writeTrigger = true;
|
||||
|
||||
public MemoryBus(string sourceFolder, VicII newVic, Sid newSid, Cia newCia1, Cia newCia2)
|
||||
{
|
||||
ram = new byte[0x10000];
|
||||
WipeMemory();
|
||||
|
||||
string basicFile = "basic";
|
||||
string charFile = "chargen";
|
||||
string kernalFile = "kernal";
|
||||
|
||||
basicRom = File.ReadAllBytes(Path.Combine(sourceFolder, basicFile));
|
||||
charRom = File.ReadAllBytes(Path.Combine(sourceFolder, charFile));
|
||||
kernalRom = File.ReadAllBytes(Path.Combine(sourceFolder, kernalFile));
|
||||
colorRam = new byte[0x1000];
|
||||
|
||||
vic = newVic;
|
||||
sid = newSid;
|
||||
cia1 = newCia1;
|
||||
cia2 = newCia2;
|
||||
cpu00 = 0x2F;
|
||||
cpu01 = 0x37;
|
||||
|
||||
layout = new MemoryBusLayout();
|
||||
UpdateLayout();
|
||||
}
|
||||
|
||||
public void ApplyCartridge(Cartridge newCart)
|
||||
{
|
||||
cart = newCart;
|
||||
cartInserted = true;
|
||||
exRomPin = cart.exRomPin;
|
||||
gamePin = cart.gamePin;
|
||||
UpdateLayout();
|
||||
}
|
||||
|
||||
public MemoryBusDesignation GetDesignation(ushort addr)
|
||||
{
|
||||
MemoryBusDesignation result;
|
||||
|
||||
if (addr < 0x1000)
|
||||
{
|
||||
result = MemoryBusDesignation.RAM;
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
result = layout.Mem1000;
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
result = layout.Mem8000;
|
||||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
result = layout.MemA000;
|
||||
}
|
||||
else if (addr < 0xD000)
|
||||
{
|
||||
result = layout.MemC000;
|
||||
}
|
||||
else if (addr < 0xE000)
|
||||
{
|
||||
result = layout.MemD000;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = layout.MemE000;
|
||||
}
|
||||
|
||||
if (result == MemoryBusDesignation.IO)
|
||||
{
|
||||
addr &= 0x0FFF;
|
||||
if (addr < 0x0400)
|
||||
{
|
||||
result = MemoryBusDesignation.Vic;
|
||||
}
|
||||
else if (addr < 0x0800)
|
||||
{
|
||||
result = MemoryBusDesignation.Sid;
|
||||
}
|
||||
else if (addr < 0x0C00)
|
||||
{
|
||||
result = MemoryBusDesignation.ColorRam;
|
||||
}
|
||||
else if (addr < 0x0D00)
|
||||
{
|
||||
result = MemoryBusDesignation.Cia1;
|
||||
}
|
||||
else if (addr < 0x0E00)
|
||||
{
|
||||
result = MemoryBusDesignation.Cia2;
|
||||
}
|
||||
else if (addr < 0x0F00)
|
||||
{
|
||||
result = MemoryBusDesignation.Expansion1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MemoryBusDesignation.Expansion2;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte Peek(ushort addr)
|
||||
{
|
||||
byte result;
|
||||
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
result = cpu00;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
result = cpu01;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryBusDesignation des = GetDesignation(addr);
|
||||
|
||||
switch (des)
|
||||
{
|
||||
case MemoryBusDesignation.Basic:
|
||||
result = basicRom[addr & 0x1FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.Character:
|
||||
result = charRom[addr & 0x0FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.Vic:
|
||||
result = vic.regs[addr & 0x3F];
|
||||
break;
|
||||
case MemoryBusDesignation.Sid:
|
||||
result = sid.regs[addr & 0x1F];
|
||||
break;
|
||||
case MemoryBusDesignation.ColorRam:
|
||||
result = colorRam[addr & 0x03FF];
|
||||
break;
|
||||
case MemoryBusDesignation.Cia1:
|
||||
result = cia1.regs[addr & 0x0F];
|
||||
break;
|
||||
case MemoryBusDesignation.Cia2:
|
||||
result = cia2.regs[addr & 0x0F];
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion1:
|
||||
result = 0;
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion2:
|
||||
result = 0;
|
||||
break;
|
||||
case MemoryBusDesignation.Kernal:
|
||||
result = kernalRom[addr & 0x1FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.RAM:
|
||||
result = ram[addr];
|
||||
break;
|
||||
case MemoryBusDesignation.ROMHi:
|
||||
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
||||
break;
|
||||
case MemoryBusDesignation.ROMLo:
|
||||
result = cart.chips[0].data[addr & cart.chips[0].romMask];
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
busData = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
byte result;
|
||||
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
result = cpu00;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
result = cpu01;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryBusDesignation des = GetDesignation(addr);
|
||||
|
||||
switch (des)
|
||||
{
|
||||
case MemoryBusDesignation.Basic:
|
||||
result = basicRom[addr & 0x1FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.Character:
|
||||
result = charRom[addr & 0x0FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.Vic:
|
||||
result = vic.Read(addr);
|
||||
break;
|
||||
case MemoryBusDesignation.Sid:
|
||||
result = sid.Read(addr);
|
||||
break;
|
||||
case MemoryBusDesignation.ColorRam:
|
||||
result = (byte)((busData & 0xF0) | (colorRam[addr & 0x03FF]));
|
||||
break;
|
||||
case MemoryBusDesignation.Cia1:
|
||||
result = cia1.Read(addr);
|
||||
break;
|
||||
case MemoryBusDesignation.Cia2:
|
||||
result = cia2.Read(addr);
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion1:
|
||||
result = 0;
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion2:
|
||||
result = 0;
|
||||
break;
|
||||
case MemoryBusDesignation.Kernal:
|
||||
result = kernalRom[addr & 0x1FFF];
|
||||
break;
|
||||
case MemoryBusDesignation.RAM:
|
||||
result = ram[addr];
|
||||
break;
|
||||
case MemoryBusDesignation.ROMHi:
|
||||
result = cart.Read(addr);
|
||||
break;
|
||||
case MemoryBusDesignation.ROMLo:
|
||||
result = cart.Read(addr);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
busData = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void UpdateLayout()
|
||||
{
|
||||
bool loRom = ((cpu01 & 0x01) != 0);
|
||||
bool hiRom = ((cpu01 & 0x02) != 0);
|
||||
bool ioEnable = ((cpu01 & 0x04) != 0);
|
||||
|
||||
if (loRom && hiRom && exRomPin && gamePin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.Basic;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.Kernal;
|
||||
}
|
||||
else if (loRom && !hiRom && exRomPin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.RAM;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.RAM;
|
||||
}
|
||||
else if (loRom && !hiRom && !exRomPin && !gamePin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.RAM;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.RAM;
|
||||
layout.MemE000 = MemoryBusDesignation.RAM;
|
||||
}
|
||||
else if ((!loRom && hiRom && gamePin) || (!loRom && !hiRom && !exRomPin))
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.RAM;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.Kernal;
|
||||
}
|
||||
else if (!loRom && !hiRom && gamePin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.RAM;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = MemoryBusDesignation.RAM;
|
||||
layout.MemE000 = MemoryBusDesignation.RAM;
|
||||
}
|
||||
else if (loRom && hiRom && gamePin && !exRomPin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.ROMLo;
|
||||
layout.MemA000 = MemoryBusDesignation.Basic;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.Kernal;
|
||||
}
|
||||
else if (!loRom && hiRom && !gamePin && !exRomPin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.RAM;
|
||||
layout.MemA000 = MemoryBusDesignation.ROMHi;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.Kernal;
|
||||
}
|
||||
else if (loRom && hiRom && !gamePin && !exRomPin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.RAM;
|
||||
layout.Mem8000 = MemoryBusDesignation.ROMLo;
|
||||
layout.MemA000 = MemoryBusDesignation.ROMHi;
|
||||
layout.MemC000 = MemoryBusDesignation.RAM;
|
||||
layout.MemD000 = ioEnable ? MemoryBusDesignation.IO : MemoryBusDesignation.Character;
|
||||
layout.MemE000 = MemoryBusDesignation.Kernal;
|
||||
}
|
||||
else if (!gamePin && exRomPin)
|
||||
{
|
||||
layout.Mem1000 = MemoryBusDesignation.Disabled;
|
||||
layout.Mem8000 = MemoryBusDesignation.ROMLo;
|
||||
layout.MemA000 = MemoryBusDesignation.Disabled;
|
||||
layout.MemC000 = MemoryBusDesignation.Disabled;
|
||||
layout.MemD000 = MemoryBusDesignation.IO;
|
||||
layout.MemE000 = MemoryBusDesignation.ROMHi;
|
||||
}
|
||||
}
|
||||
|
||||
public void WipeMemory()
|
||||
{
|
||||
for (int i = 0; i < 0x10000; i += 0x80)
|
||||
{
|
||||
for (int j = 0; j < 0x40; j++)
|
||||
ram[i + j] = 0x00;
|
||||
for (int j = 0x40; j < 0x80; j++)
|
||||
ram[i + j] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
if (addr == 0x0000)
|
||||
{
|
||||
cpu00 = val;
|
||||
}
|
||||
else if (addr == 0x0001)
|
||||
{
|
||||
cpu01 &= (byte)(~cpu00);
|
||||
cpu01 |= (byte)(cpu00 & val);
|
||||
UpdateLayout();
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryBusDesignation des = GetDesignation(addr);
|
||||
|
||||
switch (des)
|
||||
{
|
||||
case MemoryBusDesignation.Vic:
|
||||
vic.Write(addr, val);
|
||||
break;
|
||||
case MemoryBusDesignation.Sid:
|
||||
sid.Write(addr, val);
|
||||
break;
|
||||
case MemoryBusDesignation.ColorRam:
|
||||
colorRam[addr & 0x03FF] = (byte)(val & 0x0F);
|
||||
break;
|
||||
case MemoryBusDesignation.Cia1:
|
||||
cia1.Write(addr, val);
|
||||
break;
|
||||
case MemoryBusDesignation.Cia2:
|
||||
cia2.Write(addr, val);
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion1:
|
||||
break;
|
||||
case MemoryBusDesignation.Expansion2:
|
||||
break;
|
||||
case MemoryBusDesignation.RAM:
|
||||
ram[addr] = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
busData = val;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public enum SidMode
|
||||
{
|
||||
Sid6581,
|
||||
Sid8580
|
||||
}
|
||||
|
||||
public class Sid
|
||||
{
|
||||
public byte[] regs;
|
||||
|
||||
public Sid()
|
||||
{
|
||||
regs = new byte[0x20];
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
switch (addr & 0x1F)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
switch (addr & 0x1F)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,446 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public enum VicIIMode
|
||||
{
|
||||
NTSC,
|
||||
PAL
|
||||
}
|
||||
|
||||
public class VicII
|
||||
{
|
||||
// buffer
|
||||
public int[] buffer;
|
||||
public int bufferSize;
|
||||
|
||||
// palette
|
||||
public int[] palette =
|
||||
{
|
||||
Colors.ARGB(0x00, 0x00, 0x00),
|
||||
Colors.ARGB(0xFF, 0xFF, 0xFF),
|
||||
Colors.ARGB(0x68, 0x37, 0x2B),
|
||||
Colors.ARGB(0x70, 0xA4, 0xB2),
|
||||
Colors.ARGB(0x6F, 0x3D, 0x86),
|
||||
Colors.ARGB(0x58, 0x8D, 0x43),
|
||||
Colors.ARGB(0x35, 0x28, 0x79),
|
||||
Colors.ARGB(0xB8, 0xC7, 0x6F),
|
||||
Colors.ARGB(0x6F, 0x4F, 0x25),
|
||||
Colors.ARGB(0x43, 0x39, 0x00),
|
||||
Colors.ARGB(0x9A, 0x67, 0x59),
|
||||
Colors.ARGB(0x44, 0x44, 0x44),
|
||||
Colors.ARGB(0x6C, 0x6C, 0x6C),
|
||||
Colors.ARGB(0x9A, 0xD2, 0x84),
|
||||
Colors.ARGB(0x6C, 0x5E, 0xB5),
|
||||
Colors.ARGB(0x95, 0x95, 0x95)
|
||||
};
|
||||
|
||||
// interrupts
|
||||
public bool interrupt;
|
||||
public bool lightPenInterrupt;
|
||||
public bool lightPenInterruptEnabled;
|
||||
public bool rasterInterrupt;
|
||||
public bool rasterInterruptEnabled;
|
||||
public bool spriteBackgroundInterrupt;
|
||||
public bool spriteBackgroundInterruptEnabled;
|
||||
public bool spriteSpriteInterrupt;
|
||||
public bool spriteSpriteInterruptEnabled;
|
||||
|
||||
// memory
|
||||
public int characterMemoryOffset;
|
||||
public int screenMemoryOffset;
|
||||
|
||||
// lightpen
|
||||
public int lightPenX;
|
||||
public int lightPenY;
|
||||
|
||||
// raster
|
||||
public int[] backgroundColor;
|
||||
public bool backgroundMode;
|
||||
public bool bitmapMode;
|
||||
public int borderColor;
|
||||
public bool borderOn;
|
||||
public byte[] charBuffer;
|
||||
public bool extendHeight;
|
||||
public bool extendWidth;
|
||||
public int horizontalScroll;
|
||||
public bool multiColorMode;
|
||||
public int rasterInterruptLine;
|
||||
public int rasterOffset;
|
||||
public int rasterOffsetX;
|
||||
public int rasterOffsetY;
|
||||
public int rasterTotalLines;
|
||||
public int rasterWidth;
|
||||
public bool screenEnabled;
|
||||
public int verticalScroll;
|
||||
public int visibleHeight;
|
||||
public int visibleWidth;
|
||||
|
||||
// sprites
|
||||
public bool[] spriteBackgroundCollision;
|
||||
public bool[] spriteCollision;
|
||||
public int[] spriteColor;
|
||||
public bool[] spriteEnabled;
|
||||
public int[] spriteExtraColor;
|
||||
public bool[] spriteMultiColor;
|
||||
public bool[] spritePriority;
|
||||
public bool[] spriteStretchHorizontal;
|
||||
public bool[] spriteStretchVertical;
|
||||
public int[] spriteX;
|
||||
public int[] spriteY;
|
||||
|
||||
public VicSignals cpuSignal;
|
||||
public byte[] regs;
|
||||
|
||||
public VicII(VicSignals signals, VicIIMode videoMode)
|
||||
{
|
||||
cpuSignal = signals;
|
||||
|
||||
switch (videoMode)
|
||||
{
|
||||
case VicIIMode.NTSC:
|
||||
rasterWidth = 512;
|
||||
rasterTotalLines = 263;
|
||||
visibleWidth = 368;
|
||||
visibleHeight = 235;
|
||||
break;
|
||||
case VicIIMode.PAL:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize raster
|
||||
backgroundColor = new int[4];
|
||||
charBuffer = new byte[40];
|
||||
|
||||
// initialize sprites
|
||||
spriteBackgroundCollision = new bool[8];
|
||||
spriteCollision = new bool[8];
|
||||
spriteColor = new int[8];
|
||||
spriteEnabled = new bool[8];
|
||||
spriteExtraColor = new int[2];
|
||||
spriteMultiColor = new bool[8];
|
||||
spritePriority = new bool[8];
|
||||
spriteStretchHorizontal = new bool[8];
|
||||
spriteStretchVertical = new bool[8];
|
||||
spriteX = new int[8];
|
||||
spriteY = new int[8];
|
||||
|
||||
// initialize buffer
|
||||
buffer = new int[rasterWidth * rasterTotalLines];
|
||||
bufferSize = buffer.Length;
|
||||
|
||||
// initialize registers
|
||||
regs = new byte[0x40];
|
||||
for (int i = 0x2F; i <= 0x3F; i++)
|
||||
regs[i] = 0xFF;
|
||||
UpdateRegs();
|
||||
}
|
||||
|
||||
public void LockBus()
|
||||
{
|
||||
cpuSignal.Lock();
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
WritePixel(borderColor);
|
||||
|
||||
if (rasterInterruptEnabled && (rasterOffsetY == rasterInterruptLine) && (rasterOffsetX == 0))
|
||||
{
|
||||
// removed for now
|
||||
//rasterInterrupt = true;
|
||||
}
|
||||
|
||||
interrupt =
|
||||
(rasterInterrupt & rasterInterruptEnabled) |
|
||||
(spriteSpriteInterrupt & spriteSpriteInterruptEnabled) |
|
||||
(spriteBackgroundInterrupt & spriteBackgroundInterruptEnabled) |
|
||||
(lightPenInterrupt & lightPenInterruptEnabled);
|
||||
|
||||
cpuSignal.Interrupt = interrupt;
|
||||
UpdateRegs();
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
return regs[addr & 0x3F];
|
||||
}
|
||||
|
||||
public void UnlockBus()
|
||||
{
|
||||
cpuSignal.Unlock();
|
||||
}
|
||||
|
||||
public void UpdateRegs()
|
||||
{
|
||||
// these registers update on their own
|
||||
|
||||
regs[0x11] = (byte)
|
||||
((verticalScroll & 0x07) |
|
||||
(extendHeight ? 0x08 : 0x00) |
|
||||
(screenEnabled ? 0x10 : 0x00) |
|
||||
(bitmapMode ? 0x20 : 0x00) |
|
||||
(backgroundMode ? 0x40 : 0x00) |
|
||||
((rasterOffsetY & 0x100) >> 1));
|
||||
regs[0x12] = (byte)(rasterOffsetY & 0xFF);
|
||||
regs[0x13] = (byte)(lightPenX >> 1);
|
||||
regs[0x14] = (byte)(lightPenY);
|
||||
regs[0x19] = (byte)
|
||||
((rasterInterrupt ? 0x01 : 0x00) |
|
||||
(spriteBackgroundInterrupt ? 0x02 : 0x00) |
|
||||
(spriteSpriteInterrupt ? 0x04 : 0x00) |
|
||||
(lightPenInterrupt ? 0x08 : 0x00) |
|
||||
(interrupt ? 0x80 : 0x00));
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
int index = 0;
|
||||
bool allowWrite = true;
|
||||
addr &= 0x3F;
|
||||
|
||||
switch (addr & 0x3F)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
index = addr >> 1;
|
||||
spriteX[index] &= 0xFF;
|
||||
spriteX[index] |= val;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
case 0x09:
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
index = addr >> 1;
|
||||
spriteY[index] &= 0xFF;
|
||||
spriteY[index] |= val;
|
||||
break;
|
||||
case 0x10:
|
||||
spriteX[0] = (spriteX[0] & 0xFF) | ((val & 0x01) << 8);
|
||||
spriteX[1] = (spriteX[1] & 0xFF) | ((val & 0x02) << 8);
|
||||
spriteX[2] = (spriteX[2] & 0xFF) | ((val & 0x04) << 8);
|
||||
spriteX[3] = (spriteX[3] & 0xFF) | ((val & 0x08) << 8);
|
||||
spriteX[4] = (spriteX[4] & 0xFF) | ((val & 0x10) << 8);
|
||||
spriteX[5] = (spriteX[5] & 0xFF) | ((val & 0x20) << 8);
|
||||
spriteX[6] = (spriteX[6] & 0xFF) | ((val & 0x40) << 8);
|
||||
spriteX[7] = (spriteX[7] & 0xFF) | ((val & 0x80) << 8);
|
||||
break;
|
||||
case 0x11:
|
||||
verticalScroll = val & 0x07;
|
||||
extendHeight = ((val & 0x08) != 0x00);
|
||||
screenEnabled = ((val & 0x10) != 0x00);
|
||||
bitmapMode = ((val & 0x20) != 0x00);
|
||||
backgroundMode = ((val & 0x40) != 0x00);
|
||||
rasterInterruptLine = (rasterInterruptLine & 0xFF) | ((val & 0x80) << 1);
|
||||
val = (byte)((val & 0x7F) | ((rasterOffsetY & 0x100) >> 1));
|
||||
break;
|
||||
case 0x12:
|
||||
rasterInterruptLine = (rasterInterruptLine & 0x100) | val;
|
||||
allowWrite = false;
|
||||
break;
|
||||
case 0x15:
|
||||
spriteEnabled[0] = ((val & 0x01) != 0x00);
|
||||
spriteEnabled[1] = ((val & 0x02) != 0x00);
|
||||
spriteEnabled[2] = ((val & 0x04) != 0x00);
|
||||
spriteEnabled[3] = ((val & 0x08) != 0x00);
|
||||
spriteEnabled[4] = ((val & 0x10) != 0x00);
|
||||
spriteEnabled[5] = ((val & 0x20) != 0x00);
|
||||
spriteEnabled[6] = ((val & 0x40) != 0x00);
|
||||
spriteEnabled[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x16:
|
||||
horizontalScroll = val & 0x07;
|
||||
extendWidth = ((val & 0x08) != 0x00);
|
||||
multiColorMode = ((val & 0x10) != 0x00);
|
||||
bitmapMode = ((val & 0x20) != 0x00);
|
||||
val |= 0xC0;
|
||||
break;
|
||||
case 0x17:
|
||||
spriteStretchVertical[0] = ((val & 0x01) != 0x00);
|
||||
spriteStretchVertical[1] = ((val & 0x02) != 0x00);
|
||||
spriteStretchVertical[2] = ((val & 0x04) != 0x00);
|
||||
spriteStretchVertical[3] = ((val & 0x08) != 0x00);
|
||||
spriteStretchVertical[4] = ((val & 0x10) != 0x00);
|
||||
spriteStretchVertical[5] = ((val & 0x20) != 0x00);
|
||||
spriteStretchVertical[6] = ((val & 0x40) != 0x00);
|
||||
spriteStretchVertical[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x18:
|
||||
characterMemoryOffset = (int)(val & 0x0E) << 10;
|
||||
screenMemoryOffset = (int)(val & 0xF0) << 6;
|
||||
break;
|
||||
case 0x19:
|
||||
rasterInterrupt = ((val & 0x01) != 0);
|
||||
spriteSpriteInterrupt = ((val & 0x02) != 0);
|
||||
spriteBackgroundInterrupt = ((val & 0x04) != 0);
|
||||
lightPenInterrupt = ((val & 0x08) != 0);
|
||||
allowWrite = false;
|
||||
break;
|
||||
case 0x1A:
|
||||
rasterInterruptEnabled = ((val & 0x01) != 0);
|
||||
spriteSpriteInterruptEnabled = ((val & 0x02) != 0);
|
||||
spriteBackgroundInterruptEnabled = ((val & 0x04) != 0);
|
||||
lightPenInterruptEnabled = ((val & 0x08) != 0);
|
||||
break;
|
||||
case 0x1B:
|
||||
spritePriority[0] = ((val & 0x01) != 0x00);
|
||||
spritePriority[1] = ((val & 0x02) != 0x00);
|
||||
spritePriority[2] = ((val & 0x04) != 0x00);
|
||||
spritePriority[3] = ((val & 0x08) != 0x00);
|
||||
spritePriority[4] = ((val & 0x10) != 0x00);
|
||||
spritePriority[5] = ((val & 0x20) != 0x00);
|
||||
spritePriority[6] = ((val & 0x40) != 0x00);
|
||||
spritePriority[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1C:
|
||||
spriteMultiColor[0] = ((val & 0x01) != 0x00);
|
||||
spriteMultiColor[1] = ((val & 0x02) != 0x00);
|
||||
spriteMultiColor[2] = ((val & 0x04) != 0x00);
|
||||
spriteMultiColor[3] = ((val & 0x08) != 0x00);
|
||||
spriteMultiColor[4] = ((val & 0x10) != 0x00);
|
||||
spriteMultiColor[5] = ((val & 0x20) != 0x00);
|
||||
spriteMultiColor[6] = ((val & 0x40) != 0x00);
|
||||
spriteMultiColor[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1D:
|
||||
spriteStretchHorizontal[0] = ((val & 0x01) != 0x00);
|
||||
spriteStretchHorizontal[1] = ((val & 0x02) != 0x00);
|
||||
spriteStretchHorizontal[2] = ((val & 0x04) != 0x00);
|
||||
spriteStretchHorizontal[3] = ((val & 0x08) != 0x00);
|
||||
spriteStretchHorizontal[4] = ((val & 0x10) != 0x00);
|
||||
spriteStretchHorizontal[5] = ((val & 0x20) != 0x00);
|
||||
spriteStretchHorizontal[6] = ((val & 0x40) != 0x00);
|
||||
spriteStretchHorizontal[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1E:
|
||||
spriteCollision[0] = ((val & 0x01) != 0x00);
|
||||
spriteCollision[1] = ((val & 0x02) != 0x00);
|
||||
spriteCollision[2] = ((val & 0x04) != 0x00);
|
||||
spriteCollision[3] = ((val & 0x08) != 0x00);
|
||||
spriteCollision[4] = ((val & 0x10) != 0x00);
|
||||
spriteCollision[5] = ((val & 0x20) != 0x00);
|
||||
spriteCollision[6] = ((val & 0x40) != 0x00);
|
||||
spriteCollision[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1F:
|
||||
spriteBackgroundCollision[0] = ((val & 0x01) != 0x00);
|
||||
spriteBackgroundCollision[1] = ((val & 0x02) != 0x00);
|
||||
spriteBackgroundCollision[2] = ((val & 0x04) != 0x00);
|
||||
spriteBackgroundCollision[3] = ((val & 0x08) != 0x00);
|
||||
spriteBackgroundCollision[4] = ((val & 0x10) != 0x00);
|
||||
spriteBackgroundCollision[5] = ((val & 0x20) != 0x00);
|
||||
spriteBackgroundCollision[6] = ((val & 0x40) != 0x00);
|
||||
spriteBackgroundCollision[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x20:
|
||||
borderColor = val;
|
||||
break;
|
||||
case 0x21:
|
||||
backgroundColor[0] = val;
|
||||
break;
|
||||
case 0x22:
|
||||
backgroundColor[1] = val;
|
||||
break;
|
||||
case 0x23:
|
||||
backgroundColor[2] = val;
|
||||
break;
|
||||
case 0x24:
|
||||
backgroundColor[3] = val;
|
||||
break;
|
||||
case 0x25:
|
||||
spriteExtraColor[0] = val;
|
||||
break;
|
||||
case 0x26:
|
||||
spriteExtraColor[1] = val;
|
||||
break;
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
case 0x2E:
|
||||
index = addr - 0x27;
|
||||
spriteColor[index] = val;
|
||||
break;
|
||||
default:
|
||||
allowWrite = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (allowWrite)
|
||||
regs[addr] = val;
|
||||
}
|
||||
|
||||
private void WritePixel(int value)
|
||||
{
|
||||
buffer[rasterOffset] = palette[value];
|
||||
rasterOffset++;
|
||||
if (rasterOffset >= bufferSize)
|
||||
rasterOffset = 0;
|
||||
|
||||
rasterOffsetX = (rasterOffset & 0x1FF);
|
||||
rasterOffsetY = (rasterOffset >> 9);
|
||||
}
|
||||
}
|
||||
|
||||
public class VicSignals
|
||||
{
|
||||
public bool AllowCpu;
|
||||
public bool Interrupt;
|
||||
public int LockCounter;
|
||||
|
||||
public VicSignals()
|
||||
{
|
||||
AllowCpu = true;
|
||||
Interrupt = false;
|
||||
LockCounter = 0;
|
||||
}
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
if (AllowCpu)
|
||||
{
|
||||
LockCounter = 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
if (AllowCpu)
|
||||
{
|
||||
if (LockCounter > 0)
|
||||
{
|
||||
LockCounter--;
|
||||
if (LockCounter == 0)
|
||||
{
|
||||
AllowCpu = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
AllowCpu = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue