Skip to content

Commit 181e182

Browse files
committed
crash fuzz init
1 parent 3d410c5 commit 181e182

File tree

5 files changed

+127
-8
lines changed

5 files changed

+127
-8
lines changed

tests/src/crash.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use crate::{util, video, playfield};
2+
3+
pub fn fuzz() {
4+
let mut emu = util::emulator(Some(util::OG_ROM));
5+
6+
emu.reset();
7+
8+
util::run_n_vblanks(&mut emu, 8);
9+
10+
let p1_score = 0x73;
11+
let score = 0x53;
12+
let game_mode = 0xC0;
13+
let level_number = 0x44;
14+
let p1_level_number = 0x64;
15+
let lines = 0x50;
16+
let p1_lines = 0x70;
17+
let main_loop = 0x8138;
18+
let x = 0x40;
19+
let y = 0x41;
20+
let p1_x = 0x60;
21+
let p1_y = 0x61;
22+
let current_piece = 0x42;
23+
let p1_current_piece = 0x62;
24+
let auto_repeat_y = 0x4E;
25+
let p1_auto_repeat_y = 0x6E;
26+
let push_down = 0x4F;
27+
let p1_push_down = 0x6F;
28+
let render_flags = 0xA3;
29+
let clear_count = 0xD8;
30+
let play_state = 0x48;
31+
let p1_play_state = 0x68;
32+
33+
emu.memory.iram_raw[game_mode] = 4;
34+
emu.registers.pc = main_loop;
35+
36+
util::run_n_vblanks(&mut emu, 7);
37+
38+
emu.memory.iram_raw[level_number] = 154;
39+
emu.memory.iram_raw[p1_level_number] = 154;
40+
emu.memory.iram_raw[lines] = 0x89;
41+
emu.memory.iram_raw[lines+1] = 0xE;
42+
emu.memory.iram_raw[p1_lines] = 0x89;
43+
emu.memory.iram_raw[p1_lines+1] = 0xE;
44+
emu.memory.iram_raw[p1_score] = 0x99;
45+
emu.memory.iram_raw[p1_score+1] = 0x99;
46+
emu.memory.iram_raw[p1_score+2] = 0x99;
47+
emu.memory.iram_raw[score] = 0x99;
48+
emu.memory.iram_raw[score+1] = 0x99;
49+
emu.memory.iram_raw[score+2] = 0x99;
50+
51+
emu.memory.iram_raw[render_flags] = 7;
52+
53+
util::run_n_vblanks(&mut emu, 1);
54+
55+
// playfield::clear(&mut emu);
56+
57+
playfield::set_str_addr(&mut emu, 0x400, match 1 {
58+
0 => "",
59+
1 => "##### ####",
60+
2 => "##### ####\n##### ####",
61+
3 => "##### ####\n##### ####\n##### ####",
62+
4 => "##### ####\n##### ####\n##### ####\n##### ####",
63+
_ => unreachable!("line"),
64+
});
65+
66+
emu.memory.iram_raw[current_piece] = 0x11;
67+
emu.memory.iram_raw[p1_current_piece] = 0x11;
68+
emu.memory.iram_raw[x] = 0x5;
69+
emu.memory.iram_raw[y] = 0x12;
70+
emu.memory.iram_raw[p1_x] = 0x5;
71+
emu.memory.iram_raw[p1_y] = 0x12;
72+
emu.memory.iram_raw[auto_repeat_y] = 0;
73+
emu.memory.iram_raw[p1_auto_repeat_y] = 0;
74+
// emu.memory.iram_raw[push_down] = 8;
75+
// emu.memory.iram_raw[p1_push_down] = 8;
76+
// emu.memory.iram_raw[clear_count] = 9;
77+
// emu.memory.iram_raw[clear_count+1] = 5;
78+
// emu.memory.iram_raw[clear_count+2] = 5;
79+
// emu.memory.iram_raw[clear_count+3] = 5;
80+
81+
for _ in 0..100 {
82+
if emu.memory.iram_raw[play_state] == 5 || emu.memory.iram_raw[p1_play_state] == 5 {
83+
break;
84+
}
85+
println!("{}", emu.registers.pc);
86+
emu.run_until_vblank();
87+
}
88+
89+
println!("{}", emu.registers.pc);
90+
91+
video::preview(&mut emu);
92+
93+
94+
println!("{}", emu.memory.iram_raw[p1_push_down]);
95+
96+
// uncrash by replacing the PC
97+
}

