This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
use crate::runtime::{
|
||||
AudioOutput, ClientRuntime, EmulationState, FRAME_RGBA_BYTES, HostConfig, InputProvider,
|
||||
JOYPAD_BUTTON_ORDER, JOYPAD_BUTTONS_COUNT, JoypadButton, NesRuntime, NoopClock,
|
||||
RuntimeHostLoop, VideoMode, VideoOutput, button_pressed, set_button_pressed,
|
||||
button_pressed, set_button_pressed, AudioOutput, ClientRuntime, EmulationState, HostConfig,
|
||||
InputProvider, JoypadButton, NesRuntime, NoopClock, NullAudio, NullInput, NullVideo,
|
||||
RuntimeHostLoop, VideoMode, VideoOutput, FRAME_RGBA_BYTES, JOYPAD_BUTTONS_COUNT,
|
||||
JOYPAD_BUTTON_ORDER,
|
||||
};
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn nrom_test_rom() -> Vec<u8> {
|
||||
nrom_test_rom_with_program(&[0xEA, 0x4C, 0x00, 0x80])
|
||||
}
|
||||
|
||||
fn nrom_test_rom_with_program(program: &[u8]) -> Vec<u8> {
|
||||
let mut rom = vec![0u8; 16 + 16 * 1024 + 8 * 1024];
|
||||
rom[0..4].copy_from_slice(b"NES\x1A");
|
||||
rom[4] = 1; // 16 KiB PRG
|
||||
@@ -17,11 +22,7 @@ fn nrom_test_rom() -> Vec<u8> {
|
||||
rom[reset_vec] = 0x00;
|
||||
rom[reset_vec + 1] = 0x80;
|
||||
|
||||
// 0x8000: NOP; JMP $8000
|
||||
rom[prg_offset] = 0xEA;
|
||||
rom[prg_offset + 1] = 0x4C;
|
||||
rom[prg_offset + 2] = 0x00;
|
||||
rom[prg_offset + 3] = 0x80;
|
||||
rom[prg_offset..prg_offset + program.len()].copy_from_slice(program);
|
||||
rom
|
||||
}
|
||||
|
||||
@@ -83,6 +84,30 @@ fn audio_mixer_generates_samples() {
|
||||
assert_eq!(mixer.sample_rate(), 48_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn audio_mixer_accounts_for_oam_dma_stall_cycles() {
|
||||
let rom = nrom_test_rom_with_program(&[
|
||||
0xA9, 0x00, // LDA #$00
|
||||
0x8D, 0x14, 0x40, // STA $4014
|
||||
0x4C, 0x00, 0x80, // JMP $8000
|
||||
]);
|
||||
let runtime = NesRuntime::from_rom_bytes(&rom).expect("runtime init");
|
||||
let mode = runtime.video_mode();
|
||||
let mut host = RuntimeHostLoop::with_config(runtime, HostConfig::new(48_000, false));
|
||||
|
||||
let total_samples = host
|
||||
.run_frames_unpaced(120, &mut NullInput, &mut NullVideo, &mut NullAudio)
|
||||
.expect("run frames");
|
||||
|
||||
let expected = ((host.runtime().frame_number() as f64) * 48_000.0 / mode.frame_hz()).round();
|
||||
let drift_pct = ((total_samples as f64 - expected).abs() / expected) * 100.0;
|
||||
|
||||
assert!(
|
||||
drift_pct <= 2.5,
|
||||
"audio drift too high with OAM DMA: {drift_pct:.3}% (samples={total_samples}, expected={expected:.0})"
|
||||
);
|
||||
}
|
||||
|
||||
struct FixedInput;
|
||||
|
||||
impl InputProvider for FixedInput {
|
||||
|
||||
Reference in New Issue
Block a user