mirror of
https://github.com/MiSTer-devel/Gameboy_MiSTer.git
synced 2026-05-17 03:03:43 +00:00
SGB: Add option to load SGB border
This commit is contained in:
26
Gameboy.sv
26
Gameboy.sv
@@ -201,13 +201,14 @@ localparam CONF_STR = {
|
||||
"FS1,GBCGB ,Load ROM;",
|
||||
"OEF,System,Auto,Gameboy,Gameboy Color;",
|
||||
"ONO,Super Game Boy,Off,Palette,On;",
|
||||
"d5FC2,SGB,Load SGB border;",
|
||||
"-;",
|
||||
"C,Cheats;",
|
||||
"h0OH,Cheats enabled,Yes,No;",
|
||||
"-;",
|
||||
"OC,Inverted color,No,Yes;",
|
||||
"O12,Custom Palette,Off,Auto,On;",
|
||||
"h1F2,GBP,Load Palette;",
|
||||
"h1FC3,GBP,Load Palette;",
|
||||
"-;",
|
||||
"h2R9,Load Backup RAM;",
|
||||
"h2RA,Save Backup RAM;",
|
||||
@@ -325,7 +326,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io
|
||||
|
||||
.buttons(buttons),
|
||||
.status(status),
|
||||
.status_menumask({isGBC,cart_ready,sav_supported,|tint,gg_available}),
|
||||
.status_menumask({sgb_border_en,isGBC,cart_ready,sav_supported,|tint,gg_available}),
|
||||
.direct_video(direct_video),
|
||||
.gamma_bus(gamma_bus),
|
||||
.forced_scandoubler(forced_scandoubler),
|
||||
@@ -346,8 +347,9 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
wire cart_download = ioctl_download && (filetype == 8'h01 || filetype == 8'h41 || filetype == 8'h80);
|
||||
wire palette_download = ioctl_download && (filetype == 2 || !filetype);
|
||||
wire palette_download = ioctl_download && (filetype == 3 || !filetype);
|
||||
wire bios_download = ioctl_download && (filetype == 8'h40);
|
||||
wire sgb_border_download = ioctl_download && (filetype == 2);
|
||||
|
||||
wire [1:0] sdram_ds = cart_download ? 2'b11 : {cart_addr[0], ~cart_addr[0]};
|
||||
wire [15:0] sdram_do;
|
||||
@@ -675,7 +677,7 @@ gb gb (
|
||||
|
||||
.isGBC ( isGBC ),
|
||||
.isGBC_game ( isGBC_game ),
|
||||
.isSGB ( ~sgb_en[1] & ~isGBC ),
|
||||
.isSGB ( |sgb_en & ~isGBC ),
|
||||
|
||||
.joy_p54 ( joy_p54 ),
|
||||
.joy_din ( joy_do_sgb ),
|
||||
@@ -789,7 +791,7 @@ lcd lcd
|
||||
|
||||
.sgb_border_pix ( sgb_border_pix),
|
||||
.sgb_pal_en ( sgb_pal_en ),
|
||||
.sgb_en ( !sgb_en ),
|
||||
.sgb_en ( sgb_border_en ),
|
||||
|
||||
.clk_vid( CLK_VIDEO ),
|
||||
.hs ( video_hs ),
|
||||
@@ -811,7 +813,8 @@ wire [15:0] sgb_border_pix;
|
||||
wire sgb_lcd_clkena, sgb_lcd_on, sgb_lcd_vsync;
|
||||
wire [1:0] sgb_lcd_mode;
|
||||
wire sgb_pal_en;
|
||||
wire [1:0] sgb_en = {~status[24] ^ status[23], status[23]};
|
||||
wire [1:0] sgb_en = status[24:23];
|
||||
wire sgb_border_en = sgb_en[1];
|
||||
|
||||
sgb sgb (
|
||||
.reset ( reset ),
|
||||
@@ -828,7 +831,7 @@ sgb sgb (
|
||||
.joy_p54 ( joy_p54 ),
|
||||
.joy_do ( joy_do_sgb ),
|
||||
|
||||
.sgb_en ( ~sgb_en[1] & isSGB_game & ~isGBC ),
|
||||
.sgb_en ( |sgb_en & isSGB_game & ~isGBC ),
|
||||
.tint ( tint[1] ),
|
||||
|
||||
.lcd_on ( lcd_on ),
|
||||
@@ -840,6 +843,11 @@ sgb sgb (
|
||||
.h_cnt ( h_cnt ),
|
||||
.v_cnt ( v_cnt ),
|
||||
|
||||
.border_download (sgb_border_download),
|
||||
.ioctl_wr (ioctl_wr),
|
||||
.ioctl_addr (ioctl_addr),
|
||||
.ioctl_dout (ioctl_dout),
|
||||
|
||||
.sgb_border_pix ( sgb_border_pix ),
|
||||
.sgb_pal_en ( sgb_pal_en ),
|
||||
.sgb_lcd_data ( sgb_lcd_data ),
|
||||
@@ -877,8 +885,8 @@ video_freak video_freak
|
||||
.VGA_DE_IN(VGA_DE),
|
||||
.VGA_DE(),
|
||||
|
||||
.ARX((!ar) ? 12'd10 : (ar - 1'd1)),
|
||||
.ARY((!ar) ? 12'd9 : 12'd0),
|
||||
.ARX((!ar) ? (sgb_border_en ? 12'd16 : 12'd10) : (ar - 1'd1)),
|
||||
.ARY((!ar) ? (sgb_border_en ? 12'd14 : 12'd9 ) : 12'd0),
|
||||
.CROP_SIZE(0),
|
||||
.CROP_OFF(0),
|
||||
.SCALE(status[22:21])
|
||||
|
||||
@@ -114,7 +114,7 @@ parameter HTOTAL = H+HFP+HS+HBP;
|
||||
|
||||
parameter H_BORDER = 48;
|
||||
parameter V_BORDER = 40;
|
||||
parameter H_START = 4+H_BORDER;
|
||||
parameter H_START = 9+H_BORDER;
|
||||
|
||||
parameter V = 144; // height of visible area
|
||||
parameter VS_START = 37; // start of vsync
|
||||
|
||||
136
rtl/sgb.v
136
rtl/sgb.v
@@ -26,6 +26,11 @@ module sgb (
|
||||
input [1:0] joy_p54,
|
||||
output [3:0] joy_do,
|
||||
|
||||
input border_download,
|
||||
input ioctl_wr,
|
||||
input [13:0] ioctl_addr,
|
||||
input [15:0] ioctl_dout,
|
||||
|
||||
output reg [15:0] sgb_border_pix,
|
||||
|
||||
output reg sgb_pal_en,
|
||||
@@ -403,13 +408,13 @@ 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;
|
||||
reg old_border_download;
|
||||
|
||||
wire [8:0] tile_number = {tile_offset+pix_x[7:3]};
|
||||
|
||||
wire [13:0] pixel_wr_addr = {tile_number[7:0], pix_y[2:0],pix_x[2:0]};
|
||||
|
||||
// Convert 2x 2bpp tiles to 1x 4bpp tile for border output
|
||||
wire [13:0] tile_addr = {tile_number[7:1], pix_y[2:0],pix_x[2:0], tile_number[0]};
|
||||
wire [10:0] tile_addr = {tile_number[7:0], pix_y[2:0]};
|
||||
|
||||
wire [15:0] trn_data = {trn_data_h,lcd_data[1],trn_data_l,lcd_data[0]};
|
||||
|
||||
@@ -471,55 +476,70 @@ always @(posedge clk_sys) begin
|
||||
end
|
||||
end
|
||||
|
||||
old_border_download <= border_download;
|
||||
if (old_border_download ^ border_download) begin
|
||||
output_border <= ~border_download;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
localparam TILE_RAM_SIZE = 14'd8192;
|
||||
localparam TILE_MAP_SIZE = 14'd1792;
|
||||
localparam TILE_PAL_SIZE = 14'd0128;
|
||||
|
||||
(* ramstyle="no_rw_check" *) reg [15:0] tile_map_ram[32*28];
|
||||
(* ramstyle="no_rw_check" *) reg [14:0] tile_pal_ram[4*16];
|
||||
(* ramstyle="no_rw_check" *) reg [14:0] sys_pal_ram[512*4];
|
||||
(* ramstyle="no_rw_check" *) reg [15:0] attr_files_ram[45*45];
|
||||
|
||||
wire trn_data_wr = (lcd_clkena && trn_en && &pix_x[2:0] && !tile_number[8]);
|
||||
wire trn_data_wr = (ce && lcd_clkena && trn_en && &pix_x[2:0] && !tile_number[8]);
|
||||
|
||||
wire tile_map_download = (border_download && ioctl_wr && ioctl_addr >= TILE_RAM_SIZE && ioctl_addr < TILE_RAM_SIZE+TILE_MAP_SIZE);
|
||||
wire [9:0] tile_map_wr_addr = tile_map_download ? ioctl_addr[10:1] : pixel_wr_addr[12:3];
|
||||
wire [15:0] tile_map_wr_data = tile_map_download ? ioctl_dout : trn_data;
|
||||
|
||||
wire tile_pal_download = (border_download && ioctl_wr && ioctl_addr >= TILE_RAM_SIZE+TILE_MAP_SIZE && ioctl_addr < TILE_RAM_SIZE+TILE_MAP_SIZE+TILE_PAL_SIZE);
|
||||
wire [5:0] tile_pal_wr_addr = tile_pal_download ? ioctl_addr[6:1] : pixel_wr_addr[8:3];
|
||||
wire [14:0] tile_pal_wr_data = tile_pal_download ? ioctl_dout[14:0] : trn_data[14:0];
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if (ce) begin
|
||||
|
||||
if (trn_data_wr) begin
|
||||
// PCT_TRN Tile 0-111
|
||||
if (cmd == CMD_PCT_TRN && pixel_wr_addr[13:6] < 8'd112) begin
|
||||
tile_map_ram[pixel_wr_addr[12:3]] <= trn_data;
|
||||
end
|
||||
|
||||
// PCT_TRN Tile 128-135
|
||||
if (cmd == CMD_PCT_TRN && pixel_wr_addr[13:9] == 6'b10000) begin
|
||||
tile_pal_ram[pixel_wr_addr[8:3]] <= trn_data[14:0];
|
||||
end
|
||||
|
||||
if (cmd == CMD_PAL_TRN) begin
|
||||
sys_pal_ram[pixel_wr_addr[13:3]] <= trn_data[14:0];
|
||||
end
|
||||
|
||||
if (cmd == CMD_ATTR_TRN && pixel_wr_addr[13:3] < 11'd2025) begin
|
||||
attr_files_ram[pixel_wr_addr[13:3]] <= {trn_data[7:0],trn_data[15:8]};
|
||||
end
|
||||
// PCT_TRN Tile 0-111
|
||||
if ( (trn_data_wr && cmd == CMD_PCT_TRN && pixel_wr_addr[13:6] < 8'd112) || tile_map_download ) begin
|
||||
tile_map_ram[tile_map_wr_addr] <= tile_map_wr_data;
|
||||
end
|
||||
|
||||
end
|
||||
// PCT_TRN Tile 128-135
|
||||
if ( (trn_data_wr && cmd == CMD_PCT_TRN && pixel_wr_addr[13:9] == 6'b10000) || tile_pal_download ) begin
|
||||
tile_pal_ram[tile_pal_wr_addr] <= tile_pal_wr_data;
|
||||
end
|
||||
|
||||
if (trn_data_wr && cmd == CMD_PAL_TRN) begin
|
||||
sys_pal_ram[pixel_wr_addr[13:3]] <= trn_data[14:0];
|
||||
end
|
||||
|
||||
if (trn_data_wr && cmd == CMD_ATTR_TRN && pixel_wr_addr[13:3] < 11'd2025) begin
|
||||
attr_files_ram[pixel_wr_addr[13:3]] <= {trn_data[7:0],trn_data[15:8]};
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
dpram_dif #(15,2, 14,4) tile_ram (
|
||||
.clock ( clk_vid ),
|
||||
wire tile_ram_download = (border_download && ioctl_wr && ioctl_addr < TILE_RAM_SIZE);
|
||||
wire [11:0] tile_ram_wr_addr = tile_ram_download ? ioctl_addr[12:1] : {char_trn_tile,tile_addr};
|
||||
wire [15:0] tile_ram_wr_data = tile_ram_download ? ioctl_dout : trn_data;
|
||||
|
||||
.address_a ( {char_trn_tile,tile_addr} ),
|
||||
.wren_a ( lcd_clkena && trn_en && cmd == CMD_CHR_TRN && !tile_number[8] ),
|
||||
.data_a ( lcd_data ),
|
||||
dpram #(12,16) tile_ram (
|
||||
.clock_a ( clk_sys ),
|
||||
.address_a ( tile_ram_wr_addr ),
|
||||
.wren_a ( (trn_data_wr && cmd == CMD_CHR_TRN) || tile_ram_download ),
|
||||
.data_a ( tile_ram_wr_data ),
|
||||
.q_a (),
|
||||
|
||||
.address_b (tile_rd_addr),
|
||||
.wren_b (1'b0),
|
||||
.data_b (),
|
||||
.q_b (tile_data)
|
||||
.clock_b ( clk_vid ),
|
||||
.address_b ( tile_rd_addr ),
|
||||
.wren_b ( 1'b0 ),
|
||||
.data_b (),
|
||||
.q_b ( tile_data )
|
||||
);
|
||||
|
||||
reg [14:0] sys_pal_data, pal_wr_data;
|
||||
@@ -812,31 +832,59 @@ always @(posedge clk_sys) begin
|
||||
end
|
||||
end
|
||||
|
||||
function [7:0] bit_reverse;
|
||||
input [7:0] a;
|
||||
begin
|
||||
bit_reverse = {a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
reg [15:0] bg_map_data;
|
||||
reg [1:0] bg_pal_no;
|
||||
reg [13:0] tile_rd_addr;
|
||||
reg [3:0] tile_data;
|
||||
reg [14:0] pal_data;
|
||||
reg pix_visible;
|
||||
reg [11:0] tile_rd_addr;
|
||||
reg [15:0] tile_data;
|
||||
reg [7:0] tile_plane_0, tile_plane_1, tile_plane_2, tile_plane_3;
|
||||
reg [7:0] tile_out_0, tile_out_1, tile_out_2, tile_out_3;
|
||||
reg [2:0] tile_fetch_cnt;
|
||||
|
||||
wire [8:0] bg_vcnt = v_cnt >= 9'd65 ? (v_cnt-9'd65) : (v_cnt+9'd264-9'd65);
|
||||
wire [3:0] pix_data = {tile_out_3[7], tile_out_2[7], tile_out_1[7], tile_out_0[7]};
|
||||
wire [14:0] pal_data = |pix_data ? tile_pal_ram[{bg_pal_no, pix_data}] : palette[0][0:14];
|
||||
|
||||
reg [8:0] h_cnt_r, v_cnt_r;
|
||||
// border output
|
||||
always @(posedge clk_vid) begin
|
||||
if (ce_pix) begin
|
||||
|
||||
bg_map_data <= tile_map_ram[{bg_vcnt[7:3],h_cnt[7:3]}];
|
||||
h_cnt_r <= h_cnt;
|
||||
v_cnt_r <= bg_vcnt;
|
||||
|
||||
bg_pal_no <= bg_map_data[11:10];
|
||||
tile_rd_addr <= {bg_map_data[7:0],bg_map_data[15] ? ~v_cnt_r[2:0] : v_cnt_r[2:0],bg_map_data[14] ? ~h_cnt_r[2:0] : h_cnt_r[2:0]};
|
||||
if (h_cnt == 9'd424) // end of line
|
||||
tile_fetch_cnt <= 0;
|
||||
else
|
||||
tile_fetch_cnt <= tile_fetch_cnt + 1'b1;
|
||||
|
||||
pix_visible <= |tile_data;
|
||||
pal_data <= |tile_data ? tile_pal_ram[{bg_pal_no, tile_data}] : palette[0][0:14];
|
||||
if (tile_fetch_cnt == 3'd1 || tile_fetch_cnt == 3'd2) begin
|
||||
tile_rd_addr <= {bg_map_data[7:0],(tile_fetch_cnt == 3'd1 ? 1'b0 : 1'b1),(bg_map_data[15] ? ~bg_vcnt[2:0] : bg_vcnt[2:0])};
|
||||
end
|
||||
|
||||
sgb_border_pix <= output_border ? {pix_visible, pal_data} : 16'd0;
|
||||
if (tile_fetch_cnt == 3'd2) {tile_plane_1, tile_plane_0} <= tile_data;
|
||||
|
||||
if (tile_fetch_cnt == 3'd3) {tile_plane_3, tile_plane_2} <= tile_data;
|
||||
|
||||
if (&tile_fetch_cnt) begin
|
||||
if (bg_map_data[14])
|
||||
{tile_out_0, tile_out_1, tile_out_2, tile_out_3} <= {bit_reverse(tile_plane_0), bit_reverse(tile_plane_1), bit_reverse(tile_plane_2), bit_reverse(tile_plane_3)};
|
||||
else
|
||||
{tile_out_0, tile_out_1, tile_out_2, tile_out_3} <= {tile_plane_0, tile_plane_1, tile_plane_2, tile_plane_3};
|
||||
|
||||
bg_pal_no <= bg_map_data[11:10];
|
||||
end else begin
|
||||
tile_out_0 <= tile_out_0 << 1;
|
||||
tile_out_1 <= tile_out_1 << 1;
|
||||
tile_out_2 <= tile_out_2 << 1;
|
||||
tile_out_3 <= tile_out_3 << 1;
|
||||
end
|
||||
|
||||
sgb_border_pix <= output_border ? {|pix_data, pal_data} : 16'd0;
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user