tests/src/main.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
mod block;
2-
mod cycle_count;
32
mod input;
43
mod labels;
54
mod playfield;
65
mod util;
76
mod video;
87

8+
mod cycle_count;
9+
mod crash;
10+
911
mod drought;
1012
mod floor;
1113
mod garbage;
@@ -37,6 +39,8 @@ struct TestOptions {
3739
test_single: Option<String>,
3840
#[options(help = "count cycles")]
3941
cycles: bool,
42+
#[options(help = "fuzz crash")]
43+
crash: bool,
4044
#[options(help = "set SPS seed", parse(try_from_str = "parse_hex"))]
4145
sps_seed: u32,
4246
#[options(help = "print SPS pieces")]
@@ -88,6 +92,11 @@ fn main() {
8892
}
8993
}
9094

95+
// fuzz crash
96+
if options.crash {
97+
crash::fuzz();
98+
}
99+
91100
// count cycles
92101
if options.cycles {
93102
cycle_count::count_cycles();

tests/src/patch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub fn test() {
2-
let clean = include_bytes!("../../clean.nes");
2+
let clean = crate::util::OG_ROM;
33
let patch = include_bytes!("../../tetris.bps");
44

55
// check original file hasn't changed

tests/src/playfield.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@ use rusticnes_core::nes::NesState;
22
use crate::labels;
33

44
pub fn set(emu: &mut NesState, x: u16, y: u16, value: u8) {
5-
let index = ((y * 10) + x) + labels::get("playfield");
5+
set_addr(emu, labels::get("playfield"), x, y, value);
6+
}
7+
8+
pub fn set_addr(emu: &mut NesState, playfield_addr: u16, x: u16, y: u16, value: u8) {
9+
let index = ((y * 10) + x) + playfield_addr;
610
emu.memory.iram_raw[index as usize] = value;
711
}
812

913
pub fn get(emu: &NesState, x: u16, y: u16) -> u8 {
10-
let index = ((y * 10) + x) + labels::get("playfield");
14+
get_addr(emu, labels::get("playfield"), x, y)
15+
}
16+
17+
pub fn get_addr(emu: &NesState, playfield_addr: u16, x: u16, y: u16) -> u8 {
18+
let index = ((y * 10) + x) + playfield_addr;
1119
emu.memory.iram_raw[index as usize]
1220
}
1321

@@ -20,15 +28,19 @@ pub fn clear(emu: &mut NesState) {
2028
}
2129

2230
pub fn set_str(emu: &mut NesState, playfield: &str) {
23-
set_str_inner(emu, playfield, false);
31+
set_str_inner_addr(emu, labels::get("playfield"), playfield, false);
32+
}
33+
34+
pub fn set_str_addr(emu: &mut NesState, playfield_addr: u16, playfield: &str) {
35+
set_str_inner_addr(emu, playfield_addr, playfield, false);
2436
}
2537

2638
#[allow(dead_code)]
2739
pub fn set_str_top(emu: &mut NesState, playfield: &str) {
28-
set_str_inner(emu, playfield, true);
40+
set_str_inner_addr(emu, labels::get("playfield"), playfield, true);
2941
}
3042

31-
fn set_str_inner(emu: &mut NesState, playfield: &str, top: bool) {
43+
fn set_str_inner_addr(emu: &mut NesState, playfield_addr: u16, playfield: &str, top: bool) {
3244
let rows = playfield.trim_start_matches('\n').split("\n").collect::<Vec<_>>();
3345
let offset = if top {
3446
0
@@ -37,7 +49,7 @@ fn set_str_inner(emu: &mut NesState, playfield: &str, top: bool) {
3749
};
3850
rows.iter().enumerate().for_each(|(y, line)| {
3951
line.chars().enumerate().for_each(|(x, ch)| {
40-
self::set(emu, x as _, offset + y as u16, if ch == '#' { 0x7b } else { 0xef });
52+
self::set_addr(emu, playfield_addr, x as _, offset + y as u16, if ch == '#' { 0x7b } else { 0xef });
4153
});
4254
});
4355

tests/src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rusticnes_core::{ cartridge, opcodes, opcode_info };
33
use crate::{input, labels};
44

55
pub static ROM: &'static [u8] = include_bytes!("../../tetris.nes");
6+
pub static OG_ROM: &'static [u8] = include_bytes!("../../clean.nes");
67

78
pub fn rom_data() -> &'static [u8] {
89
&ROM[0x10..]

0 commit comments

Comments
 (0)