Skip to content

Commit b95e4ca

Browse files
committed
add ingame cycle counting
1 parent 64a501a commit b95e4ca

File tree

3 files changed

+144
-7
lines changed

3 files changed

+144
-7
lines changed

src/util/core.asm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ random10:
5050
bpl random10
5151
rts
5252

53+
nmiWaitStart: ; used in tests
54+
5355
; canon is waitForVerticalBlankingInterval
5456
updateAudioWaitForNmiAndResetOamStaging:
5557
jsr updateAudio_jmp
@@ -86,6 +88,8 @@ updateAudioAndWaitForNmi:
8688
beq @checkForNmi
8789
rts
8890

91+
nmiWaitEnd:
92+
8993
updateAudioWaitForNmiAndDisablePpuRendering:
9094
jsr updateAudioAndWaitForNmi
9195
lda currentPpuMask

tests/src/cycle_count.rs

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::{util, score, labels};
1+
use crate::{util, score, labels, playfield};
2+
use rusticnes_core::nes::NesState;
23

34
pub fn count_cycles() {
45
let mut emu = util::emulator(None);
@@ -29,4 +30,136 @@ pub fn count_cycles() {
2930
}
3031

3132
println!("scoring routine most cycles: {}", highest);
33+
34+
use crate::video;
35+
36+
// check clock cycles frames in each mode
37+
38+
let mut emu = util::emulator(None);
39+
let mut view = video::Video::new();
40+
41+
for _ in 0..3 { emu.run_until_vblank(); }
42+
43+
let practise_type = labels::get("practiseType") as usize;
44+
let game_mode = labels::get("gameMode") as usize;
45+
let main_loop = labels::get("mainLoop");
46+
let level_number = labels::get("levelNumber") as usize;
47+
48+
49+
emu.memory.iram_raw[practise_type] = labels::get("MODE_TRANSITION") as _;
50+
emu.memory.iram_raw[level_number] = 18;
51+
emu.memory.iram_raw[game_mode] = 4;
52+
emu.registers.pc = main_loop;
53+
54+
for _ in 0..5 { emu.run_until_vblank(); }
55+
56+
let (mut highest, mut level, mut lines) = (0, 0, 0);
57+
58+
for _ in 0..10 {
59+
60+
for line in 0..5 {
61+
emu.memory.iram_raw[labels::get("currentPiece") as usize] = 0x11;
62+
emu.memory.iram_raw[labels::get("tetriminoX") as usize] = 0x5;
63+
emu.memory.iram_raw[labels::get("tetriminoY") as usize] = 0x11;
64+
emu.memory.iram_raw[labels::get("autorepeatY") as usize] = 0;
65+
emu.memory.iram_raw[labels::get("vramRow") as usize] = 0;
66+
67+
playfield::clear(&mut emu);
68+
69+
playfield::set_str(&mut emu, match line {
70+
0 => "",
71+
1 => "##### ####",
72+
2 => "##### ####\n##### ####",
73+
3 => "##### ####\n##### ####\n##### ####",
74+
4 => "##### ####\n##### ####\n##### ####\n##### ####",
75+
_ => unreachable!("line"),
76+
});
77+
78+
emu.run_until_vblank();
79+
80+
for _ in 0..[44, 47, 47, 46, 45][line] {
81+
82+
let cycles = cycles_to_hblank(&mut emu);
83+
84+
if cycles > highest {
85+
highest = cycles;
86+
level = emu.memory.iram_raw[level_number];
87+
lines = line;
88+
}
89+
90+
println!("{}/{} ({} {})", highest, cycles, lines, level);
91+
92+
// std::thread::sleep(std::time::Duration::from_millis(50));
93+
94+
}
95+
96+
emu.ppu.render_ntsc(video::WIDTH);
97+
view.update(&emu.ppu.filtered_screen);
98+
99+
}
100+
}
101+
102+
// println!("{:#?}", (highest, level, lines));
103+
104+
105+
loop {}
106+
107+
}
108+
109+
fn cycles_to_hblank(emu: &mut NesState) -> u32 {
110+
let nmi_wait_start = labels::get("nmiWaitStart");
111+
let nmi_wait_end = labels::get("nmiWaitEnd");
112+
let mut cycles = 0;
113+
let mut done = false;
114+
115+
while emu.ppu.current_scanline == 242 {
116+
emu.cycle();
117+
if !done {
118+
cycles += 1;
119+
if emu.registers.pc >= nmi_wait_start && emu.registers.pc <= nmi_wait_end {
120+
done = true
121+
}
122+
}
123+
let mut i = 0;
124+
while emu.cpu.tick >= 1 && i < 10 {
125+
emu.cycle();
126+
if !done {
127+
cycles += 1;
128+
if emu.registers.pc >= nmi_wait_start && emu.registers.pc <= nmi_wait_end {
129+
done = true
130+
}
131+
}
132+
i += 1;
133+
}
134+
if emu.ppu.current_frame != emu.last_frame {
135+
emu.event_tracker.swap_buffers();
136+
emu.last_frame = emu.ppu.current_frame;
137+
}
138+
}
139+
while emu.ppu.current_scanline != 242 {
140+
emu.cycle();
141+
if !done {
142+
cycles += 1;
143+
if emu.registers.pc >= nmi_wait_start && emu.registers.pc <= nmi_wait_end {
144+
done = true
145+
}
146+
}
147+
let mut i = 0;
148+
while emu.cpu.tick >= 1 && i < 10 {
149+
emu.cycle();
150+
if !done {
151+
cycles += 1;
152+
if emu.registers.pc >= nmi_wait_start && emu.registers.pc <= nmi_wait_end {
153+
done = true
154+
}
155+
}
156+
i += 1;
157+
}
158+
if emu.ppu.current_frame != emu.last_frame {
159+
emu.event_tracker.swap_buffers();
160+
emu.last_frame = emu.ppu.current_frame;
161+
}
162+
}
163+
164+
cycles
32165
}

