Merge pull request #10 from JimmyStones/merge-cores

Merge in Snap Jack, Cosmic Avenger and Dorodon
This commit is contained in:
Alexey Melnikov
2021-04-21 02:44:10 +08:00
committed by GitHub
16 changed files with 779 additions and 267 deletions

View File

@@ -193,61 +193,39 @@ assign FB_FORCE_BLANK = '0;
wire [1:0] ar = status[20:19];
assign VIDEO_ARX = (!ar) ? ((status[2] ) ? 8'd4 : 8'd3) : (ar - 1'd1);
assign VIDEO_ARY = (!ar) ? ((status[2] ) ? 8'd3 : 8'd4) : 12'd0;
assign VIDEO_ARX = (!ar) ? ((status[2] | landscape) ? 8'd4 : 8'd3) : (ar - 1'd1);
assign VIDEO_ARY = (!ar) ? ((status[2] | landscape) ? 8'd3 : 8'd4) : 12'd0;
`include "build_id.v"
localparam CONF_STR = {
"A.LADYBG;;",
"H0OJK,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
"H0O2,Orientation,Vert,Horz;",
"H1H0O2,Orientation,Vert,Horz;",
"O35,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;",
"-;",
"O89,Difficulty,Easy,Medium,Hard,Hardest;",
"OB,Lives,3,5;",
"OC,Cabinet,Upright,Cocktail;",
"O6,Pause when OSD is open,On,Off;",
"P1,Pause options;",
"P1OP,Pause when OSD is open,On,Off;",
"P1OQ,Dim video after 10s,On,Off;",
"-;",
"DIP;",
"-;",
"R0,Reset;",
"J1,Start 1P,Start 2P,Coin,Pause;",
"jn,Start,Select,R,L;",
"J1,Fire,Bomb,Start 1P,Start 2P,Coin,Pause;",
"jn,A,B,Start,Select,R,L;",
"V,v",`BUILD_DATE
};
/*
-- Lives ------------------------------------------------------------------
-- 0 = 5 Lives
-- 1 = 3 Lives
'0' &
-- Free Play --------------------------------------------------------------
-- 0 = Free Play
-- 1 = No Free Play
'1' &
-- Cabinet ----------------------------------------------------------------
-- 0 = Upright
-- 1 = Cocktail
'0' &
-- Screen Freeze ----------------------------------------------------------
-- 0 = Freeze
-- 1 = No Freeze
'1' &
-- Rack Test (Cheat) ------------------------------------------------------
-- 0 = On
-- 1 = Off
'1' &
-- High Score Initials ----------------------------------------------------
-- 0 = 3-Letter Initials
-- 1 = 10-Letter Initials
'1' &
-- Difficulty -------------------------------------------------------------
-- 11 = Easy
-- 10 = Medium
-- 01 = Hard
-- 00 = Hardest
"10";
*/
wire [7:0] m_dip = {~status[11],1'b1,status[12],1'b1,1'b1,1'b1,~status[9:8]};
// Read DIPs from MRA
reg [7:0] m_dip[8]; // Active-LOW
always @(posedge clk_sys) if(ioctl_wr && (ioctl_index==254) && !ioctl_addr[24:3]) m_dip[ioctl_addr[2:0]] <= ioctl_dout;
// Read game index from MRA
localparam mod_ladybug = 0;
localparam mod_snapjack = 1;
localparam mod_cosmicavenger = 2;
reg [7:0] mod = 0;
always @(posedge clk_sys) if (ioctl_wr & (ioctl_index==1)) mod <= ioctl_dout;
//////////////////// CLOCKS ///////////////////
@@ -278,9 +256,7 @@ wire [24:0] ioctl_addr;
wire [7:0] ioctl_dout;
wire [7:0] ioctl_din;
wire [15:0] joystick_0,joystick_1;
wire [15:0] joy1 = joystick_0;
wire [15:0] joy2 = joystick_1;
wire [15:0] joy1,joy2;
wire [21:0] gamma_bus;
@@ -294,7 +270,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io
.buttons(buttons),
.status(status),
.status_menumask(direct_video),
.status_menumask({landscape,direct_video}),
.forced_scandoubler(forced_scandoubler),
.gamma_bus(gamma_bus),
.direct_video(direct_video),
@@ -307,86 +283,84 @@ hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io
.ioctl_din(ioctl_din),
.ioctl_index(ioctl_index),
.joystick_0(joystick_0),
.joystick_1(joystick_1)
.joystick_0(joy1),
.joystick_1(joy2)
);
wire no_rotate = status[2] | direct_video ;
wire m_up = joy1[3];
wire m_down = joy1[2];
wire m_left = joy1[1];
wire m_right = joy1[0];
wire m_fire = joy1[4];
wire m_bomb = joy1[5];
wire m_up_2 = joy2[3];
wire m_down_2 = joy2[2];
wire m_left_2 = joy2[1];
wire m_right_2 = joy2[0];
wire m_fire_2 = joy2[5];
wire m_bomb_2 = joy2[6];
wire m_start1 = joy1[6] | joy2[6];
wire m_start2 = joy1[7] | joy2[7];
wire m_coin = joy1[8] | joy2[8];
wire m_pause = joy1[9] | joy2[9];
reg [1:0] but_up_s;
reg [1:0] but_down_s;
reg [1:0] but_left_s;
reg [1:0] but_right_s;
wire m_up,m_down,m_left,m_right;
joyonedir jod
(
clk_sys,
1'b0,
{
joy1[3],
joy1[2],
joy1[1],
joy1[0]
},
{m_up,m_down,m_left,m_right}
);
// One-directional control generators for Lady Bug
wire [3:0] m_joyod_1;
wire [3:0] m_joyod_2;
joyonedir jod_1(clk_sys,1'b0,{m_up,m_down,m_left,m_right},m_joyod_1);
joyonedir jod_2(clk_sys,1'b0,{m_up_2,m_down_2,m_left_2,m_right_2},m_joyod_2);
wire m_up_2,m_down_2,m_left_2,m_right_2;
joyonedir jod_2
(
clk_sys,
1'b0,
{
joy2[3],
joy2[2],
joy2[1],
joy2[0]
},
{m_up_2,m_down_2,m_left_2,m_right_2}
);
// Set game specific options
reg landscape;
always @(*) begin
landscape <= 1'b0;
but_up_s <= {m_up_2,m_up};
but_down_s <= {m_down_2,m_down};
but_left_s <= {m_left_2,m_left};
but_right_s <= {m_right_2,m_right};
wire m_fire = 1'b0;
wire m_fire_2 = 1'b0;
wire m_start1 = joy1[4] | joy2[4];
wire m_start2 = joy1[5] | joy2[5];
wire m_coin = joy1[6] | joy2[6];
wire m_pause = joy1[7] | joy2[7];
// PAUSE SYSTEM
reg pause; // Pause signal (active-high)
reg pause_toggle = 1'b0; // User paused (active-high)
reg [31:0] pause_timer; // Time since pause
reg [31:0] pause_timer_dim = 32'hBEBC200; // Time until screen dim (10 seconds @ 20Mhz)
reg dim_video; // Dim video output (active-high)
// Pause when highscore module requires access, user has pressed pause, or OSD is open and option is set
assign pause = hs_access | pause_toggle | (OSD_STATUS && ~status[6]);
assign dim_video = (pause_timer >= pause_timer_dim) ? 1'b1 : 1'b0;
always @(posedge clk_sys) begin
reg old_pause;
old_pause <= m_pause;
if(~old_pause & m_pause) pause_toggle <= ~pause_toggle;
if(pause)
begin
if(reset) pause_toggle <= 0;
if(pause_timer<pause_timer_dim)
begin
pause_timer <= pause_timer + 1'b1;
end
end
else
begin
pause_timer <= 1'b0;
end
case (mod)
mod_ladybug:
begin
but_up_s <= {m_joyod_2[3],m_joyod_1[3]};
but_down_s <= {m_joyod_2[2],m_joyod_1[2]};
but_left_s <= {m_joyod_2[1],m_joyod_1[1]};
but_right_s <= {m_joyod_2[0],m_joyod_1[0]};
end
mod_snapjack:
begin
landscape <= 1'b1;
end
mod_cosmicavenger:
begin
landscape <= 1'b1;
end
default: ;
endcase
end
wire no_rotate = status[2] | direct_video | landscape;
// PAUSE SYSTEM
wire pause_cpu;
wire [5:0] rgb_out;
pause #(2,2,2,20) pause (
.*,
.user_button(m_pause),
.pause_request(hs_pause),
.options(~status[26:25])
);
wire hblank, vblank;
wire hs, vs;
wire ce_vid;
wire [1:0] r,g;
wire [1:0] b;
wire [5:0] rgb_out = dim_video ? {r >> 1,g >> 1, b >> 1} : {r,g,b};
wire [1:0] r,g, b;
reg ce_pix;
always @(posedge clk_40) begin
@@ -418,7 +392,7 @@ assign AUDIO_L = {audio, 8'd0};
assign AUDIO_R = AUDIO_L;
assign AUDIO_S = 1;
wire rom_download = ioctl_download & !ioctl_index;
wire rom_download = ioctl_download & (ioctl_index==2'd1|| ioctl_index==2'd2);
wire reset = RESET | status[0] | buttons[1] | rom_download;
ladybug ladybug
@@ -437,22 +411,23 @@ ladybug ladybug
.dn_addr(ioctl_addr[15:0]),
.dn_data(ioctl_dout),
.dn_wr(ioctl_wr & rom_download),
.dn_wr(ioctl_wr),
.dn_index(ioctl_index),
.O_AUDIO(audio),
.but_coin_s(~{1'b0,m_coin}),
.but_fire_s(~{m_fire_2,m_fire}),
.but_bomb_s(~{1'b0,1'b0}),
.but_bomb_s(~{m_bomb_2,m_bomb}),
.but_tilt_s(~{1'b0,1'b0}),
.but_select_s(~{m_start2,m_start1}),
.but_up_s(~{m_up_2,m_up}),
.but_down_s(~{m_down_2,m_down}),
.but_left_s(~{m_left_2,m_left}),
.but_right_s(~{m_right_2,m_right}),
.dip_block_1_s(m_dip),
.but_up_s(~but_up_s),
.but_down_s(~but_down_s),
.but_left_s(~but_left_s),
.but_right_s(~but_right_s),
.dip_block_1_s(~m_dip[0]),
.pause(pause),
.pause(pause_cpu),
.hs_address(hs_address),
.hs_data_out(ioctl_din),
@@ -468,6 +443,7 @@ wire [15:0]hs_address;
wire [7:0]hs_data_in;
wire hs_write;
wire hs_access;
wire hs_pause;
hiscore #(
.HS_ADDRESSWIDTH(16),
@@ -486,7 +462,8 @@ hiscore #(
.ram_address(hs_address),
.data_to_ram(hs_data_in),
.ram_write(hs_write),
.ram_access(hs_access)
.ram_access(hs_access),
.pause_cpu(hs_pause)
);
endmodule

View File

@@ -1,7 +1,7 @@
set_global_assignment -name VHDL_FILE rtl/ROM/prom_decrypt.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_3.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_2.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_1.vhd
#set_global_assignment -name VHDL_FILE rtl/ROM/prom_decrypt.vhd
#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_3.vhd
#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_2.vhd
#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_1.vhd
set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_top.vhd
set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_tone.vhd
set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_noise.vhd
@@ -37,5 +37,6 @@ set_global_assignment -name VHDL_FILE rtl/ladybug_chute.vhd
set_global_assignment -name VHDL_FILE rtl/ladybug_char.vhd
set_global_assignment -name VHDL_FILE rtl/ladybug_addr_dec.vhd
set_global_assignment -name VHDL_FILE rtl/ladybug.vhd
set_global_assignment -name VERILOG_FILE rtl/pause.v
set_global_assignment -name VERILOG_FILE rtl/hiscore.v
set_global_assignment -name SYSTEMVERILOG_FILE "Arcade-LadyBug.sv"

Binary file not shown.

View File

@@ -0,0 +1,80 @@
<misterromdescription>
<name>Cosmic Avenger</name>
<mameversion>0220</mameversion>
<setname>cavenger</setname>
<mratimestamp>20200427161917</mratimestamp>
<year>1981</year>
<manufacturer>Universal</manufacturer>
<category>Space / Defender</category>
<rbf>ladybug</rbf>
<buttons names="Fire,Bomb,Start 1P,Start 2P,Coin,Pause" default="A,B,Start,Select,R,L"/>
<switches default="38">
<dip bits="6,7" name="Lives" ids="3,4,5,2"/>
<dip bits="4,5" name="Initial High Score" ids="5000,8000,0,10000"/>
<dip bits="3" name="Cabinet" ids="Cocktail,Upright"/>
<dip bits="2" name="High Score Initials" ids="10,3"/>
<dip bits="0,1" name="Difficulty" ids="Easy,Medium,Hard,Hardest"/>
</switches>
<rom index="1">
<part>02</part>
</rom>
<rom index="0" zip="cavenger.zip" md5="f1233ff57be1767247bdd18c7b0bdf69">
<part crc="9e0cc781" name="1.c4"/>
<part crc="5ce5b950" name="2.d4"/>
<part crc="bc28218d" name="3.e4"/>
<part crc="2b32e9f5" name="4.h4"/>
<part crc="d117153e" name="5.j4"/>
<part crc="c7d366cb" name="6.k4"/>
<part crc="b022bf2d" name="8.l7"/>
<part crc="b022bf2d" name="8.l7"/>
<part crc="63357785" name="9.f7"/>
<part crc="52ad1133" name="0.h7"/>
</rom>
<rom index="2" zip="cavenger.zip" md5="121daaf5de7cca6f0855097fa2571581">
<part crc="d736b8de" name="10-1.f4"/>
<part crc="42a24dd5" name="10-2.k1"/>
<part crc="27fa3a50" name="10-3.c4"/>
<part repeat="160">00</part>
<part crc="none">
00 01 02 03 04 05 06 07
08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27
28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37
38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47
48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57
58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67
68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77
78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87
88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97
98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7
A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7
B8 B9 BA BB BC BD BE BF
C0 C1 C2 C3 C4 C5 C6 C7
C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7
D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7
E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7
F8 F9 FA FB FC FD FE FF
</part>
</rom>
<rom index="3" md5="none">
<part>
00 00 00 00 00 FF 00 02 00 02 00 01 00 FF 00 00
00 00 60 25 00 41 00 28
</part>
</rom>
<nvram index="4" size="65"/>
</misterromdescription>

80
releases/Dorodon.mra Normal file
View File

@@ -0,0 +1,80 @@
<misterromdescription>
<name>Dorodon (set 1)</name>
<mameversion>0220</mameversion>
<setname>dorodon</setname>
<mratimestamp>20200427161917</mratimestamp>
<year>1982</year>
<manufacturer>UPL (Falcon license?)</manufacturer>
<category>Maze</category>
<rbf>ladybug</rbf>
<buttons names="-,-,Start 1P,Start 2P,Coin,Pause" default="Start,Select,R,L"/>
<switches default="20">
<dip bits="7" name="Lives" ids="3,5"/>
<dip bits="6" name="Free play" ids="No,Yes"/>
<dip bits="5" name="Cabinet" ids="Cocktail,Upright"/>
<dip bits="4" name="Freeze" ids="No,Yes"/>
<dip bits="3" name="Rack Test" ids="No,Yes"/>
<dip bits="2" name="Bonus Life" ids="20000,30000"/>
<dip bits="0,1" name="Difficulty" ids="Easy,Medium,Hard,Hardest"/>
</switches>
<rom index="1">
<part>04</part>
</rom>
<rom index="0" zip="dorodon.zip" md5="72cf4f0a5baf5a53342df3908589c359">
<part crc="460aaf26" name="dorodon.0"/>
<part crc="d2451eb6" name="dorodon.1"/>
<part crc="d3c6ee6c" name="dorodon.2"/>
<part crc="d70bb50a" name="dorodon.4"/>
<part crc="e44e59e6" name="dorodon.3"/>
<part crc="5eee2b85" name="dorodon.5"/>
<part crc="395ac25a" name="dorodon.6"/>
</rom>
<rom index="2" zip="dorodon.zip" md5="535617ce1663c1a933777909b9ee0f2d">
<part crc="3f209be4" name="dorodon.bp1"/>
<part crc="8fcf0bc8" name="dorodon.bp0"/>
<part crc="27fa3a50" name="dorodon.bp2"/>
<part repeat="160">00</part>
<part crc="none">
00 F1 3F 86 4F 66 07 73
71 64 A7 59 2B 56 FB 8B
8F B6 9E 9D 04 11 BC 80
12 CB 18 5D D2 7A 85 75
B5 BE 7E 05 6E 3E D5 4B
2E 52 15 84 38 6A 6C 53
FA C8 08 B8 D4 E9 5C 22
1D 49 BD AD 46 1F E1 0A
19 5B 41 45 4A 2A B4 4D
57 90 8E 3A BB 9B E4 29
8A EB AA F0 CE EE 88 5F
33 31 C6 60 3C 9A 3D B7
63 6D AB 62 E3 78 E5 B9
EF 5E 7B 83 94 E6 D6 A1
D9 36 47 3B C4 DF 21 0C
14 E7 C3 1A 1C 28 4C 9C
50 40 91 55 D8 A4 76 9F
98 10 6B 2F A3 43 39 B1
42 72 7D 65 03 8D F2 F5
69 27 0D CA CF 1B 35 EC
A2 F7 93 70 CD 68 97 2D
37 F9 AE 26 96 E8 48 99
95 D7 B0 06 DC C9 ED 87
7F B3 17 A0 0F 25 DB DE
23 74 79 89 B2 FC 24 13
81 8C D3 C5 BF A6 16 44
0B 34 F8 D1 0E E0 09 EA
02 DD 92 F4 C1 BA 32 D0
7C 2C FD F3 61 A5 CC DA
5A 67 30 6F 82 20 AF 54
AC E2 1E C2 FE A9 58 01
77 C0 4E C7 A8 51 F6 FF
</part>
</rom>
<rom index="3" md5="none">
<part>
03 FF FF FF 00 FF 00 02 00 02 00 01 00 FF 00 00
00 00 60 73 00 1B 01 00
00 00 D3 81 00 46 0F 17
</part>
</rom>
<nvram index="4" size="97"/>
</misterromdescription>

View File

@@ -8,6 +8,19 @@
<category>Maze</category>
<category>Maze / Bugs</category>
<rbf>ladybug</rbf>
<buttons names="-,-,Start 1P,Start 2P,Coin,Pause" default="Start,Select,R,L"/>
<switches default="20">
<dip bits="7" name="Lives" ids="3,5"/>
<dip bits="6" name="Free play" ids="No,Yes"/>
<dip bits="5" name="Cabinet" ids="Cocktail,Upright"/>
<dip bits="4" name="Freeze" ids="No,Yes"/>
<dip bits="3" name="Rack Test" ids="No,Yes"/>
<dip bits="2" name="High Score Initials" ids="10,3"/>
<dip bits="0,1" name="Difficulty" ids="Easy,Medium,Hard,Hardest"/>
</switches>
<rom index="1">
<part>00</part>
</rom>
<rom index="0" zip="ladybug.zip" md5="89d961d878363b9859930a3e2c463867">
<part crc="d09e0adb" name="l1.c4"/>
<part crc="88bc4a0a" name="l2.d4"/>
@@ -20,6 +33,46 @@
<part crc="77b1da1e" name="l9.f7"/>
<part crc="aa82e00b" name="l0.h7"/>
</rom>
<rom index="2" zip="ladybug.zip" md5="0a1fac7e0e66624d5cb8836f16da9310">
<part crc="40640d8f" name="10-1.f4"/>
<part crc="df091e52" name="10-2.k1"/>
<part crc="27fa3a50" name="10-3.c4"/>
<part repeat="160">00</part>
<part crc="none">
00 01 02 03 04 05 06 07
08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27
28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37
38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47
48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57
58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67
68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77
78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87
88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97
98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7
A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7
B8 B9 BA BB BC BD BE BF
C0 C1 C2 C3 C4 C5 C6 C7
C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7
D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7
E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7
F8 F9 FA FB FC FD FE FF
</part>
</rom>
<rom index="3" md5="none">
<part>
03 FF FF FF 00 FF 00 02 00 02 00 01 00 FF 00 00

81
releases/Snap Jack.mra Normal file
View File

@@ -0,0 +1,81 @@
<misterromdescription>
<name>Snap Jack</name>
<mameversion>0220</mameversion>
<setname>snapjack</setname>
<mratimestamp>20200427161917</mratimestamp>
<year>1982</year>
<manufacturer>Universal</manufacturer>
<category>Platform / Water Diving</category>
<rbf>ladybug</rbf>
<buttons names="-,-,Start 1P,Start 2P,Coin,Pause" default="Start,Select,R,L"/>
<switches default="38">
<dip bits="6,7" name="Lives" ids="3,4,5,2"/>
<dip bits="5" name="Unused 2" ids="Yes,No"/>
<dip bits="4" name="Unused 1" ids="Yes,No"/>
<dip bits="3" name="Cabinet" ids="Cocktail,Upright"/>
<dip bits="2" name="High Score Initials" ids="10,3"/>
<dip bits="0,1" name="Difficulty" ids="Easy,Medium,Hard,Hardest"/>
</switches>
<rom index="1">
<part>01</part>
</rom>
<rom index="0" zip="snapjack.zip" md5="c84aa7495fa0af63de7a6c72c1c8b730">
<part crc="6b30fcda" name="sj1.c4"/>
<part crc="1f1088d1" name="sj2.d4"/>
<part crc="edd65f3a" name="sj3.e4"/>
<part crc="f4481192" name="sj4.h4"/>
<part crc="1bff7d05" name="sj5.j4"/>
<part crc="21793edf" name="sj6.k4"/>
<part crc="b7f105b6" name="sj8.l7"/>
<part crc="1cdb03a8" name="sj7.m7"/>
<part crc="ff2011c7" name="sj9.f7"/>
<part crc="f097babb" name="sj0.h7"/>
</rom>
<rom index="2" zip="snapjack.zip" md5="e8003cb15596c20d9a0456d6f9c36689">
<part crc="5b16fbd2" name="10-2.k1"/>
<part crc="cbbd9dd1" name="10-1.f4"/>
<part crc="27fa3a50" name="10-3.c4"/>
<part repeat="160">00</part>
<part crc="none">
00 01 02 03 04 05 06 07
08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27
28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37
38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47
48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57
58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67
68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77
78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87
88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97
98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7
A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7
B8 B9 BA BB BC BD BE BF
C0 C1 C2 C3 C4 C5 C6 C7
C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7
D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7
E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7
F8 F9 FA FB FC FD FE FF
</part>
</rom>
<rom index="3" md5="none">
<part>
00 00 00 00 00 FF 00 02 00 02 00 01 00 FF 00 00
00 00 6A 94 00 41 01 24
</part>
</rom>
<nvram index="4" size="65"/>
</misterromdescription>

View File

@@ -15,7 +15,7 @@ entity dpram is
address_b : IN STD_LOGIC_VECTOR (addr_width_g-1 DOWNTO 0);
clock_a : IN STD_LOGIC := '1';
clock_b : IN STD_LOGIC ;
data_a : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0);
data_a : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) := (others => '0');
data_b : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) := (others => '0');
enable_a : IN STD_LOGIC := '1';
enable_b : IN STD_LOGIC := '1';

