Refactored shift intsructions to not use direction

This commit is contained in:
transistor 2023-05-20 15:01:10 -07:00
parent 64b18662d5
commit d87319b605
10 changed files with 986 additions and 223 deletions

View File

@ -428,3 +428,16 @@ General Work
doesn't make a heck of a lot of sense to be changing the volume level but nothing else all the
time. It doesn't seem to set the initial frequencies. So it's possible that a bug in the Z80
code is making it run incorrectly and thus not producing correct register commands to the ym2612
2023-05-16
- I spent a bunch of time getting the Z80 tests running and fixing bugs in the implementation. It's
generally gone well. I started with 45% of the tests passing with all checks, 60% with the
undocumented flags ignored, 83% with undocumented instructions also ignored, and timing wasn't
even checked. It's now 98% passing with undocumented instructions and timing checks, but is still
only 65% passing on all tests
- Now that I added timings to the Z80, and fixed instructions, Sonic 1 has the drums in the intro,
but there's still no bass, and it still sounds incorrect in spots. But most other games still
have no sound which is baffling
- it must be a problem with either the bus architecture in the genesis, or a probably with the
CPU/coproc interface, banking, etc

View File

@ -6,7 +6,6 @@ use super::instructions::{
Size,
Sign,
Direction,
ShiftDirection,
XRegister,
BaseRegister,
IndexRegister,
@ -583,10 +582,9 @@ impl M68kDecoder {
}
fn decode_group_shift(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result<Instruction, Error> {
let dir = if (ins & 0x0100) == 0 { ShiftDirection::Right } else { ShiftDirection::Left };
match get_size(ins) {
Some(size) => {
let reg = get_low_reg(ins);
let target = Target::DirectDReg(get_low_reg(ins));
let rotation = get_high_reg(ins);
let count = if (ins & 0x0020) == 0 {
Target::Immediate(if rotation != 0 { rotation as u32 } else { 8 })
@ -594,24 +592,46 @@ impl M68kDecoder {
Target::DirectDReg(rotation)
};
match (ins & 0x0018) >> 3 {
0b00 => Ok(Instruction::ASd(count, Target::DirectDReg(reg), size, dir)),
0b01 => Ok(Instruction::LSd(count, Target::DirectDReg(reg), size, dir)),
0b10 => Ok(Instruction::ROXd(count, Target::DirectDReg(reg), size, dir)),
0b11 => Ok(Instruction::ROd(count, Target::DirectDReg(reg), size, dir)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
if (ins & 0x0100) == 0 {
match (ins & 0x0018) >> 3 {
0b00 => Ok(Instruction::ASR(count, target, size)),
0b01 => Ok(Instruction::LSR(count, target, size)),
0b10 => Ok(Instruction::ROXR(count, target, size)),
0b11 => Ok(Instruction::ROR(count, target, size)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
match (ins & 0x0018) >> 3 {
0b00 => Ok(Instruction::ASL(count, target, size)),
0b01 => Ok(Instruction::LSL(count, target, size)),
0b10 => Ok(Instruction::ROXL(count, target, size)),
0b11 => Ok(Instruction::ROL(count, target, size)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
},
None => {
if (ins & 0x800) == 0 {
let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
let count = Target::Immediate(1);
match (ins & 0x0600) >> 9 {
0b00 => Ok(Instruction::ASd(count, target, Size::Word, dir)),
0b01 => Ok(Instruction::LSd(count, target, Size::Word, dir)),
0b10 => Ok(Instruction::ROXd(count, target, Size::Word, dir)),
0b11 => Ok(Instruction::ROd(count, target, Size::Word, dir)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
let size = Size::Word;
if (ins & 0x0100) == 0 {
match (ins & 0x0600) >> 9 {
0b00 => Ok(Instruction::ASR(count, target, size)),
0b01 => Ok(Instruction::LSR(count, target, size)),
0b10 => Ok(Instruction::ROXR(count, target, size)),
0b11 => Ok(Instruction::ROR(count, target, size)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
match (ins & 0x0600) >> 9 {
0b00 => Ok(Instruction::ASL(count, target, size)),
0b01 => Ok(Instruction::LSL(count, target, size)),
0b10 => Ok(Instruction::ROXL(count, target, size)),
0b11 => Ok(Instruction::ROL(count, target, size)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
} else if self.cputype > M68kType::MC68020 {
// Bitfield instructions (MC68020+)

View File

@ -8,7 +8,6 @@ use crate::instructions::{
Size,
Sign,
Direction,
ShiftDirection,
XRegister,
BaseRegister,
IndexRegister,
@ -222,7 +221,8 @@ impl M68k {
Instruction::AND(src, dest, size) => self.execute_and(src, dest, size),
Instruction::ANDtoCCR(value) => self.execute_and_to_ccr(value),
Instruction::ANDtoSR(value) => self.execute_and_to_sr(value),
Instruction::ASd(count, target, size, shift_dir) => self.execute_asd(count, target, size, shift_dir),
Instruction::ASL(count, target, size) => self.execute_asl(count, target, size),
Instruction::ASR(count, target, size) => self.execute_asr(count, target, size),
Instruction::Bcc(cond, offset) => self.execute_bcc(cond, offset),
Instruction::BRA(offset) => self.execute_bra(offset),
Instruction::BSR(offset) => self.execute_bsr(offset),
@ -256,7 +256,8 @@ impl M68k {
Instruction::JSR(target) => self.execute_jsr(target),
Instruction::LEA(target, reg) => self.execute_lea(target, reg),
Instruction::LINK(reg, offset) => self.execute_link(reg, offset),
Instruction::LSd(count, target, size, shift_dir) => self.execute_lsd(count, target, size, shift_dir),
Instruction::LSL(count, target, size) => self.execute_lsl(count, target, size),
Instruction::LSR(count, target, size) => self.execute_lsr(count, target, size),
Instruction::MOVE(src, dest, size) => self.execute_move(src, dest, size),
Instruction::MOVEA(src, reg, size) => self.execute_movea(src, reg, size),
Instruction::MOVEfromSR(target) => self.execute_move_from_sr(target),
@ -279,8 +280,10 @@ impl M68k {
Instruction::ORtoSR(value) => self.execute_or_to_sr(value),
Instruction::PEA(target) => self.execute_pea(target),
Instruction::RESET => self.execute_reset(),
Instruction::ROd(count, target, size, shift_dir) => self.execute_rod(count, target, size, shift_dir),
Instruction::ROXd(count, target, size, shift_dir) => self.execute_roxd(count, target, size, shift_dir),
Instruction::ROL(count, target, size) => self.execute_rol(count, target, size),
Instruction::ROR(count, target, size) => self.execute_rol(count, target, size),
Instruction::ROXL(count, target, size) => self.execute_roxl(count, target, size),
Instruction::ROXR(count, target, size) => self.execute_roxr(count, target, size),
Instruction::RTE => self.execute_rte(),
Instruction::RTR => self.execute_rtr(),
Instruction::RTS => self.execute_rts(),
@ -389,7 +392,7 @@ impl M68k {
Ok(())
}
fn execute_asd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> {
fn execute_asl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let value = self.get_target_value(target, size, Used::Twice)?;
@ -397,7 +400,7 @@ impl M68k {
let mut pair = (value, false);
let mut previous_msb = get_msb(pair.0, size);
for _ in 0..count {
pair = shift_operation(pair.0, size, shift_dir, true);
pair = shift_left(pair.0, size, true);
if get_msb(pair.0, size) != previous_msb {
overflow = true;
}
@ -405,21 +408,40 @@ impl M68k {
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
let carry = match shift_dir {
ShiftDirection::Left => pair.1,
ShiftDirection::Right => if count < size.in_bits() { pair.1 } else { false }
};
self.set_arithmetic_shift_flags(pair.0, count, pair.1, overflow, size);
Ok(())
}
// Adjust flags
self.set_logic_flags(pair.0, size);
fn execute_asr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let value = self.get_target_value(target, size, Used::Twice)?;
let mut overflow = false;
let mut pair = (value, false);
let mut previous_msb = get_msb(pair.0, size);
for _ in 0..count {
pair = shift_right(pair.0, size, true);
if get_msb(pair.0, size) != previous_msb {
overflow = true;
}
previous_msb = get_msb(pair.0, size);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
let last_bit = if count < size.in_bits() { pair.1 } else { false };
self.set_arithmetic_shift_flags(pair.0, count, last_bit, overflow, size);
Ok(())
}
fn set_arithmetic_shift_flags(&mut self, result: u32, count: u32, last_bit_out: bool, overflow: bool, size: Size) {
self.set_logic_flags(result, size);
self.set_flag(Flags::Overflow, overflow);
if count != 0 {
self.set_flag(Flags::Extend, carry);
self.set_flag(Flags::Carry, carry);
self.set_flag(Flags::Extend, last_bit_out);
self.set_flag(Flags::Carry, last_bit_out);
} else {
self.set_flag(Flags::Carry, false);
}
Ok(())
}
fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), Error> {
@ -772,24 +794,39 @@ impl M68k {
Ok(())
}
fn execute_lsd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> {
fn execute_lsl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = shift_operation(pair.0, size, shift_dir, false);
pair = shift_left(pair.0, size, false);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
// Adjust flags
self.set_logic_flags(pair.0, size);
self.set_shift_flags(pair.0, count, pair.1, size);
Ok(())
}
fn execute_lsr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = shift_right(pair.0, size, false);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
self.set_shift_flags(pair.0, count, pair.1, size);
Ok(())
}
fn set_shift_flags(&mut self, result: u32, count: u32, last_bit_out: bool, size: Size) {
self.set_logic_flags(result, size);
self.set_flag(Flags::Overflow, false);
if count != 0 {
self.set_flag(Flags::Extend, pair.1);
self.set_flag(Flags::Carry, pair.1);
self.set_flag(Flags::Extend, last_bit_out);
self.set_flag(Flags::Carry, last_bit_out);
} else {
self.set_flag(Flags::Carry, false);
}
Ok(())
}
fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
@ -1094,37 +1131,57 @@ impl M68k {
Ok(())
}
fn execute_rod(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> {
fn execute_rol(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = rotate_operation(pair.0, size, shift_dir, None);
pair = rotate_left(pair.0, size, None);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
// Adjust flags
self.set_logic_flags(pair.0, size);
if pair.1 {
self.set_flag(Flags::Carry, true);
}
self.set_rotate_flags(pair.0, pair.1, size);
Ok(())
}
fn execute_roxd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> {
fn execute_ror(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = rotate_operation(pair.0, size, shift_dir, Some(self.get_flag(Flags::Extend)));
pair = rotate_right(pair.0, size, None);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
self.set_rotate_flags(pair.0, pair.1, size);
Ok(())
}
fn execute_roxl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = rotate_left(pair.0, size, Some(self.get_flag(Flags::Extend)));
self.set_flag(Flags::Extend, pair.1);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
self.set_rotate_flags(pair.0, pair.1, size);
Ok(())
}
// Adjust flags
self.set_logic_flags(pair.0, size);
if pair.1 {
fn execute_roxr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
for _ in 0..count {
pair = rotate_right(pair.0, size, Some(self.get_flag(Flags::Extend)));
self.set_flag(Flags::Extend, pair.1);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
self.set_rotate_flags(pair.0, pair.1, size);
Ok(())
}
fn set_rotate_flags(&mut self, result: u32, last_bit_out: bool, size: Size) {
self.set_logic_flags(result, size);
if last_bit_out {
self.set_flag(Flags::Carry, true);
}
Ok(())
}
fn execute_rte(&mut self) -> Result<(), Error> {
@ -1747,42 +1804,36 @@ fn overflowing_sub_signed_sized(operand1: u32, operand2: u32, size: Size) -> (u3
}
}
fn shift_operation(value: u32, size: Size, dir: ShiftDirection, arithmetic: bool) -> (u32, bool) {
match dir {
ShiftDirection::Left => {
let bit = get_msb(value, size);
match size {
Size::Byte => (((value as u8) << 1) as u32, bit),
Size::Word => (((value as u16) << 1) as u32, bit),
Size::Long => (value << 1, bit),
}
},
ShiftDirection::Right => {
let mask = if arithmetic { get_msb_mask(value, size) } else { 0 };
((value >> 1) | mask, (value & 0x1) != 0)
},
fn shift_left(value: u32, size: Size, arithmetic: bool) -> (u32, bool) {
let bit = get_msb(value, size);
match size {
Size::Byte => (((value as u8) << 1) as u32, bit),
Size::Word => (((value as u16) << 1) as u32, bit),
Size::Long => (value << 1, bit),
}
}
fn rotate_operation(value: u32, size: Size, dir: ShiftDirection, use_extend: Option<bool>) -> (u32, bool) {
match dir {
ShiftDirection::Left => {
let bit = get_msb(value, size);
let mask = if use_extend.unwrap_or(bit) { 0x01 } else { 0x00 };
match size {
Size::Byte => (mask | ((value as u8) << 1) as u32, bit),
Size::Word => (mask | ((value as u16) << 1) as u32, bit),
Size::Long => (mask | value << 1, bit),
}
},
ShiftDirection::Right => {
let bit = (value & 0x01) != 0;
let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 };
((value >> 1) | mask, bit)
},
fn shift_right(value: u32, size: Size, arithmetic: bool) -> (u32, bool) {
let mask = if arithmetic { get_msb_mask(value, size) } else { 0 };
((value >> 1) | mask, (value & 0x1) != 0)
}
fn rotate_left(value: u32, size: Size, use_extend: Option<bool>) -> (u32, bool) {
let bit = get_msb(value, size);
let mask = if use_extend.unwrap_or(bit) { 0x01 } else { 0x00 };
match size {
Size::Byte => (mask | ((value as u8) << 1) as u32, bit),
Size::Word => (mask | ((value as u16) << 1) as u32, bit),
Size::Long => (mask | value << 1, bit),
}
}
fn rotate_right(value: u32, size: Size, use_extend: Option<bool>) -> (u32, bool) {
let bit = (value & 0x01) != 0;
let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 };
((value >> 1) | mask, bit)
}
fn get_nibbles_from_byte(value: u32) -> (u32, u32) {
(value & 0xF0, value & 0x0F)
}

View File

@ -23,12 +23,6 @@ pub enum Direction {
ToTarget,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ShiftDirection {
Right,
Left,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum XRegister {
DReg(u8),
@ -103,7 +97,8 @@ pub enum Instruction {
AND(Target, Target, Size),
ANDtoCCR(u8),
ANDtoSR(u16),
ASd(Target, Target, Size, ShiftDirection),
ASL(Target, Target, Size),
ASR(Target, Target, Size),
Bcc(Condition, i32),
BRA(i32),
@ -144,7 +139,8 @@ pub enum Instruction {
LEA(Target, Register),
LINK(Register, i32),
LSd(Target, Target, Size, ShiftDirection),
LSL(Target, Target, Size),
LSR(Target, Target, Size),
MOVE(Target, Target, Size),
MOVEA(Target, Register, Size),
@ -174,8 +170,10 @@ pub enum Instruction {
PEA(Target),
RESET,
ROd(Target, Target, Size, ShiftDirection),
ROXd(Target, Target, Size, ShiftDirection),
ROL(Target, Target, Size),
ROR(Target, Target, Size),
ROXL(Target, Target, Size),
ROXR(Target, Target, Size),
RTE,
RTR,
RTS,
@ -235,15 +233,6 @@ impl fmt::Display for Sign {
}
}
impl fmt::Display for ShiftDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ShiftDirection::Right => write!(f, "r"),
ShiftDirection::Left => write!(f, "l"),
}
}
}
impl fmt::Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -405,7 +394,8 @@ impl fmt::Display for Instruction {
Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest),
Instruction::ANDtoCCR(value) => write!(f, "andib\t#{:#02x}, %ccr", value),
Instruction::ANDtoSR(value) => write!(f, "andiw\t#{:#04x}, %sr", value),
Instruction::ASd(src, dest, size, dir) => write!(f, "as{}{}\t{}, {}", dir, size, src, dest),
Instruction::ASL(src, dest, size) => write!(f, "asl{}\t{}, {}", size, src, dest),
Instruction::ASR(src, dest, size) => write!(f, "asr{}\t{}, {}", size, src, dest),
Instruction::Bcc(cond, offset) => write!(f, "b{}\t{}", cond, offset),
Instruction::BRA(offset) => write!(f, "bra\t{}", offset),
@ -451,7 +441,8 @@ impl fmt::Display for Instruction {
Instruction::LEA(target, reg) => write!(f, "lea\t{}, %a{}", target, reg),
Instruction::LINK(reg, offset) => write!(f, "link\t%a{}, {}", reg, offset),
Instruction::LSd(src, dest, size, dir) => write!(f, "ls{}{}\t{}, {}", dir, size, src, dest),
Instruction::LSL(src, dest, size) => write!(f, "lsl{}\t{}, {}", size, src, dest),
Instruction::LSR(src, dest, size) => write!(f, "lsr{}\t{}, {}", size, src, dest),
Instruction::MOVE(src, dest, size) => write!(f, "move{}\t{}, {}", size, src, dest),
Instruction::MOVEA(target, reg, size) => write!(f, "movea{}\t{}, %a{}", size, target, reg),
@ -497,8 +488,10 @@ impl fmt::Display for Instruction {
Instruction::PEA(target) => write!(f, "pea\t{}", target),
Instruction::RESET => write!(f, "reset"),
Instruction::ROd(src, dest, size, dir) => write!(f, "ro{}{}\t{}, {}", dir, size, src, dest),
Instruction::ROXd(src, dest, size, dir) => write!(f, "rox{}{}\t{}, {}", dir, size, src, dest),
Instruction::ROL(src, dest, size) => write!(f, "rol{}\t{}, {}", size, src, dest),
Instruction::ROR(src, dest, size) => write!(f, "ror{}\t{}, {}", size, src, dest),
Instruction::ROXL(src, dest, size) => write!(f, "roxl{}\t{}, {}", size, src, dest),
Instruction::ROXR(src, dest, size) => write!(f, "roxr{}\t{}, {}", size, src, dest),
Instruction::RTE => write!(f, "rte"),
Instruction::RTR => write!(f, "rtr"),
Instruction::RTS => write!(f, "rts"),

View File

@ -204,7 +204,8 @@ impl M68kInstructionTiming {
Instruction::ANDtoCCR(_) => self.add_internal(20),
Instruction::ANDtoSR(_) => self.add_internal(20),
Instruction::ASd(_, target, size, _) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::ASL(_, target, size) |
Instruction::ASR(_, target, size) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::Bcc(_, _) => self.add_internal(8).add_on_branch(2),
Instruction::BRA(_) => self.add_internal(10),
@ -255,7 +256,8 @@ impl M68kInstructionTiming {
Instruction::LEA(target, _) => self.add_indirect_set(target, 4, 8, 12, 8, 12),
Instruction::LINK(_, _) => self.add_internal(16),
Instruction::LSd(_, target, size, _) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::LSL(_, target, size) |
Instruction::LSR(_, target, size) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::MOVE(src, dest, size) => self.add_internal(4).add_two_targets(*size, src, dest),
Instruction::MOVEA(target, _, size) => self.add_internal(4).add_target(*size, target),
@ -287,8 +289,10 @@ impl M68kInstructionTiming {
Instruction::RESET => self.add_internal(132),
Instruction::ROd(_, target, size, _) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::ROXd(_, target, size, _) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::ROL(_, target, size) |
Instruction::ROR(_, target, size) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::ROXL(_, target, size) |
Instruction::ROXR(_, target, size) => self.add_word_v_long(*size, 6, 8).add_per_rep(2).add_target(*size, target),
Instruction::RTE => self.add_internal(20),
Instruction::RTR => self.add_internal(20),

View File

@ -1,7 +1,7 @@
use cpal::{Stream, SampleRate, SampleFormat, StreamConfig, StreamInstant, OutputCallbackInfo, traits::{DeviceTrait, HostTrait, StreamTrait}};
use moa_core::{warn, error};
use moa_core::{debug, error};
use crate::audio::{AudioOutput, SAMPLE_RATE};
@ -41,7 +41,7 @@ impl CpalAudioOutput {
output.put_back(clock, frame);
}
} else {
warn!("missed an audio frame");
debug!("missed an audio frame");
break;
}
}

View File

@ -4,62 +4,77 @@ use moa_core::{System, Error, EdgeSignal, ClockTime, ClockDuration, Frequency, S
use moa_core::host::{self, Host, Pixel, PixelEncoding, Frame, FrameSender};
const REG_MODE_SET_1: usize = 0x00;
const REG_MODE_SET_2: usize = 0x01;
const REG_SCROLL_A_ADDR: usize = 0x02;
const REG_WINDOW_ADDR: usize = 0x03;
const REG_SCROLL_B_ADDR: usize = 0x04;
const REG_SPRITES_ADDR: usize = 0x05;
// Register 0x06 Unused
const REG_BACKGROUND: usize = 0x07;
// Register 0x08 Unused
// Register 0x09 Unused
const REG_H_INTERRUPT: usize = 0x0A;
const REG_MODE_SET_3: usize = 0x0B;
const REG_MODE_SET_4: usize = 0x0C;
const REG_HSCROLL_ADDR: usize = 0x0D;
// Register 0x0E Unused
const REG_AUTO_INCREMENT: usize = 0x0F;
const REG_SCROLL_SIZE: usize = 0x10;
const REG_WINDOW_H_POS: usize = 0x11;
const REG_WINDOW_V_POS: usize = 0x12;
const REG_DMA_COUNTER_LOW: usize = 0x13;
const REG_DMA_COUNTER_HIGH: usize = 0x14;
const REG_DMA_ADDR_LOW: usize = 0x15;
const REG_DMA_ADDR_MID: usize = 0x16;
const REG_DMA_ADDR_HIGH: usize = 0x17;
//const STATUS_PAL_MODE: u16 = 0x0001;
const STATUS_DMA_BUSY: u16 = 0x0002;
const STATUS_IN_HBLANK: u16 = 0x0004;
const STATUS_IN_VBLANK: u16 = 0x0008;
//const STATUS_ODD_FRAME: u16 = 0x0010;
//const STATUS_SPRITE_COLLISION: u16 = 0x0020;
//const STATUS_SPRITE_OVERFLOW: u16 = 0x0040;
//const STATUS_V_INTERRUPT: u16 = 0x0080;
//const STATUS_FIFO_FULL: u16 = 0x0100;
const STATUS_FIFO_EMPTY: u16 = 0x0200;
const MODE1_BF_DISABLE_DISPLAY: u8 = 0x01;
//const MODE1_BF_ENABLE_HV_COUNTER: u8 = 0x02;
const MODE1_BF_HSYNC_INTERRUPT: u8 = 0x10;
const MODE2_BF_V_CELL_MODE: u8 = 0x08;
const MODE2_BF_DMA_ENABLED: u8 = 0x10;
const MODE2_BF_VSYNC_INTERRUPT: u8 = 0x20;
const MODE3_BF_EXTERNAL_INTERRUPT: u8 = 0x08;
const MODE3_BF_V_SCROLL_MODE: u8 = 0x04;
const MODE3_BF_H_SCROLL_MODE: u8 = 0x03;
const MODE4_BF_H_CELL_MODE: u8 = 0x01;
const MODE4_BF_SHADOW_HIGHLIGHT: u8 = 0x08;
const DEV_NAME: &str = "ym7101";
#[rustfmt::skip]
mod reg {
pub(super) const MODE_SET_1: usize = 0x00;
pub(super) const MODE_SET_2: usize = 0x01;
pub(super) const SCROLL_A_ADDR: usize = 0x02;
pub(super) const WINDOW_ADDR: usize = 0x03;
pub(super) const SCROLL_B_ADDR: usize = 0x04;
pub(super) const SPRITES_ADDR: usize = 0x05;
// Register 0x06 Unused
pub(super) const BACKGROUND: usize = 0x07;
// Register 0x08 Unused
// Register 0x09 Unused
pub(super) const H_INTERRUPT: usize = 0x0A;
pub(super) const MODE_SET_3: usize = 0x0B;
pub(super) const MODE_SET_4: usize = 0x0C;
pub(super) const HSCROLL_ADDR: usize = 0x0D;
// Register 0x0E Unused
pub(super) const AUTO_INCREMENT: usize = 0x0F;
pub(super) const SCROLL_SIZE: usize = 0x10;
pub(super) const WINDOW_H_POS: usize = 0x11;
pub(super) const WINDOW_V_POS: usize = 0x12;
pub(super) const DMA_COUNTER_LOW: usize = 0x13;
pub(super) const DMA_COUNTER_HIGH: usize = 0x14;
pub(super) const DMA_ADDR_LOW: usize = 0x15;
pub(super) const DMA_ADDR_MID: usize = 0x16;
pub(super) const DMA_ADDR_HIGH: usize = 0x17;
}
#[rustfmt::skip]
mod status {
//pub(super) const PAL_MODE: u16 = 0x0001;
pub(super) const DMA_BUSY: u16 = 0x0002;
pub(super) const IN_HBLANK: u16 = 0x0004;
pub(super) const IN_VBLANK: u16 = 0x0008;
//pub(super) const ODD_FRAME: u16 = 0x0010;
//pub(super) const SPRITE_COLLISION: u16 = 0x0020;
//pub(super) const SPRITE_OVERFLOW: u16 = 0x0040;
//pub(super) const V_INTERRUPT: u16 = 0x0080;
//pub(super) const FIFO_FULL: u16 = 0x0100;
pub(super) const FIFO_EMPTY: u16 = 0x0200;
}
#[rustfmt::skip]
mod mode1 {
pub(super) const BF_DISABLE_DISPLAY: u8 = 0x01;
//const BF_ENABLE_HV_COUNTER: u8 = 0x02;
pub(super) const BF_HSYNC_INTERRUPT: u8 = 0x10;
}
#[rustfmt::skip]
mod mode2 {
pub(super) const BF_V_CELL_MODE: u8 = 0x08;
pub(super) const BF_DMA_ENABLED: u8 = 0x10;
pub(super) const BF_VSYNC_INTERRUPT: u8 = 0x20;
}
#[rustfmt::skip]
mod mode3 {
pub(super) const BF_EXTERNAL_INTERRUPT: u8 = 0x08;
pub(super) const BF_V_SCROLL_MODE: u8 = 0x04;
pub(super) const BF_H_SCROLL_MODE: u8 = 0x03;
}
#[rustfmt::skip]
mod mode4 {
pub(super) const BF_H_CELL_MODE: u8 = 0x01;
pub(super) const BF_SHADOW_HIGHLIGHT: u8 = 0x08;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DmaType {
@ -134,12 +149,12 @@ impl Ym7101Memory {
fn set_dma_mode(&mut self, mode: DmaType) {
match mode {
DmaType::None => {
//self.status &= !STATUS_DMA_BUSY;
//self.status &= !status::DMA_BUSY;
self.transfer_dma_busy = false;
self.transfer_run = DmaType::None;
},
_ => {
//self.status |= STATUS_DMA_BUSY;
//self.status |= status::DMA_BUSY;
self.transfer_dma_busy = true;
self.transfer_run = mode;
},
@ -328,7 +343,7 @@ struct Ym7101State {
impl Default for Ym7101State {
fn default() -> Self {
Self {
status: 0x3400 | STATUS_FIFO_EMPTY,
status: 0x3400 | status::FIFO_EMPTY,
memory: Ym7101Memory::default(),
mode_1: 0,
@ -365,22 +380,22 @@ impl Default for Ym7101State {
impl Ym7101State {
#[inline(always)]
fn hsync_int_enabled(&self) -> bool {
(self.mode_1 & MODE1_BF_HSYNC_INTERRUPT) != 0
(self.mode_1 & mode1::BF_HSYNC_INTERRUPT) != 0
}
#[inline(always)]
fn vsync_int_enabled(&self) -> bool {
(self.mode_2 & MODE2_BF_VSYNC_INTERRUPT) != 0
(self.mode_2 & mode2::BF_VSYNC_INTERRUPT) != 0
}
#[inline(always)]
fn external_int_enabled(&self) -> bool {
(self.mode_3 & MODE3_BF_EXTERNAL_INTERRUPT) != 0
(self.mode_3 & mode3::BF_EXTERNAL_INTERRUPT) != 0
}
fn update_screen_size(&mut self) {
let h_cells = if (self.mode_4 & MODE4_BF_H_CELL_MODE) == 0 { 32 } else { 40 };
let v_cells = if (self.mode_2 & MODE2_BF_V_CELL_MODE) == 0 { 28 } else { 30 };
let h_cells = if (self.mode_4 & mode4::BF_H_CELL_MODE) == 0 { 32 } else { 40 };
let v_cells = if (self.mode_2 & mode2::BF_V_CELL_MODE) == 0 { 28 } else { 30 };
self.screen_size = (h_cells, v_cells);
}
@ -404,7 +419,7 @@ impl Ym7101State {
}
fn get_palette_colour(&self, palette: u8, colour: u8, mode: ColourMode, encoding: PixelEncoding) -> u32 {
let shift_enabled = (self.mode_4 & MODE4_BF_SHADOW_HIGHLIGHT) != 0;
let shift_enabled = (self.mode_4 & mode4::BF_SHADOW_HIGHLIGHT) != 0;
let rgb = self.memory.read_beu16(Memory::Cram, (((palette * 16) + colour) * 2) as usize);
if !shift_enabled || mode == ColourMode::Normal {
Pixel::Rgb(((rgb & 0x00F) << 4) as u8, (rgb & 0x0F0) as u8, ((rgb & 0xF00) >> 4) as u8).encode(encoding)
@ -415,7 +430,7 @@ impl Ym7101State {
}
fn get_hscroll(&self, hcell: usize, line: usize) -> (usize, usize) {
let scroll_addr = match self.mode_3 & MODE3_BF_H_SCROLL_MODE {
let scroll_addr = match self.mode_3 & mode3::BF_H_SCROLL_MODE {
0 => self.hscroll_addr,
2 => self.hscroll_addr + (hcell << 5),
3 => self.hscroll_addr + (hcell << 5) + (line * 2 * 2),
@ -428,7 +443,7 @@ impl Ym7101State {
}
fn get_vscroll(&self, vcell: usize) -> (usize, usize) {
let scroll_addr = if (self.mode_3 & MODE3_BF_V_SCROLL_MODE) == 0 {
let scroll_addr = if (self.mode_3 & mode3::BF_V_SCROLL_MODE) == 0 {
0
} else {
vcell >> 1
@ -505,19 +520,29 @@ impl Ym7101State {
for x in 0..(self.screen_size.0 * 8) {
let (vscrolling_a, vscrolling_b) = self.get_vscroll(x / 8);
let pixel_b_x = (x - hscrolling_b) % (self.scroll_size.0 * 8);
let pixel_b_y = (y + vscrolling_b) % (self.scroll_size.1 * 8);
let pattern_b_addr = self.get_pattern_addr(self.scroll_b_addr, pixel_b_x / 8, pixel_b_y / 8);
let pattern_b_word = self.memory.read_beu16(Memory::Vram, pattern_b_addr);
let priority_b = (pattern_b_word & 0x8000) != 0;
let pixel_b = self.get_pattern_pixel(pattern_b_word, pixel_b_x % 8, pixel_b_y % 8);
let (priority_b, pixel_b) = if self.scroll_size != (0, 0) {
let pixel_b_x = (x - hscrolling_b) % (self.scroll_size.0 * 8);
let pixel_b_y = (y + vscrolling_b) % (self.scroll_size.1 * 8);
let pattern_b_addr = self.get_pattern_addr(self.scroll_b_addr, pixel_b_x / 8, pixel_b_y / 8);
let pattern_b_word = self.memory.read_beu16(Memory::Vram, pattern_b_addr);
let priority_b = (pattern_b_word & 0x8000) != 0;
let pixel_b = self.get_pattern_pixel(pattern_b_word, pixel_b_x % 8, pixel_b_y % 8);
(priority_b, pixel_b)
} else {
(false, (0, 0))
};
let pixel_a_x = (x - hscrolling_a) % (self.scroll_size.0 * 8);
let pixel_a_y = (y + vscrolling_a) % (self.scroll_size.1 * 8);
let pattern_a_addr = self.get_pattern_addr(self.scroll_a_addr, pixel_a_x / 8, pixel_a_y / 8);
let pattern_a_word = self.memory.read_beu16(Memory::Vram, pattern_a_addr);
let mut priority_a = (pattern_a_word & 0x8000) != 0;
let mut pixel_a = self.get_pattern_pixel(pattern_a_word, pixel_a_x % 8, pixel_a_y % 8);
let (mut priority_a, mut pixel_a) = if self.scroll_size != (0, 0) {
let pixel_a_x = (x - hscrolling_a) % (self.scroll_size.0 * 8);
let pixel_a_y = (y + vscrolling_a) % (self.scroll_size.1 * 8);
let pattern_a_addr = self.get_pattern_addr(self.scroll_a_addr, pixel_a_x / 8, pixel_a_y / 8);
let pattern_a_word = self.memory.read_beu16(Memory::Vram, pattern_a_addr);
let priority_a = (pattern_a_word & 0x8000) != 0;
let pixel_a = self.get_pattern_pixel(pattern_a_word, pixel_a_x % 8, pixel_a_y % 8);
(priority_a, pixel_a)
} else {
(false, (0, 0))
};
if self.window_addr != 0 && self.is_inside_window(x, y) {
let pixel_win_x = x - self.window_pos.0.0 * 8;
@ -548,6 +573,7 @@ impl Ym7101State {
}
}
#[rustfmt::skip]
let pixels = match (priority_sprite, priority_a, priority_b) {
(false, false, true) => [ pixel_b, pixel_sprite, pixel_a, bg_colour ],
(true, false, true) => [ pixel_sprite, pixel_b, pixel_a, bg_colour ],
@ -628,12 +654,12 @@ impl Steppable for Ym7101 {
}
self.state.h_clock += diff;
if (self.state.status & STATUS_IN_HBLANK) != 0 && self.state.h_clock >= 2_340 && self.state.h_clock <= 61_160 {
self.state.status &= !STATUS_IN_HBLANK;
if (self.state.status & status::IN_HBLANK) != 0 && self.state.h_clock >= 2_340 && self.state.h_clock <= 61_160 {
self.state.status &= !status::IN_HBLANK;
self.state.current_x = 0;
}
if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.h_clock >= 61_160 {
self.state.status |= STATUS_IN_HBLANK;
if (self.state.status & status::IN_HBLANK) == 0 && self.state.h_clock >= 61_160 {
self.state.status |= status::IN_HBLANK;
self.state.current_y += 1;
self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1);
@ -647,18 +673,18 @@ impl Steppable for Ym7101 {
}
self.state.v_clock += diff;
if (self.state.status & STATUS_IN_VBLANK) != 0 && self.state.v_clock >= 1_205_992 && self.state.v_clock <= 15_424_008 {
self.state.status &= !STATUS_IN_VBLANK;
if (self.state.status & status::IN_VBLANK) != 0 && self.state.v_clock >= 1_205_992 && self.state.v_clock <= 15_424_008 {
self.state.status &= !status::IN_VBLANK;
self.state.current_y = 0;
}
if (self.state.status & STATUS_IN_VBLANK) == 0 && self.state.v_clock >= 15_424_008 {
self.state.status |= STATUS_IN_VBLANK;
if (self.state.status & status::IN_VBLANK) == 0 && self.state.v_clock >= 15_424_008 {
self.state.status |= status::IN_VBLANK;
if self.state.vsync_int_enabled() {
system.get_interrupt_controller().set(true, 6, 30)?;
}
if (self.state.mode_1 & MODE1_BF_DISABLE_DISPLAY) == 0 {
if (self.state.mode_1 & mode1::BF_DISABLE_DISPLAY) == 0 && self.state.screen_size != (0, 0) {
let mut frame = Frame::new(self.state.screen_size.0 as u32 * 8, self.state.screen_size.1 as u32 * 8, self.sender.encoding());
self.state.draw_frame(&mut frame);
self.sender.add(system.clock, frame);
@ -670,9 +696,9 @@ impl Steppable for Ym7101 {
self.state.v_clock -= 16_630_000;
}
if (self.state.mode_2 & MODE2_BF_DMA_ENABLED) != 0 {
if (self.state.mode_2 & mode2::BF_DMA_ENABLED) != 0 {
self.state.memory.step_dma(system)?;
self.state.status = (self.state.status & !STATUS_DMA_BUSY) | (if self.state.memory.transfer_dma_busy { STATUS_DMA_BUSY } else { 0 });
self.state.status = (self.state.status & !status::DMA_BUSY) | (if self.state.memory.transfer_dma_busy { status::DMA_BUSY } else { 0 });
}
Ok(Frequency::from_hz(13_423_294).period_duration() * 4)
@ -712,52 +738,52 @@ impl Ym7101 {
fn update_register_value(&mut self, reg: usize, data: u8) {
match reg {
REG_MODE_SET_1 => { self.state.mode_1 = data; },
REG_MODE_SET_2 => {
reg::MODE_SET_1 => { self.state.mode_1 = data; },
reg::MODE_SET_2 => {
self.state.mode_2 = data;
self.state.update_screen_size();
},
REG_SCROLL_A_ADDR => { self.state.scroll_a_addr = (data as usize) << 10; },
REG_WINDOW_ADDR => { self.state.window_addr = (data as usize) << 10; },
REG_SCROLL_B_ADDR => { self.state.scroll_b_addr = (data as usize) << 13; },
REG_SPRITES_ADDR => { self.state.sprites_addr = (data as usize) << 9; },
REG_BACKGROUND => { self.state.background = data; },
REG_H_INTERRUPT => { self.state.h_int_lines = data; },
REG_MODE_SET_3 => { self.state.mode_3 = data; },
REG_MODE_SET_4 => {
reg::SCROLL_A_ADDR => { self.state.scroll_a_addr = (data as usize) << 10; },
reg::WINDOW_ADDR => { self.state.window_addr = (data as usize) << 10; },
reg::SCROLL_B_ADDR => { self.state.scroll_b_addr = (data as usize) << 13; },
reg::SPRITES_ADDR => { self.state.sprites_addr = (data as usize) << 9; },
reg::BACKGROUND => { self.state.background = data; },
reg::H_INTERRUPT => { self.state.h_int_lines = data; },
reg::MODE_SET_3 => { self.state.mode_3 = data; },
reg::MODE_SET_4 => {
self.state.mode_4 = data;
self.state.update_screen_size();
},
REG_HSCROLL_ADDR => { self.state.hscroll_addr = (data as usize) << 10; },
REG_AUTO_INCREMENT => { self.state.memory.transfer_auto_inc = data as u32; },
REG_SCROLL_SIZE => {
reg::HSCROLL_ADDR => { self.state.hscroll_addr = (data as usize) << 10; },
reg::AUTO_INCREMENT => { self.state.memory.transfer_auto_inc = data as u32; },
reg::SCROLL_SIZE => {
let h = decode_scroll_size(data & 0x03);
let v = decode_scroll_size((data >> 4) & 0x03);
self.state.scroll_size = (h, v);
},
REG_WINDOW_H_POS => {
reg::WINDOW_H_POS => {
self.state.window_values.0 = data;
self.state.update_window_position();
},
REG_WINDOW_V_POS => {
reg::WINDOW_V_POS => {
self.state.window_values.1 = data;
self.state.update_window_position();
},
REG_DMA_COUNTER_LOW => {
reg::DMA_COUNTER_LOW => {
self.state.memory.transfer_count = (self.state.memory.transfer_count & 0xFF00) | data as u32;
self.state.memory.transfer_remain = self.state.memory.transfer_count;
},
REG_DMA_COUNTER_HIGH => {
reg::DMA_COUNTER_HIGH => {
self.state.memory.transfer_count = (self.state.memory.transfer_count & 0x00FF) | ((data as u32) << 8);
self.state.memory.transfer_remain = self.state.memory.transfer_count;
},
REG_DMA_ADDR_LOW => {
reg::DMA_ADDR_LOW => {
self.state.memory.transfer_src_addr = (self.state.memory.transfer_src_addr & 0xFFFE00) | ((data as u32) << 1);
},
REG_DMA_ADDR_MID => {
reg::DMA_ADDR_MID => {
self.state.memory.transfer_src_addr = (self.state.memory.transfer_src_addr & 0xFE01FF) | ((data as u32) << 9);
},
REG_DMA_ADDR_HIGH => {
reg::DMA_ADDR_HIGH => {
let mask = if (data & 0x80) == 0 { 0x7F } else { 0x3F };
self.state.memory.transfer_bits = data & 0xC0;
self.state.memory.transfer_src_addr = (self.state.memory.transfer_src_addr & 0x01FFFF) | (((data & mask) as u32) << 17);
@ -834,7 +860,7 @@ impl Addressable for Ym7101 {
}
} else {
self.state.memory.write_control_port(data)?;
self.state.status = (self.state.status & !STATUS_DMA_BUSY) | (if self.state.memory.transfer_dma_busy { STATUS_DMA_BUSY } else { 0 });
self.state.status = (self.state.status & !status::DMA_BUSY) | (if self.state.memory.transfer_dma_busy { status::DMA_BUSY } else { 0 });
}
},

View File

@ -2,7 +2,7 @@
const DEFAULT_HARTE_TESTS: &str = "tests/ProcessorTests/680x0/68000/v1/";
use std::io::prelude::*;
use std::fmt::Debug;
use std::fmt::{Debug, UpperHex};
use std::path::PathBuf;
use std::time::SystemTime;
use std::fs::{self, File};
@ -157,11 +157,14 @@ fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, Syst
Ok((cpu, system))
}
fn assert_value<T: PartialEq + Debug>(actual: T, expected: T, message: &str) -> Result<(), Error> {
fn assert_value<T>(actual: T, expected: T, message: &str) -> Result<(), Error>
where
T: PartialEq + Debug + UpperHex
{
if actual == expected {
Ok(())
} else {
Err(Error::assertion(&format!("{:?} != {:?}, {}", actual, expected, message)))
Err(Error::assertion(&format!("{:#X} != {:#X}, {}", actual, expected, message)))
}
}

View File

@ -0,0 +1,647 @@
Last run on 2023-05-15 at commit f205e231b62d62c72186c1d9f5277e2bce693380
00.json completed, all passed!
01.json completed, all passed!
02.json completed, all passed!
03.json completed, all passed!
04.json completed, all passed!
05.json completed, all passed!
06.json completed, all passed!
07.json completed, all passed!
08.json completed, all passed!
09.json completed, all passed!
0a.json completed, all passed!
0b.json completed, all passed!
0c.json completed, all passed!
0d.json completed, all passed!
0e.json completed, all passed!
0f.json completed, all passed!
10.json completed, all passed!
100.json completed, all passed!
101.json completed, all passed!
11.json completed, all passed!
12.json completed, all passed!
13.json completed, all passed!
14.json completed, all passed!
15.json completed, all passed!
16.json completed, all passed!
17.json completed, all passed!
18.json completed, all passed!
19.json completed, all passed!
1a.json completed, all passed!
1b.json completed, all passed!
1c.json completed, all passed!
1d.json completed, all passed!
1e.json completed, all passed!
1f.json completed, all passed!
20.json completed, all passed!
21.json completed, all passed!
22.json completed, all passed!
23.json completed, all passed!
24.json completed, all passed!
25.json completed, all passed!
26.json completed, all passed!
27.json completed: 547 passed, 453 FAILED
28.json completed, all passed!
29.json completed, all passed!
2a.json completed, all passed!
2b.json completed, all passed!
2c.json completed, all passed!
2d.json completed, all passed!
2e.json completed, all passed!
2f.json completed, all passed!
30.json completed, all passed!
31.json completed, all passed!
32.json completed, all passed!
33.json completed, all passed!
34.json completed, all passed!
35.json completed, all passed!
36.json completed, all passed!
37.json completed, all passed!
38.json completed, all passed!
39.json completed, all passed!
3a.json completed, all passed!
3b.json completed, all passed!
3c.json completed, all passed!
3d.json completed, all passed!
3e.json completed, all passed!
3f.json completed, all passed!
40.json completed, all passed!
41.json completed, all passed!
42.json completed, all passed!
43.json completed, all passed!
44.json completed, all passed!
45.json completed, all passed!
46.json completed, all passed!
47.json completed, all passed!
48.json completed, all passed!
49.json completed, all passed!
4a.json completed, all passed!
4b.json completed, all passed!
4c.json completed, all passed!
4d.json completed, all passed!
4e.json completed, all passed!
4f.json completed, all passed!
50.json completed, all passed!
51.json completed, all passed!
52.json completed, all passed!
53.json completed, all passed!
54.json completed, all passed!
55.json completed, all passed!
56.json completed, all passed!
57.json completed, all passed!
58.json completed, all passed!
59.json completed, all passed!
5a.json completed, all passed!
5b.json completed, all passed!
5c.json completed, all passed!
5d.json completed, all passed!
5e.json completed, all passed!
5f.json completed, all passed!
60.json completed, all passed!
61.json completed, all passed!
62.json completed, all passed!
63.json completed, all passed!
64.json completed, all passed!
65.json completed, all passed!
66.json completed, all passed!
67.json completed, all passed!
68.json completed, all passed!
69.json completed, all passed!
6a.json completed, all passed!
6b.json completed, all passed!
6c.json completed, all passed!
6d.json completed, all passed!
6e.json completed, all passed!
6f.json completed, all passed!
70.json completed, all passed!
71.json completed, all passed!
72.json completed, all passed!
73.json completed, all passed!
74.json completed, all passed!
75.json completed, all passed!
76.json completed, all passed!
77.json completed, all passed!
78.json completed, all passed!
79.json completed, all passed!
7a.json completed, all passed!
7b.json completed, all passed!
7c.json completed, all passed!
7d.json completed, all passed!
7e.json completed, all passed!
7f.json completed, all passed!
80.json completed, all passed!
81.json completed, all passed!
82.json completed, all passed!
83.json completed, all passed!
84.json completed, all passed!
85.json completed, all passed!
86.json completed, all passed!
87.json completed, all passed!
88.json completed, all passed!
89.json completed, all passed!
8a.json completed, all passed!
8b.json completed, all passed!
8c.json completed, all passed!
8d.json completed, all passed!
8e.json completed, all passed!
8f.json completed, all passed!
90.json completed, all passed!
91.json completed, all passed!
92.json completed, all passed!
93.json completed, all passed!
94.json completed, all passed!
95.json completed, all passed!
96.json completed, all passed!
97.json completed, all passed!
98.json completed, all passed!
99.json completed, all passed!
9a.json completed, all passed!
9b.json completed, all passed!
9c.json completed, all passed!
9d.json completed, all passed!
9e.json completed, all passed!
9f.json completed, all passed!
a0.json completed, all passed!
a1.json completed, all passed!
a2.json completed, all passed!
a3.json completed, all passed!
a4.json completed, all passed!
a5.json completed, all passed!
a6.json completed, all passed!
a7.json completed, all passed!
a8.json completed, all passed!
a9.json completed, all passed!
aa.json completed, all passed!
ab.json completed, all passed!
ac.json completed, all passed!
ad.json completed, all passed!
ae.json completed, all passed!
af.json completed, all passed!
b0.json completed, all passed!
b1.json completed, all passed!
b2.json completed, all passed!
b3.json completed, all passed!
b4.json completed, all passed!
b5.json completed, all passed!
b6.json completed, all passed!
b7.json completed, all passed!
b8.json completed, all passed!
b9.json completed, all passed!
ba.json completed, all passed!
bb.json completed, all passed!
bc.json completed, all passed!
bd.json completed, all passed!
be.json completed, all passed!
bf.json completed, all passed!
c0.json completed, all passed!
c1.json completed, all passed!
c2.json completed, all passed!
c3.json completed, all passed!
c4.json completed, all passed!
c5.json completed, all passed!
c6.json completed, all passed!
c7.json completed, all passed!
c8.json completed, all passed!
c9.json completed, all passed!
ca.json completed, all passed!
cb 00.json completed, all passed!
cb 01.json completed, all passed!
cb 02.json completed, all passed!
cb 03.json completed, all passed!
cb 04.json completed, all passed!
cb 05.json completed, all passed!
cb 06.json completed, all passed!
cb 07.json completed, all passed!
cb 08.json completed, all passed!
cb 09.json completed, all passed!
cb 0a.json completed, all passed!
cb 0b.json completed, all passed!
cb 0c.json completed, all passed!
cb 0d.json completed, all passed!
cb 0e.json completed, all passed!
cb 0f.json completed, all passed!
cb 10.json completed, all passed!
cb 11.json completed, all passed!
cb 12.json completed, all passed!
cb 13.json completed, all passed!
cb 14.json completed, all passed!
cb 15.json completed, all passed!
cb 16.json completed, all passed!
cb 17.json completed, all passed!
cb 18.json completed, all passed!
cb 19.json completed, all passed!
cb 1a.json completed, all passed!
cb 1b.json completed, all passed!
cb 1c.json completed, all passed!
cb 1d.json completed, all passed!
cb 1e.json completed, all passed!
cb 1f.json completed, all passed!
cb 20.json completed, all passed!
cb 21.json completed, all passed!
cb 22.json completed, all passed!
cb 23.json completed, all passed!
cb 24.json completed, all passed!
cb 25.json completed, all passed!
cb 26.json completed, all passed!
cb 27.json completed, all passed!
cb 28.json completed, all passed!
cb 29.json completed, all passed!
cb 2a.json completed, all passed!
cb 2b.json completed, all passed!
cb 2c.json completed, all passed!
cb 2d.json completed, all passed!
cb 2e.json completed, all passed!
cb 2f.json completed, all passed!
cb 38.json completed, all passed!
cb 39.json completed, all passed!
cb 3a.json completed, all passed!
cb 3b.json completed, all passed!
cb 3c.json completed, all passed!
cb 3d.json completed, all passed!
cb 3e.json completed, all passed!
cb 3f.json completed, all passed!
cb 40.json completed, all passed!
cb 41.json completed, all passed!
cb 42.json completed, all passed!
cb 43.json completed, all passed!
cb 44.json completed, all passed!
cb 45.json completed, all passed!
cb 46.json completed, all passed!
cb 47.json completed, all passed!
cb 48.json completed, all passed!
cb 49.json completed, all passed!
cb 4a.json completed, all passed!
cb 4b.json completed, all passed!
cb 4c.json completed, all passed!
cb 4d.json completed, all passed!
cb 4e.json completed, all passed!
cb 4f.json completed, all passed!
cb 50.json completed, all passed!
cb 51.json completed, all passed!
cb 52.json completed, all passed!
cb 53.json completed, all passed!
cb 54.json completed, all passed!
cb 55.json completed, all passed!
cb 56.json completed, all passed!
cb 57.json completed, all passed!
cb 58.json completed, all passed!
cb 59.json completed, all passed!
cb 5a.json completed, all passed!
cb 5b.json completed, all passed!
cb 5c.json completed, all passed!
cb 5d.json completed, all passed!
cb 5e.json completed, all passed!
cb 5f.json completed, all passed!
cb 60.json completed, all passed!
cb 61.json completed, all passed!
cb 62.json completed, all passed!
cb 63.json completed, all passed!
cb 64.json completed, all passed!
cb 65.json completed, all passed!
cb 66.json completed, all passed!
cb 67.json completed, all passed!
cb 68.json completed, all passed!
cb 69.json completed, all passed!
cb 6a.json completed, all passed!
cb 6b.json completed, all passed!
cb 6c.json completed, all passed!
cb 6d.json completed, all passed!
cb 6e.json completed, all passed!
cb 6f.json completed, all passed!
cb 70.json completed, all passed!
cb 71.json completed, all passed!
cb 72.json completed, all passed!
cb 73.json completed, all passed!
cb 74.json completed, all passed!
cb 75.json completed, all passed!
cb 76.json completed, all passed!
cb 77.json completed, all passed!
cb 78.json completed, all passed!
cb 79.json completed, all passed!
cb 7a.json completed, all passed!
cb 7b.json completed, all passed!
cb 7c.json completed, all passed!
cb 7d.json completed, all passed!
cb 7e.json completed, all passed!
cb 7f.json completed, all passed!
cb 80.json completed, all passed!
cb 81.json completed, all passed!
cb 82.json completed, all passed!
cb 83.json completed, all passed!
cb 84.json completed, all passed!
cb 85.json completed, all passed!
cb 86.json completed, all passed!
cb 87.json completed, all passed!
cb 88.json completed, all passed!
cb 89.json completed, all passed!
cb 8a.json completed, all passed!
cb 8b.json completed, all passed!
cb 8c.json completed, all passed!
cb 8d.json completed, all passed!
cb 8e.json completed, all passed!
cb 8f.json completed, all passed!
cb 90.json completed, all passed!
cb 91.json completed, all passed!
cb 92.json completed, all passed!
cb 93.json completed, all passed!
cb 94.json completed, all passed!
cb 95.json completed, all passed!
cb 96.json completed, all passed!
cb 97.json completed, all passed!
cb 98.json completed, all passed!
cb 99.json completed, all passed!
cb 9a.json completed, all passed!
cb 9b.json completed, all passed!
cb 9c.json completed, all passed!
cb 9d.json completed, all passed!
cb 9e.json completed, all passed!
cb 9f.json completed, all passed!
cb a0.json completed, all passed!
cb a1.json completed, all passed!
cb a2.json completed, all passed!
cb a3.json completed, all passed!
cb a4.json completed, all passed!
cb a5.json completed, all passed!
cb a6.json completed, all passed!
cb a7.json completed, all passed!
cb a8.json completed, all passed!
cb a9.json completed, all passed!
cb aa.json completed, all passed!
cb ab.json completed, all passed!
cb ac.json completed, all passed!
cb ad.json completed, all passed!
cb ae.json completed, all passed!
cb af.json completed, all passed!
cb b0.json completed, all passed!
cb b1.json completed, all passed!
cb b2.json completed, all passed!
cb b3.json completed, all passed!
cb b4.json completed, all passed!
cb b5.json completed, all passed!
cb b6.json completed, all passed!
cb b7.json completed, all passed!
cb b8.json completed, all passed!
cb b9.json completed, all passed!
cb ba.json completed, all passed!
cb bb.json completed, all passed!
cb bc.json completed, all passed!
cb bd.json completed, all passed!
cb be.json completed, all passed!
cb bf.json completed, all passed!
cb c0.json completed, all passed!
cb c1.json completed, all passed!
cb c2.json completed, all passed!
cb c3.json completed, all passed!
cb c4.json completed, all passed!
cb c5.json completed, all passed!
cb c6.json completed, all passed!
cb c7.json completed, all passed!
cb c8.json completed, all passed!
cb c9.json completed, all passed!
cb ca.json completed, all passed!
cb cb.json completed, all passed!
cb cc.json completed, all passed!
cb cd.json completed, all passed!
cb ce.json completed, all passed!
cb cf.json completed, all passed!
cb d0.json completed, all passed!
cb d1.json completed, all passed!
cb d2.json completed, all passed!
cb d3.json completed, all passed!
cb d4.json completed, all passed!
cb d5.json completed, all passed!
cb d6.json completed, all passed!
cb d7.json completed, all passed!
cb d8.json completed, all passed!
cb d9.json completed, all passed!
cb da.json completed, all passed!
cb db.json completed, all passed!
cb dc.json completed, all passed!
cb dd.json completed, all passed!
cb de.json completed, all passed!
cb df.json completed, all passed!
cb e0.json completed, all passed!
cb e1.json completed, all passed!
cb e2.json completed, all passed!
cb e3.json completed, all passed!
cb e4.json completed, all passed!
cb e5.json completed, all passed!
cb e6.json completed, all passed!
cb e7.json completed, all passed!
cb e8.json completed, all passed!
cb e9.json completed, all passed!
cb ea.json completed, all passed!
cb eb.json completed, all passed!
cb ec.json completed, all passed!
cb ed.json completed, all passed!
cb ee.json completed, all passed!
cb ef.json completed, all passed!
cb f0.json completed, all passed!
cb f1.json completed, all passed!
cb f2.json completed, all passed!
cb f3.json completed, all passed!
cb f4.json completed, all passed!
cb f5.json completed, all passed!
cb f6.json completed, all passed!
cb f7.json completed, all passed!
cb f8.json completed, all passed!
cb f9.json completed, all passed!
cb fa.json completed, all passed!
cb fb.json completed, all passed!
cb fc.json completed, all passed!
cb fd.json completed, all passed!
cb fe.json completed, all passed!
cb ff.json completed, all passed!
cc.json completed, all passed!
cd.json completed, all passed!
ce.json completed, all passed!
cf.json completed, all passed!
d0.json completed, all passed!
d1.json completed, all passed!
d2.json completed, all passed!
d3.json completed, all passed!
d4.json completed, all passed!
d5.json completed, all passed!
d6.json completed, all passed!
d7.json completed, all passed!
d8.json completed, all passed!
d9.json completed, all passed!
da.json completed, all passed!
db.json completed, all passed!
dc.json completed, all passed!
dd 09.json completed, all passed!
dd 19.json completed, all passed!
dd 29.json completed, all passed!
dd 36.json completed, all passed!
dd 39.json completed, all passed!
dd 46.json completed, all passed!
dd 4e.json completed, all passed!
dd 56.json completed, all passed!
dd 5e.json completed, all passed!
dd 66.json completed, all passed!
dd 6e.json completed, all passed!
dd 70.json completed, all passed!
dd 71.json completed, all passed!
dd 72.json completed, all passed!
dd 73.json completed, all passed!
dd 74.json completed, all passed!
dd 75.json completed, all passed!
dd 77.json completed, all passed!
dd 7e.json completed, all passed!
dd 86.json completed, all passed!
dd 8e.json completed, all passed!
dd 96.json completed, all passed!
dd 9e.json completed, all passed!
dd a6.json completed, all passed!
dd ae.json completed, all passed!
dd b6.json completed, all passed!
dd be.json completed, all passed!
dd e1.json completed, all passed!
dd e3.json completed, all passed!
dd e5.json completed, all passed!
dd e9.json completed, all passed!
dd f9.json completed, all passed!
de.json completed, all passed!
df.json completed, all passed!
e0.json completed, all passed!
e1.json completed, all passed!
e2.json completed, all passed!
e3.json completed, all passed!
e4.json completed, all passed!
e5.json completed, all passed!
e6.json completed, all passed!
e7.json completed, all passed!
e8.json completed, all passed!
e9.json completed, all passed!
ea.json completed, all passed!
eb.json completed, all passed!
ec.json completed, all passed!
ed 40.json completed, all passed!
ed 41.json completed, all passed!
ed 42.json completed, all passed!
ed 43.json completed, all passed!
ed 44.json completed, all passed!
ed 45.json completed, all passed!
ed 46.json completed, all passed!
ed 47.json completed, all passed!
ed 48.json completed, all passed!
ed 49.json completed, all passed!
ed 4a.json completed, all passed!
ed 4b.json completed, all passed!
ed 4c.json completed, all passed!
ed 4d.json completed, all passed!
ed 4e.json completed, all passed!
ed 4f.json completed, all passed!
ed 50.json completed, all passed!
ed 51.json completed, all passed!
ed 52.json completed, all passed!
ed 53.json completed, all passed!
ed 54.json completed, all passed!
ed 55.json completed, all passed!
ed 56.json completed, all passed!
ed 57.json completed, all passed!
ed 58.json completed, all passed!
ed 59.json completed, all passed!
ed 5a.json completed, all passed!
ed 5b.json completed, all passed!
ed 5c.json completed, all passed!
ed 5d.json completed, all passed!
ed 5e.json completed, all passed!
ed 5f.json completed, all passed!
ed 60.json completed, all passed!
ed 61.json completed, all passed!
ed 62.json completed, all passed!
ed 64.json completed, all passed!
ed 65.json completed, all passed!
ed 66.json completed, all passed!
ed 67.json completed, all passed!
ed 68.json completed, all passed!
ed 69.json completed, all passed!
ed 6a.json completed, all passed!
ed 6c.json completed, all passed!
ed 6d.json completed, all passed!
ed 6e.json completed, all passed!
ed 6f.json completed, all passed!
ed 72.json completed, all passed!
ed 73.json completed, all passed!
ed 74.json completed, all passed!
ed 75.json completed, all passed!
ed 76.json completed, all passed!
ed 77.json completed: 0 passed, 1000 FAILED
ed 78.json completed, all passed!
ed 79.json completed, all passed!
ed 7a.json completed, all passed!
ed 7b.json completed, all passed!
ed 7c.json completed, all passed!
ed 7d.json completed, all passed!
ed 7e.json completed, all passed!
ed 7f.json completed: 0 passed, 1000 FAILED
ed a0.json completed, all passed!
ed a1.json completed: 0 passed, 1000 FAILED
ed a2.json completed: 13 passed, 987 FAILED
ed a3.json completed: 0 passed, 1000 FAILED
ed a8.json completed, all passed!
ed a9.json completed: 0 passed, 1000 FAILED
ed aa.json completed: 0 passed, 1000 FAILED
ed ab.json completed: 0 passed, 1000 FAILED
ed b0.json completed, all passed!
ed b1.json completed: 0 passed, 1000 FAILED
ed b2.json completed: 0 passed, 1000 FAILED
ed b3.json completed: 0 passed, 1000 FAILED
ed b8.json completed, all passed!
ed b9.json completed: 0 passed, 1000 FAILED
ed ba.json completed: 0 passed, 1000 FAILED
ed bb.json completed: 0 passed, 1000 FAILED
ee.json completed, all passed!
ef.json completed, all passed!
f0.json completed, all passed!
f1.json completed, all passed!
f2.json completed, all passed!
f3.json completed, all passed!
f4.json completed, all passed!
f5.json completed, all passed!
f6.json completed, all passed!
f7.json completed, all passed!
f8.json completed, all passed!
f9.json completed, all passed!
fa.json completed, all passed!
fb.json completed, all passed!
fc.json completed, all passed!
fd 09.json completed, all passed!
fd 19.json completed, all passed!
fd 29.json completed, all passed!
fd 36.json completed, all passed!
fd 39.json completed, all passed!
fd 46.json completed, all passed!
fd 4e.json completed, all passed!
fd 56.json completed, all passed!
fd 5e.json completed, all passed!
fd 66.json completed, all passed!
fd 6e.json completed, all passed!
fd 70.json completed, all passed!
fd 71.json completed, all passed!
fd 72.json completed, all passed!
fd 73.json completed, all passed!
fd 74.json completed, all passed!
fd 75.json completed, all passed!
fd 77.json completed, all passed!
fd 7e.json completed, all passed!
fd 86.json completed, all passed!
fd 8e.json completed, all passed!
fd 96.json completed, all passed!
fd 9e.json completed, all passed!
fd a6.json completed, all passed!
fd ae.json completed, all passed!
fd b6.json completed, all passed!
fd be.json completed, all passed!
fd e1.json completed, all passed!
fd e3.json completed, all passed!
fd e5.json completed, all passed!
fd e9.json completed, all passed!
fd f9.json completed, all passed!
fe.json completed, all passed!
ff.json completed, all passed!
passed: 627560, failed: 14440, total 98%
completed in 0m 35s

View File

@ -1,4 +1,8 @@
* the way you're doing debugging is so bad, and something's broken with the Z80
* debugger should return a breakpoint error to the frontend, so that the frontend still runs, instead of suspending the current execution
* can you make the debugger workable in the web ui in some way? So you can have a debug window open while playing the game or something
* I like making address adapters like this (below)
* you could have busport take a closure or something which translates the address, and returns an error that will be passed up if it occurs
in order to implement the correct behaviour for address exceptions in 68k, transparently
@ -12,6 +16,8 @@
* should you make Address a newtype and add From impls for each type of numeric, and add utils to wrap address at certain boundaries and such
* should you make a means of storing different kinds of buses?
* should you make buses hide their RcRefCell?
* make functions for creating a processor instance from the cpu type (M68k::from_type()), ie. initialize the busport internally with the correct
bitwidths, but it would still be possible to initialize the CPU manually to create one that never existed as such
* 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