From 5e228c377ea6101249c69af7945ee00263f3f87c Mon Sep 17 00:00:00 2001 From: transistor Date: Sun, 7 May 2023 20:42:55 -0700 Subject: [PATCH] Fixed tests after ClockTime and Frequency changes And also removed HostData --- emulator/core/src/host/mod.rs | 2 +- emulator/core/src/host/traits.rs | 26 +--- emulator/cpus/m68k/src/tests.rs | 60 ++++---- emulator/cpus/m68k/tests/decode_tests.rs | 12 +- emulator/cpus/m68k/tests/execute_tests.rs | 16 +- .../cpus/m68k/tests/musashi_timing_tests.rs | 12 +- emulator/cpus/m68k/tests/timing_tests.rs | 12 +- emulator/cpus/z80/tests/decode_tests.rs | 6 +- emulator/cpus/z80/tests/execute_tests.rs | 6 +- emulator/frontends/common/src/audio.rs | 8 +- .../frontends/console/src/bin/moa-bench.rs | 12 +- emulator/peripherals/yamaha/src/sn76489.rs | 4 +- emulator/peripherals/yamaha/src/ym2612.rs | 12 +- .../genesis/src/peripherals/controllers.rs | 10 +- .../systems/genesis/src/peripherals/ym7101.rs | 8 +- .../2022-09-10-first-test-run-68000.txt} | 0 .../2022-09-10-first-test-run-68010.txt} | 0 .../2022-09-18-at-92-percent.txt} | 0 ...18-at-95-percent-excluding-addr-error.txt} | 0 .../2022-09-18-at-96-percent-mostly-there.txt | 129 ++++++++++++++++ ...ent-mostly-there-excluding-addr-error.txt} | 0 tests/harte_tests/src/main.rs | 18 +-- todo.txt | 144 ++++++------------ 23 files changed, 272 insertions(+), 225 deletions(-) rename tests/harte_tests/{baseline.txt => progress/2022-09-10-first-test-run-68000.txt} (100%) rename tests/harte_tests/{baseline-68010.txt => progress/2022-09-10-first-test-run-68010.txt} (100%) rename tests/harte_tests/{previous.txt => progress/2022-09-18-at-92-percent.txt} (100%) rename tests/harte_tests/{previous-excluding-addr-error.txt => progress/2022-09-18-at-95-percent-excluding-addr-error.txt} (100%) create mode 100644 tests/harte_tests/progress/2022-09-18-at-96-percent-mostly-there.txt rename tests/harte_tests/{latest-excluding-addr-error.txt => progress/2022-09-18-at-98-percent-mostly-there-excluding-addr-error.txt} (100%) diff --git a/emulator/core/src/host/mod.rs b/emulator/core/src/host/mod.rs index 71d9b14..6749e17 100644 --- a/emulator/core/src/host/mod.rs +++ b/emulator/core/src/host/mod.rs @@ -13,5 +13,5 @@ pub use self::keys::{Key, KeyEvent}; pub use self::mouse::{MouseButton, MouseEventType, MouseEvent, MouseState}; pub use self::controllers::{ControllerDevice, ControllerInput, ControllerEvent}; pub use self::input::{EventSender, EventReceiver, event_queue}; -pub use self::traits::{Host, Tty, Audio, HostData, ClockedQueue, DummyAudio}; +pub use self::traits::{Host, Tty, Audio, ClockedQueue, DummyAudio}; diff --git a/emulator/core/src/host/traits.rs b/emulator/core/src/host/traits.rs index 4ee9774..e85cf3d 100644 --- a/emulator/core/src/host/traits.rs +++ b/emulator/core/src/host/traits.rs @@ -1,6 +1,6 @@ use std::collections::VecDeque; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::{Arc, Mutex}; use crate::{ClockTime, Error}; use crate::host::gfx::FrameReceiver; @@ -50,30 +50,6 @@ pub trait Audio { } -#[derive(Clone, Debug)] -pub struct HostData(Arc>); - -impl HostData { - pub fn new(init: T) -> HostData { - HostData(Arc::new(Mutex::new(init))) - } - - pub fn lock(&self) -> MutexGuard<'_, T> { - self.0.lock().unwrap() - } -} - -impl HostData { - pub fn set(&mut self, value: T) { - *(self.0.lock().unwrap()) = value; - } - - pub fn get(&mut self) -> T { - *(self.0.lock().unwrap()) - } -} - - #[derive(Clone, Default)] pub struct ClockedQueue(Arc>>, usize); diff --git a/emulator/cpus/m68k/src/tests.rs b/emulator/cpus/m68k/src/tests.rs index 90dc733..e8ea159 100644 --- a/emulator/cpus/m68k/src/tests.rs +++ b/emulator/cpus/m68k/src/tests.rs @@ -4,7 +4,7 @@ mod decode_unit_tests { use std::rc::Rc; use std::cell::RefCell; - use moa_core::{Bus, BusPort, Address, Addressable, MemoryBlock, wrap_transmutable}; + use moa_core::{Bus, BusPort, ClockTime, Address, Addressable, MemoryBlock, wrap_transmutable}; use crate::M68kType; use crate::instructions::{Target, Size, XRegister, BaseRegister, IndexRegister}; @@ -22,7 +22,7 @@ mod decode_unit_tests { } else { BusPort::new(0, 32, 32, bus) }; - let decoder = M68kDecoder::new(cputype, 0); + let decoder = M68kDecoder::new(cputype, ClockTime::START, 0); (port, decoder) } @@ -57,7 +57,7 @@ mod decode_unit_tests { let size = Size::Long; let expected = 0x12345678; - port.write_beu32(INIT_ADDR, expected).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b010, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectAReg(2)); @@ -70,7 +70,7 @@ mod decode_unit_tests { let size = Size::Long; let expected = 0x12345678; - port.write_beu32(INIT_ADDR, expected).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b011, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegInc(2)); @@ -83,7 +83,7 @@ mod decode_unit_tests { let size = Size::Long; let expected = 0x12345678; - port.write_beu32(INIT_ADDR, expected).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b100, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectARegDec(2)); @@ -96,7 +96,7 @@ mod decode_unit_tests { let size = Size::Long; let offset = -8; - port.write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, (offset as i16) as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b101, 0b100, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(4), None, offset)); @@ -110,8 +110,8 @@ mod decode_unit_tests { let offset = -8; let brief_extension = 0x3800 | (((offset as i8) as u8) as u16); - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b110, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset)); @@ -125,8 +125,8 @@ mod decode_unit_tests { let offset = -1843235 as i32; let brief_extension = 0xF330; - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu32(INIT_ADDR + 2, offset as u32).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR + 2, offset as u32).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b110, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset)); @@ -140,8 +140,8 @@ mod decode_unit_tests { let offset = -1843235 as i32; let brief_extension = 0xF3B0; - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu32(INIT_ADDR + 2, offset as u32).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR + 2, offset as u32).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b110, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::None, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset)); @@ -155,8 +155,8 @@ mod decode_unit_tests { let offset = -1843235 as i32; let brief_extension = 0xF370; - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu32(INIT_ADDR + 2, offset as u32).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR + 2, offset as u32).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b110, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), None, offset)); @@ -169,7 +169,7 @@ mod decode_unit_tests { let size = Size::Long; let offset = -8; - port.write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, (offset as i16) as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b010, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, None, offset)); @@ -183,8 +183,8 @@ mod decode_unit_tests { let offset = -8; let brief_extension = 0x3000 | (((offset as i8) as u8) as u16); - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b011, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset)); @@ -198,8 +198,8 @@ mod decode_unit_tests { let offset = -1843235 as i32; let brief_extension = 0xF330; - port.write_beu16(INIT_ADDR, brief_extension).unwrap(); - port.write_beu32(INIT_ADDR + 2, offset as u32).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, brief_extension).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR + 2, offset as u32).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b011, Some(size)).unwrap(); assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset)); @@ -213,7 +213,7 @@ mod decode_unit_tests { let size = Size::Word; let expected = 0x1234; - port.write_beu16(INIT_ADDR, expected as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, expected as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b000, Some(size)).unwrap(); assert_eq!(target, Target::IndirectMemory(expected, Size::Word)); @@ -226,7 +226,7 @@ mod decode_unit_tests { let size = Size::Word; let expected = 0x12345678; - port.write_beu32(INIT_ADDR, expected).unwrap(); + port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b001, Some(size)).unwrap(); assert_eq!(target, Target::IndirectMemory(expected, Size::Long)); @@ -239,7 +239,7 @@ mod decode_unit_tests { let size = Size::Word; let expected = 0x1234; - port.write_beu16(INIT_ADDR, expected as u16).unwrap(); + port.write_beu16(ClockTime::START, INIT_ADDR, expected as u16).unwrap(); let target = decoder.get_mode_as_target(&mut port, 0b111, 0b100, Some(size)).unwrap(); assert_eq!(target, Target::Immediate(expected)); @@ -249,7 +249,7 @@ mod decode_unit_tests { #[cfg(test)] mod execute_unit_tests { - use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, wrap_transmutable}; + use moa_core::{System, MemoryBlock, BusPort, ClockTime, Frequency, Address, Addressable, Steppable, wrap_transmutable}; use crate::{M68k, M68kType}; use crate::execute::Used; @@ -265,17 +265,17 @@ mod execute_unit_tests { let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); - system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); - system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); + system.get_bus().write_beu32(system.clock, 0, INIT_STACK as u32).unwrap(); + system.get_bus().write_beu32(system.clock, 4, INIT_ADDR as u32).unwrap(); let port = if cputype <= M68kType::MC68010 { BusPort::new(0, 24, 16, system.bus.clone()) } else { BusPort::new(0, 24, 16, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.step(&system).unwrap(); - cpu.decoder.init(cpu.state.pc); + cpu.decoder.init(system.clock, cpu.state.pc); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); assert_eq!(cpu.decoder.instruction, Instruction::NOP); @@ -319,7 +319,7 @@ mod execute_unit_tests { let size = Size::Long; let expected = 0x12345678; let target = Target::IndirectAReg(2); - cpu.port.write_beu32(INIT_ADDR, expected).unwrap(); + cpu.port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); cpu.state.a_reg[2] = INIT_ADDR as u32; let result = cpu.get_target_value(target, size, Used::Once).unwrap(); @@ -333,7 +333,7 @@ mod execute_unit_tests { let size = Size::Long; let expected = 0x12345678; let target = Target::IndirectARegInc(2); - cpu.port.write_beu32(INIT_ADDR, expected).unwrap(); + cpu.port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); cpu.state.a_reg[2] = INIT_ADDR as u32; let result = cpu.get_target_value(target, size, Used::Once).unwrap(); @@ -348,7 +348,7 @@ mod execute_unit_tests { let size = Size::Long; let expected = 0x12345678; let target = Target::IndirectARegDec(2); - cpu.port.write_beu32(INIT_ADDR, expected).unwrap(); + cpu.port.write_beu32(ClockTime::START, INIT_ADDR, expected).unwrap(); cpu.state.a_reg[2] = (INIT_ADDR as u32) + 4; let result = cpu.get_target_value(target, size, Used::Once).unwrap(); diff --git a/emulator/cpus/m68k/tests/decode_tests.rs b/emulator/cpus/m68k/tests/decode_tests.rs index e60028d..312f2ee 100644 --- a/emulator/cpus/m68k/tests/decode_tests.rs +++ b/emulator/cpus/m68k/tests/decode_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, wrap_transmutable}; +use moa_core::{System, MemoryBlock, BusPort, ClockTime, Frequency, Address, Addressable, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_m68k::instructions::{Instruction, Target, Size, Sign, XRegister, BaseRegister, IndexRegister, Direction, ShiftDirection}; @@ -68,8 +68,8 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); - system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); - system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 0, INIT_STACK as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 4, INIT_ADDR as u32).unwrap(); // Initialize the CPU and make sure it's in the expected state let port = if cputype <= M68kType::MC68010 { @@ -77,12 +77,12 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { } else { BusPort::new(0, 24, 16, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.init().unwrap(); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); - cpu.decoder.init(INIT_ADDR as u32); + cpu.decoder.init(ClockTime::START, INIT_ADDR as u32); assert_eq!(cpu.decoder.start, INIT_ADDR as u32); assert_eq!(cpu.decoder.instruction, Instruction::NOP); (cpu, system) @@ -91,7 +91,7 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { fn load_memory(system: &System, data: &[u16]) { let mut addr = INIT_ADDR; for word in data { - system.get_bus().write_beu16(addr, *word).unwrap(); + system.get_bus().write_beu16(system.clock, addr, *word).unwrap(); addr += 2; } } diff --git a/emulator/cpus/m68k/tests/execute_tests.rs b/emulator/cpus/m68k/tests/execute_tests.rs index a9eb0b3..4599c96 100644 --- a/emulator/cpus/m68k/tests/execute_tests.rs +++ b/emulator/cpus/m68k/tests/execute_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, wrap_transmutable}; +use moa_core::{System, MemoryBlock, BusPort, ClockTime, Frequency, Address, Addressable, Steppable, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_m68k::state::M68kState; @@ -39,17 +39,17 @@ fn init_execute_test(cputype: M68kType) -> (M68k, System) { let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); - system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); - system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 0, INIT_STACK as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 4, INIT_ADDR as u32).unwrap(); let port = if cputype <= M68kType::MC68010 { BusPort::new(0, 24, 16, system.bus.clone()) } else { BusPort::new(0, 24, 16, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.step(&system).unwrap(); - cpu.decoder.init(cpu.state.pc); + cpu.decoder.init(system.clock, cpu.state.pc); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); assert_eq!(cpu.decoder.instruction, Instruction::NOP); @@ -71,7 +71,7 @@ fn build_state(state: &TestState) -> M68kState { fn load_memory(system: &System, data: &[u16]) { for i in 0..data.len() { - system.get_bus().write_beu16((i << 1) as Address, data[i]).unwrap(); + system.get_bus().write_beu16(system.clock, (i << 1) as Address, data[i]).unwrap(); } } @@ -80,7 +80,7 @@ fn run_test(case: &TestCase) { let init_state = build_state(&case.init); let mut expected_state = build_state(&case.fini); - system.get_bus().write_beu32(MEM_ADDR as Address, case.init.mem).unwrap(); + system.get_bus().write_beu32(system.clock, MEM_ADDR as Address, case.init.mem).unwrap(); load_memory(&system, case.data); cpu.state = init_state; @@ -92,7 +92,7 @@ fn run_test(case: &TestCase) { expected_state.request = cpu.state.request.clone(); assert_eq!(cpu.state, expected_state); - let mem = system.get_bus().read_beu32(MEM_ADDR as Address).unwrap(); + let mem = system.get_bus().read_beu32(system.clock, MEM_ADDR as Address).unwrap(); assert_eq!(mem, case.fini.mem); } diff --git a/emulator/cpus/m68k/tests/musashi_timing_tests.rs b/emulator/cpus/m68k/tests/musashi_timing_tests.rs index 3674ecf..87a25c9 100644 --- a/emulator/cpus/m68k/tests/musashi_timing_tests.rs +++ b/emulator/cpus/m68k/tests/musashi_timing_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, Error, MemoryBlock, BusPort, Address, Addressable, wrap_transmutable}; +use moa_core::{System, Error, MemoryBlock, BusPort, ClockTime, Frequency, Address, Addressable, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_m68k::instructions::{Instruction, Target, Size, Sign, Condition, XRegister, BaseRegister, IndexRegister, Direction, ShiftDirection}; @@ -16,8 +16,8 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); - system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); - system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 0, INIT_STACK as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 4, INIT_ADDR as u32).unwrap(); // Initialize the CPU and make sure it's in the expected state let port = if cputype <= M68kType::MC68010 { @@ -25,12 +25,12 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { } else { BusPort::new(0, 24, 16, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.init().unwrap(); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); - cpu.decoder.init(INIT_ADDR as u32); + cpu.decoder.init(ClockTime::START, INIT_ADDR as u32); assert_eq!(cpu.decoder.start, INIT_ADDR as u32); assert_eq!(cpu.decoder.instruction, Instruction::NOP); (cpu, system) @@ -39,7 +39,7 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { fn load_memory(system: &System, data: &[u16]) { let mut addr = INIT_ADDR; for word in data { - system.get_bus().write_beu16(addr, *word).unwrap(); + system.get_bus().write_beu16(system.clock, addr, *word).unwrap(); addr += 2; } } diff --git a/emulator/cpus/m68k/tests/timing_tests.rs b/emulator/cpus/m68k/tests/timing_tests.rs index 7cedc01..280f46c 100644 --- a/emulator/cpus/m68k/tests/timing_tests.rs +++ b/emulator/cpus/m68k/tests/timing_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, Error, MemoryBlock, BusPort, Address, Addressable, wrap_transmutable}; +use moa_core::{System, Error, MemoryBlock, BusPort, ClockTime, Frequency, Address, Addressable, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_m68k::instructions::{Instruction, Target, Size}; @@ -28,8 +28,8 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { let data = vec![0; 0x00100000]; let mem = MemoryBlock::new(data); system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap(); - system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap(); - system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 0, INIT_STACK as u32).unwrap(); + system.get_bus().write_beu32(ClockTime::START, 4, INIT_ADDR as u32).unwrap(); // Initialize the CPU and make sure it's in the expected state let port = if cputype <= M68kType::MC68010 { @@ -37,12 +37,12 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { } else { BusPort::new(0, 24, 16, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.init().unwrap(); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); - cpu.decoder.init(INIT_ADDR as u32); + cpu.decoder.init(ClockTime::START, INIT_ADDR as u32); assert_eq!(cpu.decoder.start, INIT_ADDR as u32); assert_eq!(cpu.decoder.instruction, Instruction::NOP); (cpu, system) @@ -51,7 +51,7 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { fn load_memory(system: &System, data: &[u16]) { let mut addr = INIT_ADDR; for word in data { - system.get_bus().write_beu16(addr, *word).unwrap(); + system.get_bus().write_beu16(system.clock, addr, *word).unwrap(); addr += 2; } } diff --git a/emulator/cpus/z80/tests/decode_tests.rs b/emulator/cpus/z80/tests/decode_tests.rs index 6e53ba1..1d3da3e 100644 --- a/emulator/cpus/z80/tests/decode_tests.rs +++ b/emulator/cpus/z80/tests/decode_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, wrap_transmutable}; +use moa_core::{System, MemoryBlock, BusPort, Frequency, Address, Addressable, wrap_transmutable}; use moa_z80::{Z80, Z80Type}; use moa_z80::state::Register; @@ -14,7 +14,7 @@ fn init_decode_test() -> (Z80, System) { system.add_addressable_device(0x0000, wrap_transmutable(mem)).unwrap(); // Initialize the CPU and make sure it's in the expected state - let mut cpu = Z80::new(Z80Type::Z80, 4_000_000, BusPort::new(0, 16, 8, system.bus.clone())); + let mut cpu = Z80::new(Z80Type::Z80, Frequency::from_mhz(4), BusPort::new(0, 16, 8, system.bus.clone())); cpu.init().unwrap(); (cpu, system) @@ -22,7 +22,7 @@ fn init_decode_test() -> (Z80, System) { fn load_memory(system: &System, data: &[u8]) { for i in 0..data.len() { - system.get_bus().write_u8(i as Address, data[i]).unwrap(); + system.get_bus().write_u8(system.clock, i as Address, data[i]).unwrap(); } } diff --git a/emulator/cpus/z80/tests/execute_tests.rs b/emulator/cpus/z80/tests/execute_tests.rs index 3a2e0fd..7d2e6d2 100644 --- a/emulator/cpus/z80/tests/execute_tests.rs +++ b/emulator/cpus/z80/tests/execute_tests.rs @@ -1,5 +1,5 @@ -use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, wrap_transmutable}; +use moa_core::{System, MemoryBlock, BusPort, Frequency, Address, Addressable, wrap_transmutable}; use moa_z80::{Z80, Z80Type}; use moa_z80::state::{Z80State, Register}; @@ -489,7 +489,7 @@ fn init_execute_test() -> (Z80, System) { system.add_addressable_device(0x0000, wrap_transmutable(mem)).unwrap(); // Initialize the CPU and make sure it's in the expected state - let mut cpu = Z80::new(Z80Type::Z80, 4_000_000, BusPort::new(0, 16, 8, system.bus.clone())); + let mut cpu = Z80::new(Z80Type::Z80, Frequency::from_mhz(4), BusPort::new(0, 16, 8, system.bus.clone())); cpu.init().unwrap(); (cpu, system) @@ -514,7 +514,7 @@ fn build_state(state: &TestState) -> Z80State { fn load_memory(system: &System, data: &[u8]) { for i in 0..data.len() { - system.get_bus().write_u8(i as Address, data[i]).unwrap(); + system.get_bus().write_u8(system.clock, i as Address, data[i]).unwrap(); } } diff --git a/emulator/frontends/common/src/audio.rs b/emulator/frontends/common/src/audio.rs index 5ee9556..b51264b 100644 --- a/emulator/frontends/common/src/audio.rs +++ b/emulator/frontends/common/src/audio.rs @@ -75,7 +75,7 @@ impl AudioMixer { AudioMixer(Arc::new(Mutex::new(AudioMixerInner { sample_rate, sources: vec![], - output: AudioOutput::new(), + output: AudioOutput::default(), }))) } @@ -173,13 +173,15 @@ pub struct AudioOutput { queue: ClockedQueue, } -impl AudioOutput { - pub fn new() -> Self { +impl Default for AudioOutput { + fn default() -> Self { Self { queue: ClockedQueue::new(5000), } } +} +impl AudioOutput { pub fn add_frame(&self, clock: ClockTime, frame: AudioFrame) { self.queue.push(clock, frame); } diff --git a/emulator/frontends/console/src/bin/moa-bench.rs b/emulator/frontends/console/src/bin/moa-bench.rs index 94062ad..6b8e3c1 100644 --- a/emulator/frontends/console/src/bin/moa-bench.rs +++ b/emulator/frontends/console/src/bin/moa-bench.rs @@ -2,17 +2,15 @@ use std::thread; use std::time::Duration; -use moa_core::{System, Error, MemoryBlock, BusPort, wrap_transmutable}; +use moa_core::{System, Frequency, MemoryBlock, BusPort, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_peripherals_generic::AtaDevice; use moa_peripherals_motorola::MC68681; -use moa_systems_computie::build_computie; - fn main() { thread::spawn(|| { - let mut system = System::new(); + let mut system = System::default(); let monitor = MemoryBlock::load("binaries/computie/monitor.bin").unwrap(); system.add_addressable_device(0x00000000, wrap_transmutable(monitor)).unwrap(); @@ -21,15 +19,15 @@ fn main() { ram.load_at(0, "binaries/computie/kernel.bin").unwrap(); system.add_addressable_device(0x00100000, wrap_transmutable(ram)).unwrap(); - let mut ata = AtaDevice::new(); + let mut ata = AtaDevice::default(); ata.load("binaries/computie/disk-with-partition-table.img").unwrap(); system.add_addressable_device(0x00600000, wrap_transmutable(ata)).unwrap(); - let mut serial = MC68681::new(); + let serial = MC68681::default(); system.add_addressable_device(0x00700000, wrap_transmutable(serial)).unwrap(); - let mut cpu = M68k::new(M68kType::MC68010, 8_000_000, BusPort::new(0, 24, 16, system.bus.clone())); + let cpu = M68k::new(M68kType::MC68010, Frequency::from_mhz(8), BusPort::new(0, 24, 16, system.bus.clone())); //cpu.enable_tracing(); //cpu.add_breakpoint(0x10781a); diff --git a/emulator/peripherals/yamaha/src/sn76489.rs b/emulator/peripherals/yamaha/src/sn76489.rs index 8a32b87..8f98c70 100644 --- a/emulator/peripherals/yamaha/src/sn76489.rs +++ b/emulator/peripherals/yamaha/src/sn76489.rs @@ -86,7 +86,6 @@ impl NoiseGenerator { pub struct Sn76489 { - clock_frequency: Frequency, first_byte: Option, source: Box, tones: Vec, @@ -94,12 +93,11 @@ pub struct Sn76489 { } impl Sn76489 { - pub fn new(host: &mut H, clock_frequency: Frequency) -> Result { + pub fn new(host: &mut H, _clock_frequency: Frequency) -> Result { let source = host.add_audio_source()?; let sample_rate = source.samples_per_second(); Ok(Self { - clock_frequency, first_byte: None, source, tones: vec![ToneGenerator::new(sample_rate); 3], diff --git a/emulator/peripherals/yamaha/src/ym2612.rs b/emulator/peripherals/yamaha/src/ym2612.rs index 52b440b..7814c15 100644 --- a/emulator/peripherals/yamaha/src/ym2612.rs +++ b/emulator/peripherals/yamaha/src/ym2612.rs @@ -300,7 +300,7 @@ impl EnvelopeGenerator { EnvelopeState::Sustain | EnvelopeState::Release => { // Convert it to a fixed point decimal number of 4 bit : 8 bits, which will be the output - self.envelope = self.envelope + (increment << 2); + self.envelope += increment << 2; if self.envelope > MAX_ENVELOPE || self.envelope_state == EnvelopeState::Release && self.envelope >= ENVELOPE_CENTER { self.envelope = MAX_ENVELOPE; } @@ -680,14 +680,6 @@ impl Channel { } } -fn sign_extend_u16(value: u16, size: usize) -> i16 { - if value & (1 << (size + 1)) == 0 { - value as i16 - } else { - (value | 0xFFFF << (size + 1)) as i16 - } -} - struct Dac { enabled: bool, @@ -726,7 +718,6 @@ pub struct Ym2612 { selected_reg_0: Option, selected_reg_1: Option, - clock_frequency: Frequency, fm_clock_period: ClockDuration, next_fm_clock: FmClock, envelope_clock: EnvelopeClock, @@ -758,7 +749,6 @@ impl Ym2612 { selected_reg_0: None, selected_reg_1: None, - clock_frequency, fm_clock_period, next_fm_clock: 0, envelope_clock: 0, diff --git a/emulator/systems/genesis/src/peripherals/controllers.rs b/emulator/systems/genesis/src/peripherals/controllers.rs index 504441f..998f037 100644 --- a/emulator/systems/genesis/src/peripherals/controllers.rs +++ b/emulator/systems/genesis/src/peripherals/controllers.rs @@ -1,7 +1,7 @@ use moa_core::{warn, info}; -use moa_core::{System, Error, ClockTime, ClockDuration, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{self, Host, HostData, ControllerDevice, ControllerInput, ControllerEvent, EventReceiver}; +use moa_core::{System, Error, ClockTime, ClockDuration, Signal, Address, Addressable, Steppable, Transmutable}; +use moa_core::host::{self, Host, ControllerDevice, ControllerInput, ControllerEvent, EventReceiver}; const REG_VERSION: Address = 0x01; @@ -91,7 +91,7 @@ pub struct GenesisControllers { port_1: GenesisControllerPort, port_2: GenesisControllerPort, expansion: GenesisControllerPort, - interrupt: HostData, + interrupt: Signal, reset_timer: ClockDuration, } @@ -105,12 +105,12 @@ impl GenesisControllers { port_1: GenesisControllerPort::default(), port_2: GenesisControllerPort::default(), expansion: GenesisControllerPort::default(), - interrupt: HostData::new(false), + interrupt: Signal::new(false), reset_timer: ClockDuration::ZERO, }) } - pub fn get_interrupt_signal(&self) -> HostData { + pub fn get_interrupt_signal(&self) -> Signal { self.interrupt.clone() } diff --git a/emulator/systems/genesis/src/peripherals/ym7101.rs b/emulator/systems/genesis/src/peripherals/ym7101.rs index 382d30d..06e88bd 100644 --- a/emulator/systems/genesis/src/peripherals/ym7101.rs +++ b/emulator/systems/genesis/src/peripherals/ym7101.rs @@ -1,7 +1,7 @@ use moa_core::{debug, warn, error}; -use moa_core::{System, Error, EdgeSignal, ClockTime, ClockDuration, Frequency, Address, Addressable, Steppable, Inspectable, Transmutable, TransmutableBox, read_beu16, dump_slice}; -use moa_core::host::{self, Host, Pixel, PixelEncoding, Frame, FrameSender, HostData}; +use moa_core::{System, Error, EdgeSignal, ClockTime, ClockDuration, Frequency, Signal, Address, Addressable, Steppable, Inspectable, Transmutable, TransmutableBox, read_beu16, dump_slice}; +use moa_core::host::{self, Host, Pixel, PixelEncoding, Frame, FrameSender}; const REG_MODE_SET_1: usize = 0x00; @@ -685,12 +685,12 @@ pub struct Ym7101 { state: Ym7101State, sn_sound: TransmutableBox, - pub external_interrupt: HostData, + pub external_interrupt: Signal, pub frame_complete: EdgeSignal, } impl Ym7101 { - pub fn new(host: &mut H, external_interrupt: HostData, sn_sound: TransmutableBox) -> Ym7101 { + pub fn new(host: &mut H, external_interrupt: Signal, sn_sound: TransmutableBox) -> Ym7101 { let (sender, receiver) = host::frame_queue(320, 224); host.add_video_source(receiver).unwrap(); diff --git a/tests/harte_tests/baseline.txt b/tests/harte_tests/progress/2022-09-10-first-test-run-68000.txt similarity index 100% rename from tests/harte_tests/baseline.txt rename to tests/harte_tests/progress/2022-09-10-first-test-run-68000.txt diff --git a/tests/harte_tests/baseline-68010.txt b/tests/harte_tests/progress/2022-09-10-first-test-run-68010.txt similarity index 100% rename from tests/harte_tests/baseline-68010.txt rename to tests/harte_tests/progress/2022-09-10-first-test-run-68010.txt diff --git a/tests/harte_tests/previous.txt b/tests/harte_tests/progress/2022-09-18-at-92-percent.txt similarity index 100% rename from tests/harte_tests/previous.txt rename to tests/harte_tests/progress/2022-09-18-at-92-percent.txt diff --git a/tests/harte_tests/previous-excluding-addr-error.txt b/tests/harte_tests/progress/2022-09-18-at-95-percent-excluding-addr-error.txt similarity index 100% rename from tests/harte_tests/previous-excluding-addr-error.txt rename to tests/harte_tests/progress/2022-09-18-at-95-percent-excluding-addr-error.txt diff --git a/tests/harte_tests/progress/2022-09-18-at-96-percent-mostly-there.txt b/tests/harte_tests/progress/2022-09-18-at-96-percent-mostly-there.txt new file mode 100644 index 0000000..a6c947f --- /dev/null +++ b/tests/harte_tests/progress/2022-09-18-at-96-percent-mostly-there.txt @@ -0,0 +1,129 @@ +Last run on 2022-09-18 at commit 94d3e1d3894e6588ff6daa55f0ba82473b1e74c7 + +ABCD.json completed: 7993 passed, 72 FAILED +ADD.b.json completed, all passed! +ADD.l.json completed: 7736 passed, 329 FAILED +ADD.w.json completed: 7712 passed, 353 FAILED +ADDA.l.json completed, all passed! +ADDA.w.json completed, all passed! +ADDX.b.json completed, all passed! +ADDX.l.json completed: 5472 passed, 2593 FAILED +ADDX.w.json completed, all passed! +AND.b.json completed, all passed! +AND.l.json completed: 7779 passed, 286 FAILED +AND.w.json completed: 7764 passed, 301 FAILED +ANDItoCCR.json completed, all passed! +ANDItoSR.json completed, all passed! +ASL.b.json completed: 7238 passed, 827 FAILED +ASL.l.json completed: 6471 passed, 1594 FAILED +ASL.w.json completed: 7053 passed, 1012 FAILED +ASR.b.json completed: 7547 passed, 518 FAILED +ASR.l.json completed: 7092 passed, 973 FAILED +ASR.w.json completed: 7513 passed, 552 FAILED +BCHG.json completed, all passed! +BCLR.json completed, all passed! +BSET.json completed, all passed! +BSR.json completed, all passed! +BTST.json completed: 8052 passed, 13 FAILED +Bcc.json completed, all passed! +CHK.json completed: 7744 passed, 321 FAILED +CLR.b.json completed, all passed! +CLR.l.json completed: 7472 passed, 593 FAILED +CLR.w.json completed: 7465 passed, 600 FAILED +CMP.b.json completed, all passed! +CMP.l.json completed, all passed! +CMP.w.json completed, all passed! +CMPA.l.json completed, all passed! +CMPA.w.json completed, all passed! +DBcc.json completed, all passed! +DIVS.json completed, all passed! +DIVU.json completed: 8064 passed, 1 FAILED +EOR.b.json completed, all passed! +EOR.l.json completed: 7519 passed, 546 FAILED +EOR.w.json completed: 7525 passed, 540 FAILED +EORItoCCR.json completed, all passed! +EORItoSR.json completed, all passed! +EXG.json completed, all passed! +EXT.l.json completed, all passed! +EXT.w.json completed, all passed! +JMP.json completed, all passed! +JSR.json completed, all passed! +LEA.json completed, all passed! +LINK.json completed, all passed! +LSL.b.json completed: 7809 passed, 256 FAILED +LSL.l.json completed: 7056 passed, 1009 FAILED +LSL.w.json completed: 7523 passed, 542 FAILED +LSR.b.json completed: 7817 passed, 248 FAILED +LSR.l.json completed: 7072 passed, 993 FAILED +LSR.w.json completed: 7541 passed, 524 FAILED +MOVE.b.json completed, all passed! +MOVE.l.json completed: 5827 passed, 2238 FAILED +MOVE.q.json completed, all passed! +MOVE.w.json completed: 5855 passed, 2210 FAILED +MOVEA.l.json completed, all passed! +MOVEA.w.json completed, all passed! +MOVEM.l.json completed: 6035 passed, 2030 FAILED +MOVEM.w.json completed: 6431 passed, 1634 FAILED +MOVEP.l.json completed: 4036 passed, 4029 FAILED +MOVEP.w.json completed: 4046 passed, 4019 FAILED +MOVEfromSR.json completed: 6896 passed, 1169 FAILED +MOVEfromUSP.json completed, all passed! +MOVEtoCCR.json completed, all passed! +MOVEtoSR.json completed, all passed! +MOVEtoUSP.json completed, all passed! +MULS.json completed, all passed! +MULU.json completed, all passed! +NBCD.json completed: 8037 passed, 28 FAILED +NEG.b.json completed, all passed! +NEG.l.json completed: 7552 passed, 513 FAILED +NEG.w.json completed: 7531 passed, 534 FAILED +NEGX.b.json completed, all passed! +NEGX.l.json completed: 7520 passed, 545 FAILED +NEGX.w.json completed: 7510 passed, 555 FAILED +NOP.json completed, all passed! +NOT.b.json completed, all passed! +NOT.l.json completed: 7512 passed, 553 FAILED +NOT.w.json completed: 7530 passed, 535 FAILED +OR.b.json completed, all passed! +OR.l.json completed: 7756 passed, 309 FAILED +OR.w.json completed: 7765 passed, 300 FAILED +ORItoCCR.json completed, all passed! +ORItoSR.json completed, all passed! +PEA.json completed, all passed! +RESET.json completed, all passed! +ROL.b.json completed, all passed! +ROL.l.json completed, all passed! +ROL.w.json completed: 7882 passed, 183 FAILED +ROR.b.json completed, all passed! +ROR.l.json completed, all passed! +ROR.w.json completed: 7907 passed, 158 FAILED +ROXL.b.json completed: 8039 passed, 26 FAILED +ROXL.l.json completed: 8029 passed, 36 FAILED +ROXL.w.json completed: 7892 passed, 173 FAILED +ROXR.b.json completed: 8037 passed, 28 FAILED +ROXR.l.json completed: 8022 passed, 43 FAILED +ROXR.w.json completed: 7880 passed, 185 FAILED +RTE.json completed, all passed! +RTR.json completed, all passed! +RTS.json completed, all passed! +SBCD.json completed: 6809 passed, 1256 FAILED +SUB.b.json completed, all passed! +SUB.l.json completed: 7747 passed, 318 FAILED +SUB.w.json completed: 7716 passed, 349 FAILED +SUBA.l.json completed, all passed! +SUBA.w.json completed, all passed! +SUBX.b.json completed, all passed! +SUBX.l.json completed: 5481 passed, 2584 FAILED +SUBX.w.json completed, all passed! +SWAP.json completed, all passed! +Scc.json completed, all passed! +TAS.json completed, all passed! +TRAP.json completed, all passed! +TRAPV.json completed, all passed! +TST.b.json completed, all passed! +TST.l.json completed, all passed! +TST.w.json completed, all passed! +UNLINK.json completed, all passed! + +passed: 957924, failed: 42136, total 96% +completed in 24m 47s diff --git a/tests/harte_tests/latest-excluding-addr-error.txt b/tests/harte_tests/progress/2022-09-18-at-98-percent-mostly-there-excluding-addr-error.txt similarity index 100% rename from tests/harte_tests/latest-excluding-addr-error.txt rename to tests/harte_tests/progress/2022-09-18-at-98-percent-mostly-there-excluding-addr-error.txt diff --git a/tests/harte_tests/src/main.rs b/tests/harte_tests/src/main.rs index 0ab2ede..c9792af 100644 --- a/tests/harte_tests/src/main.rs +++ b/tests/harte_tests/src/main.rs @@ -11,7 +11,7 @@ use clap::{Parser, ArgEnum}; use flate2::read::GzDecoder; use serde_derive::Deserialize; -use moa_core::{System, Error, MemoryBlock, BusPort, Address, Addressable, Steppable, wrap_transmutable}; +use moa_core::{System, Error, MemoryBlock, BusPort, Frequency, Address, Addressable, Steppable, wrap_transmutable}; use moa_m68k::{M68k, M68kType}; use moa_m68k::state::Status; @@ -149,7 +149,7 @@ fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, Syst } else { BusPort::new(0, 32, 32, system.bus.clone()) }; - let mut cpu = M68k::new(cputype, 10_000_000, port); + let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port); cpu.state.status = Status::Running; load_state(&mut cpu, &mut system, state)?; @@ -189,12 +189,12 @@ fn load_state(cpu: &mut M68k, system: &mut System, initial: &TestState) -> Resul // Load instructions into memory for (i, ins) in initial.prefetch.iter().enumerate() { - system.get_bus().write_beu16((initial.pc + (i as u32 * 2)) as u64, *ins)?; + system.get_bus().write_beu16(system.clock, (initial.pc + (i as u32 * 2)) as u64, *ins)?; } // Load data bytes into memory for (addr, byte) in initial.ram.iter() { - system.get_bus().write_u8(*addr as u64, *byte)?; + system.get_bus().write_u8(system.clock, *addr as u64, *byte)?; } Ok(()) @@ -227,13 +227,13 @@ fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(), // Load instructions into memory for (i, ins) in expected.prefetch.iter().enumerate() { let addr = expected.pc + (i as u32 * 2); - let actual = system.get_bus().read_beu16(addr as Address & addr_mask)?; + let actual = system.get_bus().read_beu16(system.clock, addr as Address & addr_mask)?; assert_value(actual, *ins, &format!("prefetch at {:x}", addr))?; } // Load data bytes into memory for (addr, byte) in expected.ram.iter() { - let actual = system.get_bus().read_u8(*addr as Address & addr_mask)?; + let actual = system.get_bus().read_u8(system.clock, *addr as Address & addr_mask)?; assert_value(actual, *byte, &format!("ram at {:x}", addr))?; } @@ -242,7 +242,7 @@ fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(), fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> { let clock_elapsed = cpu.step(&system)?; - let cycles = clock_elapsed / (1_000_000_000 / cpu.frequency as u64); + let cycles = clock_elapsed / cpu.frequency.period_duration(); assert_state(&cpu, &system, &case.final_state)?; @@ -265,8 +265,8 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> { if args.debug { case.dump(); println!(""); - initial_cpu.dump_state(); - cpu.dump_state(); + initial_cpu.dump_state(system.clock); + cpu.dump_state(system.clock); } println!("FAILED: {}", err.msg); } diff --git a/todo.txt b/todo.txt index 0c4522b..cbe4762 100644 --- a/todo.txt +++ b/todo.txt @@ -1,112 +1,65 @@ +* address repeater on ym2612 doesn't seem to work the same, when it's on the 68000 device. The Z80 device doesn't have an affect, but maybe it's not being used +* sound doesn't work on a lot of games... is it a problem with the Z80 accessing the YM2612, or the lack of YM timers? or something else? +* make the ym generate audio in sync so the DAC timings can be more accurate +* add stereo output to ym2612 +* you need to scale the output sample to be +/- 1.0 instead of 0-1.0 +* fix ym2612 sound generation (no drums/bass, no LFO, etc) + * what if, to allow a device to have multiple steppable functions, you pass the system in, or otherwise provide some mechanism for each device to create sub devices which are scheduled independently - -* for some unknown reason, the js-based updater works much better than the rust based one, but the rust based one just goes back to - a fixed time per loop instead of trying to speed up - -* need to remove HostData and replace the interrupt with Signal -* make Signal directional, by making SignalDriver and SignalInput or SignalReceiver -* should you combine the input updaters into one thing and have a queue for communicating? Even if you have 3 input channels, you can - make them all use the same generic type for the input queue -* you need to refactor the audio mixer stuff to reject data quicker and stay in sync, but how to deal with sim time-dilation -* make the pixels frontend use an rc refcell object, or rc object to directly control the frontend object while also making it accessible - to the run loop -* add support for the controller inputs in the pixels web frontend -* clean up pixels frontend - -* make the ym generate audio in sync so the DAC timings can be more accurate -* change the host things to use queues instead - -* add rust runtime checks for math to look for overflow errors -* I think the overflowing add and subs return the original number and not the overflowed result. I might have already checked that - in the m68k impl but I should check again - -* you need to scale the output sample to be +/- 1.0 instead of 0-1.0 - -* AudioFrame (and possibly the mixer and source) should be moved to the core, it should probably have the sample rate -* need to be able to support stereo output eventually - -* can you make the frontend more adaptive to the input that the devices are using -* change the name of the functions that take Host to be `with_host` or `register` or something -* need to re-add a mechanism for audio frame dialation, either based on speed, or somehow automatic, use clocks and make them aligned -* maybe I should make ClockDuration use picos as the base instead, and use u64 since that gives like 212 days or something instead of 5h - and should prevent split nanoseconds which is the main concern -* the audio needs to not run if nothing is using it or there's constant buffer underruns - -* fix ym2612 sound generation -* sound doesn't work on a lot of games... is it a problem with the Z80 accessing the YM2612, or the lack of YM timers? or something else? - -* add opentelemetry if it can be wasm compatible, or some kind of timing for giving an average framerate - -* add doc strings everywhere -* get rustfmt, rustdoc, and clippy working in some kind of semi-automatic fashion - -* the interrupt controller stuff is really not good. It should be more like busport, and connected to a device at startup (eg. create - interrupt controller, then create objects that use that controller and pass in values, maybe an option so that the controller doesn't - have to be hooked up, meaning hardware interrupts would not be used. - -* along with the interrupt stuff, I'm kind of thinking of packaging things a bit differently, like using a tuple struct for the rc refcell - transmutable abstraction, so that you can avoid the need for explicit borrows - -* improve performance * should it be possible to reschedule multiple events at different intervals to reduce the times a given step function is called? Some have multiple clocks, or multiple things at different clocks, and making them each an event would mean they could be smaller and faster, but at the cost of having more events on the queue when re-scheduling. There needs to be a mechanism to avoid the event queue ballooning due to an error +* can you somehow make devices have two step functions for running things at different times? (I'm thinking ym2612 audio gen vs timers) + +* for some unknown reason, the js-based updater works much better than the rust based one, but the rust based one just goes back to + a fixed time per loop instead of trying to speed up +* can you refactor the update timeout to put it in rust? Would that make it faster? (the tricky part is the closure) + +* make Signal directional, by making SignalDriver and SignalInput or SignalReceiver +* clean up pixels frontend + +* modify cpal code to skip audio until caught up +* AudioFrame (and possibly the mixer and source) should be moved to the core, it should probably have the sample rate +* split AudioOutput into a sender and receiver +* can you eliminate the source-to-mixer queues? + + +* should you rename devices.rs traits.rs? +* the interrupt controller stuff is really not good. It should be more like busport, and connected to a device at startup (eg. create + interrupt controller, then create objects that use that controller and pass in values, maybe an option so that the controller doesn't + have to be hooked up, meaning hardware interrupts would not be used. +* I'm kind of thinking of packaging things a bit differently, like using a tuple struct for the rc refcell + transmutable abstraction, so that you can avoid the need for explicit borrows + +* add rust runtime checks for math to look for overflow errors +* I think the overflowing add and subs return the original number and not the overflowed result. I might have already checked that + in the m68k impl but I should check again +* double check the functioning of the banked areas and register settings for Z80 coprocessor +* test the Z80 more, add tests +* add opentelemetry if it can be wasm compatible, or some kind of timing for giving an average framerate +* improve performance + +* can you make the frontend more adaptive to the input that the devices are using +* maybe I should make ClockDuration use picos as the base instead, and use u64 since that gives like 212 days or something instead of 5h + and should prevent split nanoseconds which is the main concern +* make the keys easier to config... + +* add doc strings everywhere +* get rustfmt, rustdoc, and clippy working in some kind of semi-automatic fashion + * add ability to serialize/deserialize state into something, so it can be restored... (maybe not worth it though) -* can you refactor the update timeout to put it in rust? Would that make it faster? (the tricky part is the closure) -* re-enable sound on webassembly, see if it works (it does not. Very lagged and jittery with what sounds like repeated frames) - -* can you somehow speed up the memory accessing through the sim? The dyn Addressable is causing a fair amount of overhead -* can you somehow make devices have two step functions for running things at different times? (I'm thinking ym2612 audio gen vs timers) -* should you rename devices.rs traits.rs? - - -* the pixel format idea didn't work because of window resizing and the fact that the frame needs to be adjusted in size because the window can't always be resized... -* add mouse support to synth app - -* test the Z80 more, add tests -* double check the functioning of the banked areas and register settings for Z80 coprocessor - -* make the keys easier to config... * can you make the debugger more accessible, so a web interface could access the data and display it, in light of the fact that println isn't available in wasm Web Assembly: * can you make the web interface nicer with like... a picture of a genesis or something - * would a different pixel format help at all? - * can you limit the size of the window that pixels generates? - * can you automatically adjust the speed based on the calculated framerate (if you moved that to Rust) - * enable sound in web assembly - - -* add ability to disable one or the other audio chips in the genesis -* make it possible to disable audio in browser * make it possible to compile without audio support (minifb frontend requires it atm) -* should you have a separate attenuation value for each input in the mixer so that you can make one chip quieter (the sn76489 is pretty loud, and I added a fixed offset to the attenuation for now) - - - - - -Audio: - * address repeater on ym2612 doesn't seem to work the same, when it's on the 68000 device. The Z80 device doesn't have an affect, but maybe it's not being used - - * should you represent audio as frequencies rather than amplitude so that time dilation is more accurate? Would possible require less - accurate simulation of the audio - - * Removing at a sample-level granularity would compress or lengthen the waveforms, so it would be better to mix/drop a whole chunk at - once (either predetermined by the audio system or determined by each device by the amount of samples it writes at once). The chunk - size could either be specified by the device in microseconds or something, or can be inferred by the sample_rate and the size of the - chunk. - - * you could make the sound device be an object that is passed back to the simulation section like SimplePty. You need to either register - a callback with the frontend sound system that is called when it needs data, or you write to a shared buffer which is passed back to the - frontend when it needs it, or it has a copy it can use directly System/Traits: @@ -140,9 +93,6 @@ Genesis/Mega Drive: * there is an issue with Mortal Kombat 2 where it will crash randomly at the start of a fight. The code is actually swapping stacks a bunch of times, and at some point, the stack is corrupted or something and it `rts`s to the wrong address... - * implement sn76489 and ym2612 for audio - * there's a bug when Sonic 2 goes to the demo screen, it's all corrupted (could it be a dma copy error) - * the 68000/Z80 bank switching is probably buggy * the H/V counters are not accurate because it seems to count at different speeds in the blanking period (time vs return value numbers don't divide properly) * make the ym7101 set/reset the v_int occurred flag based on the interrupt controller @@ -167,9 +117,13 @@ Macintosh: Z80: + * add instruction timings to Z80 * unimplemented: CPD, CPDR, CPI, CPIR, DAA, IND, INDR, INI, INIR, INic, INx, OTDR, OTIR, OUTD, OUTI, OUTic, OUTx, RETI, RETN, RLD, RRD +Synth: + + * add mouse support to synth app * can you eventually make the system connections all configurable via a config file?