GBC: added colour management to BG, full flags support for sprites (not used yet)

This commit is contained in:
Bruno Duarte Gouveia
2018-12-23 20:58:59 +00:00
parent 11a54c84ee
commit 034ca1ca96
4 changed files with 65 additions and 24 deletions

View File

@@ -488,7 +488,7 @@ wire cart_rd;
wire cart_wr;
wire lcd_clkena;
wire [1:0] lcd_data;
wire [14:0] lcd_data;
wire [1:0] lcd_mode;
wire lcd_on;
@@ -534,7 +534,7 @@ lcd lcd (
.pclk ( clk_sys ),
.pce ( ce_pix ),
.clk ( clk_cpu ),
.isGBC ( /*status[11]*/ ),
.isGBC ( status[11] ),
.tint ( status[1] ),
.inv ( status[12] ),

7
gb.v
View File

@@ -152,6 +152,7 @@ GBse cpu (
wire clk_cpu = clk;
reg cpu_speed; // - 0 Normal mode (4MHz) - 1 Double Speed Mode (8MHz)
reg prepare_switch; // set to 1 to toggle speed
assign speed = cpu_speed;
always @(posedge clk2x) begin
if(reset) begin
@@ -359,6 +360,8 @@ video video (
.reset ( reset ),
.clk ( clk ),
.clk_dma ( clk_cpu ), //can be 2x in cgb double speed mode
.isGBC ( isGBC ),
.irq ( video_irq ),
@@ -378,6 +381,9 @@ video video (
.vram_addr ( video_addr ),
.vram_data ( vram_do ),
// vram connection bank1 (GBC)
.vram1_data ( vram1_do ),
.dma_rd ( dma_rd ),
.dma_addr ( dma_addr ),
.dma_data ( dma_data )
@@ -399,7 +405,6 @@ wire vram1_wren = video_rd?1'b0:vram_bank&&((hdma_rd&&isGBC)||cpu_wr_vram);
wire [12:0] vram_addr = video_rd?video_addr:(dma_rd&&dma_sel_vram)?dma_addr[12:0]:(hdma_rd&&isGBC)?hdma_target_addr[12:0]:cpu_addr[12:0];
spram #(13) vram0 (
.clock ( clk ),
.address ( vram_addr ),

View File

@@ -64,14 +64,14 @@ wire visible = v_visible && (h_cnt + 8'd8 >= x_pos) && (h_cnt < x_pos);
// x position within sprite, mirror horizontally if required
wire [7:0] col_n = h_cnt - x_pos;
wire [2:0] col = flags[1]?col_n[2:0]:~col_n[2:0];
wire [2:0] col = flags[5]?col_n[2:0]:~col_n[2:0];
assign pixel_data = { data1[col], data0[col] };
assign pixel_active = (pixel_data != 0) && visible;
// y position within sprite, mirror vertically if required
wire [7:0] row_n = v_cnt - y_pos;
wire [3:0] row = flags[2]?~row_n[3:0]:row_n[3:0];
wire [3:0] row = flags[6]?~row_n[3:0]:row_n[3:0];
// 16 pixel tall sprites use one more rwo counter bit and the lsb
// of the tile index is ignored
@@ -79,13 +79,13 @@ wire [10:0] addr8 = { tile , row[2:0]};
wire [10:0] addr16 = { tile[7:1] , row};
assign addr = size16?addr16:addr8;
assign pixel_cmap = flags[0];
assign pixel_prio = flags[3];
assign pixel_cmap = flags[4];
assign pixel_prio = flags[7];
reg [7:0] y_pos;
reg [7:0] x_pos;
reg [7:0] tile;
reg [3:0] flags;
reg [7:0] flags;
always @(posedge clk) begin
if(oam_wr) begin
@@ -93,7 +93,7 @@ always @(posedge clk) begin
0: y_pos <= oam_di;
1: x_pos <= oam_di;
2: tile <= oam_di;
3: flags <= oam_di[7:4];
3: flags <= oam_di;
endcase
end
end
@@ -102,6 +102,6 @@ assign oam_do =
(oam_addr == 0)?y_pos:
(oam_addr == 1)?x_pos:
(oam_addr == 2)?tile:
{ flags, 4'h0 };
flags;
endmodule

64
video.v
View File

@@ -36,7 +36,7 @@ module video (
// output to lcd
output lcd_on,
output lcd_clkena,
output [1:0] lcd_data,
output [14:0] lcd_data,
output reg irq,
// vram connection
@@ -44,6 +44,9 @@ module video (
output vram_rd,
output [12:0] vram_addr,
input [7:0] vram_data,
// vram connection bank1 (GBC)
input [7:0] vram1_data,
// dma connection
output dma_rd,
@@ -299,27 +302,36 @@ assign cpu_do =
assign lcd_data = stage2_data;
assign lcd_clkena = stage2_clkena;
reg [1:0] stage2_data;
reg [14:0] stage2_data;
reg stage2_clkena;
reg [1:0] stage2_buffer [159:0];
reg [2:0] stage2_bgp_buffer [19:0]; //GBC only keep record of palette used for tile
reg [7:0] stage2_wptr;
reg [7:0] stage2_rptr;
reg [4:0] bg_palette_rptr; //GBC
reg [2:0] bg_palette_rcnt;
wire [5:0] palette_index = (stage2_bgp_buffer[bg_palette_rptr] << 3) + (stage2_buffer[stage2_rptr]<<1); //gbc
// apply bg palette
wire [1:0] stage2_bg_pix = (!lcdc_bg_ena && !window_ena)?2'b11: // background off?
(stage2_buffer[stage2_rptr] == 2'b00)?bgp[1:0]:
(stage2_buffer[stage2_rptr] == 2'b01)?bgp[3:2]:
(stage2_buffer[stage2_rptr] == 2'b10)?bgp[5:4]:
bgp[7:6];
wire [14:0] stage2_bg_pix = (!lcdc_bg_ena && !window_ena)?15'h7FFF: // background off?
isGBC?{bgpd[palette_index+1][6:0],bgpd[palette_index]}: //gbc
(stage2_buffer[stage2_rptr] == 2'b00)?{13'd0,bgp[1:0]}:
(stage2_buffer[stage2_rptr] == 2'b01)?{13'd0,bgp[3:2]}:
(stage2_buffer[stage2_rptr] == 2'b10)?{13'd0,bgp[5:4]}:
{13'd0,bgp[7:6]};
// apply sprite palette
wire [7:0] obp = sprite_pixel_cmap?obp1:obp0;
wire [1:0] sprite_pix =
(sprite_pixel_data == 2'b00)?obp[1:0]:
(sprite_pixel_data == 2'b01)?obp[3:2]:
(sprite_pixel_data == 2'b10)?obp[5:4]:
obp[7:6];
wire [14:0] sprite_pix =
(sprite_pixel_data == 2'b00)?{13'd0,obp[1:0]}:
(sprite_pixel_data == 2'b01)?{13'd0,obp[3:2]}:
(sprite_pixel_data == 2'b10)?{13'd0,obp[5:4]}:
{13'd0,obp[7:6]};
// a sprite pixel is visible if
// - sprites are enabled
@@ -335,6 +347,8 @@ always @(posedge clk) begin
if(h_cnt == 455) begin
stage2_wptr <= 8'h00;
stage2_rptr <= 8'h00;
bg_palette_rptr <= 5'd0; //GBC
bg_palette_rcnt <= 3'b111;
end
if(stage1_clkena) begin
@@ -349,6 +363,10 @@ always @(posedge clk) begin
else stage2_data <= stage2_bg_pix;
stage2_rptr <= stage2_rptr + 8'd1;
bg_palette_rcnt <= bg_palette_rcnt - 3'd1;
if (bg_palette_rcnt==0)
bg_palette_rptr <= bg_palette_rptr + 5'd1;
end
end
@@ -363,20 +381,38 @@ reg [7:0] tile_shift_0;
reg [7:0] tile_shift_1;
reg [7:0] bg_tile;
reg [7:0] bg_tile_attr; //GBC
reg [7:0] bg_tile_data0;
reg [7:0] bg_tile_data1;
reg [4:0] bg_palette_wptr; //GBC
wire stage1_clkena = !vblank && hdvalid;
wire [1:0] stage1_data = { tile_shift_1[7], tile_shift_0[7] };
// read data half a clock cycle after ram has been selected
always @(posedge clk) begin
if (reset || (h_cnt == 455))
bg_palette_wptr <= 5'd0;
// every memory access is two pixel cycles
if(h_cnt[0]) begin
if(bg_tile_map_rd) bg_tile <= vram_data;
if(bg_tile_data0_rd) bg_tile_data0 <= vram_data;
if(bg_tile_data1_rd) bg_tile_data1 <= vram_data;
if (isGBC) begin
if(bg_tile_map_rd) begin
bg_tile_attr <= vram1_data; //get tile attr from vram bank1
stage2_bgp_buffer[bg_palette_wptr] <= vram1_data[2:0]; //keep a copy of the palette used
bg_palette_wptr <= bg_palette_wptr + 5'd1;
end
if(bg_tile_data0_rd) bg_tile_data0 <= bg_tile_attr[3]?vram1_data:vram_data;
if(bg_tile_data1_rd) bg_tile_data1 <= bg_tile_attr[3]?vram1_data:vram_data;
end else begin
if(bg_tile_data0_rd) bg_tile_data0 <= vram_data;
if(bg_tile_data1_rd) bg_tile_data1 <= vram_data;
end
// sprite data is evaluated inside the sprite engine
end