tools/cycles.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ highCountLong = 0
88
function startFrame(address, value)
99
state = emu.getState()
1010
waitForVBlankTrigger = false
11-
lastCycles = state.cpu.cycleCount
11+
lastCycles = state["cpu.cycleCount"]
1212
highCountShort = highCountShort + 1
1313
highCountLong = highCountLong + 1
1414
if highCountShort > 30 then
@@ -29,18 +29,18 @@ function vblankCheck(address, value)
2929
if waitForVBlankTrigger == false then
3030
waitForVBlankTrigger = true
3131
state = emu.getState()
32-
diff = state.cpu.cycleCount - lastCycles
32+
diff = state["cpu.cycleCount"] - lastCycles
3333
if diff > highestShort then
3434
highestShort = diff
3535
end
3636
if diff > highestLong then
3737
highestLong = diff
3838
end
3939
emu.drawRectangle(8, 8, 150, 36, 0x000000, true, 1)
40-
emu.drawString(12, 9, "used cycles - " .. diff .. cyclePCT(diff), 0xFFFFFF, 0xFF000000, 1)
41-
emu.drawString(12, 21, "highest/sec/2 - " .. highestShort .. cyclePCT(highestShort), 0xFFFFFF, 0xFF000000, 1)
42-
emu.drawString(12, 33, "highest/2sec - " .. highestLong .. cyclePCT(highestLong), 0xFFFFFF, 0xFF000000, 1)
40+
emu.drawString(12, 9, "used cycles - " .. diff .. cyclePCT(diff), 0xFFFFFF, 0xFF000000, 0, 1)
41+
emu.drawString(12, 21, "highest/sec/2 - " .. highestShort .. cyclePCT(highestShort), 0xFFFFFF, 0xFF000000, 0, 1)
42+
emu.drawString(12, 33, "highest/2sec - " .. highestLong .. cyclePCT(highestLong), 0xFFFFFF, 0xFF000000, 0, 1)
4343
end
4444
end
45-
emu.addMemoryCallback(vblankCheck, emu.memCallbackType.cpuRead, 0x33)
45+
emu.addMemoryCallback(vblankCheck, emu.callbackType.read, 0x33)
4646
emu.addEventCallback(startFrame, emu.eventType.startFrame)

0 commit comments

Comments
 (0)