Atari7800Hawk: Core Cleanup
-now gets in game in choplifter -implement player controls -fix memory mapping bugs -clean up code -implement more video modes There is still a serious timing bug that i need to track down and a lot of video mode work to do, but getting in game is at least making progress.
This commit is contained in:
parent
3c3915caa2
commit
170381597b
|
@ -1,4 +1,5 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||
|
@ -17,6 +18,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
public bool cpu_halt_pending;
|
||||
public bool cpu_resume_pending;
|
||||
|
||||
// input state of controllers and console
|
||||
public byte p1_state;
|
||||
public byte p2_state;
|
||||
public byte con_state;
|
||||
|
||||
// there are 4 maria cycles in a CPU cycle (fast access, both NTSC and PAL)
|
||||
// if the 6532 or TIA are accessed (PC goes to one of those addresses) the next access will be slower by 1/2 a CPU cycle
|
||||
// i.e. it will take 6 Maria cycles instead of 4
|
||||
|
@ -42,15 +48,19 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
HardReset();
|
||||
}
|
||||
|
||||
_islag = true;
|
||||
|
||||
p1_state = GetControllerState(controller, 1);
|
||||
p2_state = GetControllerState(controller, 2);
|
||||
con_state = GetConsoleState(controller);
|
||||
|
||||
maria.RunFrame();
|
||||
|
||||
if (_islag)
|
||||
{
|
||||
_lagcount++;
|
||||
}
|
||||
|
||||
// read the controller state here for now
|
||||
GetControllerState(controller);
|
||||
|
||||
maria.RunFrame();
|
||||
}
|
||||
|
||||
public void RunCPUCycle()
|
||||
|
@ -67,7 +77,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
if (cpu_cycle <= (2 + (slow_access ? 1 : 0)))
|
||||
{
|
||||
cpu_is_haltable = true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_is_haltable = false;
|
||||
}
|
||||
|
@ -127,13 +138,42 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
}
|
||||
|
||||
private void GetControllerState(IController controller)
|
||||
public byte GetControllerState(IController controller, int index)
|
||||
{
|
||||
InputCallbacks.Call();
|
||||
|
||||
ushort port1 = _controllerDeck.ReadPort1(controller);
|
||||
if (index == 1)
|
||||
return _controllerDeck.ReadPort1(controller);
|
||||
else
|
||||
return _controllerDeck.ReadPort2(controller);
|
||||
}
|
||||
|
||||
ushort port2 = _controllerDeck.ReadPort2(controller);
|
||||
public byte GetConsoleState(IController controller)
|
||||
{
|
||||
byte result = 0;
|
||||
|
||||
if (controller.IsPressed("Right Difficulty"))
|
||||
{
|
||||
result |= (1 << 7);
|
||||
}
|
||||
if (controller.IsPressed("Left Difficulty"))
|
||||
{
|
||||
result |= (1 << 6);
|
||||
}
|
||||
if (!controller.IsPressed("Pause"))
|
||||
{
|
||||
result |= (1 << 3);
|
||||
}
|
||||
if (!controller.IsPressed("Select"))
|
||||
{
|
||||
result |= (1 << 1);
|
||||
}
|
||||
if (!controller.IsPressed("Reset"))
|
||||
{
|
||||
result |= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int Frame => _frame;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
|
||||
|
||||
private bool _islag = true;
|
||||
public bool _islag = true;
|
||||
private int _lagcount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
(addr, value) => Maria_regs[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"6532 Registers",
|
||||
regs_6532.Length,
|
||||
"6532 RAM",
|
||||
RAM_6532.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => regs_6532[addr],
|
||||
(addr, value) => regs_6532[addr] = value,
|
||||
addr => RAM_6532[addr],
|
||||
(addr, value) => RAM_6532[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Ram Block 0",
|
||||
|
|
|
@ -59,23 +59,23 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
ser.Sync("IsLag", ref _islag);
|
||||
_controllerDeck.SyncState(ser);
|
||||
|
||||
ser.Sync("IsLag", ref A7800_control_register);
|
||||
ser.Sync("IsLag", ref _isPAL);
|
||||
ser.Sync("A7800_control_register", ref A7800_control_register);
|
||||
ser.Sync("_isPAL", ref _isPAL);
|
||||
|
||||
ser.Sync("IsLag", ref TIA_regs, false);
|
||||
ser.Sync("IsLag", ref Maria_regs, false);
|
||||
ser.Sync("IsLag", ref RAM, false);
|
||||
ser.Sync("IsLag", ref regs_6532, false);
|
||||
ser.Sync("IsLag", ref hs_bios_mem, false);
|
||||
ser.Sync("TIA_regs", ref TIA_regs, false);
|
||||
ser.Sync("Maria_regs", ref Maria_regs, false);
|
||||
ser.Sync("RAM", ref RAM, false);
|
||||
ser.Sync("RAM_6532", ref RAM_6532, false);
|
||||
ser.Sync("hs_bios_mem", ref hs_bios_mem, false);
|
||||
|
||||
ser.Sync("IsLag", ref cycle);
|
||||
ser.Sync("IsLag", ref cpu_cycle);
|
||||
ser.Sync("IsLag", ref cpu_is_haltable);
|
||||
ser.Sync("IsLag", ref cpu_is_halted);
|
||||
ser.Sync("IsLag", ref cpu_halt_pending);
|
||||
ser.Sync("IsLag", ref cpu_resume_pending);
|
||||
ser.Sync("cycle", ref cycle);
|
||||
ser.Sync("cpu_cycle", ref cpu_cycle);
|
||||
ser.Sync("cpu_is_haltable", ref cpu_is_haltable);
|
||||
ser.Sync("cpu_is_halted", ref cpu_is_halted);
|
||||
ser.Sync("cpu_halt_pending", ref cpu_halt_pending);
|
||||
ser.Sync("cpu_resume_pending", ref cpu_resume_pending);
|
||||
|
||||
ser.Sync("IsLag", ref slow_access);
|
||||
ser.Sync("slow_access", ref slow_access);
|
||||
|
||||
|
||||
ser.EndSection();
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
public byte[] TIA_regs = new byte[0x20];
|
||||
public byte[] Maria_regs = new byte[0x20];
|
||||
public byte[] RAM = new byte[0x1000];
|
||||
public byte[] regs_6532 = new byte[0x80];
|
||||
public byte[] RAM_6532 = new byte[0x80];
|
||||
public byte[] hs_bios_mem = new byte[0x800];
|
||||
|
||||
public readonly byte[] _rom;
|
||||
|
@ -52,6 +52,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
maria = new Maria();
|
||||
tia = new TIA();
|
||||
m6532 = new M6532();
|
||||
|
||||
cpu = new MOS6502X
|
||||
{
|
||||
ReadMemory = ReadMemory,
|
||||
|
@ -140,6 +142,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
|
||||
maria.Core = this;
|
||||
m6532.Core = this;
|
||||
|
||||
ser.Register<IVideoProvider>(maria);
|
||||
ser.Register<ISoundProvider>(tia);
|
||||
|
@ -165,12 +168,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
cpu.SetCallbacks(ReadMemory, ReadMemory, ReadMemory, WriteMemory);
|
||||
|
||||
maria.Reset();
|
||||
m6532 = new M6532();
|
||||
|
||||
m6532.Reset();
|
||||
|
||||
TIA_regs = new byte[0x20];
|
||||
Maria_regs = new byte[0x20];
|
||||
RAM = new byte[0x1000];
|
||||
regs_6532 = new byte[0x80];
|
||||
|
||||
cpu_cycle = 0;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
"Power",
|
||||
"Reset",
|
||||
"Select",
|
||||
"BW", // should be "Color"??
|
||||
"BW",
|
||||
"Left Difficulty", // better not put P# on these as they might not correspond to player numbers
|
||||
"Right Difficulty"
|
||||
"Right Difficulty",
|
||||
"Pause"
|
||||
})
|
||||
.ToList()
|
||||
};
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
{
|
||||
byte Read(IController c);
|
||||
|
||||
byte ReadFire(IController c);
|
||||
|
||||
ControllerDefinition Definition { get; }
|
||||
|
||||
void SyncState(Serializer ser);
|
||||
|
@ -39,6 +41,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
return 0;
|
||||
}
|
||||
|
||||
public byte ReadFire(IController c)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
|
@ -67,18 +74,28 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
public byte Read(IController c)
|
||||
{
|
||||
byte result = 0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
byte result = 0xF;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (c.IsPressed(Definition.BoolButtons[i]))
|
||||
{
|
||||
result |= HandControllerButtons[i];
|
||||
result -= (byte)(1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
if (PortNum==1)
|
||||
{
|
||||
result = (byte)(result << 4);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte ReadFire(IController c)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
|
||||
|
@ -94,11 +111,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
private static byte[] HandControllerButtons =
|
||||
{
|
||||
0x60, // UP
|
||||
0xC0, // Down
|
||||
0xA0, // Left
|
||||
0x48, // Right
|
||||
0x81 // Fire
|
||||
0x0, // UP
|
||||
0x0, // Down
|
||||
0x0, // Left
|
||||
0x0, // Right
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
// Emulates the M6532 RIOT Chip
|
||||
public class M6532
|
||||
{
|
||||
|
||||
public A7800Hawk Core { get; set; }
|
||||
|
||||
private byte _ddRa = 0x00;
|
||||
private byte _ddRb = 0x00;
|
||||
private byte _outputA = 0x00;
|
||||
|
@ -13,7 +16,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
public M6532()
|
||||
{
|
||||
|
||||
// arbitrary value to start with.
|
||||
Timer.Value = 0x73;
|
||||
Timer.PrescalerShift = 10;
|
||||
|
@ -31,10 +33,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
var registerAddr = (ushort)(addr & 0x0007);
|
||||
if (registerAddr == 0x00)
|
||||
{
|
||||
Core._islag = false;
|
||||
|
||||
// Read Output reg A
|
||||
// Combine readings from player 1 and player 2
|
||||
// actually depends on setting in SWCHCNTA (aka DDRa)
|
||||
byte temp = 0;// (byte)(_core.ReadControls1(peek) & 0xF0 | ((_core.ReadControls2(peek) >> 4) & 0x0F));
|
||||
byte temp = (byte)(Core.p1_state | Core.p2_state);
|
||||
temp = (byte)(temp & ~_ddRa);
|
||||
temp = (byte)(temp + (_outputA & _ddRa));
|
||||
return temp;
|
||||
|
@ -49,7 +53,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
if (registerAddr == 0x02)
|
||||
{
|
||||
// Read Output reg B
|
||||
byte temp = 0;// _core.ReadConsoleSwitches(peek);
|
||||
byte temp = Core.con_state;
|
||||
temp = (byte)(temp & ~_ddRb);
|
||||
return temp;
|
||||
}
|
||||
|
@ -173,6 +177,18 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// arbitrary value to start with.
|
||||
Timer.Value = 0x73;
|
||||
Timer.PrescalerShift = 10;
|
||||
Timer.PrescalerCount = 1 << Timer.PrescalerShift;
|
||||
|
||||
_ddRa = 0x00;
|
||||
_ddRb = 0x00;
|
||||
_outputA = 0x00;
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("M6532");
|
||||
|
|
|
@ -165,6 +165,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
Core.Maria_regs[8] = 0; // we have now left VBLank
|
||||
base_scanline = 0;
|
||||
sl_DMA_complete = false;
|
||||
Core.cpu.RDY = true;
|
||||
|
||||
// Now proceed with the remaining scanlines
|
||||
// the first one is a pre-render line, since we didn't actually put any data into the buffer yet
|
||||
|
@ -214,7 +215,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
// add the current graphics to the buffer
|
||||
draw_scanline(scanline - 21);
|
||||
}
|
||||
|
||||
//Console.Write("Scanline");
|
||||
//Console.WriteLine(scanline - 21);
|
||||
scanline++;
|
||||
cycle = 0;
|
||||
Core.tia._hsyncCnt = 0;
|
||||
|
@ -267,7 +269,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
// or at the end of this list
|
||||
if ((temp & 0x1F) == 0)
|
||||
{
|
||||
if ((temp & 0xE0) == 0)
|
||||
if (!temp.Bit(6))
|
||||
{
|
||||
// at the end of the list, time to end the DMA
|
||||
// check if we are at the end of the zone
|
||||
|
@ -290,10 +292,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
GFX_Objects[header_counter].ind_mode = temp.Bit(5);
|
||||
header_pointer++;
|
||||
temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer)));
|
||||
GFX_Objects[header_counter].addr |= (ushort)((temp + current_DLL_offset)<< 8);
|
||||
GFX_Objects[header_counter].addr |= (ushort)((temp/* + current_DLL_offset*/)<< 8);
|
||||
header_pointer++;
|
||||
temp = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me)
|
||||
|
||||
if (temp_w == 0)
|
||||
{
|
||||
// important note here. In 5 byte mode, width 0 actually counts as 32
|
||||
|
@ -360,6 +363,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
// in 5 byte mode, we first have to check if we are in direct or indirect mode
|
||||
if (GFX_Objects[header_counter].ind_mode)
|
||||
{
|
||||
//Console.Write(" Indirect graphics");
|
||||
|
||||
int ch_size = 0;
|
||||
|
||||
if (Core.Maria_regs[0x1C].Bit(4))
|
||||
|
@ -374,7 +379,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
|
||||
// the address here is specified by CHAR_BASE maria registers
|
||||
ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF);
|
||||
//ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF);
|
||||
ushort addr = (ushort)(ReadMemory(GFX_Objects[header_counter].addr));
|
||||
addr |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8);
|
||||
|
||||
for (int i = 0; i < GFX_Objects[header_counter].width; i ++)
|
||||
|
@ -398,7 +404,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
// do direct reads same as in 4 byte mode
|
||||
for (int i = 0; i < GFX_Objects[header_counter].width; i++)
|
||||
{
|
||||
GFX_Objects[header_counter].obj[i] = ReadMemory((ushort)(GFX_Objects[header_counter].addr + i));
|
||||
GFX_Objects[header_counter].obj[i] = ReadMemory((ushort)((GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,6 +451,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
display_zone_counter++;
|
||||
ushort temp_addr = (ushort)(display_zone_pointer + 3 * display_zone_counter);
|
||||
byte temp = ReadMemory(temp_addr);
|
||||
|
||||
current_DLL_addr = (ushort)(ReadMemory((ushort)(temp_addr + 1)) << 8);
|
||||
current_DLL_addr |= ReadMemory((ushort)(temp_addr + 2));
|
||||
|
||||
|
@ -469,85 +476,133 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
int local_palette;
|
||||
int index;
|
||||
int color;
|
||||
int obj_index;
|
||||
int counter;
|
||||
|
||||
int disp_mode = Core.Maria_regs[0x1C] & 0x3;
|
||||
|
||||
scanline_buffer = new int[320];
|
||||
int temp_bg = Core.Maria_regs[0];
|
||||
|
||||
if (disp_mode == 0)
|
||||
|
||||
for (int i = 0; i < 320; i++)
|
||||
{
|
||||
for (int i = 0; i < header_counter_max; i++)
|
||||
scanline_buffer[i] = _palette[temp_bg];
|
||||
}
|
||||
|
||||
for (int i = 0; i < header_counter_max; i++)
|
||||
{
|
||||
local_start = GFX_Objects[i].h_pos;
|
||||
local_palette = GFX_Objects[i].palette;
|
||||
|
||||
// the two different rendering paths are basically controlled by write mode
|
||||
if (GFX_Objects[i].write_mode)
|
||||
{
|
||||
local_start = GFX_Objects[i].h_pos;
|
||||
local_width = GFX_Objects[i].width * 4;
|
||||
local_palette = GFX_Objects[i].palette;
|
||||
|
||||
counter = 3;
|
||||
obj_index = 0;
|
||||
for (int j = local_start; j < local_start + local_width; j++)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disp_mode == 0)
|
||||
{
|
||||
index = j;
|
||||
if (index > 255) index -= 256;
|
||||
if (index < 160)
|
||||
local_width = GFX_Objects[i].width;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
color = GFX_Objects[i].obj[obj_index];
|
||||
color = (color >> (counter * 2)) & 0x3; // this is now the color index (0-3) we choose from the palette
|
||||
|
||||
if (color != 0) // transparent
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + color];
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
|
||||
// the top 4 bits from this are the color, the bottom 4 are the luminosity
|
||||
// this is already conveniently arranged in the palette
|
||||
scanline_buffer[index * 2] = _palette[color];
|
||||
scanline_buffer[index * 2 + 1] = _palette[color];
|
||||
if (index > 511) index -= 512;
|
||||
if (index < 320)
|
||||
{
|
||||
color = GFX_Objects[i].obj[j];
|
||||
|
||||
// this is now the color index (0-3) we choose from the palette
|
||||
if (k>=6)
|
||||
{
|
||||
color = (color >> 6) & 0x3;
|
||||
|
||||
}
|
||||
else if (k>=4)
|
||||
{
|
||||
color = (color >> 4) & 0x3;
|
||||
|
||||
}
|
||||
else if (k>=2)
|
||||
{
|
||||
color = (color >> 2) & 0x3;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = color & 0x3;
|
||||
}
|
||||
|
||||
if (color != 0) // transparent
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + color];
|
||||
|
||||
// the top 4 bits from this are the color, the bottom 4 are the luminosity
|
||||
// this is already conveniently arranged in the palette
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (disp_mode == 2) // note: 1 is not used
|
||||
{
|
||||
local_width = GFX_Objects[i].width;
|
||||
// here the palette is determined by palette bit 2 only
|
||||
// hence only palette 0 or 4 is available
|
||||
local_palette = GFX_Objects[i].palette & 0x4;
|
||||
|
||||
int temp_c0 = GFX_Objects[i].palette & 0x1;
|
||||
int temp_c1 = GFX_Objects[i].palette & 0x2;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = (GFX_Objects[i].obj[j] >> k) & 1;
|
||||
color = (color << 1) | ((k % 2 == 0) ? temp_c0 : temp_c1);
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
if (index > 511) index -= 512;
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
|
||||
color = Core.Maria_regs[local_palette + color];
|
||||
|
||||
// the top 4 bits from this are the color, the bottom 4 are the luminosity
|
||||
// this is already conveniently arranged in the palette
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
counter--;
|
||||
if (counter == -1)
|
||||
{
|
||||
counter = 3;
|
||||
obj_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (disp_mode==2) // note 1 is not used
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < header_counter_max; i++)
|
||||
{
|
||||
local_start = GFX_Objects[i].h_pos;
|
||||
local_width = GFX_Objects[i].width;
|
||||
local_palette = GFX_Objects[i].palette;
|
||||
|
||||
counter = 3;
|
||||
obj_index = 0;
|
||||
for (int j = 0; j < local_width; j++)
|
||||
else
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = (GFX_Objects[i].obj[j] >> k) & 1;
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
if (index > 511) index -= 512;
|
||||
if (index < 320 && color == 1)
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + 2]; // automatically use index 2 here
|
||||
local_width = GFX_Objects[i].width;
|
||||
|
||||
// the top 4 bits from this are the color, the bottom 4 are the luminosity
|
||||
// this is already conveniently arranged in the palette
|
||||
scanline_buffer[index] = _palette[color];
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = (GFX_Objects[i].obj[j] >> k) & 1;
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
if (index > 511) index -= 512;
|
||||
if (index < 320 && color == 1)
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + 2]; // automatically use index 2 here
|
||||
|
||||
// the top 4 bits from this are the color, the bottom 4 are the luminosity
|
||||
// this is already conveniently arranged in the palette
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// send buffer to the video buffer
|
||||
for (int i = 0; i < 320; i ++)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,20 @@
|
|||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
// X = don't care
|
||||
/*
|
||||
1. TIA 0000 00XX 0000 0000 - 0000 00XX 0001 1111
|
||||
2. MARIA 0000 00XX 0010 0000 - 0000 00XX 0011 1111
|
||||
3. 6532 0000 0010 1000 0000 - 0000 0010 1111 1111
|
||||
PORTS
|
||||
4. 6532 0000 010X 1000 0000 - 0000 010X 1111 1111
|
||||
RAM(DON'T USE)
|
||||
5. RAM 0001 1000 0000 0000 - 0010 0111 1111 1111
|
||||
6. RAM 00X0 000A 0100 0000 - 00X0 000A 1111 1111
|
||||
SHADOW
|
||||
7. RAM 001X X000 0000 0000 - 001X X111 1111 1111
|
||||
*/
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||
{
|
||||
public partial class A7800Hawk
|
||||
|
@ -11,76 +25,71 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
{
|
||||
MemoryCallbacks.CallReads(addr);
|
||||
|
||||
if (addr < 0x0400) {
|
||||
if ((addr & 0xFF) < 0x20)
|
||||
if ((addr & 0xFCE0) == 0)
|
||||
{
|
||||
// return TIA registers or control register if it is still unlocked
|
||||
if ((A7800_control_register & 0x1) == 0)
|
||||
{
|
||||
// return TIA registers or control register if it is still unlocked
|
||||
if ((A7800_control_register & 0x1) == 0 && (addr < 0x20))
|
||||
{
|
||||
return 0xFF; // TODO: what to return here?
|
||||
}
|
||||
else
|
||||
{
|
||||
return TIA_regs[addr & 0x1F]; // TODO: what to return here?
|
||||
}
|
||||
}
|
||||
else if ((addr & 0xFF) < 0x40)
|
||||
{
|
||||
if ((A7800_control_register & 0x2) > 0)
|
||||
{
|
||||
return Maria_regs[(addr & 0x3F) - 0x20];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
else if (addr < 0x100)
|
||||
{
|
||||
// RAM block 0
|
||||
return RAM[addr - 0x40 + 0x840];
|
||||
}
|
||||
else if (addr < 0x200)
|
||||
{
|
||||
// RAM block 1
|
||||
return RAM[addr - 0x140 + 0x940];
|
||||
}
|
||||
else if (addr < 0x300)
|
||||
{
|
||||
if (addr > 0x280)
|
||||
return regs_6532[addr - 0x280];
|
||||
else
|
||||
return 0xFF; // unclear what is mapped from 0x240 - 0x280
|
||||
return 0xFF; // TODO: what to return here?
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF; // what is mapped here?
|
||||
return TIA_regs[addr & 0x1F]; // TODO: what to return here?
|
||||
}
|
||||
}
|
||||
else if (addr < 0x480)
|
||||
else if ((addr & 0xFCE0) == 0x20)
|
||||
{
|
||||
// cartridge space available
|
||||
return mapper.ReadMemory(addr);
|
||||
if ((A7800_control_register & 0x2) > 0)
|
||||
{
|
||||
return Maria_regs[addr & 0x1F];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF; // TODO: What if Maria is off?
|
||||
}
|
||||
}
|
||||
else if (addr < 0x500)
|
||||
else if ((addr & 0xFF80) == 0x280)
|
||||
{
|
||||
// this is where RAM for the 6532 resides for use in 2600 mode
|
||||
return 0xFF;
|
||||
//return regs_6532[addr & 0x1F];
|
||||
return m6532.ReadMemory(addr, false);
|
||||
}
|
||||
else if (addr < 0x1800)
|
||||
else if ((addr & 0xFE80) == 0x480)
|
||||
{
|
||||
// cartridge space available
|
||||
return mapper.ReadMemory(addr);
|
||||
return RAM_6532[addr & 0x7F];
|
||||
}
|
||||
else if (addr < 0x2800)
|
||||
else if ((addr >= 0x1800) && (addr < 0x2800))
|
||||
{
|
||||
return RAM[addr - 0x1800];
|
||||
return RAM[addr -0x1800];
|
||||
}
|
||||
else if (addr < 0x4000)
|
||||
else if ((addr >= 0x40) && (addr < 0x100))
|
||||
{
|
||||
// RAM block 0
|
||||
return RAM[addr - 0x40 + 0x840];
|
||||
}
|
||||
else if ((addr >= 0x140) && (addr < 0x200))
|
||||
{
|
||||
// RAM block 1
|
||||
return RAM[addr - 0x140 + 0x940];
|
||||
}
|
||||
else if ((addr >= 0x2800) && (addr < 0x3000))
|
||||
{
|
||||
return RAM[(addr & 0x7FF) + 0x800];
|
||||
}
|
||||
else if ((addr >= 0x3000) && (addr < 0x4000))
|
||||
{
|
||||
// could be either RAM mirror or ROM
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
else if ((addr >= 0x400) && (addr < 0x480))
|
||||
{
|
||||
// cartridge space available
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
else if ((addr >= 0x500) && (addr < 0x1800))
|
||||
{
|
||||
// cartridge space available
|
||||
return mapper.ReadMemory(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.ReadMemory(addr);
|
||||
|
@ -91,96 +100,82 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
{
|
||||
MemoryCallbacks.CallWrites(addr);
|
||||
|
||||
if (addr < 0x0400)
|
||||
if ((addr & 0xFCE0) == 0)
|
||||
{
|
||||
if ((addr & 0xFF) < 0x20)
|
||||
// return TIA registers or control register if it is still unlocked
|
||||
if ((A7800_control_register & 0x1) == 0)
|
||||
{
|
||||
// return TIA registers or control register if it is still unlocked
|
||||
if ((A7800_control_register & 0x1) == 0 && (addr < 0x20))
|
||||
{
|
||||
A7800_control_register = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIA_regs[addr & 0x1F] = value;
|
||||
tia.WriteMemory((ushort)(addr & 0x1F), value, false);
|
||||
}
|
||||
}
|
||||
else if ((addr & 0xFF) < 0x40)
|
||||
{
|
||||
if ((A7800_control_register & 0x2) > 0)
|
||||
{
|
||||
var temp = (addr & 0x3F) - 0x20;
|
||||
|
||||
// register 8 is read only and controlled by Maria
|
||||
if (temp != 8)
|
||||
Maria_regs[temp] = value;
|
||||
|
||||
if (temp==4) // WSYNC
|
||||
cpu.RDY = false;
|
||||
/*
|
||||
Console.WriteLine("Maria Regs: ");
|
||||
|
||||
for (int i = 0; i < 0x20; i++)
|
||||
{
|
||||
Console.Write(Maria_regs[i]);
|
||||
Console.Write(" ");
|
||||
}
|
||||
Console.WriteLine(" ");
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if (addr < 0x100)
|
||||
{
|
||||
// RAM block 0
|
||||
RAM[addr - 0x40 + 0x840] = value;
|
||||
}
|
||||
else if (addr < 0x200)
|
||||
{
|
||||
// RAM block 1
|
||||
RAM[addr - 0x140 + 0x940] = value;
|
||||
}
|
||||
else if (addr < 0x300)
|
||||
{
|
||||
if (addr > 0x280)
|
||||
regs_6532[addr - 0x280] = value;
|
||||
A7800_control_register = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// what is mapped here?
|
||||
TIA_regs[addr & 0x1F] = value;
|
||||
tia.WriteMemory((ushort)(addr & 0x1F), value, false);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x480)
|
||||
else if ((addr & 0xFCE0) == 0x20)
|
||||
{
|
||||
// cartridge space available
|
||||
mapper.WriteMemory(addr, value);
|
||||
if ((A7800_control_register & 0x2) > 0)
|
||||
{
|
||||
// register 8 is read only and controlled by Maria
|
||||
var temp = addr & 0x1F;
|
||||
if (temp != 8)
|
||||
Maria_regs[temp] = value;
|
||||
|
||||
if (temp == 4) // WSYNC
|
||||
cpu.RDY = false;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: What if Maria is off?
|
||||
}
|
||||
}
|
||||
else if (addr < 0x500)
|
||||
else if ((addr & 0xFF80) == 0x280)
|
||||
{
|
||||
// this is where RAM for the 6532 resides for use in 2600 mode
|
||||
// is it accessible in 7800 mode?
|
||||
m6532.WriteMemory(addr, value);
|
||||
}
|
||||
else if (addr < 0x1800)
|
||||
else if ((addr & 0xFE80) == 0x480)
|
||||
{
|
||||
// cartridge space available
|
||||
mapper.WriteMemory(addr, value);
|
||||
RAM_6532[addr & 0x7F] = value;
|
||||
}
|
||||
else if (addr < 0x2800)
|
||||
else if ((addr >= 0x1800) && (addr < 0x2800))
|
||||
{
|
||||
RAM[addr - 0x1800] = value;
|
||||
}
|
||||
else if (addr < 0x4000)
|
||||
else if ((addr >= 0x40) && (addr < 0x100))
|
||||
{
|
||||
// RAM block 0
|
||||
RAM[addr - 0x40 + 0x840] = value;
|
||||
}
|
||||
else if ((addr >= 0x140) && (addr < 0x200))
|
||||
{
|
||||
// RAM block 1
|
||||
RAM[addr - 0x140 + 0x940] = value;
|
||||
}
|
||||
else if ((addr >= 0x2800) && (addr < 0x3000))
|
||||
{
|
||||
RAM[(addr & 0x7FF) + 0x800] = value;
|
||||
}
|
||||
else if ((addr >= 0x3000) && (addr < 0x4000))
|
||||
{
|
||||
// could be either RAM mirror or ROM
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
else if ((addr >= 0x400) && (addr < 0x480))
|
||||
{
|
||||
// cartridge space available
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
else if ((addr >= 0x500) && (addr < 0x1800))
|
||||
{
|
||||
// cartridge space available
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// cartridge and other OPSYS
|
||||
mapper.WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue