Skip to content

Commit 938d066

Browse files
committed
test ppu updates during vblank
while testing this i found that updating the score, lines, and hz display all in the same frame takes too long. currently this isn't an issue because negative delay doesn't go back that far, but if needed there are several ways to optimize this (e.g. delay the hz update until the next piece spawn, don't update hz during entry delay, etc.)
1 parent 565d6d8 commit 938d066

File tree

3 files changed

+77
-2
lines changed

3 files changed

+77
-2
lines changed

src/nmi/render_mode_play_and_demo.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ render_mode_play_and_demo:
9393
and #RENDER_SCORE
9494
beq @renderHz
9595

96-
; 8 safe tile writes freed from stats / hz
96+
; 9 safe tile writes freed from stats / hz
9797
; (lazy render hz for 10 more)
9898
; 1 added in level (3 total)
9999
; 2 added in lines (5 total)

tests/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod sps;
1717
mod toprow;
1818
mod tspins;
1919
mod hz_display;
20+
mod nmi;
2021

2122
use gumdrop::Options;
2223

@@ -47,7 +48,7 @@ struct TestOptions {
4748
fn main() {
4849
let options = TestOptions::parse_args_default_or_exit();
4950

50-
let tests: [(&str, fn()); 11] = [
51+
let tests: [(&str, fn()); 12] = [
5152
("garbage4", garbage::test_garbage4_crash),
5253
("floor", floor::test),
5354
("tspins", tspins::test),
@@ -59,6 +60,7 @@ fn main() {
5960
("sps", sps::test),
6061
("palettes", palettes::test),
6162
("hz_display", hz_display::test),
63+
("nmi", nmi::test),
6264
];
6365

6466
// run tests

tests/src/nmi.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::{labels, playfield, util};
2+
3+
/// makes sure nmi exits quickly enough
4+
pub fn test() {
5+
let mut emu = util::emulator(None);
6+
7+
let main_loop = labels::get("mainLoop");
8+
let game_mode = labels::get("gameMode") as usize;
9+
let level_number = labels::get("levelNumber") as usize;
10+
let nmi_label = labels::get("nmi");
11+
let hz_flag = labels::get("hzFlag") as usize;
12+
let render_flags = labels::get("renderFlags") as usize;
13+
14+
// spend a few frames bootstrapping
15+
for _ in 0..3 {
16+
emu.run_until_vblank();
17+
}
18+
19+
// copied setup from garbage.rs
20+
emu.memory.iram_raw[hz_flag] = 1;
21+
emu.memory.iram_raw[game_mode] = 4;
22+
emu.memory.iram_raw[level_number] = 18;
23+
emu.registers.pc = main_loop;
24+
25+
for _ in 0..11 {
26+
emu.run_until_vblank();
27+
}
28+
29+
// sets up a triple in the top of the board
30+
emu.memory.iram_raw[labels::get("currentPiece") as usize] = 0x0F; // L piece
31+
emu.memory.iram_raw[labels::get("tetriminoX") as usize] = 0x6;
32+
emu.memory.iram_raw[labels::get("tetriminoY") as usize] = 0x0;
33+
emu.memory.iram_raw[labels::get("vramRow") as usize] = 0;
34+
emu.memory.iram_raw[labels::get("autorepeatY") as usize] = 0;
35+
36+
playfield::set_str(&mut emu, r##"
37+
##### ###
38+
##### ###
39+
###### ###
40+
###### ###
41+
#########
42+
#########
43+
#########
44+
#########
45+
#########
46+
#########
47+
#########
48+
#########
49+
#########
50+
#########
51+
#########
52+
#########
53+
#########
54+
#########
55+
#########
56+
######### "##);
57+
58+
for _ in 0..50 {
59+
// loop until pc is at the instruction after the jsr copyOamStagingToOam
60+
while emu.registers.pc != nmi_label + 25 {
61+
emu.step();
62+
if emu.ppu.current_scanline == 261 {
63+
panic!("render took too long!");
64+
}
65+
}
66+
// cannot render hz on the same frame score/lines are updated
67+
let state = emu.memory.iram_raw[labels::get("playState") as usize];
68+
if state != 5 {
69+
emu.memory.iram_raw[render_flags] |= 0x10;
70+
}
71+
emu.run_until_vblank();
72+
}
73+
}

0 commit comments

Comments
 (0)