Merge pull request #36 from brNX/master

Game Genie Codes Support
This commit is contained in:
sorgelig
2019-05-05 22:03:21 +08:00
committed by GitHub
4 changed files with 146 additions and 4 deletions

View File

@@ -351,6 +351,7 @@ set_location_assignment PIN_W20 -to SW[3]
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl"
set_global_assignment -name SYSTEMVERILOG_FILE gamegenie.sv
set_global_assignment -name CDF_FILE jtag.cdf
set_global_assignment -name QIP_FILE sys/sys.qip
set_global_assignment -name QIP_FILE t80/T80.qip

View File

@@ -147,6 +147,8 @@ localparam CONF_STR1 = {
"OEF,System,Auto,Gameboy,Gameboy Color;",
"-;",
"OC,Inverted color,No,Yes;",
"FC,GG,Game Genie Code;",
"OH,Game Genie,ON,OFF;",
"O1,Palette,Grayscale,Custom;"
};
@@ -250,9 +252,11 @@ hps_io #(.STRLEN(($size(CONF_STR1)>>3) + ($size(CONF_STR2)>>3) + ($size(CONF_STR
///////////////////////////////////////////////////
wire cart_download = ioctl_download && (filetype == 8'h01 || filetype == 8'h41 || filetype == 8'h80);
wire palette_download = ioctl_download && (filetype == 8'h05 || filetype == 8'h00);
wire palette_download = ioctl_download && (filetype == 8'h07 || filetype == 8'h00);
wire bios_download = ioctl_download && (filetype == 8'h40);
wire type_gg = filetype == 8'h04;
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 = cart_download ? ioctl_dout : 16'd0;
@@ -527,6 +531,7 @@ gb gb (
.reset ( reset ),
.clk ( clk_cpu ), // the whole gameboy runs on 4mhnz
.clk2x ( clk_cpu2x ), // ~8MHz in dualspeed mode (GBC)
.new_game_load ( cart_download),
.fast_boot ( 0 ),
.joystick ( joystick ),
@@ -553,7 +558,10 @@ gb gb (
.lcd_data ( lcd_data ),
.lcd_mode ( lcd_mode ),
.lcd_on ( lcd_on ),
.speed ( speed )
.speed ( speed ),
.gg (status[17]),
.gg_code (gg_code)
);
// the lcd to vga converter
@@ -634,6 +642,29 @@ dpram_dif #(12,8,11,16) boot_rom_gbc (
.q_b ()
);
///////////////////////// GAME GENIE //////////////////////////////////
reg [34:0] gg_code;
// Code layout:
// {clock bit, enable, compare enable, 15'b address, 8'b compare, 8'b replace}
// 34 33 32 31:16 15:8 7:0
reg [3:0] old_ioctl_addr;
always_ff @(posedge clk_sys) begin
gg_code[34] <= 1'b0;
old_ioctl_addr <= ioctl_addr[3:0];
gg_code[34] <= 1'b0;
if (ioctl_download && type_gg) begin
case (ioctl_addr[3:0])
0: gg_code[32] <= ioctl_dout[0]; // Compare Enable
4: gg_code[31:16] <= ioctl_dout; // Address
8: gg_code[15:8] <= ioctl_dout[7:0]; // compare byte
12: gg_code[7:0] <= ioctl_dout[7:0]; // replace byte
14: gg_code[34] <= 1'b1; // Clock it in
endcase
end
end
///////////////////////// BRAM SAVE/LOAD /////////////////////////////

86
gamegenie.sv Normal file
View File

@@ -0,0 +1,86 @@
// NES Game Genie handling by Kitrinx
// Apr 21, 2019
// Code layout:
// {clock bit, enable, compare enable, 15'b address, 8'b compare, 8'b replace}
// 34 33 32 31:16 15:8 7:0
localparam MAX_CODES = 32;
module geniecodes(
input clk,
input reset,
input enable,
input [15:0] addr_in,
input [7:0] data_in,
input [37:0] code,
output genie_ovr,
output [7:0] genie_data
);
reg [33:0] codes[MAX_CODES];
// If MAX_INDEX is changes, these need to be made larger
wire [4:0] index, dup_index;
reg [4:0] next_index;
wire found_dup;
assign index = found_dup ? dup_index : next_index;
// See if the code exists already, so it can be disabled if loaded again
always_comb begin
int x;
dup_index = 0;
found_dup = 0;
for (x = 0; x < MAX_CODES; x = x + 1'b1) begin
if (codes[x][31:16] == code[31:16]) begin
dup_index = x[4:0];
found_dup = 1'b1;
end
end
end
reg code_change;
always_ff @(posedge clk) begin
int x;
if (reset) begin
next_index <= 0;
code_change <= 0;
for (x = 0; x < MAX_CODES; x = x + 1) codes[x] <= 34'd0;
end else begin
code_change <= code[34];
if (code[34] & ~code_change) begin // detect posedge
// Disable the code if it's the exact same code loaded again, otherwise,
// replace it enabled if it has the same address, otherwise, add a new code
codes[index] <= found_dup ? ((codes[index][15:0] == code[15:0]) ? {codes[index][33] ? 1'b0 : 1'b1, code[32:0]} : {1'b1, code[32:0]}) : {1'b1, code[32:0]};
if (~found_dup) next_index <= next_index + 1'b1;
end
end
end
always_comb begin
int x;
genie_ovr = 1'b0;
genie_data = 8'd0;
x = 0;
if (enable) begin
for (x = 0; x < MAX_CODES; x = x + 1'b1) begin
if (codes[x][33] && codes[x][31:16] == addr_in) begin
if (codes[x][32]) begin // Check for compare bit if needed
if (codes[x][15:8] == data_in) begin
genie_ovr = 1'b1;
genie_data = codes[x][7:0];
end
end else begin // Otherwise just match
genie_ovr = 1'b1;
genie_data = codes[x][7:0];
end
end
end
end
end
endmodule

28
gb.v
View File

@@ -21,6 +21,7 @@
module gb (
input reset,
input new_game_load,
input clk,
input clk2x,
@@ -51,7 +52,10 @@ module gb (
output [1:0] lcd_mode,
output lcd_on,
output speed //GBC
output speed, //GBC
input gg,
input [34:0] gg_code
);
// include cpu
@@ -151,11 +155,31 @@ GBse cpu (
.HALT_n ( ),
.BUSAK_n ( ),
.A ( cpu_addr ),
.DI ( cpu_di ),
.DI ( genie_ovr ? genie_data : cpu_di),
.DO ( cpu_do ),
.STOP ( cpu_stop )
);
// --------------------------------------------------------------------
// --------------------------- Game Genie -----------------------------
// --------------------------------------------------------------------
wire genie_ovr;
wire [7:0] genie_data;
geniecodes codes (
.clk (clk2x),
.reset (new_game_load),
.enable (~gg),
.addr_in (cpu_addr),
.data_in (cpu_di),
.code (gg_code),
.genie_ovr (genie_ovr),
.genie_data (genie_data)
);
// --------------------------------------------------------------------
// --------------------- Speed Toggle KEY1 (GBC)-----------------------
// --------------------------------------------------------------------