From a0d7e9231f760fb7e400c25d2daab301bc755d45 Mon Sep 17 00:00:00 2001 From: paulb-nl Date: Sun, 5 Jul 2020 10:47:26 +0200 Subject: [PATCH] SGB fixes --- Gameboy.sv | 16 ++++++++-------- rtl/lcd.v | 4 ++-- rtl/sgb.v | 48 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/Gameboy.sv b/Gameboy.sv index a52c374..37ba089 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -152,7 +152,7 @@ assign AUDIO_MIX = status[8:7]; // 0 1 2 3 // 01234567890123456789012345678901 // 0123456789ABCDEFGHIJKLMNOPQRSTUV -// XXXXXXXXXXX XXXX XXXX XX +// XXXXXXXXXXXXXXXX XXXX XX `include "build_id.v" localparam CONF_STR = { @@ -165,7 +165,7 @@ localparam CONF_STR = { "h0OH,Cheats enabled,Yes,No;", "-;", "OC,Inverted color,No,Yes;", - "O1,Palette,Auto,Custom;", + "O12,Custom Palette,Off,Auto,On;", "h1F2,GBP,Load Palette;", "-;", "h2R9,Load Backup RAM;", @@ -177,7 +177,7 @@ localparam CONF_STR = { "O5,Stabilize video(buffer),Off,On;", "O78,Stereo mix,none,25%,50%,100%;", "-;", - "O2,Boot,Normal,Fast;", + "OB,Boot,Normal,Fast;", "O6,Link Port,Disabled,Enabled;", "-;", "R0,Reset;", @@ -260,7 +260,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io .buttons(buttons), .status(status), - .status_menumask({sav_supported,tint,gg_available}), + .status_menumask({sav_supported,|tint,gg_available}), .direct_video(direct_video), .gamma_bus(gamma_bus), .forced_scandoubler(forced_scandoubler), @@ -562,7 +562,7 @@ gb gb ( .ce ( ce_cpu ), // the whole gameboy runs on 4mhnz .ce_2x ( ce_cpu2x ), // ~8MHz in dualspeed mode (GBC) - .fast_boot ( status[2] ), + .fast_boot ( status[11] ), .isGBC ( isGBC ), .isGBC_game ( isGBC_game ), @@ -614,7 +614,7 @@ wire video_hs, video_vs; wire HBlank, VBlank; wire ce_pix; wire [8:0] h_cnt, v_cnt; -wire tint = status[1]; +wire [1:0] tint = status[2:1]; lcd lcd ( @@ -627,7 +627,7 @@ lcd lcd .isGBC ( isGBC ), - .tint ( tint ), + .tint ( |tint ), .inv ( status[12] ), .double_buffer( status[5]), @@ -679,7 +679,7 @@ sgb sgb ( .joy_do ( joy_do_sgb ), .sgb_en ( ~sgb_en[1] & isSGB_game & ~isGBC ), - .tint ( tint ), + .tint ( tint[1] ), .lcd_on ( lcd_on ), .lcd_clkena ( lcd_clkena ), diff --git a/rtl/lcd.v b/rtl/lcd.v index 5b3b9c2..9a1b882 100644 --- a/rtl/lcd.v +++ b/rtl/lcd.v @@ -209,12 +209,12 @@ always@(posedge clk_vid) begin r <= r10[8:1]; g <= {g10[6:0],1'b0}; b <= b10[8:1]; - end else if (tint) begin - {r,g,b} <= (pixel==0) ? pal1 : (pixel==1) ? pal2 : (pixel==2) ? pal3 : pal4; end else if (sgb_pal_en) begin r <= {r5,r5[4:2]}; g <= {g5,g5[4:2]}; b <= {b5,b5[4:2]}; + end else if (tint) begin + {r,g,b} <= (pixel==0) ? pal1 : (pixel==1) ? pal2 : (pixel==2) ? pal3 : pal4; end else begin {r,g,b} <= {3{grey}}; end diff --git a/rtl/sgb.v b/rtl/sgb.v index 2628167..5224947 100644 --- a/rtl/sgb.v +++ b/rtl/sgb.v @@ -112,14 +112,14 @@ always @(posedge clk_sys) begin old_p15 <= p15; old_p14 <= p14; - if (old_p15 & old_p14 & sgb_en) begin + if (sgb_en) begin // Reset pulse if (~p15 & ~p14) begin {cnt, byte_cnt, packet_end} <= 0; end - if (p15 ^ p14) begin + if ( old_p15 & old_p14 & (p15 ^ p14) ) begin if (~packet_end) begin data <= {~p15,data[7:1]}; cnt <= cnt + 1'b1; @@ -127,11 +127,10 @@ always @(posedge clk_sys) begin end end - end - - // Corrupt packet. p15 and p14 should both go high after one is low. - if ( (old_p15 ^ p15) & (old_p15 ^ old_p14) & (p15 ^ p14) ) begin - packet_end <= 1'b1; + // Corrupt packet. p15 and p14 should both go high after one is low. + if ( (old_p15 ^ p15) & (old_p15 ^ old_p14) & (p15 ^ p14) ) begin + packet_end <= 1'b1; + end end trn_start <= 0; @@ -201,6 +200,7 @@ always @(posedge clk_sys) begin {CMD_PAL23,4'd9}, {CMD_PAL03,4'd9}: pal0123_no <= 2'd3; endcase + end CMD_PAL_SET: case (byte_cnt) @@ -390,6 +390,7 @@ reg [7:0] pix_x, pix_y; reg [8:0] tile_offset; reg [6:0] trn_data_h, trn_data_l; reg output_border = 0; +reg pct_trn_done, chr_trn_done; wire [8:0] tile_number = {tile_offset+pix_x[7:3]}; @@ -402,7 +403,10 @@ wire [15:0] trn_data = {trn_data_h,lcd_data[1],trn_data_l,lcd_data[0]}; always @(posedge clk_sys) begin - if (ce) begin + if (reset) begin + pct_trn_done <= 0; + chr_trn_done <= 0; + end else if (ce) begin frame_end <= 0; old_lcd_off <= lcd_off; @@ -430,7 +434,10 @@ always @(posedge clk_sys) begin if (pix_x == 8'd159 && pix_y == 8'd103) begin // 256 tiles trn_en <= 0; - if (trn_en && cmd == CMD_PCT_TRN) output_border <= 1'b1; + if (trn_en) begin + if (cmd == CMD_PCT_TRN) pct_trn_done <= 1'b1; + if (cmd == CMD_CHR_TRN) chr_trn_done <= 1'b1; + end end end @@ -441,10 +448,15 @@ always @(posedge clk_sys) begin trn_wait <= 0; if (trn_wait) begin trn_en <= 1'b1; - if (cmd == CMD_CHR_TRN) output_border <= 0; + if (cmd == CMD_CHR_TRN || cmd == CMD_PCT_TRN) output_border <= 0; end end + if (pct_trn_done & chr_trn_done & !mask_en) begin + pct_trn_done <= 0; + chr_trn_done <= 0; + output_border <= 1'b1; + end end end @@ -488,7 +500,7 @@ dpram_dif #(15,2, 14,4) tile_ram ( .clock ( clk_vid ), .address_a ( {char_trn_tile,tile_addr} ), - .wren_a ( lcd_clkena && trn_en && cmd == CMD_CHR_TRN), + .wren_a ( lcd_clkena && trn_en && cmd == CMD_CHR_TRN && !tile_number[8] ), .data_a ( lcd_data ), .q_a (), @@ -525,6 +537,7 @@ always @(posedge clk_sys) begin pal_set_wait <= 0; pal_set_busy <= 1'b1; pal_set_cnt <= 0; + pal_set_cnt_r <= 0; end sys_pal_data <= sys_pal_ram[{sys_pal_no[pal_set_cnt[3:2]], pal_set_cnt[1:0]}]; @@ -822,31 +835,34 @@ reg [14:0] lcd_data_r; reg [1:0] pal_no; reg lcd_clkena_r, lcd_on_r; reg [1:0] lcd_mode_r; +reg [1:0] mask_en_r; wire [1:0] lcd_data_2 = lcd_data_r[1:0]; // Lcd pixel output always @(posedge clk_sys) begin if (ce) begin + if (lcd_off) mask_en_r <= mask_en; + pal_no <= attr_file[tile_number*2 +: 2]; lcd_data_r <= lcd_data; lcd_clkena_r <= lcd_clkena; lcd_mode_r <= lcd_mode; lcd_on_r <= lcd_on; - if (~sgb_en | ((~output_sgb_pal | tint) & !mask_en) ) begin + if (~sgb_en | ((~output_sgb_pal | tint) & !mask_en_r) ) begin sgb_lcd_data <= lcd_data_r; - end else if (mask_en == 2'd2) begin + end else if (mask_en_r == 2'd2) begin sgb_lcd_data <= 0; - end else if (!lcd_data_2 || mask_en == 2'd3) begin + end else if (!lcd_data_2 || mask_en_r == 2'd3) begin sgb_lcd_data <= palette[0][0:14]; end else begin sgb_lcd_data <= palette[pal_no][lcd_data_2*15 +:15]; end - sgb_lcd_clkena <= (mask_en != 2'd1) ? lcd_clkena_r : 1'b0; + sgb_lcd_clkena <= (~sgb_en || mask_en_r != 2'd1) ? lcd_clkena_r : 1'b0; sgb_lcd_mode <= lcd_mode_r; sgb_lcd_on <= lcd_on_r; - sgb_pal_en <= sgb_en & (output_sgb_pal || |mask_en); + sgb_pal_en <= sgb_en & ( (output_sgb_pal & ~tint) || |mask_en_r); end end