From a7ecdccc434307d09a8a226deb427e48ba39ac61 Mon Sep 17 00:00:00 2001 From: "U-COOKIE\\kitri" Date: Fri, 30 Nov 2018 14:13:59 -0600 Subject: [PATCH 1/3] Add custom palette loading --- Gameboy.sv | 69 ++++++++++++++++++++++++------------- lcd.v | 24 ++++++++----- palettes/Biverted.gbp | Bin 0 -> 16 bytes palettes/DMG.gbp | Bin 0 -> 16 bytes palettes/Yellow.gbp | Bin 0 -> 16 bytes palettes/gbpalette.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 33 deletions(-) create mode 100644 palettes/Biverted.gbp create mode 100644 palettes/DMG.gbp create mode 100644 palettes/Yellow.gbp create mode 100644 palettes/gbpalette.c diff --git a/Gameboy.sv b/Gameboy.sv index 469b48a..2ce7359 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; @@ -115,7 +115,7 @@ assign {UART_RTS, UART_TXD, UART_DTR} = 0; assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; assign LED_USER = ioctl_download; -assign LED_DISK = 0; +assign LED_DISK = palette_download; assign LED_POWER = 0; assign VIDEO_ARX = status[3] ? 8'd16 : 8'd4; @@ -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'h8201547153165C639200000000000000; + 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 @@ -480,6 +495,12 @@ lcd lcd ( .tint ( status[1] ), .inv ( status[4] ), + // Palettes + .pal1 (palette[127:110]), + .pal2 (palette[109:92]), + .pal3 (palette[91:74]), + .pal4 (palette[73:56]), + // serial interface .clkena ( lcd_clkena ), .data ( lcd_data ), diff --git a/lcd.v b/lcd.v index e94a271..1a5a1a9 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 [17:0] pal1, + input [17:0] pal2, + input [17:0] pal3, + input [17:0] pal4, input tint, input inv, @@ -137,18 +143,18 @@ 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 [5:0] pal_r = (pixel==0)?pal1[17:12]:(pixel==1)?pal2[17:12]: + (pixel==2)?pal3[17:12]:pal4[17:12]; +wire [5:0] pal_g = (pixel==0)?pal1[11:6] :(pixel==1)?pal2[11:6] : + (pixel==2)?pal3[11:6] :pal4[11:6] ; +wire [5:0] pal_b = (pixel==0)?pal1[5:0] :(pixel==1)?pal2[5:0] : + (pixel==2)?pal3[5:0] :pal4[5: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; +assign r = blank?6'b000000:tint?pal_r:grey; +assign g = blank?6'b000000:tint?pal_g:grey; +assign b = blank?6'b000000:tint?pal_b:grey; endmodule diff --git a/palettes/Biverted.gbp b/palettes/Biverted.gbp new file mode 100644 index 0000000000000000000000000000000000000000..b44c2581f7bfe2630a25bb14d6eb499d67bd53cc GIT binary patch literal 16 Tcmca!|9<<8>whoQFhBqRQ@sZD literal 0 HcmV?d00001 diff --git a/palettes/DMG.gbp b/palettes/DMG.gbp new file mode 100644 index 0000000000000000000000000000000000000000..310b52c8b700c9bf22f2a51d243ec5bad90fce70 GIT binary patch literal 16 ScmZo-3@Hp2i%Fiu0096a4FdxJ literal 0 HcmV?d00001 diff --git a/palettes/Yellow.gbp b/palettes/Yellow.gbp new file mode 100644 index 0000000000000000000000000000000000000000..baa7403efe19d4a8bce2d3617f15682e266b397c GIT binary patch literal 16 TcmbRDQDK3yq(LDI0|Wp7DxU)} literal 0 HcmV?d00001 diff --git a/palettes/gbpalette.c b/palettes/gbpalette.c new file mode 100644 index 0000000..b5c2d54 --- /dev/null +++ b/palettes/gbpalette.c @@ -0,0 +1,77 @@ +#include +#include +#include + +// GBP file format is simple. There are 4 palette colors using 6 bit +// rgb, starting from lightest ending in darkest for a total of 9 bytes. +// The last several bytes are 0, reserved for future use. + +void gbp_bitcopy(__uint128_t *dest, uint32_t dest_from, uint32_t source, + uint32_t source_from, uint32_t len) +{ + for (uint32_t x = 0; x < len; x++) { + uint8_t bit = (uint8_t) ((source & (1 << (source_from - x))) ? 1 : 0); + *dest |= (__uint128_t) bit << (dest_from - x); + } +} + +uint32_t gbp_get_color(void) +{ + char buffer[100]; + + printf ("Red (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + uint8_t red = (uint8_t) strtol(buffer, NULL, 10); + + printf ("Green (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + uint8_t green = (uint8_t) strtol(buffer, NULL, 10); + + printf ("Blue (0-255): "); + fgets(buffer, sizeof(buffer), stdin); + uint8_t blue = (uint8_t) strtol(buffer, NULL, 10); + + return (uint32_t) (((red >> 2) << 12) | ((green >> 2) << 6) | (blue >> 2)); +} + +int main (int argc, char **argv) +{ + __uint128_t palette = 0; + + if (argc < 1) { + 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"); + uint32_t color1 = gbp_get_color(); + + printf("Color 2:\n"); + uint32_t color2 = gbp_get_color(); + + printf("Color 3:\n"); + uint32_t color3 = gbp_get_color(); + + printf("Color 4:\n"); + uint32_t color4 = gbp_get_color(); + + gbp_bitcopy(&palette, 127, color1, 17, 18); + gbp_bitcopy(&palette, 109, color2, 17, 18); + gbp_bitcopy(&palette, 91, color3, 17, 18); + gbp_bitcopy(&palette, 73, color4, 17, 18); + + uint8_t *pal = (uint8_t *) &palette; + for (uint32_t x = 0; x < 16; x++) { + fwrite(&pal[15 - x], 1, 1, f); + } + + fclose(f); + + return 0; +} \ No newline at end of file From 9445c2d1cceda8d7cd4917623094e0621d6c7f43 Mon Sep 17 00:00:00 2001 From: "U-COOKIE\\kitri" Date: Fri, 30 Nov 2018 16:08:30 -0600 Subject: [PATCH 2/3] convert to 8 bit color --- Gameboy.sv | 22 ++++++++++----------- lcd.v | 35 ++++++++++++++++----------------- palettes/Biverted.gbp | Bin 16 -> 16 bytes palettes/DMG.gbp | Bin 16 -> 16 bytes palettes/Yellow.gbp | Bin 16 -> 16 bytes palettes/gbpalette.c | 44 ++++++++++++++---------------------------- 6 files changed, 42 insertions(+), 59 deletions(-) diff --git a/Gameboy.sv b/Gameboy.sv index 2ce7359..4f60b75 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -115,7 +115,7 @@ assign {UART_RTS, UART_TXD, UART_DTR} = 0; assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; assign LED_USER = ioctl_download; -assign LED_DISK = palette_download; +assign LED_DISK = 0; assign LED_POWER = 0; assign VIDEO_ARX = status[3] ? 8'd16 : 8'd4; @@ -130,7 +130,7 @@ localparam CONF_STR1 = { "F,GB;", "-;", "O4,Inverted color,No,Yes;", - "O1,Palette,Grayscale,Custom;", + "O1,Palette,Grayscale,Custom;" }; localparam CONF_STR2 = { @@ -415,7 +415,7 @@ wire [8:0] mbc_bank = // HuC3?HuC3_addr: {7'b0000000, cart_addr[14:13]}; // no MBC, 32k linear address -reg [127:0] palette = 128'h8201547153165C639200000000000000; +reg [127:0] palette = 128'h828214517356305A5F1A3B4900000000; always @(posedge clk_sys) begin if(!pll_locked) begin @@ -484,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 ( @@ -496,10 +496,10 @@ lcd lcd ( .inv ( status[4] ), // Palettes - .pal1 (palette[127:110]), - .pal2 (palette[109:92]), - .pal3 (palette[91:74]), - .pal4 (palette[73:56]), + .pal1 (palette[127:104]), + .pal2 (palette[103:80]), + .pal3 (palette[79:56]), + .pal4 (palette[55:32]), // serial interface .clkena ( lcd_clkena ), @@ -516,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 1a5a1a9..fd0b8fb 100644 --- a/lcd.v +++ b/lcd.v @@ -10,10 +10,10 @@ module lcd ( input [1:0] mode, //palette - input [17:0] pal1, - input [17:0] pal2, - input [17:0] pal3, - input [17:0] pal4, + input [23:0] pal1, + input [23:0] pal2, + input [23:0] pal3, + input [23:0] pal4, input tint, input inv, @@ -27,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 @@ -143,18 +143,17 @@ end wire [1:0] pixel = on? (pixel_reg ^ {inv,inv}) :2'b00; // gameboy "color" palette -wire [5:0] pal_r = (pixel==0)?pal1[17:12]:(pixel==1)?pal2[17:12]: - (pixel==2)?pal3[17:12]:pal4[17:12]; -wire [5:0] pal_g = (pixel==0)?pal1[11:6] :(pixel==1)?pal2[11:6] : - (pixel==2)?pal3[11:6] :pal4[11:6] ; -wire [5:0] pal_b = (pixel==0)?pal1[5:0] :(pixel==1)?pal2[5:0] : - (pixel==2)?pal3[5:0] :pal4[5:0] ; +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?pal_r:grey; -assign g = blank?6'b000000:tint?pal_g:grey; -assign b = blank?6'b000000:tint?pal_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 index b44c2581f7bfe2630a25bb14d6eb499d67bd53cc..f90bfa0add18e09fe7703c1d0283d837c2c9182c 100644 GIT binary patch literal 16 Wcmcb1=g;2l-}_?zma%whoQFhBqRQ@sZD diff --git a/palettes/DMG.gbp b/palettes/DMG.gbp index 310b52c8b700c9bf22f2a51d243ec5bad90fce70..f2c1732eb62c62aa97dfa95326fd17280b34a286 100644 GIT binary patch literal 16 VcmZo_5(z90Gl+_pvi4*E0stwX1G)eJ literal 16 ScmZo-3@Hp2i%Fiu0096a4FdxJ diff --git a/palettes/Yellow.gbp b/palettes/Yellow.gbp index baa7403efe19d4a8bce2d3617f15682e266b397c..418b508546417ef4458d29714dd66ae3d1d28894 100644 GIT binary patch literal 16 WcmbQUN1$N=he3*gjDP?G5C8xyWCM`^ literal 16 TcmbRDQDK3yq(LDI0|Wp7DxU)} diff --git a/palettes/gbpalette.c b/palettes/gbpalette.c index b5c2d54..c6a076e 100644 --- a/palettes/gbpalette.c +++ b/palettes/gbpalette.c @@ -1,42 +1,34 @@ #include #include #include +#include -// GBP file format is simple. There are 4 palette colors using 6 bit -// rgb, starting from lightest ending in darkest for a total of 9 bytes. +// 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_bitcopy(__uint128_t *dest, uint32_t dest_from, uint32_t source, - uint32_t source_from, uint32_t len) -{ - for (uint32_t x = 0; x < len; x++) { - uint8_t bit = (uint8_t) ((source & (1 << (source_from - x))) ? 1 : 0); - *dest |= (__uint128_t) bit << (dest_from - x); - } -} -uint32_t gbp_get_color(void) +void gbp_get_color(uint8_t *palette, uint32_t index) { char buffer[100]; printf ("Red (0-255): "); fgets(buffer, sizeof(buffer), stdin); - uint8_t red = (uint8_t) strtol(buffer, NULL, 10); + palette[index] = (uint8_t) strtol(buffer, NULL, 10); printf ("Green (0-255): "); fgets(buffer, sizeof(buffer), stdin); - uint8_t green = (uint8_t) strtol(buffer, NULL, 10); + palette[index + 1] = (uint8_t) strtol(buffer, NULL, 10); printf ("Blue (0-255): "); fgets(buffer, sizeof(buffer), stdin); - uint8_t blue = (uint8_t) strtol(buffer, NULL, 10); - - return (uint32_t) (((red >> 2) << 12) | ((green >> 2) << 6) | (blue >> 2)); + palette[index + 2] = (uint8_t) strtol(buffer, NULL, 10); } int main (int argc, char **argv) { - __uint128_t palette = 0; + uint8_t palette[16]; + memset(palette, 0, sizeof(palette)); if (argc < 1) { printf("Usage: %s \n", argv[0]); @@ -50,26 +42,18 @@ int main (int argc, char **argv) } printf("Color 1:\n"); - uint32_t color1 = gbp_get_color(); + gbp_get_color(palette, 0); printf("Color 2:\n"); - uint32_t color2 = gbp_get_color(); + gbp_get_color(palette, 3); printf("Color 3:\n"); - uint32_t color3 = gbp_get_color(); + gbp_get_color(palette, 6); printf("Color 4:\n"); - uint32_t color4 = gbp_get_color(); + gbp_get_color(palette, 9); - gbp_bitcopy(&palette, 127, color1, 17, 18); - gbp_bitcopy(&palette, 109, color2, 17, 18); - gbp_bitcopy(&palette, 91, color3, 17, 18); - gbp_bitcopy(&palette, 73, color4, 17, 18); - - uint8_t *pal = (uint8_t *) &palette; - for (uint32_t x = 0; x < 16; x++) { - fwrite(&pal[15 - x], 1, 1, f); - } + fwrite(palette, 1, 16, f); fclose(f); From f1d297f41a925170c50b1db67b360033b1b715d8 Mon Sep 17 00:00:00 2001 From: "U-COOKIE\\kitri" Date: Fri, 30 Nov 2018 16:14:16 -0600 Subject: [PATCH 3/3] fix off-by-one in palette creator --- palettes/gbpalette.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/palettes/gbpalette.c b/palettes/gbpalette.c index c6a076e..d8004c9 100644 --- a/palettes/gbpalette.c +++ b/palettes/gbpalette.c @@ -30,7 +30,7 @@ int main (int argc, char **argv) uint8_t palette[16]; memset(palette, 0, sizeof(palette)); - if (argc < 1) { + if (argc < 2) { printf("Usage: %s \n", argv[0]); return 1; }