Skip to content

Commit

Permalink
feat: Virtual Super Scope and Justifier lightgun support. (#32)
Browse files Browse the repository at this point in the history
* feat: Virtual Super Scope and Justifier lightgun support.

* Added lightgun d-pad aim speed setting and updated README with lightgun details.

* fix: README capitalization.
  • Loading branch information
iequalshane authored Sep 25, 2022
1 parent 61d68b1 commit 3d7d3c0
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 45 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ The currently supported expansion chips are SA-1 (Super Mario RPG), Super FX (GS

The Analogue Pocket framework doesn't currently allow for customizing video modes directly, so if you dislike the default 8:7 aspect ratio/want to change to 4:3, you can change it by modifying `Cores/agg23.SNES/video.json` and rearranging the config objects.

Proper PAL support also requires editing these files to have an expanded vertical pixel height.
Proper PAL support also requires editing these files to have an expanded vertical pixel height.

### Lightguns

Core supports virtual lightguns by enabling the "Use Super Scope" or "Use Justifier" settings. Most lightgun games user the Super Scope but Lethal Enforcers uses the Justifier. The crosshair can be controlled with the D-Pad or left joystick, using the A button to fire and the B button to reload. D-Pad aim sensitivity can be adjusted with the "D-Pad Aim Speed" setting.

**NOTE:** Joystick support for aiming only appears to work when a controller is paired over Bluetooth and not connected to the Analogue Dock directly by USB.
59 changes: 58 additions & 1 deletion dist/Cores/agg23.SNES/interact.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,65 @@
"value": 1
},
{
"name": "Use 4:3 video",
"name": "Lightgun Options",
"id": 30,
"type": "action",
"enabled": false
},
{
"name": "No Lightgun",
"id": 31,
"group": 3,
"type": "radio",
"enabled": true,
"address": "0x00000104",
"persist": true,
"writeonly": true,
"defaultval": 1,
"value": 0
},
{
"name": "Use Super Scope",
"id": 32,
"group": 3,
"type": "radio",
"enabled": true,
"address": "0x00000104",
"writeonly": true,
"persist": true,
"value": 1
},
{
"name": "Use Justifier",
"id": 33,
"group": 3,
"type": "radio",
"enabled": true,
"address": "0x00000104",
"writeonly": true,
"persist": true,
"value": 3
},
{
"name": "D-Pad Aim Speed",
"id": 34,
"type": "slider_u32",
"enabled": true,
"address": "0x00000108",
"persist": true,
"writeonly": true,
"defaultval": 3,
"graphical": {
"signed": false,
"min": 1,
"max": 10,
"adjust_small": 1,
"adjust_large": 4
}
},
{
"name": "Use 4:3 video",
"id": 40,
"type": "check",
"enabled": true,
"address": "0x00000200",
Expand Down
25 changes: 25 additions & 0 deletions src/fpga/core/core_top.v
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,13 @@ module core_top (
32'h00000100: begin
multitap_enabled <= bridge_wr_data[0];
end
32'h00000104: begin
lightgun_enabled <= bridge_wr_data[0];
lightgun_type <= bridge_wr_data[1];
end
32'h00000108: begin
lightgun_dpad_aim_speed <= bridge_wr_data[7:0];
end
32'h00000200: begin
use_4_3_video <= bridge_wr_data[0];
end
Expand Down Expand Up @@ -586,6 +593,7 @@ module core_top (
wire [15:0] cont2_key_s;
wire [15:0] cont3_key_s;
wire [15:0] cont4_key_s;
wire [31:0] cont1_joy_s;

synch_3 #(
.WIDTH(32)
Expand Down Expand Up @@ -618,11 +626,22 @@ module core_top (
cont4_key_s,
clk_sys_21_48
);

synch_3 #(
.WIDTH(32)
) joy1_s (
cont1_joy,
cont1_joy_s,
clk_sys_21_48
);

wire PAL;

// Settings
reg multitap_enabled;
reg lightgun_enabled;
reg lightgun_type;
reg [7:0] lightgun_dpad_aim_speed;
reg use_4_3_video;

MAIN_SNES snes (
Expand All @@ -633,6 +652,9 @@ module core_top (

// Settings
.multitap_enabled(multitap_enabled),
.lightgun_enabled(lightgun_enabled),
.lightgun_type(lightgun_type),
.lightgun_dpad_aim_speed(lightgun_dpad_aim_speed),

// Input
.p1_button_a(cont1_key_s[4]),
Expand All @@ -648,6 +670,9 @@ module core_top (
.p1_dpad_left(cont1_key_s[2]),
.p1_dpad_right(cont1_key_s[3]),

.p1_lstick_x(cont1_joy_s[7:0]),
.p1_lstick_y(cont1_joy_s[15:8]),

.p2_button_a(cont2_key_s[4]),
.p2_button_b(cont2_key_s[5]),
.p2_button_x(cont2_key_s[6]),
Expand Down
54 changes: 44 additions & 10 deletions src/fpga/core/rtl/lightgun.sv
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ module lightgun
input CLK,
input RESET,

input [24:0] MOUSE,
input MOUSE_XY,
//input [24:0] MOUSE,
//input MOUSE_XY,

input [7:0] JOY_X,JOY_Y,
input F,C,T,P,

input UP,
input DOWN,
input LEFT,
input RIGHT,
input [7:0] DPAD_AIM_SPEED,

input HDE,VDE,
input CLKPIX,

Expand All @@ -23,7 +29,7 @@ module lightgun
output [1:0] PORT_DO
);

parameter CROSS_SZ = 8'd3;
parameter CROSS_SZ = 8'd4;

assign PORT_DO = {1'b1, GUN_TYPE ? JUSTIFIER_LATCH[31] : JOY_LATCH0[7]};
assign TARGET = {{2{~Ttr & ~offscreen & draw}}, Ttr & ~offscreen & draw};
Expand Down Expand Up @@ -69,11 +75,14 @@ end

reg [8:0] lg_x, lg_y, x, y;

wire [9:0] new_x = {lg_x[8],lg_x} + {{2{MOUSE[4]}},MOUSE[15:8]};
wire [9:0] new_y = {lg_y[8],lg_y} - {{2{MOUSE[5]}},MOUSE[23:16]};
wire [9:0] new_x = {lg_x[8],lg_x};// + {{2{MOUSE[4]}},MOUSE[15:8]};
wire [9:0] new_y = {lg_y[8],lg_y};// - {{2{MOUSE[5]}},MOUSE[23:16]};

wire [8:0] j_x = {~JOY_X[7], JOY_X[6:0]};
wire [8:0] j_y = {~JOY_Y[7], JOY_Y[6:0]};
// HACK
reg [7:0] old_joy_x;
reg [7:0] old_joy_y;
reg [8:0] j_x;
reg [8:0] j_y;

reg offscreen = 0, draw = 0;
reg [21:0] port_p6_sr;
Expand All @@ -89,7 +98,7 @@ always @(posedge CLK) begin
jy1 <= {8'd0, j_y} * vtotal;
jy2 <= jy1;

old_ms <= MOUSE[24];
/*old_ms <= MOUSE[24];
if(MOUSE_XY) begin
if(old_ms ^ MOUSE[24]) begin
if(new_x[9]) lg_x <= 0;
Expand All @@ -101,11 +110,11 @@ always @(posedge CLK) begin
else lg_y <= new_y[8:0];
end
end
else begin
else begin*/
lg_x <= j_x;
lg_y <= jy2[16:8];
if(jy2[16:8] > vtotal) lg_y <= vtotal;
end
//end

old_pix <= CLKPIX;
if(~old_pix & CLKPIX) begin
Expand All @@ -123,6 +132,31 @@ always @(posedge CLK) begin

old_vde <= VDE;
if(~old_vde & VDE) begin

old_joy_x <= JOY_X;
old_joy_y <= JOY_Y;
if(old_joy_x != JOY_X || old_joy_y != JOY_Y) begin
j_x <= JOY_X[7:0];
j_y <= JOY_Y[7:0];
end else begin
if(LEFT) begin
if (j_x >= DPAD_AIM_SPEED) j_x <= j_x - DPAD_AIM_SPEED;
else j_x <= 0;
end
if(RIGHT) begin
if(lg_x <= 8'd255 - DPAD_AIM_SPEED) j_x <= j_x + DPAD_AIM_SPEED;
else j_x <= 8'd255;
end
if(UP) begin
if (j_y >= DPAD_AIM_SPEED) j_y <= j_y - DPAD_AIM_SPEED;
else j_y <= 0;
end
if(DOWN) begin
if (j_y < vtotal - DPAD_AIM_SPEED) j_y <= j_y + DPAD_AIM_SPEED;
else j_y <= vtotal;
end
end

x <= lg_x;
y <= lg_y;
xm <= lg_x - CROSS_SZ;
Expand Down
84 changes: 51 additions & 33 deletions src/fpga/core/rtl/mister_top/SNES.sv
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ module MAIN_SNES (

// Settings
input wire multitap_enabled,
input wire lightgun_enabled,
input wire lightgun_type,
input wire [7:0] lightgun_dpad_aim_speed,

// Inputs
input wire p1_button_a,
Expand All @@ -21,6 +24,9 @@ module MAIN_SNES (
input wire p1_dpad_left,
input wire p1_dpad_right,

input wire [7:0] p1_lstick_x,
input wire [7:0] p1_lstick_y,

input wire p2_button_a,
input wire p2_button_b,
input wire p2_button_x,
Expand Down Expand Up @@ -136,8 +142,8 @@ module MAIN_SNES (
wire [63:0] status = 0;
wire [5:0] ioctl_index = 0; // TODO
wire GUN_BTN = status[27];
wire [1:0] GUN_MODE = status[26:25];
wire GUN_TYPE = status[34];
wire [1:0] GUN_MODE = 2'd1;//status[26:25];
wire GUN_TYPE = 0;//status[34];
wire GSU_TURBO = status[18];
wire BLEND = ~status[16];
wire [1:0] mouse_mode = status[6:5];
Expand Down Expand Up @@ -293,9 +299,14 @@ module MAIN_SNES (

wire vblank_n;
wire hblank_n;
wire dotclk;

assign vblank = ~vblank_n;
assign hblank = ~hblank_n;

wire [7:0] R;
wire [7:0] G;
wire [7:0] B;

main main (
.RESET_N(RESET_N),
Expand Down Expand Up @@ -350,14 +361,14 @@ module MAIN_SNES (
.ARAM_OE_N(ARAM_OE_N),
.ARAM_WE_N(ARAM_WE_N),

.R(video_r),
.G(video_g),
.B(video_b),
.R(R),
.G(G),
.B(B),

// .FIELD(FIELD), // TODO
// .INTERLACE(INTERLACE),
// .HIGH_RES(HIGH_RES),
// .DOTCLK(DOTCLK_out),
.DOTCLK(dotclk),

.HBLANKn(hblank_n),
.VBLANKn(vblank_n),
Expand Down Expand Up @@ -430,6 +441,12 @@ module MAIN_SNES (
if (div == 2) RESET_N <= ~reset;
end

always @(posedge clk_sys) begin
video_r <= (LG_TARGET && lightgun_enabled) ? {8{LG_TARGET[0]}} : R;
video_g <= (LG_TARGET && lightgun_enabled) ? {8{LG_TARGET[1]}} : G;
video_b <= (LG_TARGET && lightgun_enabled) ? {8{LG_TARGET[2]}} : B;
end

//////////////////////////// MEMORY ///////////////////////////////////

reg [16:0] mem_fill_addr;
Expand Down Expand Up @@ -781,40 +798,41 @@ module MAIN_SNES (
// .MOUSE_EN(mouse_mode[1])
);

wire LG_P6_out;
// wire [1:0] LG_DO;
// wire [2:0] LG_TARGET;
// wire LG_T = ((GUN_MODE[0]&joy0[6]) | (GUN_MODE[1]&joy1[6])); // always from joysticks
wire LG_P6_out;
wire [1:0] LG_DO;
wire [2:0] LG_TARGET;

// lightgun lightgun
// (
// .CLK(clk_sys),
// .RESET(reset),
lightgun lightgun (
.CLK(clk_sys),
.RESET(reset),

// .MOUSE(ps2_mouse),
// .MOUSE_XY(&GUN_MODE),
.JOY_X(p1_lstick_x),
.JOY_Y(p1_lstick_y),

// .JOY_X(GUN_MODE[0] ? joy0_x : joy1_x),
// .JOY_Y(GUN_MODE[0] ? joy0_y : joy1_y),
.F(p1_button_a),
.C(p1_button_b),
.T(p1_button_x),
.P(p1_button_y),

// .F(GUN_BTN ? ps2_mouse[0] : ((GUN_MODE[0]&(joy0[4]|joy0[9]) | (GUN_MODE[1]&(joy1[4]|joy1[9]))))),
// .C(GUN_BTN ? ps2_mouse[1] : ((GUN_MODE[0]&(joy0[5]|joy0[8]) | (GUN_MODE[1]&(joy1[5]|joy0[8]))))),
// .T(LG_T), // always from joysticks
// .P(ps2_mouse[2] | ((GUN_MODE[0]&joy0[7]) | (GUN_MODE[1]&joy1[7]))), // always from joysticks and mouse
.UP(p1_dpad_up),
.DOWN(p1_dpad_down),
.LEFT(p1_dpad_left),
.RIGHT(p1_dpad_right),
.DPAD_AIM_SPEED(lightgun_dpad_aim_speed),

// .HDE(~HBlank),
// .VDE(~VBlank),
// .CLKPIX(DOTCLK),
.HDE(hblank_n),
.VDE(vblank_n),
.CLKPIX(dotclk),

// .TARGET(LG_TARGET),
// .SIZE(status[28]),
// .GUN_TYPE(GUN_TYPE),
.TARGET(LG_TARGET),
.SIZE(0),
.GUN_TYPE(lightgun_type),

// .PORT_LATCH(JOY_STRB),
// .PORT_CLK(JOY2_CLK),
// .PORT_P6(LG_P6_out),
// .PORT_DO(LG_DO)
// );
.PORT_LATCH(JOY_STRB),
.PORT_CLK(JOY2_CLK),
.PORT_P6(LG_P6_out),
.PORT_DO(LG_DO)
);

// 1 [oooo|ooo) 7 - 1:+5V 2:Clk 3:Strobe 4:D0 5:D1 6: I/O 7:Gnd

Expand Down

0 comments on commit 3d7d3c0

Please sign in to comment.