From 614497a4e1aac62a49dd3525381bf2bb641dd6fd Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Sat, 12 Apr 2025 11:55:12 -0500 Subject: [PATCH 1/8] Implemented scaling down in line mode, fixed a faulty slope accumulator latency workaround, count now draws the right number of pixels in both line copy and fill. --- src/vhdl/gs4510.vhdl | 100 +++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index a09f00ca9..00daf0eac 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -4064,6 +4064,14 @@ begin variable line_y_move : std_logic := '0'; variable line_y_move_negative : std_logic := '0'; + -- Skip accumulators for line scaling. DMAgic adds + -- the source/destination skip value to these in line mode + -- in order to not perform line calculations on some + -- cycles. This allows for scaling the source and destination + -- lines down by an arbitrary amount. + variable line_skip_accumulator : unsigned(15 downto 0) := x"0100"; + variable line_source_skip_accumulator : unsigned(15 downto 0) := x"0100"; + variable add_result : unsigned(11 downto 0); -- has NVZC flags and result begin @@ -5756,6 +5764,10 @@ begin end if; dmagic_list_counter <= 0; phi_add_backlog <= '1'; phi_new_backlog <= 1; + + -- Reset the line scaling accumulators + line_skip_accumulator := x"0100"; + line_source_skip_accumulator := x"0100"; when DMAgicReadOptions => reg_dmagic_addr <= reg_dmagic_addr + 1; @@ -5807,7 +5819,7 @@ begin when x"8d" => reg_dmagic_slope_fraction_start(7 downto 0) <= memory_read_value; when x"8e" => reg_dmagic_slope_fraction_start(15 downto 8) <= memory_read_value; when x"8f" => reg_dmagic_line_mode <= memory_read_value(7); - reg_dmagic_line_mode_skip_pixels <= (others => memory_read_value(7)); + reg_dmagic_line_mode_skip_pixels <= memory_read_value(7) & '0'; reg_dmagic_line_x_or_y <= memory_read_value(6); reg_dmagic_line_slope_negative <= memory_read_value(5); -- @ IO:GS $D705 - Enhanced DMAgic job option $90 $xx = Set bits 16 -- 23 of DMA length to allow DMA operations >64KB. @@ -5823,7 +5835,7 @@ begin when x"9d" => reg_dmagic_s_slope_fraction_start(7 downto 0) <= memory_read_value; when x"9e" => reg_dmagic_s_slope_fraction_start(15 downto 8) <= memory_read_value; when x"9f" => reg_dmagic_s_line_mode <= memory_read_value(7); - reg_dmagic_s_line_mode_skip_pixels <= (others => memory_read_value(7)); + reg_dmagic_s_line_mode_skip_pixels <= memory_read_value(7) & '0'; reg_dmagic_s_line_x_or_y <= memory_read_value(6); reg_dmagic_s_line_slope_negative <= memory_read_value(5); @@ -5962,6 +5974,11 @@ begin -- And set IO visibility based on destination bank flags -- since we are only writing. cpuport_value(0) <= dmagic_dest_bank_temp(7); + + -- When destination line mode is set, skip the first counter decrement cycle. + -- Since line mode skips the first cycle to allow for slope accumulator + -- latency, the counter is decremented one too many times. + dmagic_first_read <= reg_dmagic_line_mode; when "00" => -- copy dmagic_first_read <= '1'; @@ -6051,8 +6068,15 @@ begin else -- We are in line mode. + if reg_dmagic_line_mode_skip_pixels="00" then + line_skip_accumulator := line_skip_accumulator + reg_dmagic_dst_skip; + end if; + -- Add fractional position - reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; + if line_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_line_mode_skip_pixels /= "11" then + reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; + end if; + -- Check if we have accumulated a whole pixel of movement? line_x_move := '0'; line_x_move_negative := '0'; @@ -6075,10 +6099,13 @@ begin -- pixel. The first pixel will thus effectively be written to -- twice. if reg_dmagic_line_mode_skip_pixels="00" then - if reg_dmagic_line_x_or_y='0' then - line_x_move := '1'; - else - line_y_move := '1'; + if line_skip_accumulator(15 downto 8) /= x"00" then + if reg_dmagic_line_x_or_y='0' then + line_x_move := '1'; + else + line_y_move := '1'; + end if; + line_skip_accumulator := x"00" & line_skip_accumulator(7 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then @@ -6223,7 +6250,12 @@ begin state <= DMAgicTrigger; end if; else - dmagic_count <= dmagic_count - 1; + -- Skip the first decrement in line mode. + if dmagic_first_read = '0' then + dmagic_count <= dmagic_count - 1; + else + dmagic_first_read <= '0'; + end if; if pending_dma_busy='1' then state <= DMAgicFillPauseForAudioDMA; @@ -6259,7 +6291,6 @@ begin -- and can read or write on every cycle. -- so we need to read the first byte now. - reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels(0) & "0"; reg_dmagic_s_line_mode_skip_pixels <= reg_dmagic_s_line_mode_skip_pixels(0) & "0"; -- Do memory read @@ -6274,8 +6305,15 @@ begin if reg_dmagic_s_line_mode='1' then -- We are in line mode. - -- Add fractional position - reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; + if reg_dmagic_s_line_mode_skip_pixels="00" then + line_source_skip_accumulator := line_source_skip_accumulator + reg_dmagic_src_skip; + end if; + + if line_source_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_s_line_mode_skip_pixels /= "11" then + -- Add fractional position + reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; + end if; + -- Check if we have accumulated a whole pixel of movement? line_x_move := '0'; line_x_move_negative := '0'; @@ -6294,10 +6332,13 @@ begin end if; -- Also move major axis (which is always in the forward direction) if reg_dmagic_s_line_mode_skip_pixels="00" then - if reg_dmagic_s_line_x_or_y='0' then - line_x_move := '1'; - else - line_y_move := '1'; + if line_source_skip_accumulator(15 downto 8) /= x"00" then + if reg_dmagic_s_line_x_or_y='0' then + line_x_move := '1'; + else + line_y_move := '1'; + end if; + line_source_skip_accumulator := x"00" & line_source_skip_accumulator(7 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then @@ -6459,12 +6500,22 @@ begin -- Update address and check for end of job. -- XXX Ignores modulus, whose behaviour is insufficiently defined -- in the C65 specifications document + + reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels(0) & "0"; + if reg_dmagic_line_mode='1' then -- Line mode with copy, so that textured lines can be drawn -- We are in line mode. + if reg_dmagic_line_mode_skip_pixels="00" then + line_skip_accumulator := line_skip_accumulator + reg_dmagic_dst_skip; + end if; + -- Add fractional position - reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; + if line_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_line_mode_skip_pixels /= "11" then + reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; + end if; + -- Check if we have accumulated a whole pixel of movement? line_x_move := '0'; line_x_move_negative := '0'; @@ -6482,11 +6533,14 @@ begin end if; end if; -- Also move major axis (which is always in the forward direction) - if reg_dmagic_line_mode_skip_pixels= "00" then - if reg_dmagic_line_x_or_y='0' then - line_x_move := '1'; - else - line_y_move := '1'; + if reg_dmagic_line_mode_skip_pixels="00" then + if line_skip_accumulator(15 downto 8) /= x"00" then + if reg_dmagic_line_x_or_y='0' then + line_x_move := '1'; + else + line_y_move := '1'; + end if; + line_skip_accumulator := x"00" & line_skip_accumulator(7 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then @@ -6640,7 +6694,9 @@ begin state <= DMAgicTrigger; end if; else - dmagic_count <= dmagic_count - 1; + if reg_dmagic_line_mode = '0' or reg_dmagic_line_mode_skip_pixels = "00" then + dmagic_count <= dmagic_count - 1; + end if; end if; end if; when DMAgicCopyPauseForAudioDMA => From 5e3bce347d297a451c6c7f8eaa0b4b53ac2811a5 Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Sat, 12 Apr 2025 15:09:42 -0500 Subject: [PATCH 2/8] Switched skip rate to 65536ths in line mode --- src/vhdl/gs4510.vhdl | 55 +++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 00daf0eac..1bed1c67b 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -4069,8 +4069,10 @@ begin -- in order to not perform line calculations on some -- cycles. This allows for scaling the source and destination -- lines down by an arbitrary amount. - variable line_skip_accumulator : unsigned(15 downto 0) := x"0100"; - variable line_source_skip_accumulator : unsigned(15 downto 0) := x"0100"; + variable line_skip_accumulator : unsigned(17 downto 0) := "01" & x"0000"; + variable line_source_skip_accumulator : unsigned(17 downto 0) := "01" & x"0000"; + variable line_dest_skip_rate_set : std_logic := '0'; + variable line_source_skip_rate_set : std_logic := '0'; variable add_result : unsigned(11 downto 0); -- has NVZC flags and result @@ -5766,8 +5768,12 @@ begin phi_add_backlog <= '1'; phi_new_backlog <= 1; -- Reset the line scaling accumulators - line_skip_accumulator := x"0100"; - line_source_skip_accumulator := x"0100"; + line_skip_accumulator := "01" & x"0000"; + line_source_skip_accumulator := "01" & x"0000"; + + -- Reset skip rate override flags. Used to reset the skip rate units in line mode. + line_dest_skip_rate_set := '0'; + line_source_skip_rate_set := '0'; when DMAgicReadOptions => reg_dmagic_addr <= reg_dmagic_addr + 1; @@ -5788,12 +5794,16 @@ begin when x"81" => reg_dmagic_dst_mb <= memory_read_value; -- @ IO:GS $D705 - Enhanced DMAgic job option $82 $xx = Set source skip rate (/256ths of bytes) when x"82" => reg_dmagic_src_skip(7 downto 0) <= memory_read_value; + line_source_skip_rate_set := '1'; -- @ IO:GS $D705 - Enhanced DMAgic job option $83 $xx = Set source skip rate (whole bytes) when x"83" => reg_dmagic_src_skip(15 downto 8) <= memory_read_value; + line_source_skip_rate_set := '1'; -- @ IO:GS $D705 - Enhanced DMAgic job option $84 $xx = Set destination skip rate (/256ths of bytes) when x"84" => reg_dmagic_dst_skip(7 downto 0) <= memory_read_value; + line_dest_skip_rate_set := '1'; -- @ IO:GS $D705 - Enhanced DMAgic job option $85 $xx = Set destination skip rate (whole bytes) when x"85" => reg_dmagic_dst_skip(15 downto 8) <= memory_read_value; + line_dest_skip_rate_set := '1'; -- @ IO:GS $D705 - Enhanced DMAgic job option $86 $xx = Don't write to destination if byte value = $xx, and option $06 enabled when x"86" => reg_dmagic_transparent_value <= memory_read_value; -- For hardware line drawing, we need to know about the @@ -6069,11 +6079,16 @@ begin -- We are in line mode. if reg_dmagic_line_mode_skip_pixels="00" then - line_skip_accumulator := line_skip_accumulator + reg_dmagic_dst_skip; + if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then + line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); + else + -- Since the skip rate isn't set, set scale to 1. + line_skip_accumulator := "01" & x"0000"; + end if; end if; -- Add fractional position - if line_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_line_mode_skip_pixels /= "11" then + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels /= "11" then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6099,13 +6114,13 @@ begin -- pixel. The first pixel will thus effectively be written to -- twice. if reg_dmagic_line_mode_skip_pixels="00" then - if line_skip_accumulator(15 downto 8) /= x"00" then + if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; else line_y_move := '1'; end if; - line_skip_accumulator := x"00" & line_skip_accumulator(7 downto 0); + line_skip_accumulator := "00" & line_skip_accumulator(15 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then @@ -6306,10 +6321,14 @@ begin -- We are in line mode. if reg_dmagic_s_line_mode_skip_pixels="00" then - line_source_skip_accumulator := line_source_skip_accumulator + reg_dmagic_src_skip; + if line_source_skip_rate_set = '1' and reg_dmagic_src_skip /= x"0000" then + line_source_skip_accumulator := line_source_skip_accumulator + ("00" & reg_dmagic_src_skip); + else + line_source_skip_accumulator := "01" & x"0000"; + end if; end if; - if line_source_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_s_line_mode_skip_pixels /= "11" then + if line_source_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_s_line_mode_skip_pixels /= "11" then -- Add fractional position reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; end if; @@ -6332,13 +6351,13 @@ begin end if; -- Also move major axis (which is always in the forward direction) if reg_dmagic_s_line_mode_skip_pixels="00" then - if line_source_skip_accumulator(15 downto 8) /= x"00" then + if line_source_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_s_line_x_or_y='0' then line_x_move := '1'; else line_y_move := '1'; end if; - line_source_skip_accumulator := x"00" & line_source_skip_accumulator(7 downto 0); + line_source_skip_accumulator := "00" & line_source_skip_accumulator(15 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then @@ -6508,11 +6527,15 @@ begin -- We are in line mode. if reg_dmagic_line_mode_skip_pixels="00" then - line_skip_accumulator := line_skip_accumulator + reg_dmagic_dst_skip; + if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then + line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); + else + line_skip_accumulator := "01" & x"0000"; + end if; end if; -- Add fractional position - if line_skip_accumulator(15 downto 8) /= x"00" and reg_dmagic_line_mode_skip_pixels /= "11" then + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels /= "11" then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6534,13 +6557,13 @@ begin end if; -- Also move major axis (which is always in the forward direction) if reg_dmagic_line_mode_skip_pixels="00" then - if line_skip_accumulator(15 downto 8) /= x"00" then + if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; else line_y_move := '1'; end if; - line_skip_accumulator := x"00" & line_skip_accumulator(7 downto 0); + line_skip_accumulator := "00" & line_skip_accumulator(15 downto 0); end if; end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then From dee7588f95663929f7a434f54f29d94e877083dd Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Sun, 13 Apr 2025 14:39:13 -0500 Subject: [PATCH 3/8] Cleaned up documentation. --- src/vhdl/gs4510.vhdl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 1bed1c67b..6ce9e43eb 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -6079,15 +6079,21 @@ begin -- We are in line mode. if reg_dmagic_line_mode_skip_pixels="00" then + -- Accumulate scale value, but only if the skip rate was manually specified. + -- A skip rate of $0000 is treated as skipping 1 byte per cycle (which + -- equates to not scaling down) since not moving the address forwards at all + -- in line mode does not make any sense. if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); else - -- Since the skip rate isn't set, set scale to 1. + -- Since the skip rate isn't set, don't scale. line_skip_accumulator := "01" & x"0000"; end if; end if; - -- Add fractional position + -- Add fractional position, but only when DMAgic has waited for enough cycles, according + -- to the skip rate. The skip accumulators start at a value of $10000, so this will + -- always run in the first few cycles. if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels /= "11" then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6114,12 +6120,17 @@ begin -- pixel. The first pixel will thus effectively be written to -- twice. if reg_dmagic_line_mode_skip_pixels="00" then + -- Only allow major axis movement when the skip accumulator + -- is greater than $10000. if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; else line_y_move := '1'; end if; + -- Trim off the two most significant bits, but leave the rest + -- of the skip accumulator intact, so that skip values greater + -- than $8000 work correctly. line_skip_accumulator := "00" & line_skip_accumulator(15 downto 0); end if; end if; From 6bafc71d782a69079be68413cc1c790eb46dc1fa Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Wed, 14 Jan 2026 11:10:38 -0600 Subject: [PATCH 4/8] experimental fix for DMAgic line mode inconsistent startup states --- src/vhdl/gs4510.vhdl | 88 ++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 75c465410..a073a254d 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -603,7 +603,7 @@ architecture Behavioural of gs4510 is signal reg_dmagic_line_mode : std_logic := '0'; signal reg_dmagic_line_x_or_y : std_logic := '0'; signal reg_dmagic_line_slope_negative : std_logic := '0'; - signal reg_dmagic_line_mode_skip_pixels : std_logic_vector(1 downto 0) := "00"; + signal reg_dmagic_line_mode_skip_pixels : integer range 0 to 3 := 0; signal reg_dmagic_s_x8_offset : unsigned(15 downto 0) := x"0000"; signal reg_dmagic_s_y8_offset : unsigned(15 downto 0) := x"0000"; @@ -613,7 +613,7 @@ architecture Behavioural of gs4510 is signal reg_dmagic_s_line_mode : std_logic := '0'; signal reg_dmagic_s_line_x_or_y : std_logic := '0'; signal reg_dmagic_s_line_slope_negative : std_logic := '0'; - signal reg_dmagic_s_line_mode_skip_pixels : std_logic_vector(1 downto 0) := "00"; + signal reg_dmagic_s_line_mode_skip_pixels : integer range 0 to 3 := 0; signal dmagic_option_id : unsigned(7 downto 0) := x"00"; signal reg_dmagic_draw_spiral : std_logic := '0'; @@ -3859,7 +3859,7 @@ begin reg_dmagic_line_slope_negative <= '0'; dmagic_slope_overflow_toggle <= '0'; reg_dmagic_line_mode <= '0'; - reg_dmagic_line_mode_skip_pixels <= (others => '0'); + reg_dmagic_line_mode_skip_pixels <= 0; reg_dmagic_line_x_or_y <= '0'; reg_dmagic_s_x8_offset <= x"0000"; @@ -3869,7 +3869,7 @@ begin reg_dmagic_s_line_slope_negative <= '0'; dmagic_s_slope_overflow_toggle <= '0'; reg_dmagic_s_line_mode <= '0'; - reg_dmagic_s_line_mode_skip_pixels <= (others => '0'); + reg_dmagic_s_line_mode_skip_pixels <= 0; reg_dmagic_s_line_x_or_y <= '0'; reg_dmagic_floppy_mode <= '0'; @@ -5834,7 +5834,6 @@ begin when x"8d" => reg_dmagic_slope_fraction_start(7 downto 0) <= memory_read_value; when x"8e" => reg_dmagic_slope_fraction_start(15 downto 8) <= memory_read_value; when x"8f" => reg_dmagic_line_mode <= memory_read_value(7); - reg_dmagic_line_mode_skip_pixels <= memory_read_value(7) & '0'; reg_dmagic_line_x_or_y <= memory_read_value(6); reg_dmagic_line_slope_negative <= memory_read_value(5); -- @ IO:GS $D705 - Enhanced DMAgic job option $90 $xx = Set bits 16 -- 23 of DMA length to allow DMA operations >64KB. @@ -5856,7 +5855,6 @@ begin when x"9d" => reg_dmagic_s_slope_fraction_start(7 downto 0) <= memory_read_value; when x"9e" => reg_dmagic_s_slope_fraction_start(15 downto 8) <= memory_read_value; when x"9f" => reg_dmagic_s_line_mode <= memory_read_value(7); - reg_dmagic_s_line_mode_skip_pixels <= memory_read_value(7) & '0'; reg_dmagic_s_line_x_or_y <= memory_read_value(6); reg_dmagic_s_line_slope_negative <= memory_read_value(5); @@ -5991,6 +5989,22 @@ begin pre_dma_cpuport_bits <= cpuport_value(2 downto 0); cpuport_value(2 downto 1) <= "10"; + -- setup delay states for destination line mode + -- slope accumulator takes a cycle to set up, and the first read cycle is bad anyways + if reg_dmagic_line_mode = '1' then + reg_dmagic_line_mode_skip_pixels <= 1; + else + reg_dmagic_line_mode_skip_pixels <= 0; + end if; + + -- setup delay states for source line mode + -- one cycle for slope accumulator + if reg_dmagic_s_line_mode = '1' then + reg_dmagic_s_line_mode_skip_pixels <= 1; + else + reg_dmagic_s_line_mode_skip_pixels <= 0; + end if; + case dmagic_cmd(1 downto 0) is when "11" => -- fill state <= DMAgicFill; @@ -6003,7 +6017,7 @@ begin -- Since line mode skips the first cycle to allow for slope accumulator -- latency, the counter is decremented one too many times. dmagic_first_read <= reg_dmagic_line_mode; - + when "00" => -- copy dmagic_first_read <= '1'; state <= DMagicCopyRead; @@ -6041,8 +6055,12 @@ begin -- Fill memory at dmagic_dest_addr with dmagic_src_addr(7 downto 0) -- Clear first pixel of line flag - reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels(0) & "0"; - reg_dmagic_s_line_mode_skip_pixels <= reg_dmagic_s_line_mode_skip_pixels(0) & "0"; + if reg_dmagic_line_mode_skip_pixels /= 0 then + reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels - 1; + end if; + if reg_dmagic_s_line_mode_skip_pixels /= 0 then + reg_dmagic_s_line_mode_skip_pixels <= reg_dmagic_s_line_mode_skip_pixels - 1; + end if; -- Do memory write phi_add_backlog <= '1'; phi_new_backlog <= 1; @@ -6092,7 +6110,7 @@ begin else -- We are in line mode. - if reg_dmagic_line_mode_skip_pixels="00" then + if reg_dmagic_line_mode_skip_pixels = 0 then -- Accumulate scale value, but only if the skip rate was manually specified. -- A skip rate of $0000 is treated as skipping 1 byte per cycle (which -- equates to not scaling down) since not moving the address forwards at all @@ -6104,11 +6122,11 @@ begin line_skip_accumulator := "01" & x"0000"; end if; end if; - + -- Add fractional position, but only when DMAgic has waited for enough cycles, according -- to the skip rate. The skip accumulators start at a value of $10000, so this will -- always run in the first few cycles. - if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels /= "11" then + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels <= 1 then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6133,7 +6151,7 @@ begin -- so handle this by not advancing the major axis on the first -- pixel. The first pixel will thus effectively be written to -- twice. - if reg_dmagic_line_mode_skip_pixels="00" then + if reg_dmagic_line_mode_skip_pixels = 0 then -- Only allow major axis movement when the skip accumulator -- is greater than $10000. if line_skip_accumulator(17 downto 16) /= "00" then @@ -6290,11 +6308,11 @@ begin state <= DMAgicTrigger; end if; else - -- Skip the first decrement in line mode. - if dmagic_first_read = '0' then + dmagic_first_read <= '0'; + + -- Skip the first decrements in line mode. + if reg_dmagic_line_mode_skip_pixels = 0 then dmagic_count <= dmagic_count - 1; - else - dmagic_first_read <= '0'; end if; if pending_dma_busy='1' then @@ -6331,7 +6349,9 @@ begin -- and can read or write on every cycle. -- so we need to read the first byte now. - reg_dmagic_s_line_mode_skip_pixels <= reg_dmagic_s_line_mode_skip_pixels(0) & "0"; + if reg_dmagic_s_line_mode_skip_pixels /= 0 then + reg_dmagic_s_line_mode_skip_pixels <= reg_dmagic_s_line_mode_skip_pixels - 1; + end if; -- Do memory read phi_add_backlog <= '1'; phi_new_backlog <= 1; @@ -6345,7 +6365,7 @@ begin if reg_dmagic_s_line_mode='1' then -- We are in line mode. - if reg_dmagic_s_line_mode_skip_pixels="00" then + if reg_dmagic_s_line_mode_skip_pixels = 0 then if line_source_skip_rate_set = '1' and reg_dmagic_src_skip /= x"0000" then line_source_skip_accumulator := line_source_skip_accumulator + ("00" & reg_dmagic_src_skip); else @@ -6353,7 +6373,7 @@ begin end if; end if; - if line_source_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_s_line_mode_skip_pixels /= "11" then + if line_source_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_s_line_mode_skip_pixels <= 1 then -- Add fractional position reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; end if; @@ -6375,7 +6395,7 @@ begin end if; end if; -- Also move major axis (which is always in the forward direction) - if reg_dmagic_s_line_mode_skip_pixels="00" then + if reg_dmagic_s_line_mode_skip_pixels = 0 then if line_source_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_s_line_x_or_y='0' then line_x_move := '1'; @@ -6499,7 +6519,8 @@ begin dmagic_src_addr <= dmagic_src_addr - (256*1) - (256*8); end if; end if; - elsif dmagic_src_hold='0' then + elsif dmagic_src_hold='0' and reg_dmagic_s_line_mode_skip_pixels = 0 then + -- only increment source address if there are no cycles to skip. reg_dmagic_s_line_mode_skip_pixels is zero when not in line mode. if dmagic_src_direction='0' then dmagic_src_addr(35 downto 0) <= dmagic_src_addr(35 downto 0) + reg_dmagic_src_skip; else @@ -6540,27 +6561,31 @@ begin phi_add_backlog <= '1'; phi_new_backlog <= 1; - if dmagic_first_read = '0' then + -- check if line mode will independently wait a cycle to avoid logic that makes my head hurt + if dmagic_first_read = '0' or reg_dmagic_line_mode_skip_pixels /= 0 then -- Update address and check for end of job. -- XXX Ignores modulus, whose behaviour is insufficiently defined -- in the C65 specifications document - reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels(0) & "0"; - + if reg_dmagic_line_mode_skip_pixels /= 0 then + reg_dmagic_line_mode_skip_pixels <= reg_dmagic_line_mode_skip_pixels - 1; + end if; + if reg_dmagic_line_mode='1' then -- Line mode with copy, so that textured lines can be drawn -- We are in line mode. - if reg_dmagic_line_mode_skip_pixels="00" then + if reg_dmagic_line_mode_skip_pixels = 0 then if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); else line_skip_accumulator := "01" & x"0000"; end if; end if; - + -- Add fractional position - if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels /= "11" then + -- Wait until the last skipped cycle to start updating the slope accumulator + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels <= 1 then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6581,7 +6606,7 @@ begin end if; end if; -- Also move major axis (which is always in the forward direction) - if reg_dmagic_line_mode_skip_pixels="00" then + if reg_dmagic_line_mode_skip_pixels = 0 then if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; @@ -6706,7 +6731,8 @@ begin end if; end if; -- end of line mode case - elsif dmagic_dest_hold='0' then + elsif dmagic_dest_hold='0' and reg_dmagic_line_mode_skip_pixels = 0 then + -- reg_dmagic_line_mode_skip_pixels is zero when line mode is disabled if dmagic_dest_direction='0' then dmagic_dest_addr(35 downto 0) <= dmagic_dest_addr(35 downto 0) + reg_dmagic_dst_skip; else @@ -6742,7 +6768,7 @@ begin state <= DMAgicTrigger; end if; else - if reg_dmagic_line_mode = '0' or reg_dmagic_line_mode_skip_pixels = "00" then + if reg_dmagic_line_mode = '0' or reg_dmagic_line_mode_skip_pixels = 0 then dmagic_count <= dmagic_count - 1; end if; end if; From 0630c6b2bce8021d2921463e12e52ecc44d2b68b Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Wed, 14 Jan 2026 13:37:03 -0600 Subject: [PATCH 5/8] Moved initial slope accumulation to startup state, should hopefully eradicate the wacky startup alignment issues --- src/vhdl/gs4510.vhdl | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index a073a254d..004dcca34 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -5989,18 +5989,22 @@ begin pre_dma_cpuport_bits <= cpuport_value(2 downto 0); cpuport_value(2 downto 1) <= "10"; - -- setup delay states for destination line mode + -- setup delay states for destination line mode and perform initial slope accumulation -- slope accumulator takes a cycle to set up, and the first read cycle is bad anyways if reg_dmagic_line_mode = '1' then - reg_dmagic_line_mode_skip_pixels <= 1; + dmagic_slope_overflow_toggle <= reg_dmagic_slope_fraction_start(16); + reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; + reg_dmagic_line_mode_skip_pixels <= 0; else reg_dmagic_line_mode_skip_pixels <= 0; end if; - -- setup delay states for source line mode + -- setup delay states for source line mode and perform initial slope accumulation -- one cycle for slope accumulator if reg_dmagic_s_line_mode = '1' then - reg_dmagic_s_line_mode_skip_pixels <= 1; + dmagic_s_slope_overflow_toggle <= reg_dmagic_s_slope_fraction_start(16); + reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; + reg_dmagic_s_line_mode_skip_pixels <= 0; else reg_dmagic_s_line_mode_skip_pixels <= 0; end if; @@ -6126,7 +6130,7 @@ begin -- Add fractional position, but only when DMAgic has waited for enough cycles, according -- to the skip rate. The skip accumulators start at a value of $10000, so this will -- always run in the first few cycles. - if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels <= 1 then + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels < 1 then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6135,7 +6139,7 @@ begin line_x_move_negative := '0'; line_y_move := '0'; line_y_move_negative := '0'; - if dmagic_slope_overflow_toggle /= reg_dmagic_slope_fraction_start(16) then + if dmagic_slope_overflow_toggle /= reg_dmagic_slope_fraction_start(16) and reg_dmagic_line_mode_skip_pixels < 1 then dmagic_slope_overflow_toggle <= reg_dmagic_slope_fraction_start(16); -- Yes: Advance in minor axis if reg_dmagic_line_x_or_y='0' then @@ -6373,7 +6377,7 @@ begin end if; end if; - if line_source_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_s_line_mode_skip_pixels <= 1 then + if line_source_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_s_line_mode_skip_pixels < 1 then -- Add fractional position reg_dmagic_s_slope_fraction_start <= reg_dmagic_s_slope_fraction_start + reg_dmagic_s_slope; end if; @@ -6383,7 +6387,7 @@ begin line_x_move_negative := '0'; line_y_move := '0'; line_y_move_negative := '0'; - if dmagic_s_slope_overflow_toggle /= reg_dmagic_s_slope_fraction_start(16) then + if dmagic_s_slope_overflow_toggle /= reg_dmagic_s_slope_fraction_start(16) and reg_dmagic_s_line_mode_skip_pixels < 1 then dmagic_s_slope_overflow_toggle <= reg_dmagic_s_slope_fraction_start(16); -- Yes: Advance in minor axis if reg_dmagic_s_line_x_or_y='0' then @@ -6539,7 +6543,12 @@ begin report "DMAgicCopyWrite: dmagic_src_addr=$" & to_hstring(dmagic_src_addr(35 downto 8)) &"."&to_hstring(dmagic_src_addr(7 downto 0)) & " (reg_dmagic_src_skip=$" & to_hstring(reg_dmagic_src_skip)&"), memory_read_value=$" & to_hexstring(memory_read_value); - dmagic_first_read <= '0'; + + -- Only start writing on last delay cycle + if reg_dmagic_line_mode_skip_pixels <= 1 then + dmagic_first_read <= '0'; + end if; + reg_t <= memory_read_value; -- Set IO visibility for source @@ -6585,7 +6594,7 @@ begin -- Add fractional position -- Wait until the last skipped cycle to start updating the slope accumulator - if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels <= 1 then + if line_skip_accumulator(17 downto 16) /= "00" and reg_dmagic_line_mode_skip_pixels < 1 then reg_dmagic_slope_fraction_start <= reg_dmagic_slope_fraction_start + reg_dmagic_slope; end if; @@ -6594,7 +6603,7 @@ begin line_x_move_negative := '0'; line_y_move := '0'; line_y_move_negative := '0'; - if dmagic_slope_overflow_toggle /= reg_dmagic_slope_fraction_start(16) then + if dmagic_slope_overflow_toggle /= reg_dmagic_slope_fraction_start(16) and reg_dmagic_line_mode_skip_pixels < 1 then dmagic_slope_overflow_toggle <= reg_dmagic_slope_fraction_start(16); -- Yes: Advance in minor axis if reg_dmagic_line_x_or_y='0' then From e650178347a5c7c5796d582a2f79076df646e6c0 Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Wed, 14 Jan 2026 15:23:00 -0600 Subject: [PATCH 6/8] Gated line mode scaling behind bit 4 of line mode config --- src/vhdl/gs4510.vhdl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 004dcca34..84595a077 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -604,6 +604,7 @@ architecture Behavioural of gs4510 is signal reg_dmagic_line_x_or_y : std_logic := '0'; signal reg_dmagic_line_slope_negative : std_logic := '0'; signal reg_dmagic_line_mode_skip_pixels : integer range 0 to 3 := 0; + signal reg_dmagic_line_mode_enable_scaling : std_logic := '0'; signal reg_dmagic_s_x8_offset : unsigned(15 downto 0) := x"0000"; signal reg_dmagic_s_y8_offset : unsigned(15 downto 0) := x"0000"; @@ -614,6 +615,7 @@ architecture Behavioural of gs4510 is signal reg_dmagic_s_line_x_or_y : std_logic := '0'; signal reg_dmagic_s_line_slope_negative : std_logic := '0'; signal reg_dmagic_s_line_mode_skip_pixels : integer range 0 to 3 := 0; + signal reg_dmagic_s_line_mode_enable_scaling : std_logic := '0'; signal dmagic_option_id : unsigned(7 downto 0) := x"00"; signal reg_dmagic_draw_spiral : std_logic := '0'; @@ -3860,6 +3862,7 @@ begin dmagic_slope_overflow_toggle <= '0'; reg_dmagic_line_mode <= '0'; reg_dmagic_line_mode_skip_pixels <= 0; + reg_dmagic_line_mode_enable_scaling <= '0'; -- Scaling defaults to disabled for line mode reg_dmagic_line_x_or_y <= '0'; reg_dmagic_s_x8_offset <= x"0000"; @@ -3870,6 +3873,7 @@ begin dmagic_s_slope_overflow_toggle <= '0'; reg_dmagic_s_line_mode <= '0'; reg_dmagic_s_line_mode_skip_pixels <= 0; + reg_dmagic_s_line_mode_enable_scaling <= '0'; -- Scaling defaults to disabled for line mode reg_dmagic_s_line_x_or_y <= '0'; reg_dmagic_floppy_mode <= '0'; @@ -5836,6 +5840,7 @@ begin when x"8f" => reg_dmagic_line_mode <= memory_read_value(7); reg_dmagic_line_x_or_y <= memory_read_value(6); reg_dmagic_line_slope_negative <= memory_read_value(5); + reg_dmagic_line_mode_enable_scaling <= memory_read_value(4); -- @ IO:GS $D705 - Enhanced DMAgic job option $90 $xx = Set bits 16 -- 23 of DMA length to allow DMA operations >64KB. when x"90" => dmagic_count(23 downto 16) <= memory_read_value; @@ -5857,6 +5862,7 @@ begin when x"9f" => reg_dmagic_s_line_mode <= memory_read_value(7); reg_dmagic_s_line_x_or_y <= memory_read_value(6); reg_dmagic_s_line_slope_negative <= memory_read_value(5); + reg_dmagic_s_line_mode_enable_scaling <= memory_read_value(4); when others => null; end case; @@ -6119,7 +6125,7 @@ begin -- A skip rate of $0000 is treated as skipping 1 byte per cycle (which -- equates to not scaling down) since not moving the address forwards at all -- in line mode does not make any sense. - if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then + if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" and reg_dmagic_line_mode_enable_scaling = '1' then line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); else -- Since the skip rate isn't set, don't scale. @@ -6370,7 +6376,7 @@ begin -- We are in line mode. if reg_dmagic_s_line_mode_skip_pixels = 0 then - if line_source_skip_rate_set = '1' and reg_dmagic_src_skip /= x"0000" then + if line_source_skip_rate_set = '1' and reg_dmagic_src_skip /= x"0000" and reg_dmagic_s_line_mode_enable_scaling = '1' then line_source_skip_accumulator := line_source_skip_accumulator + ("00" & reg_dmagic_src_skip); else line_source_skip_accumulator := "01" & x"0000"; @@ -6585,7 +6591,7 @@ begin -- We are in line mode. if reg_dmagic_line_mode_skip_pixels = 0 then - if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" then + if line_dest_skip_rate_set = '1' and reg_dmagic_dst_skip /= x"0000" and reg_dmagic_line_mode_enable_scaling = '1' then line_skip_accumulator := line_skip_accumulator + ("00" & reg_dmagic_dst_skip); else line_skip_accumulator := "01" & x"0000"; From c8f8bcac7d5a36508b373144e2d0c7aeed2e9576 Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Thu, 15 Jan 2026 12:01:44 -0600 Subject: [PATCH 7/8] Made line mode major axis reversible via direction bit --- src/vhdl/gs4510.vhdl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 84595a077..2071a8d51 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -6164,11 +6164,14 @@ begin if reg_dmagic_line_mode_skip_pixels = 0 then -- Only allow major axis movement when the skip accumulator -- is greater than $10000. + -- Set major axis invert to direction if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; + line_x_move_negative := dmagic_dest_direction; else line_y_move := '1'; + line_y_move_negative := dmagic_dest_direction; end if; -- Trim off the two most significant bits, but leave the rest -- of the skip accumulator intact, so that skip values greater @@ -6404,13 +6407,15 @@ begin line_x_move_negative := reg_dmagic_s_line_slope_negative; end if; end if; - -- Also move major axis (which is always in the forward direction) + -- Also move major axis, using direction of pointer as direction of travel if reg_dmagic_s_line_mode_skip_pixels = 0 then if line_source_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_s_line_x_or_y='0' then line_x_move := '1'; + line_x_move_negative := dmagic_src_direction; else line_y_move := '1'; + line_y_move_negative := dmagic_src_direction; end if; line_source_skip_accumulator := "00" & line_source_skip_accumulator(15 downto 0); end if; @@ -6620,13 +6625,15 @@ begin line_x_move_negative := reg_dmagic_line_slope_negative; end if; end if; - -- Also move major axis (which is always in the forward direction) + -- Also move major axis, using pointer direction as travel direction if reg_dmagic_line_mode_skip_pixels = 0 then if line_skip_accumulator(17 downto 16) /= "00" then if reg_dmagic_line_x_or_y='0' then line_x_move := '1'; + line_x_move_negative := dmagic_dest_direction; else line_y_move := '1'; + line_y_move_negative := dmagic_dest_direction; end if; line_skip_accumulator := "00" & line_skip_accumulator(15 downto 0); end if; From 9d03dbcfd6543142d39558f2121dcbda5c56a394 Mon Sep 17 00:00:00 2001 From: Unkn0wn Date: Sun, 25 Jan 2026 16:21:43 -0600 Subject: [PATCH 8/8] Fixed a faulty comparison for character boundary crossing in the Y axis --- src/vhdl/gs4510.vhdl | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/vhdl/gs4510.vhdl b/src/vhdl/gs4510.vhdl index 2071a8d51..c05482022 100755 --- a/src/vhdl/gs4510.vhdl +++ b/src/vhdl/gs4510.vhdl @@ -6181,7 +6181,7 @@ begin end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then -- Y = Y + 1 - if dmagic_dest_addr(14 downto 11)="111" then + if dmagic_dest_addr(13 downto 11)="111" then -- Will overflow between Y cards dmagic_dest_addr <= dmagic_dest_addr + (256*8) + (reg_dmagic_y8_offset&"00000000"); @@ -6191,7 +6191,7 @@ begin end if; elsif line_x_move='0' and line_y_move='1' and line_y_move_negative='1' then -- Y = Y - 1 - if dmagic_dest_addr(14 downto 11)="000" then + if dmagic_dest_addr(13 downto 11)="000" then -- Will overflow between X cards dmagic_dest_addr <= dmagic_dest_addr - (256*8) - (reg_dmagic_y8_offset&"00000000"); @@ -6221,12 +6221,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='0' then -- X = X + 1, Y = Y + 1 - if dmagic_dest_addr(14 downto 8)="111111" then + if dmagic_dest_addr(13 downto 8)="111111" then -- positive overflow on both dmagic_dest_addr <= dmagic_dest_addr + (256*9) + (reg_dmagic_x8_offset&"00000000") + (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="111" then + elsif dmagic_dest_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr + (256*9) + (reg_dmagic_y8_offset&"00000000"); @@ -6240,12 +6240,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='1' then -- X = X + 1, Y = Y - 1 - if dmagic_dest_addr(14 downto 8)="000111" then + if dmagic_dest_addr(13 downto 8)="000111" then -- positive card overflow on X, negative on Y dmagic_dest_addr <= dmagic_dest_addr + (256*1) - (256*8) + (reg_dmagic_x8_offset&"00000000") - (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="000" then + elsif dmagic_dest_addr(13 downto 11)="000" then -- negative card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr + (256*1) - (256*8) - (reg_dmagic_y8_offset&"00000000"); @@ -6258,12 +6258,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='0' then -- X = X - 1, Y = Y + 1 - if dmagic_dest_addr(14 downto 8)="111000" then + if dmagic_dest_addr(13 downto 8)="111000" then -- negative card overflow on X, positive on Y dmagic_dest_addr <= dmagic_dest_addr - (256*1) + (256*8) - (reg_dmagic_x8_offset&"00000000") + (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="111" then + elsif dmagic_dest_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr - (256*1) + (256*8) + (reg_dmagic_y8_offset&"00000000"); @@ -6276,12 +6276,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='1' then -- X = X - 1, Y = Y - 1 - if dmagic_dest_addr(14 downto 8)="000000" then + if dmagic_dest_addr(13 downto 8)="000000" then -- negative card overflow on X, negative on Y dmagic_dest_addr <= dmagic_dest_addr - (256*1) - (256*8) - (reg_dmagic_x8_offset&"00000000") - (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="000" then + elsif dmagic_dest_addr(13 downto 11)="000" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr - (256*1) - (256*8) - (reg_dmagic_y8_offset&"00000000"); @@ -6422,7 +6422,7 @@ begin end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then -- Y = Y + 1 - if dmagic_src_addr(14 downto 11)="111" then + if dmagic_src_addr(13 downto 11)="111" then -- Will overflow between Y cards dmagic_src_addr <= dmagic_src_addr + (256*8) + (reg_dmagic_s_y8_offset&"00000000"); @@ -6432,7 +6432,7 @@ begin end if; elsif line_x_move='0' and line_y_move='1' and line_y_move_negative='1' then -- Y = Y - 1 - if dmagic_src_addr(14 downto 11)="000" then + if dmagic_src_addr(13 downto 11)="000" then -- Will overflow between X cards dmagic_src_addr <= dmagic_src_addr - (256*8) - (reg_dmagic_s_y8_offset&"00000000"); @@ -6462,12 +6462,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='0' then -- X = X + 1, Y = Y + 1 - if dmagic_src_addr(14 downto 8)="111111" then + if dmagic_src_addr(13 downto 8)="111111" then -- positive overflow on both dmagic_src_addr <= dmagic_src_addr + (256*9) + (reg_dmagic_s_x8_offset&"00000000") + (reg_dmagic_s_y8_offset&"00000000"); - elsif dmagic_src_addr(14 downto 11)="111" then + elsif dmagic_src_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_src_addr <= dmagic_src_addr + (256*9) + (reg_dmagic_s_y8_offset&"00000000"); @@ -6481,12 +6481,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='1' then -- X = X + 1, Y = Y - 1 - if dmagic_src_addr(14 downto 8)="000111" then + if dmagic_src_addr(13 downto 8)="000111" then -- positive card overflow on X, negative on Y dmagic_src_addr <= dmagic_src_addr + (256*1) - (256*8) + (reg_dmagic_s_x8_offset&"00000000") - (reg_dmagic_s_y8_offset&"00000000"); - elsif dmagic_src_addr(14 downto 11)="000" then + elsif dmagic_src_addr(13 downto 11)="000" then -- negative card overflow on Y only dmagic_src_addr <= dmagic_src_addr + (256*1) - (256*8) - (reg_dmagic_s_y8_offset&"00000000"); @@ -6499,12 +6499,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='0' then -- X = X - 1, Y = Y + 1 - if dmagic_src_addr(14 downto 8)="111000" then + if dmagic_src_addr(13 downto 8)="111000" then -- negative card overflow on X, positive on Y dmagic_src_addr <= dmagic_src_addr - (256*1) + (256*8) - (reg_dmagic_s_x8_offset&"00000000") + (reg_dmagic_s_y8_offset&"00000000"); - elsif dmagic_src_addr(14 downto 11)="111" then + elsif dmagic_src_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_src_addr <= dmagic_src_addr - (256*1) + (256*8) + (reg_dmagic_s_y8_offset&"00000000"); @@ -6517,12 +6517,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='1' then -- X = X - 1, Y = Y - 1 - if dmagic_src_addr(14 downto 8)="000000" then + if dmagic_src_addr(13 downto 8)="000000" then -- negative card overflow on X, negative on Y dmagic_src_addr <= dmagic_src_addr - (256*1) - (256*8) - (reg_dmagic_s_x8_offset&"00000000") - (reg_dmagic_s_y8_offset&"00000000"); - elsif dmagic_src_addr(14 downto 11)="000" then + elsif dmagic_src_addr(13 downto 11)="000" then -- positive card overflow on Y only dmagic_src_addr <= dmagic_src_addr - (256*1) - (256*8) - (reg_dmagic_s_y8_offset&"00000000"); @@ -6640,7 +6640,7 @@ begin end if; if line_x_move='0' and line_y_move='1' and line_y_move_negative='0' then -- Y = Y + 1 - if dmagic_dest_addr(14 downto 11)="111" then + if dmagic_dest_addr(13 downto 11)="111" then -- Will overflow between Y cards dmagic_dest_addr <= dmagic_dest_addr + (256*8) + (reg_dmagic_y8_offset&"00000000"); @@ -6650,7 +6650,7 @@ begin end if; elsif line_x_move='0' and line_y_move='1' and line_y_move_negative='1' then -- Y = Y - 1 - if dmagic_dest_addr(14 downto 11)="000" then + if dmagic_dest_addr(13 downto 11)="000" then -- Will overflow between X cards dmagic_dest_addr <= dmagic_dest_addr - (256*8) - (reg_dmagic_y8_offset&"00000000"); @@ -6680,12 +6680,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='0' then -- X = X + 1, Y = Y + 1 - if dmagic_dest_addr(14 downto 8)="111111" then + if dmagic_dest_addr(13 downto 8)="111111" then -- positive overflow on both dmagic_dest_addr <= dmagic_dest_addr + (256*9) + (reg_dmagic_x8_offset&"00000000") + (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="111" then + elsif dmagic_dest_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr + (256*9) + (reg_dmagic_y8_offset&"00000000"); @@ -6699,12 +6699,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='0' and line_y_move='1' and line_y_move_negative='1' then -- X = X + 1, Y = Y - 1 - if dmagic_dest_addr(14 downto 8)="000111" then + if dmagic_dest_addr(13 downto 8)="000111" then -- positive card overflow on X, negative on Y dmagic_dest_addr <= dmagic_dest_addr + (256*1) - (256*8) + (reg_dmagic_x8_offset&"00000000") - (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="000" then + elsif dmagic_dest_addr(13 downto 11)="000" then -- negative card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr + (256*1) - (256*8) - (reg_dmagic_y8_offset&"00000000"); @@ -6717,12 +6717,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='0' then -- X = X - 1, Y = Y + 1 - if dmagic_dest_addr(14 downto 8)="111000" then + if dmagic_dest_addr(13 downto 8)="111000" then -- negative card overflow on X, positive on Y dmagic_dest_addr <= dmagic_dest_addr - (256*1) + (256*8) - (reg_dmagic_x8_offset&"00000000") + (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="111" then + elsif dmagic_dest_addr(13 downto 11)="111" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr - (256*1) + (256*8) + (reg_dmagic_y8_offset&"00000000"); @@ -6735,12 +6735,12 @@ begin end if; elsif line_x_move='1' and line_x_move_negative='1' and line_y_move='1' and line_y_move_negative='1' then -- X = X - 1, Y = Y - 1 - if dmagic_dest_addr(14 downto 8)="000000" then + if dmagic_dest_addr(13 downto 8)="000000" then -- negative card overflow on X, negative on Y dmagic_dest_addr <= dmagic_dest_addr - (256*1) - (256*8) - (reg_dmagic_x8_offset&"00000000") - (reg_dmagic_y8_offset&"00000000"); - elsif dmagic_dest_addr(14 downto 11)="000" then + elsif dmagic_dest_addr(13 downto 11)="000" then -- positive card overflow on Y only dmagic_dest_addr <= dmagic_dest_addr - (256*1) - (256*8) - (reg_dmagic_y8_offset&"00000000");