mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-21 19:30:52 +00:00
Fixed tests after ClockTime and Frequency changes
And also removed HostData
This commit is contained in:
parent
6389fa0482
commit
5e228c377e
@ -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};
|
||||
|
||||
|
@ -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<T>(Arc<Mutex<T>>);
|
||||
|
||||
impl<T> HostData<T> {
|
||||
pub fn new(init: T) -> HostData<T> {
|
||||
HostData(Arc::new(Mutex::new(init)))
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> MutexGuard<'_, T> {
|
||||
self.0.lock().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> HostData<T> {
|
||||
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<T>(Arc<Mutex<VecDeque<(ClockTime, T)>>>, usize);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<AudioFrame>,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -86,7 +86,6 @@ impl NoiseGenerator {
|
||||
|
||||
|
||||
pub struct Sn76489 {
|
||||
clock_frequency: Frequency,
|
||||
first_byte: Option<u8>,
|
||||
source: Box<dyn Audio>,
|
||||
tones: Vec<ToneGenerator>,
|
||||
@ -94,12 +93,11 @@ pub struct Sn76489 {
|
||||
}
|
||||
|
||||
impl Sn76489 {
|
||||
pub fn new<H: Host>(host: &mut H, clock_frequency: Frequency) -> Result<Self, Error> {
|
||||
pub fn new<H: Host>(host: &mut H, _clock_frequency: Frequency) -> Result<Self, Error> {
|
||||
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],
|
||||
|
@ -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<NonZeroU8>,
|
||||
selected_reg_1: Option<NonZeroU8>,
|
||||
|
||||
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,
|
||||
|
@ -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<bool>,
|
||||
interrupt: Signal<bool>,
|
||||
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<bool> {
|
||||
pub fn get_interrupt_signal(&self) -> Signal<bool> {
|
||||
self.interrupt.clone()
|
||||
}
|
||||
|
||||
|
@ -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<bool>,
|
||||
pub external_interrupt: Signal<bool>,
|
||||
pub frame_complete: EdgeSignal,
|
||||
}
|
||||
|
||||
impl Ym7101 {
|
||||
pub fn new<H: Host>(host: &mut H, external_interrupt: HostData<bool>, sn_sound: TransmutableBox) -> Ym7101 {
|
||||
pub fn new<H: Host>(host: &mut H, external_interrupt: Signal<bool>, sn_sound: TransmutableBox) -> Ym7101 {
|
||||
let (sender, receiver) = host::frame_queue(320, 224);
|
||||
host.add_video_source(receiver).unwrap();
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
144
todo.txt
144
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?
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user