From af39f65b035104c12ebcef4d620a72422bfd9f80 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 23 Nov 2018 10:20:52 -0600 Subject: [PATCH] A7800: cycle based DMA list fetching --- .../Consoles/Atari/A7800Hawk/Maria.cs | 168 +++++++++++------- 1 file changed, 104 insertions(+), 64 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs index de709e0aaf..c7dc7de1e1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -71,6 +71,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public int header_counter; public int header_pointer; // since headers could be 4 or 5 bytes, we need a seperate pointer + public ushort addr_t; + public int ch_size; + public int scan_index; + public int read_time; + public bool zero_hole; // the first DMA hole does not save cycles // variables for drawing a pixel int color; @@ -186,9 +191,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } } - if (cycle == 428 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER)) + if (cycle == 453 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER)) { - //Console.WriteLine(scanline); if (current_DLL_offset == 0) { DMA_phase = DMA_SHUTDOWN_LAST; @@ -215,9 +219,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk if (cycle == 133) { disp_mode = Core.Maria_regs[0x1C] & 0x3; - BG_latch_1 = Core.Maria_regs[0]; - } + BG_latch_1 = Core.Maria_regs[0]; + + color = line_ram[local_GFX_index, pixel]; @@ -434,101 +439,136 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { if (DMA_phase_counter == 1) { - ushort addr_t = 0; + addr_t = 0; + scan_index = 0; + read_time = 0; + zero_hole = false; // in 5 byte mode, we first have to check if we are in direct or indirect mode if (GFX_Objects[header_counter].ind_mode) { - int ch_size = 0; + ch_size = 0; if (Core.Maria_regs[0x1C].Bit(4)) { - graphics_read_time = 9 * GFX_Objects[header_counter].width; + graphics_read_time = 9; ch_size = 2; } else { - graphics_read_time = 6 * GFX_Objects[header_counter].width; + graphics_read_time = 6; ch_size = 1; } - - // the address here is specified by CHAR_BASE maria registers - // ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF); - for (int i = 0; i < GFX_Objects[header_counter].width; i++) - { - addr_t = ReadMemory((ushort)(GFX_Objects[header_counter].addr + i)); - addr_t |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8); - - if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000)) - { - if (i * ch_size < 128) - { - GFX_Objects[header_counter].obj[i * ch_size] = 0; - } - if ((i * ch_size + 1 < 128) && (ch_size == 2)) - { - GFX_Objects[header_counter].obj[i * ch_size + 1] = 0; - } - if (i != 0) - { - if (ch_size == 1) - { - graphics_read_time -= 6; - } - else - { - graphics_read_time -= 9; - } - } - - } - else - { - if (i * ch_size < 128) - { - GFX_Objects[header_counter].obj[i * ch_size] = ReadMemory(addr_t); - fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, ch_size, GFX_Objects[header_counter].obj[i * ch_size], GFX_Objects[header_counter].write_mode); - } - if (((i * ch_size + 1) < 128) && (ch_size == 2)) - { - GFX_Objects[header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1)); - fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 1, ch_size, GFX_Objects[header_counter].obj[i * ch_size + 1], GFX_Objects[header_counter].write_mode); - } - } - } } else { - graphics_read_time = 3 * GFX_Objects[header_counter].width; + graphics_read_time = 3; + } - for (int i = 0; i < GFX_Objects[header_counter].width; i++) + if (graphics_read_time == 0) + { + // We have read the graphics data, for this header, now return to the header list + // This loop will continue until a header indicates its time to stop + DMA_phase = DMA_HEADER; + DMA_phase_counter = 0; + return; + } + } + + if (read_time == 0) + { + bool skip = true; + + while (skip) + { + if (GFX_Objects[header_counter].ind_mode) { - addr_t = (ushort)(GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + i); + addr_t = ReadMemory((ushort)(GFX_Objects[header_counter].addr + scan_index)); + addr_t |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8); + } + else + { + addr_t = (ushort)(GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + scan_index); + } - if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000)) + if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000)) + { + if (GFX_Objects[header_counter].ind_mode) { - GFX_Objects[header_counter].obj[i] = 0; - if (i != 0) - { - graphics_read_time -= 3; + if (scan_index * ch_size < 128) + { + GFX_Objects[header_counter].obj[scan_index * ch_size] = 0; + } + if ((scan_index * ch_size + 1 < 128) && (ch_size == 2)) + { + GFX_Objects[header_counter].obj[scan_index * ch_size + 1] = 0; } } else { - GFX_Objects[header_counter].obj[i] = ReadMemory(addr_t); - fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, 1, GFX_Objects[header_counter].obj[i], GFX_Objects[header_counter].write_mode); + GFX_Objects[header_counter].obj[scan_index] = 0; } + + if (scan_index == 0) + { + skip = false; + zero_hole = true; + } + else + { + scan_index++; + if (scan_index == GFX_Objects[header_counter].width) + { + skip = false; + } + } + } + else + { + skip = false; } } } - if (DMA_phase_counter == graphics_read_time || graphics_read_time == 0) + read_time++; + if (read_time == graphics_read_time) + { + if (!zero_hole) + { + // in 5 byte mode, we first have to check if we are in direct or indirect mode + if (GFX_Objects[header_counter].ind_mode) + { + if (scan_index * ch_size < 128) + { + GFX_Objects[header_counter].obj[scan_index * ch_size] = ReadMemory(addr_t); + fill_line_ram(GFX_Objects[header_counter].h_pos * 2, scan_index, 0, ch_size, GFX_Objects[header_counter].obj[scan_index * ch_size], GFX_Objects[header_counter].write_mode); + } + if (((scan_index * ch_size + 1) < 128) && (ch_size == 2)) + { + GFX_Objects[header_counter].obj[scan_index * ch_size + 1] = ReadMemory((ushort)(addr_t + 1)); + fill_line_ram(GFX_Objects[header_counter].h_pos * 2, scan_index, 1, ch_size, GFX_Objects[header_counter].obj[scan_index * ch_size + 1], GFX_Objects[header_counter].write_mode); + } + } + else + { + GFX_Objects[header_counter].obj[scan_index] = ReadMemory(addr_t); + fill_line_ram(GFX_Objects[header_counter].h_pos * 2, scan_index, 0, 1, GFX_Objects[header_counter].obj[scan_index], GFX_Objects[header_counter].write_mode); + } + } + + zero_hole = false; + scan_index++; + read_time = 0; + } + + if (scan_index == GFX_Objects[header_counter].width) { // We have read the graphics data, for this header, now return to the header list // This loop will continue until a header indicates its time to stop DMA_phase = DMA_HEADER; DMA_phase_counter = 0; } + return; }