diff --git a/Gameboy.sv b/Gameboy.sv index b90a2a6..57df4a0 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -49,7 +49,7 @@ module emu output VGA_HS, output VGA_VS, output VGA_DE, // = ~(VBlank | HBlank) - output VGA_F1, + output VGA_F1, output [1:0] VGA_SL, output LED_USER, // 1 - ON, 0 - OFF. @@ -97,14 +97,14 @@ module emu output SDRAM_nCS, output SDRAM_nCAS, output SDRAM_nRAS, - output SDRAM_nWE, - - input UART_CTS, - output UART_RTS, - input UART_RXD, - output UART_TXD, - output UART_DTR, - input UART_DSR + output SDRAM_nWE, + + input UART_CTS, + output UART_RTS, + input UART_RXD, + output UART_TXD, + output UART_DTR, + input UART_DSR ); assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = 0; @@ -124,17 +124,22 @@ assign VIDEO_ARY = status[3] ? 8'd9 : 8'd3; assign AUDIO_MIX = status[8:7]; `include "build_id.v" -localparam CONF_STR = { +localparam CONF_STR1 = { "GAMEBOY;;", "-;", "F,GB;", "-;", - "O1,LCD tint,White,Yellow;", - "O4,Inverted,No,Yes;", + "O4,Inverted color,No,Yes;", + "O1,Palette,Grayscale,Custom;" +}; + +localparam CONF_STR2 = { + ",GBP;", + "-;", "O3,Aspect ratio,4:3,16:9;", "O78,Stereo mix,none,25%,50%,100%;", "-;", - "O2,Boot,Normal,Fast;", + "O2,Boot,Normal,Fast;", "-;", "R6,Reset;", "J1,A,B,Select,Start;", @@ -168,19 +173,21 @@ reg ioctl_wait; wire [15:0] joystick_0, joystick_1; wire [15:0] joystick = joystick_0 | joystick_1; +wire [7:0] filetype; -hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io +hps_io #(.STRLEN(($size(CONF_STR1)>>3) + ($size(CONF_STR2)>>3) + 1), .WIDE(1)) hps_io ( .clk_sys(clk_sys), .HPS_BUS(HPS_BUS), - .conf_str(CONF_STR), + .conf_str({CONF_STR1,status[1]?"F":"+",CONF_STR2}), .ioctl_download(ioctl_download), .ioctl_wr(ioctl_wr), .ioctl_addr(ioctl_addr), .ioctl_dout(ioctl_dout), .ioctl_wait(ioctl_wait), + .ioctl_index(filetype), .buttons(buttons), .status(status), @@ -191,13 +198,16 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io /////////////////////////////////////////////////// +wire cart_download = ioctl_download && (filetype == 8'h01); +wire palette_download = ioctl_download && (filetype == 8'h04); + // TODO: ds for cart ram write -wire [1:0] sdram_ds = ioctl_download ? 2'b11 : {cart_addr[0], ~cart_addr[0]}; +wire [1:0] sdram_ds = cart_download ? 2'b11 : {cart_addr[0], ~cart_addr[0]}; wire [15:0] sdram_do; -wire [15:0] sdram_di = ioctl_download ? ioctl_dout : {cart_di, cart_di}; -wire [23:0] sdram_addr = ioctl_download? ioctl_addr[24:1]: {3'b000, mbc_bank, cart_addr[12:1]}; -wire sdram_oe = ~ioctl_download & cart_rd; -wire sdram_we = ioctl_download ? dn_write : cart_ram_wr; +wire [15:0] sdram_di = cart_download ? ioctl_dout : {cart_di, cart_di}; +wire [23:0] sdram_addr = cart_download? ioctl_addr[24:1]: {3'b000, mbc_bank, cart_addr[12:1]}; +wire sdram_oe = ~cart_download & cart_rd; +wire sdram_we = cart_download? dn_write : cart_ram_wr; assign SDRAM_CKE = 1; @@ -405,18 +415,23 @@ wire [8:0] mbc_bank = // HuC3?HuC3_addr: {7'b0000000, cart_addr[14:13]}; // no MBC, 32k linear address +reg [127:0] palette = 128'h828214517356305A5F1A3B4900000000; + always @(posedge clk_sys) begin if(!pll_locked) begin cart_mbc_type <= 8'h00; cart_rom_size <= 8'h00; cart_ram_size <= 8'h00; end else begin - if(ioctl_download & ioctl_wr) begin + if(cart_download & ioctl_wr) begin case(ioctl_addr) 'h146: cart_mbc_type <= ioctl_dout[15:8]; 'h148: { cart_ram_size, cart_rom_size } <= ioctl_dout; endcase - end + end + end + if (palette_download & ioctl_wr) begin + palette[127:0] <= {palette[111:0], ioctl_dout[7:0], ioctl_dout[15:8]}; end end @@ -439,7 +454,7 @@ wire lcd_on; assign AUDIO_S = 0; -wire reset = (RESET | status[0] | status[6] | buttons[1] | ioctl_download); +wire reset = (RESET | status[0] | status[6] | buttons[1] | cart_download); // the gameboy itself @@ -469,7 +484,7 @@ gb gb ( ); // the lcd to vga converter -wire [5:0] video_r, video_g, video_b; +wire [7:0] video_r, video_g, video_b; wire video_hs, video_vs, video_bl; lcd lcd ( @@ -480,6 +495,12 @@ lcd lcd ( .tint ( status[1] ), .inv ( status[4] ), + // Palettes + .pal1 (palette[127:104]), + .pal2 (palette[103:80]), + .pal3 (palette[79:56]), + .pal4 (palette[55:32]), + // serial interface .clkena ( lcd_clkena ), .data ( lcd_data ), @@ -495,9 +516,9 @@ lcd lcd ( ); assign VGA_SL = 0; -assign VGA_R = {video_r,video_r[5:4]}; -assign VGA_G = {video_g,video_g[5:4]}; -assign VGA_B = {video_b,video_b[5:4]}; +assign VGA_R = video_r; +assign VGA_G = video_g; +assign VGA_B = video_b; assign VGA_DE = ~video_bl; assign CLK_VIDEO = clk_sys; assign CE_PIXEL = ce_pix2; diff --git a/lcd.v b/lcd.v index e94a271..fd0b8fb 100644 --- a/lcd.v +++ b/lcd.v @@ -8,6 +8,12 @@ module lcd ( input clkena, input [1:0] data, input [1:0] mode, + + //palette + input [23:0] pal1, + input [23:0] pal2, + input [23:0] pal3, + input [23:0] pal4, input tint, input inv, @@ -21,9 +27,9 @@ module lcd ( output reg hs, output reg vs, output reg blank, - output [5:0] r, - output [5:0] g, - output [5:0] b + output [7:0] r, + output [7:0] g, + output [7:0] b ); // Mode 00: h-blank @@ -137,18 +143,17 @@ end wire [1:0] pixel = on? (pixel_reg ^ {inv,inv}) :2'b00; // gameboy "color" palette -wire [5:0] yellow_r = (pixel==0)?6'b100111:(pixel==1)?6'b100000: // 1:100011 - (pixel==2)?6'b001100:6'b000111; -wire [5:0] yellow_g = (pixel==0)?6'b101111:(pixel==1)?6'b101000: // 1:101011 - (pixel==2)?6'b011001:6'b000100; -wire [5:0] yellow_b = (pixel==0)?6'b000100:(pixel==1)?6'b000010: // 1:000100 - (pixel==2)?6'b001100:6'b000100; +wire [7:0] pal_r = (pixel==0)?pal1[23:16]:(pixel==1)?pal2[23:16]: + (pixel==2)?pal3[23:16]:pal4[23:16]; +wire [7:0] pal_g = (pixel==0)?pal1[15:8] :(pixel==1)?pal2[15:8] : + (pixel==2)?pal3[15:8] :pal4[15:8] ; +wire [7:0] pal_b = (pixel==0)?pal1[7:0] :(pixel==1)?pal2[7:0] : + (pixel==2)?pal3[7:0] :pal4[7:0] ; // greyscale -wire [5:0] grey = (pixel==0)?6'd63:(pixel==1)?6'd42:(pixel==2)?6'd24:6'd0; - -assign r = blank?6'b000000:tint?yellow_r:grey; -assign g = blank?6'b000000:tint?yellow_g:grey; -assign b = blank?6'b000000:tint?yellow_b:grey; +wire [7:0] grey = (pixel==0)?8'd252:(pixel==1)?8'd168:(pixel==2)?8'd96:8'd0; +assign r = blank?8'b00000000:tint?pal_r:grey; +assign g = blank?8'b00000000:tint?pal_g:grey; +assign b = blank?8'b00000000:tint?pal_b:grey; endmodule diff --git a/palettes/Biverted.gbp b/palettes/Biverted.gbp new file mode 100644 index 0000000..f90bfa0 Binary files /dev/null and b/palettes/Biverted.gbp differ diff --git a/palettes/DMG.gbp b/palettes/DMG.gbp new file mode 100644 index 0000000..f2c1732 Binary files /dev/null and b/palettes/DMG.gbp differ diff --git a/palettes/Yellow.gbp b/palettes/Yellow.gbp new file mode 100644 index 0000000..418b508 Binary files /dev/null and b/palettes/Yellow.gbp differ diff --git a/palettes/gbpalette.c b/palettes/gbpalette.c new file mode 100644 index 0000000..d8004c9 --- /dev/null +++ b/palettes/gbpalette.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +// GBP file format is simple. There are 4 palette colors using 8 bit +// rgb, starting from lightest ending in darkest for a total of 12 bytes. +// The last several bytes are 0, reserved for future use. + + +void gbp_get_color(uint8_t *palette, uint32_t index) +{ + char buffer[100]; + + printf ("Red (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + palette[index] = (uint8_t) strtol(buffer, NULL, 10); + + printf ("Green (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + palette[index + 1] = (uint8_t) strtol(buffer, NULL, 10); + + printf ("Blue (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + palette[index + 2] = (uint8_t) strtol(buffer, NULL, 10); +} + +int main (int argc, char **argv) +{ + uint8_t palette[16]; + memset(palette, 0, sizeof(palette)); + + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + FILE *f = fopen(argv[1], "w"); + if (!f) { + printf("Unable to open %s for writing.\n", argv[1]); + return 1; + } + + printf("Color 1:\n"); + gbp_get_color(palette, 0); + + printf("Color 2:\n"); + gbp_get_color(palette, 3); + + printf("Color 3:\n"); + gbp_get_color(palette, 6); + + printf("Color 4:\n"); + gbp_get_color(palette, 9); + + fwrite(palette, 1, 16, f); + + fclose(f); + + return 0; +} \ No newline at end of file