View File

@@ -29,6 +29,7 @@
0004 - 2021-03-15 - Fix ram_access assignment
0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes
0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header
0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states
============================================================================
*/
@@ -56,16 +57,40 @@ module hiscore
output [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data
output [7:0] data_to_ram, // Data to write to game RAM
output reg ram_write, // Write to game RAM (active high)
output ram_access // RAM read or write required (active high)
output ram_access, // RAM read or write required (active high)
output reg pause_cpu // Pause core CPU to prepare for/relax after RAM access
);
// Parameters read from config header
reg [31:0] START_WAIT =1'b0; // Delay before beginning check process
reg [15:0] CHECK_WAIT =8'hFF; // Delay between start/end check attempts
reg [15:0] CHECK_HOLD =8'd2; // Hold time for start/end check reads
reg [15:0] WRITE_HOLD =8'd2; // Hold time for game RAM writes
reg [15:0] WRITE_REPEATCOUNT =8'b1; // Number of times to write score to game RAM
reg [15:0] WRITE_REPEATWAIT =8'b1111; // Delay between subsequent write attempts to game RAM
reg [31:0] START_WAIT =32'd0; // Delay before beginning check process
reg [15:0] CHECK_WAIT =16'hFF; // Delay between start/end check attempts
reg [15:0] CHECK_HOLD =16'd2; // Hold time for start/end check reads
reg [15:0] WRITE_HOLD =16'd2; // Hold time for game RAM writes
reg [15:0] WRITE_REPEATCOUNT =16'b1; // Number of times to write score to game RAM
reg [15:0] WRITE_REPEATWAIT =16'b1111; // Delay between subsequent write attempts to game RAM
reg [7:0] ACCESS_PAUSEPAD =8'd4; // Cycles to wait with paused CPU before and after RAM access
// State machine constants
localparam SM_STATEWIDTH = 4; // Width of state machine net
localparam SM_INIT = 0;
localparam SM_TIMER = 1;
localparam SM_CHECKPREP = 2;
localparam SM_CHECKBEGIN = 3;
localparam SM_CHECKSTARTVAL = 4;
localparam SM_CHECKENDVAL = 5;
localparam SM_CHECKCANCEL = 6;
localparam SM_WRITEPREP = 7;
localparam SM_WRITEBEGIN = 8;
localparam SM_WRITEREADY = 9;
localparam SM_WRITEDONE = 10;
localparam SM_WRITECOMPLETE = 11;
localparam SM_WRITERETRY = 12;
localparam SM_STOPPED = 13;
/*
Hiscore config data structure (version 1)
@@ -107,9 +132,9 @@ Hiscore config data structure (version 1)
*/
localparam HS_VERSION =6; // Version identifier for module
localparam HS_VERSION =7; // Version identifier for module
localparam HS_DUMPFORMAT =1; // Version identifier for dump format
localparam HS_HEADERLENGTH =4'b1111; // Size of header chunk (default=16 bytes)
localparam HS_HEADERLENGTH =16; // Size of header chunk (default=16 bytes)
// HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data
@@ -132,18 +157,18 @@ assign uploading_dump = ioctl_upload && (ioctl_index==HS_DUMPINDEX);
assign ram_access = uploading_dump | writing_scores | checking_scores;
assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0];
reg [3:0] state = 4'b0000; // Current state machine index
reg [3:0] next_state = 4'b0000; // Next state machine index to move to after wait timer expires
reg [(SM_STATEWIDTH-1):0] state = SM_INIT; // Current state machine index
reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT; // Next state machine index to move to after wait timer expires
reg [31:0] wait_timer; // Wait timer for inital/read/write delays
reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry
reg [CFG_ADDRESSWIDTH-1:0] total_entries=1'b0; // Total count of config table entries
reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries
reg reset_last = 1'b0; // Last cycle reset
reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt
reg [7:0] last_ioctl_index; // Last cycle HPS IO index
reg last_ioctl_download=0; // Last cycle HPS IO download
reg last_ioctl_upload=0; // Last cycle HPS IO upload
reg last_ioctl_download = 0;// Last cycle HPS IO download
reg last_ioctl_upload = 0; // Last cycle HPS IO upload
reg [7:0] last_ioctl_dout; // Last cycle HPS IO data out
reg [7:0] last_ioctl_dout2; // Last cycle +1 HPS IO data out
reg [7:0] last_ioctl_dout3; // Last cycle +2 HPS IO data out
@@ -235,12 +260,16 @@ begin
// Get header chunk data
if(parsing_header)
begin
if(ioctl_wr & (header_chunk == 4'd3)) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout };
if(ioctl_wr & (header_chunk == 4'd5)) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout };
if(ioctl_wr & (header_chunk == 4'd7)) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout };
if(ioctl_wr & (header_chunk == 4'd9)) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout };
if(ioctl_wr & (header_chunk == 4'd11)) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout };
if(ioctl_wr & (header_chunk == 4'd13)) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout };
if(ioctl_wr)
begin
if(header_chunk == 4'd3) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd5) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd7) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd9) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout };
if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= ioctl_dout;
end
end
else
begin
@@ -285,8 +314,8 @@ begin
if (reset_last == 1'b1 && reset == 1'b0)
begin
wait_timer <= START_WAIT;
next_state <= 4'b0000;
state <= 4'b1111;
next_state <= SM_INIT;
state <= SM_TIMER;
counter <= 1'b0;
initialised <= initialised + 1'b1;
end
@@ -317,34 +346,45 @@ begin
begin
// State machine to write data to game RAM
case (state)
4'b0000: // Start state machine
SM_INIT: // Start state machine
begin
// Setup base addresses
local_addr <= 0;
base_io_addr <= 25'b0;
// Reset entry counter and states
counter <= 0;
writing_scores <= 1'b0;
checking_scores <= 1'b0;
state <= 4'b0001;
// Setup base addresses
local_addr <= 0;
base_io_addr <= 25'b0;
// Reset entry counter and states
counter <= 0;
writing_scores <= 1'b0;
checking_scores <= 1'b0;
pause_cpu <= 1'b0;
state <= SM_CHECKPREP;
end
4'b0001: // Start start/end check run
// Start/end check states
// ----------------------
SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access
begin
checking_scores <= 1'b1;
ram_addr <= {1'b0, addr_base};
state <= 4'b0010;
wait_timer <= CHECK_HOLD;
state <= SM_TIMER;
next_state <= SM_CHECKBEGIN;
pause_cpu <= 1'b1;
wait_timer <= ACCESS_PAUSEPAD;
end
4'b0010: // Start check
SM_CHECKBEGIN: // Begin start/end check run - enable RAM access
begin
checking_scores <= 1'b1;
ram_addr <= {1'b0, addr_base};
state <= SM_CHECKSTARTVAL;
wait_timer <= CHECK_HOLD;
end
SM_CHECKSTARTVAL: // Start check
begin
// Check for matching start value
if(wait_timer != CHECK_HOLD & ioctl_din == start_val)
begin
// Prepare end check
ram_addr <= end_addr;
state <= 4'b0100;
state <= SM_CHECKENDVAL;
wait_timer <= CHECK_HOLD;
end
else
@@ -357,24 +397,24 @@ begin
else
begin
// - If no match after read wait then stop check run and schedule restart of state machine
next_state <= 4'b0000;
state <= 4'b1111;
next_state <= SM_CHECKCANCEL;
state <= SM_TIMER;
checking_scores <= 1'b0;
wait_timer <= CHECK_WAIT;
wait_timer <= ACCESS_PAUSEPAD;
end
end
end
4'b0100: // End check
SM_CHECKENDVAL: // End check
begin
// Check for matching end value
if (wait_timer != CHECK_HOLD & ioctl_din == end_val)
begin
if (counter == total_entries)
begin
// If this was the last entry then move to phase II, copying scores into game ram
// If this was the last entry then move on to writing scores to game ram
checking_scores <= 1'b0;
state <= 4'b1001;
state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused
counter <= 1'b0;
write_counter <= 1'b0;
ram_write <= 1'b0;
@@ -384,7 +424,7 @@ begin
begin
// Increment counter and restart state machine to check next entry
counter <= counter + 1'b1;
state <= 4'b0001;
state <= SM_CHECKBEGIN;
end
end
else
@@ -396,25 +436,58 @@ begin
end
else
begin
// - If no match after read wait then stop check run and reset state machine
state <= 4'b0000;
// - If no match after read wait then stop check run and schedule restart of state machine
next_state <= SM_CHECKCANCEL;
state <= SM_TIMER;
checking_scores <= 1'b0;
wait_timer <= CHECK_WAIT;
wait_timer <= ACCESS_PAUSEPAD;
end
end
end
//
// this section walks through our temporary ram and copies into game ram
// it needs to happen in chunks, because the game ram isn't necessarily consecutive
4'b0110:
SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused
begin
local_addr <= local_addr + 1'b1;
pause_cpu <= 1'b0;
next_state <= SM_INIT;
state <= SM_TIMER;
wait_timer <= CHECK_WAIT;
end
// Write to game RAM states
// ----------------------
SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts)
begin
state <= SM_TIMER;
next_state <= SM_WRITEBEGIN;
pause_cpu <= 1'b1;
wait_timer <= ACCESS_PAUSEPAD;
end
SM_WRITEBEGIN: // Writing scores to game RAM begins
begin
writing_scores <= 1'b1; // Enable muxes if necessary
write_counter <= write_counter + 1'b1;
state <= SM_WRITEREADY;
end
SM_WRITEREADY: // local ram should be correct, start write to game RAM
begin
ram_addr <= addr_base + (local_addr - base_io_addr);
state <= SM_TIMER;
next_state <= SM_WRITEDONE;
wait_timer <= WRITE_HOLD;
ram_write <= 1'b1;
end
SM_WRITEDONE:
begin
local_addr <= local_addr + 1'b1; // Increment to next byte of entry
if (ram_addr == end_addr)
begin
// End of entry reached
if (counter == total_entries)
begin
state <= 4'b1000;
state <= SM_WRITECOMPLETE;
end
else
begin
@@ -422,58 +495,49 @@ begin
counter <= counter + 1'b1;
write_counter <= 1'b0;
base_io_addr <= local_addr + 1'b1;
state <= 4'b1001;
state <= SM_WRITEBEGIN;
end
end
else
begin
state <= 4'b1010;
state <= SM_WRITEREADY;
end
ram_write <= 1'b0;
end
4'b1000: // Hiscore write to RAM completed
SM_WRITECOMPLETE: // Hiscore write to RAM completed
begin
ram_write <= 1'b0;
writing_scores <= 1'b0;
state <= SM_TIMER;
if(write_counter < WRITE_REPEATCOUNT)
begin
// Schedule next write
state <= 4'b1111;
next_state <= 4'b1001;
next_state <= SM_WRITERETRY;
local_addr <= 0;
wait_timer <= WRITE_REPEATWAIT;
end
end
4'b1001: // Writing scores to game RAM begins
begin
writing_scores <= 1'b1; // indicate that writing has begun, will hold pause until write is complete if hooked up in core
write_counter <= write_counter + 1'b1;
state <= 4'b1010;
end
4'b1010: // local ram is correct
begin
state <= 4'b1110;
ram_addr <= addr_base + (local_addr - base_io_addr);
ram_write <= 1'b1;
wait_timer <= WRITE_HOLD;
end
4'b1110: // hold write for wait_timer
begin
if (wait_timer > 1'b0)
begin
wait_timer <= wait_timer - 1'b1;
end
else
begin
state <= 4'b0110;
next_state <= SM_STOPPED;
wait_timer <= ACCESS_PAUSEPAD;
end
end
4'b1111: // timer wait state
SM_WRITERETRY: // Stop pause and schedule next write
begin
pause_cpu <= 1'b0;
state <= SM_TIMER;
next_state <= SM_WRITEPREP;
wait_timer <= WRITE_REPEATWAIT;
end
SM_STOPPED:
begin
pause_cpu <= 1'b0;
end
SM_TIMER: // timer wait state
begin
if (wait_timer > 1'b0)
wait_timer <= wait_timer - 1'b1;

View File

@@ -57,6 +57,7 @@ port (
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0);
-- VGA Interface ----------------------------------------------------------
O_VIDEO_R : out std_logic_vector( 1 downto 0);
@@ -137,6 +138,8 @@ architecture struct of ladybug is
signal but_chute_s : std_logic_vector( 1 downto 0) := (others=>'0');
signal rom_cpu1_cs, rom_cpu2_cs, rom_cpu3_cs, rom_sprite_l_cs, rom_sprite_u_cs, rom_char_l_cs, rom_char_u_cs : std_logic;
signal rom_download : std_logic;
begin
O_PIXCE <= clk_en_5mhz_s;
@@ -189,7 +192,11 @@ begin
hs_data_in => hs_data_in,
hs_data_out => hs_data_out,
hs_write => hs_write,
hs_access => hs_access
hs_access => hs_access,
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
dn_index => dn_index
);
-----------------------------------------------------------------------------
@@ -211,12 +218,13 @@ begin
rom_sprite_u_cs <= '1' when dn_addr(15 downto 12)=X"7" else '0';
rom_char_l_cs <= '1' when dn_addr(15 downto 12)=X"8" else '0';
rom_char_u_cs <= '1' when dn_addr(15 downto 12)=X"9" else '0';
rom_download <= '1' when dn_wr = '1' and dn_index(7 downto 0) = "00000000" else '0';
inst_rom_spritel : work.dpram generic map (12,8)
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_sprite_l_cs,
wren_a => rom_download and rom_sprite_l_cs,
address_a => dn_addr(11 downto 0),
data_a => dn_data,
@@ -229,7 +237,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_sprite_u_cs,
wren_a => rom_download and rom_sprite_u_cs,
address_a => dn_addr(11 downto 0),
data_a => dn_data,
@@ -242,7 +250,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_char_l_cs,
wren_a => rom_download and rom_char_l_cs,
address_a => dn_addr(11 downto 0),
data_a => dn_data,
@@ -255,7 +263,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_char_u_cs,
wren_a => rom_download and rom_char_u_cs,
address_a => dn_addr(11 downto 0),
data_a => dn_data,
@@ -268,7 +276,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_cpu1_cs,
wren_a => rom_download and rom_cpu1_cs,
address_a => dn_addr(12 downto 0),
data_a => dn_data,
@@ -281,7 +289,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_cpu2_cs,
wren_a => rom_download and rom_cpu2_cs,
address_a => dn_addr(12 downto 0),
data_a => dn_data,
@@ -294,7 +302,7 @@ begin
port map
(
clock_a => clk_20mhz_s,
wren_a => dn_wr and rom_cpu3_cs,
wren_a => rom_download and rom_cpu3_cs,
address_a => dn_addr(12 downto 0),
data_a => dn_data,

View File

@@ -50,6 +50,7 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ladybug_cpu_unit is
port (
@@ -78,6 +79,11 @@ entity ladybug_cpu_unit is
cs12_n_o : out std_logic;
cs13_n_o : out std_logic;
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0);
pause : in std_logic;
hs_address : in std_logic_vector(15 downto 0);
@@ -114,6 +120,8 @@ architecture struct of ladybug_cpu_unit is
signal ram_cpu_cs_n_s : std_logic;
signal vcc_s : std_logic;
signal decrypt_prom_wr : std_logic;
begin
vcc_s <= '1';
@@ -156,24 +164,24 @@ begin
-----------------------------------------------------------------------------
-- The CPU RAM
-----------------------------------------------------------------------------
cpu_ram_b : entity work.ladybug_cpu_ram
port map (
clk1_i => clk_20mhz_i,
clk_en1_i => clk_en_4mhz_i,
a1_i => a_s(11 downto 0),
cs1_n_i => cs_n_s(6),
we1_n_i => wr_n_s,
d1_i => d_from_cpu_s,
d1_o => d_from_ram_s,
cpu_ram_b : entity work.ladybug_cpu_ram
port map (
clk1_i => clk_20mhz_i,
clk_en1_i => clk_en_4mhz_i,
a1_i => a_s(11 downto 0),
cs1_n_i => cs_n_s(6),
we1_n_i => wr_n_s,
d1_i => d_from_cpu_s,
d1_o => d_from_ram_s,
clk2_i => clk_20mhz_i,
clk_en2_i => '1',
a2_i => hs_address(11 downto 0),
cs2_n_i => '0',
we2_n_i => not hs_write,
d2_i => hs_data_in,
d2_o => hs_data_out
);
clk2_i => clk_20mhz_i,
clk_en2_i => '1',
a2_i => hs_address(11 downto 0),
cs2_n_i => '0',
we2_n_i => not hs_write,
d2_i => hs_data_in,
d2_o => hs_data_out
);
-----------------------------------------------------------------------------
-- The Address Decoder
@@ -228,12 +236,19 @@ begin
-- Decrytion PROMs
-----------------------------------------------------------------------------
decrypt_prom : entity work.prom_decrypt
port map (
CLK => clk_20mhz_i,
ADDR => rom_cpu_d_i,
DATA => d_decrypted_s
);
decrypt_prom_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8) = '1') else '0';
decrypt_prom : entity work.dpram generic map(8,8)
port map (
clock_a => clk_20mhz_i,
address_a => dn_addr(7 downto 0),
data_a => dn_data,
wren_a => decrypt_prom_wr,
clock_b => clk_20mhz_i,
address_b => rom_cpu_d_i,
q_b => d_decrypted_s
);
-----------------------------------------------------------------------------
-- Only opcodes (i.e. instruction fetches) have to be decrypted

View File

@@ -91,6 +91,11 @@ entity ladybug_machine is
rom_sprite_a_o : out std_logic_vector(11 downto 0);
rom_sprite_d_i : in std_logic_vector(15 downto 0);
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0);
pause : in std_logic;
-- Hiscore
hs_address : in std_logic_vector(15 downto 0);
@@ -253,7 +258,11 @@ begin
hs_address => hs_address,
hs_data_in => hs_data_in,
hs_data_out => hs_data_out_cpu,
hs_write => hs_write and hs_cs_cpu
hs_write => hs_write and hs_cs_cpu,
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
dn_index => dn_index
);
-----------------------------------------------------------------------------
@@ -302,7 +311,11 @@ begin
hs_address => hs_address,
hs_data_in => hs_data_in,
hs_data_out => hs_data_out_vram,
hs_write => hs_write and hs_cs_vram
hs_write => hs_write and hs_cs_vram,
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
dn_index => dn_index
);
-----------------------------------------------------------------------------

View File

@@ -57,7 +57,11 @@ entity ladybug_rgb is
sig_i : in std_logic_vector(4 downto 1);
rgb_r_o : out std_logic_vector(1 downto 0);
rgb_g_o : out std_logic_vector(1 downto 0);
rgb_b_o : out std_logic_vector(1 downto 0)
rgb_b_o : out std_logic_vector(1 downto 0);
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0)
);
end ladybug_rgb;
@@ -68,6 +72,8 @@ architecture rtl of ladybug_rgb is
signal rgb_s : std_logic_vector(8 downto 1);
signal rgb_n_q : std_logic_vector(8 downto 1);
signal prom_wr : std_logic;
begin
-----------------------------------------------------------------------------
@@ -98,12 +104,20 @@ begin
-----------------------------------------------------------------------------
-- The RGB Conversion PROM
-----------------------------------------------------------------------------
rgb_prom_b : entity work.prom_10_2
port map (
CLK => clk_20mhz_i,
ADDR => a_s,
DATA => rgb_s
);
prom_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0001") else '0';
rgb_prom_b : entity work.dpram generic map(5,8)
port map (
clock_a => clk_20mhz_i,
address_a => dn_addr(4 downto 0),
data_a => dn_data,
wren_a => prom_wr,
clock_b => clk_20mhz_i,
address_b => a_s,
q_b => rgb_s
);
-----------------------------------------------------------------------------
-- Process rgb_latch

View File

@@ -81,7 +81,12 @@ port (
sig_o : out std_logic_vector( 4 downto 1);
-- Sprite ROM Interface ---------------------------------------------------
rom_sprite_a_o : out std_logic_vector(11 downto 0);
rom_sprite_d_i : in std_logic_vector(15 downto 0)
rom_sprite_d_i : in std_logic_vector(15 downto 0);
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0)
);
end ladybug_sprite;
@@ -169,6 +174,9 @@ architecture rtl of ladybug_sprite is
signal vram_q : std_logic_vector(15 downto 0);
signal prom_F4_wr : std_logic;
signal prom_C4_wr : std_logic;
begin
-----------------------------------------------------------------------------
@@ -505,11 +513,18 @@ begin
lu_a_s(1) <= qh2_s;
lu_a_s(0) <= qh1_s;
prom_F4 : entity work.prom_10_1
prom_F4_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0000") else '0';
prom_F4 : entity work.dpram generic map(5,8)
port map (
CLK => clk_20mhz_i,
ADDR => lu_a_s,
DATA => lu_d_s
clock_a => clk_20mhz_i,
address_a => dn_addr(4 downto 0),
data_a => dn_data,
wren_a => prom_F4_wr,
clock_b => clk_20mhz_i,
address_b => lu_a_s,
q_b => lu_d_s
);
lu_d_mux_s <= lu_d_s(3 downto 0) when cl_q(3) = '0' else lu_d_s(7 downto 4);
@@ -523,13 +538,19 @@ begin
ctrl_lu_a_s(3) <= h_i(0);
ctrl_lu_a_s(4) <= h_i(1);
prom_C4 : entity work.prom_10_3
prom_C4_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0010") else '0';
prom_C4 : entity work.dpram generic map(5,8)
port map (
CLK => clk_20mhz_i,
ADDR => ctrl_lu_a_s,
DATA => ctrl_lu_d_s
);
clock_a => clk_20mhz_i,
address_a => dn_addr(4 downto 0),
data_a => dn_data,
wren_a => prom_C4_wr,
clock_b => clk_20mhz_i,
address_b => ctrl_lu_a_s,
q_b => ctrl_lu_d_s
);
-----------------------------------------------------------------------------
-- Process ctrl_lu_seq
--

View File

@@ -87,6 +87,11 @@ entity ladybug_video_unit is
rom_sprite_a_o : out std_logic_vector(11 downto 0);
rom_sprite_d_i : in std_logic_vector(15 downto 0);
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
dn_index : in std_logic_vector(7 downto 0);
pause : in std_logic;
hs_address : in std_logic_vector(15 downto 0);
@@ -220,7 +225,11 @@ begin
blank_i => blank_s,
sig_o => sig_s,
rom_sprite_a_o => rom_sprite_a_o,
rom_sprite_d_i => rom_sprite_d_i
rom_sprite_d_i => rom_sprite_d_i,
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
dn_index => dn_index
);
@@ -236,10 +245,13 @@ begin
sig_i => sig_s,
rgb_r_o => rgb_r_o,
rgb_g_o => rgb_g_o,
rgb_b_o => rgb_b_o
rgb_b_o => rgb_b_o,
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
dn_index => dn_index
);
-----------------------------------------------------------------------------
-- Bus Multiplexer
-----------------------------------------------------------------------------

93
rtl/pause.v Normal file
View File

@@ -0,0 +1,93 @@
//============================================================================
// Generic pause handling for MiSTer cores.
//
// https://github.com/JimmyStones/Pause_MiSTer
//
// Copyright (c) 2021 Jim Gregory
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
/*
Features:
- Pause can be triggered by user input, hiscore module or OSD opening (optionally controlled by setting in OSD)
- When paused the RGB outputs will be halved after 10 seconds to reduce burn-in (optionally controlled by setting in OSD)
- Reset signal will cancel user triggered pause
Version history:
0001 - 2021-03-15 - First marked release
============================================================================
*/
module pause #(
parameter RW=8, // Width of red channel
parameter GW=8, // Width of green channel
parameter BW=8, // Width of blue channel
parameter CLKSPD = 12 // Main clock speed in MHz
)
(
input clk_sys, // Core system clock (should match HPS module)
input reset, // CPU reset signal (active-high)
input user_button, // User pause button signal (active-high)
input pause_request, // Pause requested by other code (active-high)
input [1:0] options, // Pause options from OSD
// [0] = pause in OSD (active-high)
// [1] = dim video (active-high)
input OSD_STATUS, // OSD is open (active-high)
input [(RW-1):0] r, // Red channel
input [(GW-1):0] g, // Green channel
input [(BW-1):0] b, // Blue channel
output pause_cpu, // Pause signal to CPU (active-high)
output [(RW+GW+BW-1):0] rgb_out // RGB output to arcade_video module
);
// Option constants
localparam pause_in_osd = 1'b0;
localparam dim_video = 1'b1;
reg pause_toggle = 1'b0; // User paused (active-high)
reg [31:0] pause_timer = 1'b0; // Time since pause
reg [31:0] dim_timeout = (CLKSPD*10000000); // Time until video output dim (10 seconds @ CLKSPD Mhz)
assign pause_cpu = (pause_request | pause_toggle | (OSD_STATUS & options[pause_in_osd])) & !reset;
always @(posedge clk_sys) begin
// Track user pause button down
reg user_button_last;
user_button_last <= user_button;
if(!user_button_last & user_button) pause_toggle <= ~pause_toggle;
// Clear user pause on reset
if(pause_toggle & reset) pause_toggle <= 0;
if(pause_cpu & options[dim_video])
begin
// Track pause duration for video dim
if((pause_timer<dim_timeout))
begin
pause_timer <= pause_timer + 1'b1;
end
end
else
begin
pause_timer <= 1'b0;
end
end
// Dim video output if pause timer exceeds threshold
assign rgb_out = (pause_timer >= dim_timeout) ? {r >> 1,g >> 1, b >> 1} : {r,g,b};
endmodule