mirror of
https://github.com/MiSTer-devel/Gameboy_MiSTer.git
synced 2026-04-19 03:04:09 +00:00
Video: Window fixes for WX=A6, no sprite fetching if sprites are disabled on DMG
* Video: Window fixes for WX=A6 * Video: no sprite fetching if sprites are disabled on DMG
This commit is contained in:
@@ -24,7 +24,8 @@ module sprites (
|
||||
input ce,
|
||||
input ce_cpu,
|
||||
input size16,
|
||||
input isGBC_game,
|
||||
input isGBC,
|
||||
input sprite_en,
|
||||
|
||||
input lcd_on,
|
||||
|
||||
@@ -163,7 +164,7 @@ wire [0:9] sprite_x_matches = {
|
||||
sprite_x[9] == h_cnt
|
||||
};
|
||||
|
||||
assign sprite_fetch = |sprite_x_matches & oam_fetch;
|
||||
assign sprite_fetch = |sprite_x_matches & oam_fetch & (isGBC | sprite_en);
|
||||
|
||||
wire [3:0] active_sprite =
|
||||
sprite_x_matches[0] ? 4'd0 :
|
||||
|
||||
81
rtl/video.v
81
rtl/video.v
@@ -71,8 +71,8 @@ sprites sprites (
|
||||
.ce ( ce ),
|
||||
.ce_cpu ( ce_cpu ),
|
||||
.size16 ( lcdc_spr_siz ),
|
||||
.isGBC_game ( isGBC&&isGBC_game ),
|
||||
|
||||
.isGBC ( isGBC ),
|
||||
.sprite_en( lcdc_spr_ena ),
|
||||
.lcd_on ( lcd_on ),
|
||||
|
||||
.v_cnt ( v_cnt ),
|
||||
@@ -228,7 +228,8 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
wire mode3_end = ~sprite_found & (pcnt == 8'd167);
|
||||
wire mode3_end = isGBC ? pcnt_end : (~sprite_found & pcnt_end);
|
||||
|
||||
reg mode3_end_l;
|
||||
always @(posedge clk) begin
|
||||
if (!lcd_on) begin
|
||||
@@ -254,7 +255,7 @@ assign vblank_irq = vblank_l;
|
||||
// Except on the first line when the LCD is enabled after being disabled
|
||||
// where it starts at cycle 0.
|
||||
wire oam = lcd_on & ~end_of_line & ~oam_eval_end;
|
||||
wire mode3 = lcd_on & ~mode3_end_l & oam_eval_end;
|
||||
wire mode3 = lcd_on & (isGBC ? ~mode3_end : ~mode3_end_l) & oam_eval_end;
|
||||
|
||||
assign mode =
|
||||
vblank_l ? 2'b01 :
|
||||
@@ -361,6 +362,8 @@ reg skip_en;
|
||||
reg [7:0] skip;
|
||||
reg [7:0] pcnt;
|
||||
|
||||
wire pcnt_end = ( pcnt == (isGBC ? 8'd168 : 8'd167) );
|
||||
wire pcnt_reset = end_of_line & ~vblank;
|
||||
always @(posedge clk) begin
|
||||
if (!lcd_on) begin
|
||||
skip_en <= 1'b0;
|
||||
@@ -382,12 +385,12 @@ always @(posedge clk) begin
|
||||
|
||||
// Pixels 0-7 are for fetching partially offscreen sprites and window.
|
||||
// Pixels 8-167 are output to the display.
|
||||
if(~skip_en && pcnt != 8'd167)
|
||||
if(~skip_en & ~pcnt_end)
|
||||
pcnt <= pcnt + 1'd1;
|
||||
|
||||
end
|
||||
|
||||
if (end_of_line & ~vblank) begin
|
||||
if (pcnt_reset) begin
|
||||
pcnt <= 8'd0;
|
||||
end
|
||||
end
|
||||
@@ -395,11 +398,6 @@ end
|
||||
|
||||
reg [8:0] h_cnt; // max 455
|
||||
reg [7:0] v_cnt; // max 153
|
||||
reg [7:0] win_line;
|
||||
|
||||
// TODO: Fix window_x = A6. Hblank starts when it should be waiting for the window fetching to end
|
||||
wire win_start = lcdc_win_ena && ~sprite_fetch_hold && ~skip_en && ~bg_shift_empty && (v_cnt >= wy) && (pcnt == wx) && (wx < 8'hA6);
|
||||
reg window_ena;
|
||||
|
||||
// vcnt_reset goes high a few cycles after v_cnt is incremented to 153.
|
||||
// It resets v_cnt back to 0 and keeps it in reset until the following line.
|
||||
@@ -409,19 +407,16 @@ reg vcnt_reset;
|
||||
always @(posedge clk) begin
|
||||
if (!lcdc_on) begin
|
||||
v_cnt <= 8'd0;
|
||||
win_line <= 8'd0;
|
||||
vcnt_reset <= 1'b0;
|
||||
end else if (ce) begin
|
||||
if (~vcnt_reset && h_cnt == 9'd455) begin
|
||||
v_cnt <= v_cnt + 1'b1;
|
||||
if (window_ena) win_line <= win_line + 1'b1;
|
||||
end
|
||||
|
||||
if (end_of_line && &h_cnt[1:0]) begin
|
||||
vcnt_reset <= line153;
|
||||
if (line153) begin
|
||||
v_cnt <= 8'd0;
|
||||
win_line <= 8'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -436,35 +431,51 @@ reg [4:0] win_col;
|
||||
wire [9:0] win_map_addr = {win_line[7:3], win_col[4:0]};
|
||||
|
||||
wire [9:0] bg_tile_map_addr = window_ena ? win_map_addr : bg_map_addr;
|
||||
|
||||
reg [7:0] win_line;
|
||||
wire [2:0] tile_line = window_ena ? win_line[2:0] : bg_line[2:0];
|
||||
|
||||
reg window_match, window_ena_d;
|
||||
|
||||
wire win_start = mode3 && lcdc_win_ena && ~sprite_fetch_hold && ~skip_en && ~bg_shift_empty && (v_cnt >= wy) && (pcnt == wx) && (wx < 8'hA7);
|
||||
wire window_ena = window_match & ~pcnt_reset & lcdc_win_ena;
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
if (!lcdc_on) begin
|
||||
//reset counters
|
||||
h_cnt <= 9'd0;
|
||||
window_ena <= 1'b0;
|
||||
window_match <= 1'b0;
|
||||
window_ena_d <= 1'b0;
|
||||
win_col <= 5'd0;
|
||||
win_line <= 8'd0;
|
||||
end else if (ce) begin
|
||||
h_cnt <= h455 ? 9'd0 : h_cnt + 9'd1;
|
||||
|
||||
if(h_cnt != 455) begin
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
|
||||
if(win_start) begin
|
||||
win_col <= 5'd0; // window always start with its very left
|
||||
window_ena <= 1'b1;
|
||||
end
|
||||
|
||||
// Increment when fetching is done and not waiting for sprites.
|
||||
if(window_ena && ~sprite_fetch_hold && bg_fetch_done && bg_reload_shift)
|
||||
win_col <= win_col + 1'b1;
|
||||
|
||||
end else begin
|
||||
window_ena <= 1'b0; // next line starts with background
|
||||
|
||||
// end of line reached
|
||||
h_cnt <= 9'd0;
|
||||
|
||||
if(win_start) begin
|
||||
window_match <= 1'b1;
|
||||
end
|
||||
|
||||
window_ena_d <= window_ena;
|
||||
if (vblank_l)
|
||||
win_line <= 8'd0;
|
||||
else if (window_ena_d & ~window_ena)
|
||||
win_line <= win_line + 1'b1;
|
||||
|
||||
if (window_match & ~mode3_end_l & mode3_end) begin
|
||||
// DMG glitch: If WX = A6 then window_match stays high through VBlank
|
||||
// until WY > v_cnt which means the window always appears on line 0.
|
||||
if (isGBC || wx != 8'hA6 || wy > v_cnt) begin
|
||||
window_match <= 1'b0; // next line starts with background
|
||||
end
|
||||
end
|
||||
|
||||
// Increment when fetching is done and not waiting for sprites.
|
||||
if(window_ena && ~sprite_fetch_hold && bg_fetch_done && bg_reload_shift)
|
||||
win_col <= win_col + 1'b1;
|
||||
|
||||
if (~lcdc_win_ena | pcnt_reset) win_col <= 5'd0;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -622,7 +633,9 @@ always @(posedge clk) begin
|
||||
if (~sprite_fetch_hold || sprite_fetch_done) sprite_fetch_cycle <= 0;
|
||||
|
||||
// Window start, reset fetching
|
||||
if (win_start || !mode3) begin
|
||||
// DMG glitch: fetching is not reset if WX = A6. The following lines all show
|
||||
// the window from the start of the line.
|
||||
if ( (win_start && (isGBC || wx != 8'hA6)) || !mode3) begin
|
||||
bg_fetch_cycle <= 0;
|
||||
bg_shift_cnt <= 0;
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user