mirror of
https://github.com/transistorfet/moa.git
synced 2024-05-29 04:41:29 +00:00
Fixed some decoder bugs in m68k
This commit is contained in:
parent
148b4dcf2c
commit
1b6cbfa831
|
@ -74,7 +74,7 @@ impl M68kDecoder {
|
||||||
OPCG_BIT_OPS => {
|
OPCG_BIT_OPS => {
|
||||||
let optype = (ins & 0x0F00) >> 8;
|
let optype = (ins & 0x0F00) >> 8;
|
||||||
|
|
||||||
if (ins & 0x3F) == 0b111100 {
|
if (ins & 0x13F) == 0x03C {
|
||||||
match (ins & 0x00C0) >> 6 {
|
match (ins & 0x00C0) >> 6 {
|
||||||
0b00 => {
|
0b00 => {
|
||||||
let data = self.read_instruction_word(memory)?;
|
let data = self.read_instruction_word(memory)?;
|
||||||
|
@ -171,11 +171,15 @@ impl M68kDecoder {
|
||||||
let ins_0f00 = ins & 0xF00;
|
let ins_0f00 = ins & 0xF00;
|
||||||
let ins_00f0 = ins & 0x0F0;
|
let ins_00f0 = ins & 0x0F0;
|
||||||
|
|
||||||
if (ins & 0x180) == 0x180 && (ins & 0x038) != 0 {
|
if (ins & 0x180) == 0x180 {
|
||||||
if (ins & 0x040) == 0 {
|
if (ins & 0x040) == 0 {
|
||||||
let size = match get_size(ins) {
|
let size = match get_size(ins) {
|
||||||
Some(Size::Word) => Size::Word,
|
Some(Size::Word) => Size::Word,
|
||||||
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
// TODO 2021-12-14: the docs for the 68000 show the size field, even though it says it only operates on words
|
||||||
|
// and according to some other sources, it seems they are parsed and executed on the 68000, so
|
||||||
|
// I'm removing the check that only allows this on the MC68020
|
||||||
|
//Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
||||||
|
Some(Size::Long) => Size::Long,
|
||||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -698,11 +702,11 @@ impl M68kDecoder {
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => {
|
0b000 => {
|
||||||
let value = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word) as u32;
|
let value = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word) as u32;
|
||||||
Target::IndirectMemory(value)
|
Target::IndirectMemory(value, Size::Word)
|
||||||
},
|
},
|
||||||
0b001 => {
|
0b001 => {
|
||||||
let value = self.read_instruction_long(memory)?;
|
let value = self.read_instruction_long(memory)?;
|
||||||
Target::IndirectMemory(value)
|
Target::IndirectMemory(value, Size::Long)
|
||||||
},
|
},
|
||||||
0b010 => {
|
0b010 => {
|
||||||
let displacement = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word);
|
let displacement = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word);
|
||||||
|
@ -754,7 +758,7 @@ impl M68kDecoder {
|
||||||
(0..((self.end - self.start) / 2)).map(|offset|
|
(0..((self.end - self.start) / 2)).map(|offset|
|
||||||
Ok(format!("{:04x} ", memory.read_beu16((self.start + (offset * 2)) as Address).unwrap()))
|
Ok(format!("{:04x} ", memory.read_beu16((self.start + (offset * 2)) as Address).unwrap()))
|
||||||
).collect();
|
).collect();
|
||||||
println!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction);
|
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,7 +811,6 @@ fn get_condition(ins: u16) -> Condition {
|
||||||
0b1101 => Condition::LessThan,
|
0b1101 => Condition::LessThan,
|
||||||
0b1110 => Condition::GreaterThan,
|
0b1110 => Condition::GreaterThan,
|
||||||
0b1111 => Condition::LessThanOrEqual,
|
0b1111 => Condition::LessThanOrEqual,
|
||||||
|
|
||||||
_ => Condition::True,
|
_ => Condition::True,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use super::state::{M68k, M68kType, Status, Flags, Exceptions, InterruptPriority}
|
||||||
impl Steppable for M68k {
|
impl Steppable for M68k {
|
||||||
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
|
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
|
||||||
self.step_internal(system)?;
|
self.step_internal(system)?;
|
||||||
Ok((1_000_000_000 / self.frequency as u64) * 4)
|
Ok((1_000_000_000 / self.frequency as u64) * 4 as ClockElapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_error(&mut self, system: &System) {
|
fn on_error(&mut self, system: &System) {
|
||||||
|
@ -756,11 +756,11 @@ impl M68k {
|
||||||
let addr = self.get_a_reg_mut(reg);
|
let addr = self.get_a_reg_mut(reg);
|
||||||
*addr = new_value;
|
*addr = new_value;
|
||||||
},
|
},
|
||||||
Instruction::UnimplementedA(ins) => {
|
Instruction::UnimplementedA(_) => {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
self.exception(Exceptions::LineAEmulator as u8, false)?;
|
self.exception(Exceptions::LineAEmulator as u8, false)?;
|
||||||
},
|
},
|
||||||
Instruction::UnimplementedF(ins) => {
|
Instruction::UnimplementedF(_) => {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
self.exception(Exceptions::LineFEmulator as u8, false)?;
|
self.exception(Exceptions::LineFEmulator as u8, false)?;
|
||||||
},
|
},
|
||||||
|
@ -771,8 +771,8 @@ impl M68k {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mut mask: u16) -> Result<(), Error> {
|
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), Error> {
|
||||||
let mut addr = self.get_target_address(target)?;
|
let addr = self.get_target_address(target)?;
|
||||||
|
|
||||||
// If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored
|
// If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored
|
||||||
if self.cputype >= M68kType::MC68020 {
|
if self.cputype >= M68kType::MC68020 {
|
||||||
|
@ -786,13 +786,13 @@ impl M68k {
|
||||||
}
|
}
|
||||||
|
|
||||||
let post_addr = match target {
|
let post_addr = match target {
|
||||||
Target::IndirectARegInc(reg) => {
|
Target::IndirectARegInc(_) => {
|
||||||
if dir != Direction::FromTarget {
|
if dir != Direction::FromTarget {
|
||||||
return Err(Error::new(&format!("Cannot use {:?} with {:?}", target, dir)));
|
return Err(Error::new(&format!("Cannot use {:?} with {:?}", target, dir)));
|
||||||
}
|
}
|
||||||
self.move_memory_to_registers(addr, size, mask)?
|
self.move_memory_to_registers(addr, size, mask)?
|
||||||
},
|
},
|
||||||
Target::IndirectARegDec(reg) => {
|
Target::IndirectARegDec(_) => {
|
||||||
if dir != Direction::ToTarget {
|
if dir != Direction::ToTarget {
|
||||||
return Err(Error::new(&format!("Cannot use {:?} with {:?}", target, dir)));
|
return Err(Error::new(&format!("Cannot use {:?} with {:?}", target, dir)));
|
||||||
}
|
}
|
||||||
|
@ -937,7 +937,7 @@ impl M68k {
|
||||||
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
||||||
self.get_address_sized(intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32) as Address, size)
|
self.get_address_sized(intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32) as Address, size)
|
||||||
},
|
},
|
||||||
Target::IndirectMemory(addr) => {
|
Target::IndirectMemory(addr, _) => {
|
||||||
self.get_address_sized(addr as Address, size)
|
self.get_address_sized(addr as Address, size)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -984,7 +984,7 @@ impl M68k {
|
||||||
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
||||||
self.set_address_sized(intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32) as Address, value, size)?;
|
self.set_address_sized(intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32) as Address, value, size)?;
|
||||||
},
|
},
|
||||||
Target::IndirectMemory(addr) => {
|
Target::IndirectMemory(addr, _) => {
|
||||||
self.set_address_sized(addr as Address, value, size)?;
|
self.set_address_sized(addr as Address, value, size)?;
|
||||||
},
|
},
|
||||||
_ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
_ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
|
||||||
|
@ -1012,7 +1012,7 @@ impl M68k {
|
||||||
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
let intermediate = self.get_address_sized(base_value.wrapping_add(base_disp as u32) as Address, Size::Long)?;
|
||||||
intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32)
|
intermediate.wrapping_add(index_value as u32).wrapping_add(outer_disp as u32)
|
||||||
},
|
},
|
||||||
Target::IndirectMemory(addr) => {
|
Target::IndirectMemory(addr, _) => {
|
||||||
addr
|
addr
|
||||||
},
|
},
|
||||||
_ => return Err(Error::new(&format!("Invalid addressing target: {:?}", target))),
|
_ => return Err(Error::new(&format!("Invalid addressing target: {:?}", target))),
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub enum Target {
|
||||||
IndirectRegOffset(BaseRegister, Option<IndexRegister>, i32),
|
IndirectRegOffset(BaseRegister, Option<IndexRegister>, i32),
|
||||||
IndirectMemoryPreindexed(BaseRegister, Option<IndexRegister>, i32, i32),
|
IndirectMemoryPreindexed(BaseRegister, Option<IndexRegister>, i32, i32),
|
||||||
IndirectMemoryPostindexed(BaseRegister, Option<IndexRegister>, i32, i32),
|
IndirectMemoryPostindexed(BaseRegister, Option<IndexRegister>, i32, i32),
|
||||||
IndirectMemory(u32),
|
IndirectMemory(u32, Size),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -285,6 +285,15 @@ impl fmt::Display for ControlRegister {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RegOrImmediate {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
RegOrImmediate::DReg(reg) => write!(f, "%d{}", reg),
|
||||||
|
RegOrImmediate::Immediate(value) => write!(f, "#{:#02x}", value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for XRegister {
|
impl fmt::Display for XRegister {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -339,13 +348,50 @@ impl fmt::Display for Target {
|
||||||
let index_str = fmt_index_disp(index_reg);
|
let index_str = fmt_index_disp(index_reg);
|
||||||
write!(f, "([{}#{:08x}]{} + #{:08x})", base_reg, base_disp, index_str, outer_disp)
|
write!(f, "([{}#{:08x}]{} + #{:08x})", base_reg, base_disp, index_str, outer_disp)
|
||||||
},
|
},
|
||||||
Target::IndirectMemory(value) => write!(f, "(#{:08x})", value),
|
Target::IndirectMemory(value, size) => if *size == Size::Word {
|
||||||
|
write!(f, "(#{:04x})", value)
|
||||||
|
} else {
|
||||||
|
write!(f, "(#{:08x})", value)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_movem_mask(mask: u16) -> String {
|
fn fmt_movem_mask(mut mask: u16, target: &Target) -> String {
|
||||||
format!("something")
|
let mut output = vec![];
|
||||||
|
|
||||||
|
match target {
|
||||||
|
Target::IndirectARegDec(_) => {
|
||||||
|
for i in (0..8).rev() {
|
||||||
|
if (mask & 0x01) != 0 {
|
||||||
|
output.push(format!("%a{}", i));
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
for i in (0..8).rev() {
|
||||||
|
if (mask & 0x01) != 0 {
|
||||||
|
output.push(format!("%d{}", i));
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
for i in 0..8 {
|
||||||
|
if (mask & 0x01) != 0 {
|
||||||
|
output.push(format!("%d{}", i));
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
for i in 0..8 {
|
||||||
|
if (mask & 0x01) != 0 {
|
||||||
|
output.push(format!("%a{}", i));
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
output.join("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Instruction {
|
impl fmt::Display for Instruction {
|
||||||
|
@ -353,6 +399,8 @@ impl fmt::Display for Instruction {
|
||||||
match self {
|
match self {
|
||||||
Instruction::ABCD(src, dest) => write!(f, "abcd\t{}, {}", src, dest),
|
Instruction::ABCD(src, dest) => write!(f, "abcd\t{}, {}", src, dest),
|
||||||
Instruction::ADD(src, dest, size) => write!(f, "add{}\t{}, {}", size, src, dest),
|
Instruction::ADD(src, dest, size) => write!(f, "add{}\t{}, {}", size, src, dest),
|
||||||
|
Instruction::ADDA(target, reg, size) => write!(f, "adda{}\t{}, %a{}", size, target, reg),
|
||||||
|
Instruction::ADDX(src, dest, size) => write!(f, "addx{}\t{}, {}", size, src, dest),
|
||||||
Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest),
|
Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest),
|
||||||
Instruction::ANDtoCCR(value) => write!(f, "andb\t{:02x}, %ccr", value),
|
Instruction::ANDtoCCR(value) => write!(f, "andb\t{:02x}, %ccr", value),
|
||||||
Instruction::ANDtoSR(value) => write!(f, "andw\t{:04x}, %sr", value),
|
Instruction::ANDtoSR(value) => write!(f, "andw\t{:04x}, %sr", value),
|
||||||
|
@ -365,7 +413,15 @@ impl fmt::Display for Instruction {
|
||||||
Instruction::BCLR(src, dest, size) => write!(f, "bclr{}\t{}, {}", size, src, dest),
|
Instruction::BCLR(src, dest, size) => write!(f, "bclr{}\t{}, {}", size, src, dest),
|
||||||
Instruction::BSET(src, dest, size) => write!(f, "bset{}\t{}, {}", size, src, dest),
|
Instruction::BSET(src, dest, size) => write!(f, "bset{}\t{}, {}", size, src, dest),
|
||||||
Instruction::BTST(src, dest, size) => write!(f, "btst{}\t{}, {}", size, src, dest),
|
Instruction::BTST(src, dest, size) => write!(f, "btst{}\t{}, {}", size, src, dest),
|
||||||
//Instruction::BKPT(value),
|
Instruction::BFCHG(target, offset, width) => write!(f, "bfchg\t{}, {}, {}", target, offset, width),
|
||||||
|
Instruction::BFCLR(target, offset, width) => write!(f, "bfclr\t{}, {}, {}", target, offset, width),
|
||||||
|
Instruction::BFEXTS(target, offset, width, reg) => write!(f, "bfexts\t{}, {}, {}, %d{}", target, offset, width, reg),
|
||||||
|
Instruction::BFEXTU(target, offset, width, reg) => write!(f, "bfextu\t{}, {}, {}, %d{}", target, offset, width, reg),
|
||||||
|
Instruction::BFFFO(target, offset, width, reg) => write!(f, "bfffo\t{}, {}, {}, %d{}", target, offset, width, reg),
|
||||||
|
Instruction::BFINS(reg, target, offset, width) => write!(f, "bfins\t%d{}, {}, {}, {}", reg, target, offset, width),
|
||||||
|
Instruction::BFSET(target, offset, width) => write!(f, "bfset\t{}, {}, {}", target, offset, width),
|
||||||
|
Instruction::BFTST(target, offset, width) => write!(f, "bftst\t{}, {}, {}", target, offset, width),
|
||||||
|
Instruction::BKPT(value) => write!(f, "bkpt\t{}", value),
|
||||||
|
|
||||||
Instruction::CHK(target, reg, size) => write!(f, "chk{}\t{}, %d{}", size, target, reg),
|
Instruction::CHK(target, reg, size) => write!(f, "chk{}\t{}, %d{}", size, target, reg),
|
||||||
Instruction::CLR(target, size) => write!(f, "clr{}\t{}", size, target),
|
Instruction::CLR(target, size) => write!(f, "clr{}\t{}", size, target),
|
||||||
|
@ -405,8 +461,8 @@ impl fmt::Display for Instruction {
|
||||||
Direction::FromTarget => write!(f, "movec\t{}, {}", target, reg),
|
Direction::FromTarget => write!(f, "movec\t{}, {}", target, reg),
|
||||||
},
|
},
|
||||||
Instruction::MOVEM(target, size, dir, mask) => match dir {
|
Instruction::MOVEM(target, size, dir, mask) => match dir {
|
||||||
Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask), target),
|
Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask, target), target),
|
||||||
Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask)),
|
Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask, target)),
|
||||||
},
|
},
|
||||||
Instruction::MOVEP(dreg, areg, offset, size, dir) => match dir {
|
Instruction::MOVEP(dreg, areg, offset, size, dir) => match dir {
|
||||||
Direction::ToTarget => write!(f, "movep{}\t%d{}, ({}, %a{})", size, dreg, areg, offset),
|
Direction::ToTarget => write!(f, "movep{}\t%d{}, ({}, %a{})", size, dreg, areg, offset),
|
||||||
|
@ -448,6 +504,8 @@ impl fmt::Display for Instruction {
|
||||||
Instruction::Scc(cond, target) => write!(f, "s{}\t{}", cond, target),
|
Instruction::Scc(cond, target) => write!(f, "s{}\t{}", cond, target),
|
||||||
Instruction::STOP(value) => write!(f, "stop\t#{:04x}", value),
|
Instruction::STOP(value) => write!(f, "stop\t#{:04x}", value),
|
||||||
Instruction::SUB(src, dest, size) => write!(f, "sub{}\t{}, {}", size, src, dest),
|
Instruction::SUB(src, dest, size) => write!(f, "sub{}\t{}, {}", size, src, dest),
|
||||||
|
Instruction::SUBA(target, reg, size) => write!(f, "suba{}\t{}, %a{}", size, target, reg),
|
||||||
|
Instruction::SUBX(src, dest, size) => write!(f, "subx{}\t{}, {}", size, src, dest),
|
||||||
Instruction::SWAP(reg) => write!(f, "swap\t%d{}", reg),
|
Instruction::SWAP(reg) => write!(f, "swap\t%d{}", reg),
|
||||||
|
|
||||||
Instruction::TAS(target) => write!(f, "tas\t{}", target),
|
Instruction::TAS(target) => write!(f, "tas\t{}", target),
|
||||||
|
@ -456,7 +514,8 @@ impl fmt::Display for Instruction {
|
||||||
Instruction::TRAPV => write!(f, "trapv"),
|
Instruction::TRAPV => write!(f, "trapv"),
|
||||||
|
|
||||||
Instruction::UNLK(reg) => write!(f, "unlk\t%a{}", reg),
|
Instruction::UNLK(reg) => write!(f, "unlk\t%a{}", reg),
|
||||||
_ => write!(f, "UNIMPL"),
|
Instruction::UnimplementedA(ins) => write!(f, "coproc_a\t{:#06x}", ins),
|
||||||
|
Instruction::UnimplementedF(ins) => write!(f, "coproc_f\t{:#06x}", ins),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::devices::{Address, Addressable, Debuggable};
|
use crate::devices::{Address, Debuggable};
|
||||||
|
|
||||||
use super::state::Z80;
|
use super::state::Z80;
|
||||||
use super::decode::Z80Decoder;
|
use super::decode::Z80Decoder;
|
||||||
|
|
|
@ -217,6 +217,10 @@ impl BusPort {
|
||||||
pub fn dump_memory(&mut self, addr: Address, count: Address) {
|
pub fn dump_memory(&mut self, addr: Address, count: Address) {
|
||||||
self.subdevice.borrow_mut().dump_memory(self.offset + (addr & self.address_mask), count)
|
self.subdevice.borrow_mut().dump_memory(self.offset + (addr & self.address_mask), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn data_width(&self) -> u8 {
|
||||||
|
self.data_width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Addressable for BusPort {
|
impl Addressable for BusPort {
|
||||||
|
|
34
todo.txt
34
todo.txt
|
@ -1,20 +1,7 @@
|
||||||
|
|
||||||
* for the mixer, it might be easier to have a buffer for each source, but then you'd need to have a list of all sources, even though
|
* when a MOVE's targets are both ARegDec, the 2 extra clocks can be combined (-2 clocks in this one case)
|
||||||
each source has a copy of the mixer as well... Likely there'd be a sub object in Source which is the buffer and anything else needed
|
|
||||||
by the mixer
|
|
||||||
|
|
||||||
* I'm leaning towards having an object that data is written to by the device. The device can decide how often to update. The issue is
|
|
||||||
knowing what data to exclude or insert when mixing the incoming buffers
|
|
||||||
* 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.
|
|
||||||
|
|
||||||
* how do you know how big an audio frame should be? How do other emulators do audio without stretching or compressing the waveforms, and
|
|
||||||
can/should I do mixing as well, given that I have 2 sources, and at least for those two, they should be connected to the same output
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* should you rename devices.rs traits.rs?
|
* should you rename devices.rs traits.rs?
|
||||||
* add command line arguments to speed up or slow down either the frame rate limiter or the simulated time per frame
|
* add command line arguments to speed up or slow down either the frame rate limiter or the simulated time per frame
|
||||||
|
@ -32,6 +19,25 @@
|
||||||
* you could modify read()/write() in Addressable to return the number of bytes read or written for dynamic bus sizing used by the MC68020+
|
* you could modify read()/write() in Addressable to return the number of bytes read or written for dynamic bus sizing used by the MC68020+
|
||||||
|
|
||||||
|
|
||||||
|
Audio:
|
||||||
|
* for the mixer, it might be easier to have a buffer for each source, but then you'd need to have a list of all sources, even though
|
||||||
|
each source has a copy of the mixer as well... Likely there'd be a sub object in Source which is the buffer and anything else needed
|
||||||
|
by the mixer
|
||||||
|
|
||||||
|
* I'm leaning towards having an object that data is written to by the device. The device can decide how often to update. The issue is
|
||||||
|
knowing what data to exclude or insert when mixing the incoming buffers
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
* how do you know how big an audio frame should be? How do other emulators do audio without stretching or compressing the waveforms, and
|
||||||
|
can/should I do mixing as well, given that I have 2 sources, and at least for those two, they should be connected to the same output
|
||||||
|
* 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
|
||||||
|
|
||||||
|
|
||||||
Debugger:
|
Debugger:
|
||||||
|
|
||||||
* how can you improve the debugger?
|
* how can you improve the debugger?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user