mirror of
https://github.com/MiSTer-devel/SMS_MiSTer.git
synced 2026-05-17 03:04:32 +00:00
VDP: Fix legacy modes (Super Boy I/II) while maintaining Mode 4 compatibility (#178)
* Added support for loading Master System BIOS files. Master System BIOS files can now be used to boot games and play built-in titles. * Fix lightgun position calculation for vertical aim The Master System core exhibited a vertical aim deviation with the lightgun, even when properly calibrated. The offset was zero at the top of the screen but increased progressively toward the bottom. This commit corrects the lightgun position calculation logic, ensuring accurate aiming across the full vertical range of the screen. * Implement Soft Reset (Console Reset Button) via OSD and Controller - Added a "Soft Reset" option to the OSD menu. - Implemented falling-edge triggering for the OSD reset to ensure the pulse fires after the menu closes. - Added a ~37ms pulse stretcher to guarantee the Z80 CPU polling loop detects the reset press. - Mapped the controller 'Select' button to trigger the Soft Reset signal. - Routed the signal to I/O port $DD bit 4 (active-low), matching the physical reset button behavior on original SMS hardware. - Improves compatibility and usability for games that utilize the reset button to return to the title screen or menu. * VDP: Fix legacy modes (Super Boy I/II) while maintaining Mode 4 compatibility vdp_background.vhd: Refactor legacy mode (Graphics I, II, Text) rendering logic to fix Super Boy I and II. Correct VRAM addressing for Graphics II (Mode 2) to properly handle banked pattern and color tables. vdp_main.vhd: Ensure vertical scroll wrapping remains correct for Mode 4. This prevents graphical regressions in titles like After Burner (SMS) and Fray (GG). vdp.vhd: Add smode_M2 signal to propagate mode bits for proper legacy mode decoding. video.vhd: Refine high-resolution (224/240 line) timing detection logic. --------- Co-authored-by: Fabricio Breve <7475908+fbreve@users.noreply.github.com>
This commit is contained in:
@@ -112,6 +112,7 @@ architecture Behavioral of vdp is
|
||||
signal mode_M3: std_logic;
|
||||
signal mode_M4: std_logic;
|
||||
signal xmode_M1: std_logic;
|
||||
signal xmode_M2: std_logic;
|
||||
signal xmode_M3: std_logic;
|
||||
signal xmode_M4: std_logic;
|
||||
|
||||
@@ -119,6 +120,7 @@ begin
|
||||
|
||||
mask_column <= mask_column0;
|
||||
xmode_M1<= mode_M1 and mode_M2 ;
|
||||
xmode_M2<= mode_M2;
|
||||
xmode_M3<= mode_M3 and mode_M2 ;
|
||||
xmode_M4<= mode_M4;
|
||||
|
||||
@@ -145,6 +147,7 @@ begin
|
||||
palettemode => palettemode,
|
||||
y1 => y1,
|
||||
smode_M1 => xmode_M1,
|
||||
smode_M2 => xmode_M2,
|
||||
smode_M3 => xmode_M3,
|
||||
smode_M4 => xmode_M4,
|
||||
ysj_quirk => ysj_quirk,
|
||||
|
||||
@@ -14,6 +14,7 @@ port (
|
||||
scroll_x: in std_logic_vector(7 downto 0);
|
||||
disable_hscroll: in std_logic;
|
||||
smode_M1: in std_logic;
|
||||
smode_M2: in std_logic;
|
||||
smode_M3: in std_logic;
|
||||
smode_M4: in std_logic;
|
||||
ysj_quirk: in std_logic;
|
||||
@@ -37,6 +38,7 @@ architecture rtl of vdp_background is
|
||||
signal priority_latch: std_logic;
|
||||
signal flip_x : std_logic;
|
||||
|
||||
signal datap : std_logic_vector(7 downto 0);
|
||||
signal datac : std_logic_vector(7 downto 0);
|
||||
signal data0 : std_logic_vector(7 downto 0);
|
||||
signal data1 : std_logic_vector(7 downto 0);
|
||||
@@ -109,11 +111,21 @@ begin
|
||||
else
|
||||
case x(2 downto 0) is
|
||||
when "000" => vram_A <= table_address & y(7 downto 3) & x(7 downto 3);
|
||||
when "010" => vram_A <= pt_address(13) & ( y(7 downto 6) and pt_address(12 downto 11) )&
|
||||
tile_index(7 downto 0) & y(2 downto 0);
|
||||
when "011" => vram_A <= ct_address(13) & ( y(7 downto 6) and ct_address(12 downto 11) )&
|
||||
tile_index(7 downto 0) &
|
||||
y(2 downto 0);
|
||||
when "010" =>
|
||||
if smode_M2 = '1' then -- Graphics II (Mode 2)
|
||||
vram_A <= pt_address(13) & ( y(7 downto 6) and pt_address(12 downto 11) )&
|
||||
tile_index(7 downto 0) & y(2 downto 0);
|
||||
else -- Default / Graphics I / Text
|
||||
vram_A <= pt_address(13 downto 11) & tile_index(7 downto 0) & y(2 downto 0);
|
||||
end if;
|
||||
when "011" =>
|
||||
if smode_M2 = '1' then -- Graphics II (Mode 2)
|
||||
vram_A <= ct_address(13) &
|
||||
( (y(7 downto 6) & tile_index(7 downto 3)) and ct_address(12 downto 6) ) &
|
||||
tile_index(2 downto 0) & y(2 downto 0);
|
||||
else -- Default / Graphics I
|
||||
vram_A <= ct_address(13 downto 6) & '0' & tile_index(7 downto 3);
|
||||
end if;
|
||||
when others =>
|
||||
end case;
|
||||
end if ;
|
||||
@@ -151,16 +163,18 @@ begin
|
||||
when "001" =>
|
||||
tile_index(7 downto 0) <= vram_D;
|
||||
when "011" =>
|
||||
datac <= vram_D;
|
||||
when "100" =>
|
||||
flip_x <= '0' ;
|
||||
palette <='0' ;
|
||||
priority_latch <= '0' ;
|
||||
for i in 0 to 7 loop
|
||||
data0(i) <= (not datac(i) and vram_D(0)) or (datac(i) and vram_D(4)) ;
|
||||
data1(i) <= (not datac(i) and vram_D(1)) or (datac(i) and vram_D(5)) ;
|
||||
data2(i) <= (not datac(i) and vram_D(2)) or (datac(i) and vram_D(6)) ;
|
||||
data3(i) <= (not datac(i) and vram_D(3)) or (datac(i) and vram_D(7)) ;
|
||||
datap <= vram_D;
|
||||
when "101" =>
|
||||
datac <= vram_D;
|
||||
when "110" =>
|
||||
flip_x <= '0' ;
|
||||
palette <='0' ;
|
||||
priority_latch <= '0' ;
|
||||
for i in 0 to 7 loop
|
||||
data0(i) <= (datap(i) and datac(4)) or (not datap(i) and datac(0));
|
||||
data1(i) <= (datap(i) and datac(5)) or (not datap(i) and datac(1));
|
||||
data2(i) <= (datap(i) and datac(6)) or (not datap(i) and datac(2));
|
||||
data3(i) <= (datap(i) and datac(7)) or (not datap(i) and datac(3));
|
||||
end loop;
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
@@ -30,6 +30,7 @@ entity vdp_main is
|
||||
mask_column0: in std_logic;
|
||||
black_column: in std_logic;
|
||||
smode_M1: in std_logic;
|
||||
smode_M2: in std_logic;
|
||||
smode_M3: in std_logic;
|
||||
smode_M4: in std_logic;
|
||||
ysj_quirk: in std_logic;
|
||||
@@ -104,10 +105,10 @@ begin
|
||||
vram_D => vram_D,
|
||||
color => bg_color,
|
||||
smode_M1 => smode_M1,
|
||||
smode_M2 => smode_M2,
|
||||
smode_M3 => smode_M3,
|
||||
smode_M4 => smode_M4,
|
||||
ysj_quirk => ysj_quirk,
|
||||
|
||||
priority => bg_priority);
|
||||
|
||||
vdp_spr_inst: entity work.vdp_sprites
|
||||
@@ -141,7 +142,7 @@ begin
|
||||
variable bg_active : boolean;
|
||||
begin
|
||||
y1 <= '1';
|
||||
if ((x>48 and x<=208) or (ggres='0' and x<=256 and x>0)) and -- thank you slingshot
|
||||
if ((x>48 and x<=208) or (ggres='0' and x<=256 and x>0)) and -- thank you slingshot
|
||||
(mask_column0='0' or x>=9) and display_on='1' then
|
||||
if (((y>=24 and y<168) and smode_M1='0')
|
||||
or ((y>=40 and y<184) and smode_M1='1')
|
||||
|
||||
@@ -13,7 +13,9 @@ entity video is
|
||||
mask_column: in std_logic := '0';
|
||||
cut_mask: in std_logic;
|
||||
smode_M1: in std_logic;
|
||||
smode_M2: in std_logic;
|
||||
smode_M3: in std_logic;
|
||||
smode_M4: in std_logic;
|
||||
|
||||
x: out std_logic_vector(8 downto 0);
|
||||
y: out std_logic_vector(8 downto 0);
|
||||
@@ -40,7 +42,7 @@ begin
|
||||
vcount <= vcount + 1;
|
||||
if pal = '1' then
|
||||
-- VCounter: 0-258, 458-511 = 313 steps
|
||||
if smode_M1='1' then
|
||||
if smode_M1='1' and smode_M2='1' then
|
||||
if vcount = 258 then
|
||||
vcount <= conv_std_logic_vector(458,9);
|
||||
elsif vcount = 461 then
|
||||
@@ -48,7 +50,7 @@ begin
|
||||
elsif vcount = 464 then
|
||||
vsync <= '0';
|
||||
end if;
|
||||
elsif smode_M3='1' then
|
||||
elsif smode_M3='1' and smode_M2='1' then
|
||||
if vcount = 266 then
|
||||
vcount <= conv_std_logic_vector(482,9);
|
||||
elsif vcount = 482 then
|
||||
@@ -68,7 +70,7 @@ begin
|
||||
end if;
|
||||
else
|
||||
-- NTSC mode 224 lines ...
|
||||
if smode_M1='1' then
|
||||
if smode_M1='1' and smode_M2='1' then
|
||||
if vcount = 234 then
|
||||
vcount <= conv_std_logic_vector(485,9);
|
||||
elsif vcount = 487 then
|
||||
@@ -77,7 +79,7 @@ begin
|
||||
vsync <= '0';
|
||||
end if;
|
||||
-- NTSC mode 240 lines -- this mode is not suposed to work anyway
|
||||
elsif smode_M3='1' then
|
||||
elsif smode_M3='1' and smode_M2='1' then
|
||||
if vcount = 261 then -- needs to be > 240 to generate an IRQ
|
||||
vcount <= conv_std_logic_vector(0,9);
|
||||
elsif vcount = 257 then
|
||||
@@ -115,16 +117,16 @@ begin
|
||||
x <= hcount;
|
||||
y <= vcount;
|
||||
|
||||
vbl_st <= conv_std_logic_vector(184,9) when (smode_M1='1' and ggres='1')
|
||||
else conv_std_logic_vector(224,9) when smode_M1 = '1'
|
||||
else conv_std_logic_vector(240,9) when smode_M3 = '1'
|
||||
vbl_st <= conv_std_logic_vector(184,9) when (smode_M1='1' and smode_M2='1' and ggres='1')
|
||||
else conv_std_logic_vector(224,9) when (smode_M1 = '1' and smode_M2 = '1')
|
||||
else conv_std_logic_vector(240,9) when (smode_M3 = '1' and smode_M2 = '1')
|
||||
else conv_std_logic_vector(216,9) when border = '1' and pal = '0'
|
||||
else conv_std_logic_vector(240,9) when border = '1'
|
||||
else conv_std_logic_vector(192,9) when ggres = '0'
|
||||
else conv_std_logic_vector(168,9);
|
||||
|
||||
vbl_end <= conv_std_logic_vector(40,9) when (smode_M1='1' and ggres='1')
|
||||
else conv_std_logic_vector(000,9) when smode_M1 = '1' or smode_M3 = '1' or (border = '0' and ggres = '0')
|
||||
else conv_std_logic_vector(000,9) when (smode_M1 = '1' and smode_M2 = '1') or (smode_M3 = '1' and smode_M2 = '1') or (border = '0' and ggres = '0')
|
||||
else conv_std_logic_vector(488,9) when border = '1' and pal = '0'
|
||||
else conv_std_logic_vector(458,9) when border = '1'
|
||||
else conv_std_logic_vector(024,9);
|
||||
|
||||
Reference in New Issue
Block a user