From 170381597b30f4db8c76f79e93ccb0ef3b538cbf Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 5 Jul 2017 16:14:27 -0400 Subject: [PATCH] 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. --- .../Atari/A7800Hawk/A7800Hawk.IEmulator.cs | 58 ++++- .../A7800Hawk/A7800Hawk.IInputPollable.cs | 2 +- .../A7800Hawk/A7800Hawk.IMemoryDomains.cs | 8 +- .../Atari/A7800Hawk/A7800Hawk.IStatable.cs | 28 +-- .../Consoles/Atari/A7800Hawk/A7800Hawk.cs | 10 +- .../A7800Hawk/A7800HawkControllerDeck.cs | 5 +- .../Atari/A7800Hawk/A7800HawkControllers.cs | 32 ++- .../Consoles/Atari/A7800Hawk/M6532.cs | 22 +- .../Consoles/Atari/A7800Hawk/Maria.cs | 179 +++++++++----- .../Consoles/Atari/A7800Hawk/MemoryMap.cs | 231 +++++++++--------- 10 files changed, 350 insertions(+), 225 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs index 6e1ceae60d..57813916ae 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -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; diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs index f2c5b97360..349ab3b549 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs @@ -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; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs index 5090e1f139..cdda3798f3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs @@ -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", diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs index d3dc977e6f..6c5b9f7dbc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs @@ -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(); diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs index a34a2151fd..d36f29c318 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -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(maria); ser.Register(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; } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs index 131ab32082..8bbb8d9e21 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs @@ -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() }; diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs index 72ca92171d..a902de8ccd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs @@ -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 }; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs index 58a54af72f..74a5209996 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs @@ -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"); diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs index 8b906345c5..635dc41561 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -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 ++) { diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs index ff9886ba07..902a35c041 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs @@ -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); } } - - } }