Fixed all clippy warnings

This commit is contained in:
transistor 2023-03-05 20:19:49 -08:00
parent 0ac3f48b64
commit 7bdd63bc76
50 changed files with 377 additions and 566 deletions

1
.clippy.toml Normal file
View File

@ -0,0 +1 @@
msrv = "1.60.0"

View File

@ -6,6 +6,7 @@ use crate::system::System;
use crate::devices::{Address, Addressable, Debuggable, TransmutableBox};
#[derive(Default)]
pub struct Debugger {
last_command: Option<String>,
repeat: u32,
@ -14,14 +15,6 @@ pub struct Debugger {
impl Debugger {
pub fn new() -> Self {
Self {
last_command: None,
repeat: 0,
trace_only: false,
}
}
pub fn breakpoint_occurred(&mut self) {
self.trace_only = false;
}
@ -60,7 +53,7 @@ impl Debugger {
}
pub fn run_debugger_command(&mut self, system: &System, debug_obj: &mut dyn Debuggable, args: &[&str]) -> Result<bool, Error> {
if args.len() == 0 {
if args.is_empty() {
// The Default Command
return Ok(true);
}
@ -202,7 +195,7 @@ impl Debugger {
fn check_repeat_arg(&mut self, args: &[&str]) -> Result<(), Error> {
if args.len() > 1 {
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?;
self.repeat = args[1].parse::<u32>().map_err(|_| Error::new("Unable to parse repeat number"))?;
self.last_command = Some(args[0].to_string());
}
Ok(())

View File

@ -32,6 +32,7 @@ pub trait Interruptable {
}
/// A device that can be addressed to read data from or write data to the device.
#[allow(clippy::len_without_is_empty)]
pub trait Addressable {
fn len(&self) -> usize;
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error>;

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ErrorType {
Assertion,
Emulator,

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControllerDevice {
A,
B,
@ -7,7 +7,7 @@ pub enum ControllerDevice {
D,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControllerEvent {
DpadUp(bool),
DpadDown(bool),

View File

@ -7,7 +7,7 @@ use crate::Error;
pub const MASK_COLOUR: u32 = 0xFFFFFFFF;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Frame {
pub width: u32,
pub height: u32,
@ -131,7 +131,7 @@ impl FrameQueue {
pub fn new(width: u32, height: u32) -> Self {
Self {
max_size: (width, height),
queue: ClockedQueue::new(),
queue: Default::default(),
}
}

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Key {
A,
B,

View File

@ -106,14 +106,10 @@ impl<T: Copy> HostData<T> {
}
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct ClockedQueue<T>(Arc<Mutex<VecDeque<(Clock, T)>>>);
impl<T: Clone> ClockedQueue<T> {
pub fn new() -> Self {
Self(Arc::new(Mutex::new(VecDeque::new())))
}
pub fn push(&self, clock: Clock, data: T) {
self.0.lock().unwrap().push_back((clock, data));
}

View File

@ -9,15 +9,17 @@ pub struct InterruptController {
highest: u8,
}
impl InterruptController {
pub fn new() -> InterruptController {
impl Default for InterruptController {
fn default() -> InterruptController {
InterruptController {
target: None,
interrupts: vec![(false, 0); 7],
highest: 0,
}
}
}
impl InterruptController {
pub fn set_target(&mut self, dev: TransmutableBox) -> Result<(), Error> {
if self.target.is_some() {
return Err(Error::new("Interruptable device already set, and interrupt controller only supports one receiver"));

View File

@ -2,6 +2,7 @@
use std::fs;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Write;
use crate::info;
use crate::error::Error;
@ -31,9 +32,7 @@ impl MemoryBlock {
pub fn load_at(&mut self, addr: Address, filename: &str) -> Result<(), Error> {
match fs::read(filename) {
Ok(contents) => {
for i in 0..contents.len() {
self.contents[(addr as usize) + i] = contents[i];
}
self.contents[(addr as usize)..(addr as usize) + contents.len()].copy_from_slice(&contents);
Ok(())
},
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
@ -55,9 +54,7 @@ impl Addressable for MemoryBlock {
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
for i in 0..data.len() {
data[i] = self.contents[(addr as usize) + i];
}
data.copy_from_slice(&self.contents[(addr as usize)..(addr as usize) + data.len()]);
Ok(())
}
@ -66,9 +63,7 @@ impl Addressable for MemoryBlock {
return Err(Error::breakpoint(&format!("Attempt to write to read-only memory at {:x} with data {:?}", addr, data)));
}
for i in 0..data.len() {
self.contents[(addr as usize) + i] = data[i];
}
self.contents[(addr as usize) .. (addr as usize) + data.len()].copy_from_slice(data);
Ok(())
}
}
@ -160,7 +155,7 @@ pub struct Block {
pub dev: TransmutableBox,
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Bus {
blocks: Vec<Block>,
ignore_unmapped: bool,
@ -169,15 +164,6 @@ pub struct Bus {
}
impl Bus {
pub fn new() -> Bus {
Bus {
ignore_unmapped: false,
blocks: vec!(),
watchers: vec!(),
watcher_modified: false,
}
}
pub fn set_ignore_unmapped(&mut self, ignore_unmapped: bool) {
self.ignore_unmapped = ignore_unmapped;
}
@ -204,7 +190,7 @@ impl Bus {
}
}
}
return Err(Error::new(&format!("No segment found at {:#010x}", addr)));
Err(Error::new(&format!("No segment found at {:#010x}", addr)))
}
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
@ -218,7 +204,7 @@ impl Bus {
println!("{}", line);
return;
}
line += &format!("{:#06x} ", word.unwrap());
write!(line, "{:#06x} ", word.unwrap()).unwrap();
addr += 2;
count -= 2;
}
@ -264,7 +250,7 @@ impl Addressable for Bus {
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
if let Some(_) = self.watchers.iter().position(|a| *a == addr) {
if self.watchers.iter().any(|a| *a == addr) {
println!("watch: writing to address {:#06x} with {:?}", addr, data);
self.watcher_modified = true;
}
@ -352,7 +338,7 @@ pub fn dump_slice(data: &[u8], mut count: usize) {
let to = if count < 16 { count / 2 } else { 8 };
for _ in 0..to {
let word = read_beu16(&data[addr..]);
line += &format!("{:#06x} ", word);
write!(line, "{:#06x} ", word).unwrap();
addr += 2;
count -= 2;
}

View File

@ -62,7 +62,7 @@ impl<'input> AssemblyParser<'input> {
let list = self.parse_list_of_words()?;
AssemblyLine::Directive(name, list)
},
word if word.chars().nth(0).map(|ch| is_word(ch)).unwrap_or(false) => {
word if word.chars().next().map(is_word).unwrap_or(false) => {
let next = self.lexer.peek();
if next.is_some() && next.as_ref().unwrap() == ":" {
self.lexer.expect_next()?;
@ -152,7 +152,7 @@ impl<'input> AssemblyParser<'input> {
Ok(AssemblyOperand::Immediate(number))
},
_ => {
if is_digit(token.chars().nth(0).unwrap()) {
if is_digit(token.chars().next().unwrap()) {
let number = parse_any_number(self.lexer.lineno(), &token)?;
Ok(AssemblyOperand::Immediate(number))
} else {
@ -164,12 +164,12 @@ impl<'input> AssemblyParser<'input> {
}
fn parse_any_number(lineno: usize, string: &str) -> Result<usize, Error> {
let (radix, numeric) = if string.starts_with("0x") {
(16, &string[2..])
} else if string.starts_with("0b") {
(2, &string[2..])
} else if string.starts_with("0o") {
(8, &string[2..])
let (radix, numeric) = if let Some(s) = string.strip_prefix("0x") {
(16, s)
} else if let Some(s) = string.strip_prefix("0b") {
(2, s)
} else if let Some(s) = string.strip_prefix("0o") {
(8, s)
} else {
(10, string)
};

View File

@ -37,11 +37,13 @@ impl<T: Copy> Signal<T> {
#[derive(Clone, Debug)]
pub struct EdgeSignal(Signal<bool>);
impl EdgeSignal {
pub fn new() -> Self {
impl Default for EdgeSignal {
fn default() -> Self {
EdgeSignal(Signal::new(false))
}
}
impl EdgeSignal {
pub fn signal(&mut self) {
self.0.set(true);
}
@ -53,8 +55,10 @@ impl EdgeSignal {
}
}
type ObservableCallback<T> = Box<dyn Fn(&T)>;
#[derive(Clone)]
pub struct ObservableSignal<T>(Rc<RefCell<(T, Option<Box<dyn Fn(&T)>>)>>);
pub struct ObservableSignal<T>(Rc<RefCell<(T, Option<ObservableCallback<T>>)>>);
impl<T> ObservableSignal<T> {
pub fn new(init: T) -> ObservableSignal<T> {
@ -84,11 +88,13 @@ impl<T> Observable<T> for ObservableSignal<T> {
pub struct ObservableEdgeSignal(ObservableSignal<bool>);
impl ObservableEdgeSignal {
pub fn new() -> Self {
impl Default for ObservableEdgeSignal {
fn default() -> Self {
ObservableEdgeSignal(ObservableSignal::new(false))
}
}
impl ObservableEdgeSignal {
pub fn set(&mut self) {
*self.0.borrow_mut() = true;
self.0.notify();

View File

@ -25,23 +25,25 @@ pub struct System {
pub break_signal: Option<EdgeSignal>,
}
impl System {
pub fn new() -> System {
System {
impl Default for System {
fn default() -> Self {
Self {
clock: 0,
devices: HashMap::new(),
event_queue: vec![],
debug_enabled: Cell::new(false),
debugger: RefCell::new(Debugger::new()),
debugger: RefCell::new(Debugger::default()),
bus: Rc::new(RefCell::new(Bus::new())),
interrupt_controller: RefCell::new(InterruptController::new()),
bus: Rc::new(RefCell::new(Bus::default())),
interrupt_controller: RefCell::new(InterruptController::default()),
break_signal: None,
}
}
}
impl System {
pub fn get_bus(&self) -> RefMut<'_, Bus> {
self.bus.borrow_mut()
}
@ -91,7 +93,7 @@ impl System {
fn process_one_event(&mut self) -> Result<(), Error> {
let mut event_device = self.event_queue.pop().unwrap();
self.clock = event_device.next_clock;
let result = match event_device.device.borrow_mut().as_steppable().unwrap().step(&self) {
let result = match event_device.device.borrow_mut().as_steppable().unwrap().step(self) {
Ok(diff) => {
event_device.next_clock = self.clock + diff;
Ok(())
@ -152,7 +154,7 @@ impl System {
pub fn exit_error(&mut self) {
for (_, dev) in self.devices.iter() {
match dev.borrow_mut().as_steppable() {
Some(dev) => dev.on_error(&self),
Some(dev) => dev.on_error(self),
None => { },
}
}
@ -162,7 +164,7 @@ impl System {
if self.debug_enabled.get() {
let top = self.event_queue[self.event_queue.len() - 1].device.clone();
if top.borrow_mut().as_debuggable().map(|debug| debug.debugging_enabled()).unwrap_or(false) {
if let Err(err) = self.debugger.borrow_mut().run_debugger(&self, top.clone()) {
if let Err(err) = self.debugger.borrow_mut().run_debugger(self, top.clone()) {
println!("Error: {:?}", err);
}
}

View File

@ -11,8 +11,8 @@ pub struct AverageTimer {
pub start: Option<Instant>,
}
impl AverageTimer {
pub fn new() -> AverageTimer {
impl Default for AverageTimer {
fn default() -> AverageTimer {
AverageTimer {
high: 0,
average: 0.0,
@ -21,7 +21,9 @@ impl AverageTimer {
start: None,
}
}
}
impl AverageTimer {
pub fn start(&mut self) {
//self.start = Some(Instant::now())
}
@ -47,28 +49,18 @@ impl fmt::Display for AverageTimer {
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct CpuTimer {
pub decode: AverageTimer,
pub execute: AverageTimer,
pub cycle: AverageTimer,
}
impl CpuTimer {
pub fn new() -> CpuTimer {
CpuTimer {
decode: AverageTimer::new(),
execute: AverageTimer::new(),
cycle: AverageTimer::new(),
}
}
}
impl fmt::Display for CpuTimer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Decode: {}\n", self.decode)?;
write!(f, "Execute: {}\n", self.execute)?;
write!(f, "Cycle: {}\n", self.cycle)?;
writeln!(f, "Decode: {}", self.decode)?;
writeln!(f, "Execute: {}", self.execute)?;
writeln!(f, "Cycle: {}", self.cycle)?;
Ok(())
}
}

View File

@ -141,7 +141,7 @@ impl M68kAssembler {
self.labels.insert(label.clone(), self.output.len() - 1);
},
AssemblyLine::Instruction(name, list) => {
self.convert_instruction(lineno, &name, &list)?;
self.convert_instruction(lineno, name, list)?;
},
}
Ok(())
@ -255,7 +255,7 @@ impl M68kAssembler {
let (effective_address_left, additional_words_left) = convert_target(lineno, &args[0], operation_size, Disallow::None)?;
let (effective_address_right, additional_words_right) = convert_target(lineno, &args[1], operation_size, Disallow::None)?;
let effective_address_left = (effective_address_left >> 3) | (effective_address_left << 3);
self.output.push(0x0000 | encode_size_for_move(operation_size) | effective_address_left | effective_address_right);
self.output.push(encode_size_for_move(operation_size) | effective_address_left | effective_address_right);
self.output.extend(additional_words_left);
self.output.extend(additional_words_right);
},
@ -371,23 +371,23 @@ impl M68kAssembler {
};
match &args {
&[AssemblyOperand::Immediate(_), AssemblyOperand::Register(_)] => {
[AssemblyOperand::Immediate(_), AssemblyOperand::Register(_)] => {
let mut immediate = parser::expect_immediate(lineno, &args[0])?;
if immediate < 1 || immediate > 8 {
if !(1..=8).contains(&immediate) {
return Err(Error::new(&format!("error at line {}: immediate value must be between 1 and 8, found {:?}", lineno, args)));
} else if immediate == 8 {
immediate = 0;
}
let reg = expect_data_register(lineno, &args[1])?;
self.output.push(opcode | ((immediate as u16) << 9) | direction | encode_size(operation_size) | (0b0 << 5) | reg);
self.output.push(opcode | ((immediate as u16) << 9) | direction | encode_size(operation_size) /*(0b0 << 5)*/ | reg);
},
&[AssemblyOperand::Register(_), AssemblyOperand::Register(_)] => {
[AssemblyOperand::Register(_), AssemblyOperand::Register(_)] => {
let bit_reg = expect_data_register(lineno, &args[0])?;
let reg = expect_data_register(lineno, &args[1])?;
self.output.push(opcode | ((bit_reg as u16) << 9) | direction | encode_size(operation_size) | (0b1 << 5) | reg);
},
//&[_] => {
//[_] => {
// let (effective_address, additional_words) = convert_target(lineno, &args[0], Size::Word, Disallow::NoRegsImmediateOrPC)?;
// self.output.push(opcode | effective_address);
// self.output.extend(additional_words);
@ -414,7 +414,7 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
disallow.check(lineno, Disallow::NoIndirectPost)?;
if args.len() == 1 && operator == "+" {
if let AssemblyOperand::Register(name) = &args[0] {
if name.starts_with("a") {
if name.starts_with('a') {
let reg = expect_reg_num(lineno, name)?;
return Ok(((0b011 << 3) | reg, vec![]));
}
@ -426,7 +426,7 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
disallow.check(lineno, Disallow::NoIndirectPre)?;
if args.len() == 1 && operator == "-" {
if let AssemblyOperand::Register(name) = &args[0] {
if name.starts_with("a") {
if name.starts_with('a') {
let reg = expect_reg_num(lineno, name)?;
return Ok(((0b100 << 3) | reg, vec![]));
} else if name == "sp" {
@ -442,12 +442,12 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
fn convert_register(lineno: usize, name: &str, disallow: Disallow) -> Result<(u16, Vec<u16>), Error> {
match name {
name if name.starts_with("d") => {
name if name.starts_with('d') => {
disallow.check(lineno, Disallow::NoDReg)?;
let reg = expect_reg_num(lineno, name)?;
Ok(((0b000 << 3) | reg, vec![]))
Ok((/*(0b000 << 3)*/ reg, vec![]))
},
name if name.starts_with("a") => {
name if name.starts_with('a') => {
disallow.check(lineno, Disallow::NoAReg)?;
let reg = expect_reg_num(lineno, name)?;
Ok(((0b001 << 3) | reg, vec![]))
@ -462,12 +462,12 @@ fn convert_register(lineno: usize, name: &str, disallow: Disallow) -> Result<(u1
fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow) -> Result<(u16, Vec<u16>), Error> {
match &args {
&[AssemblyOperand::Register(name)] => {
[AssemblyOperand::Register(name)] => {
disallow.check(lineno, Disallow::NoIndirect)?;
let reg = expect_address_reg_num(lineno, name)?;
Ok(((0b010 << 3) | reg, vec![]))
},
&[AssemblyOperand::Immediate(address)] => {
[AssemblyOperand::Immediate(address)] => {
disallow.check(lineno, Disallow::NoIndirectImmediate)?;
if *address < u16::MAX as usize {
Ok((0b111000, convert_immediate(lineno, *address, Size::Word)?))
@ -475,7 +475,7 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
Ok((0b111001, convert_immediate(lineno, *address, Size::Long)?))
}
},
&[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name)] => {
[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name)] => {
if name == "pc" {
disallow.check(lineno, Disallow::NoPCRelative)?;
Ok((0b111010, convert_immediate(lineno, *offset, Size::Word)?))
@ -485,9 +485,9 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
Ok(((0b101 << 3) | reg, convert_immediate(lineno, *offset, Size::Word)?))
}
},
&[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name), AssemblyOperand::Register(index)] => {
[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name), AssemblyOperand::Register(index)] => {
let index_reg = expect_reg_num(lineno, index)?;
let da_select = if index.starts_with("a") { 1 << 15 } else { 0 };
let da_select = if index.starts_with('a') { 1 << 15 } else { 0 };
if name == "pc" {
disallow.check(lineno, Disallow::NoPCRelativeIndex)?;
Ok((0b111011, vec![da_select | (index_reg << 12) | ((*offset as u16) & 0xff)]))
@ -504,13 +504,13 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
}
}
fn convert_reg_and_other<'a>(lineno: usize, args: &'a [AssemblyOperand], _disallow: Disallow) -> Result<(u16, u16, &'a AssemblyOperand), Error> {
fn convert_reg_and_other(lineno: usize, args: &[AssemblyOperand], _disallow: Disallow) -> Result<(u16, u16, &AssemblyOperand), Error> {
match &args {
&[AssemblyOperand::Register(reg), effective_address] => {
Ok(((0b1 << 8), expect_reg_num(lineno, &reg)?, effective_address))
[AssemblyOperand::Register(reg), effective_address] => {
Ok(((0b1 << 8), expect_reg_num(lineno, reg)?, effective_address))
},
&[effective_address, AssemblyOperand::Register(reg)] => {
Ok(((0b0 << 8), expect_reg_num(lineno, &reg)?, effective_address))
[effective_address, AssemblyOperand::Register(reg)] => {
Ok(((0b0 << 8), expect_reg_num(lineno, reg)?, effective_address))
},
_ => {
Err(Error::new(&format!("error at line {}: expected register and effective address, but found {:?}", lineno, args)))
@ -540,7 +540,7 @@ fn convert_immediate(lineno: usize, value: usize, size: Size) -> Result<Vec<u16>
fn expect_data_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16, Error> {
if let AssemblyOperand::Register(name) = operand {
if name.starts_with("d") {
if name.starts_with('d') {
return expect_reg_num(lineno, name);
}
}
@ -549,7 +549,7 @@ fn expect_data_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16,
fn expect_address_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16, Error> {
if let AssemblyOperand::Register(name) = operand {
if name.starts_with("d") {
if name.starts_with('d') {
return expect_reg_num(lineno, name);
}
}
@ -557,7 +557,7 @@ fn expect_address_register(lineno: usize, operand: &AssemblyOperand) -> Result<u
}
fn expect_address_reg_num(lineno: usize, name: &str) -> Result<u16, Error> {
if name.starts_with("a") {
if name.starts_with('a') {
return expect_reg_num(lineno, name);
}
Err(Error::new(&format!("error at line {}: expected an address register, but found {:?}", lineno, name)))

View File

@ -4,18 +4,12 @@ use moa_core::{System, Error, Address, Addressable, Debuggable};
use super::state::M68k;
use super::decode::M68kDecoder;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct StackTracer {
pub calls: Vec<u32>,
}
impl StackTracer {
pub fn new() -> StackTracer {
StackTracer {
calls: vec![],
}
}
pub fn push_return(&mut self, addr: u32) {
self.calls.push(addr);
}
@ -26,7 +20,7 @@ impl StackTracer {
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct M68kDebugger {
pub enabled: bool,
pub breakpoints: Vec<u32>,
@ -35,18 +29,6 @@ pub struct M68kDebugger {
pub stack_tracer: StackTracer,
}
impl M68kDebugger {
pub fn new() -> M68kDebugger {
M68kDebugger {
enabled: false,
breakpoints: vec!(),
use_tracing: false,
step_until_return: None,
stack_tracer: StackTracer::new(),
}
}
}
impl Debuggable for M68k {
fn debugging_enabled(&mut self) -> bool {
self.debugger.enabled

View File

@ -50,7 +50,7 @@ impl M68kDecoder {
pub fn new(cputype: M68kType, start: u32) -> M68kDecoder {
M68kDecoder {
cputype,
start: start,
start,
end: start,
instruction_word: 0,
instruction: Instruction::NOP,
@ -85,7 +85,7 @@ impl M68kDecoder {
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
0b0010 => Ok(Instruction::ANDtoCCR(data as u8)),
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
0b01 => {
@ -94,10 +94,10 @@ impl M68kDecoder {
0b0000 => Ok(Instruction::ORtoSR(data)),
0b0010 => Ok(Instruction::ANDtoSR(data)),
0b1010 => Ok(Instruction::EORtoSR(data)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if (ins & 0x138) == 0x108 {
let dreg = get_high_reg(ins);
@ -124,7 +124,7 @@ impl M68kDecoder {
0b01 => Ok(Instruction::BCHG(bitnum, target, size)),
0b10 => Ok(Instruction::BCLR(bitnum, target, size)),
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
let size = get_size(ins);
@ -143,7 +143,7 @@ impl M68kDecoder {
0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())),
0b1010 => Ok(Instruction::EOR(Target::Immediate(data), target, size.unwrap())),
0b1100 => Ok(Instruction::CMP(Target::Immediate(data), target, size.unwrap())),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
},
@ -221,7 +221,7 @@ impl M68kDecoder {
match get_size(ins) {
Some(size) => Ok(Instruction::CLR(target, size)),
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
None => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
0b100 => {
@ -236,7 +236,7 @@ impl M68kDecoder {
None => Ok(Instruction::MOVEtoSR(target)),
}
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if ins_0f00 == 0x800 || ins_0f00 == 0x900 {
let opmode = (ins & 0x01C0) >> 6;
@ -269,7 +269,7 @@ impl M68kDecoder {
(0b111, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if ins_0f00 == 0xA00 {
if (ins & 0x0FF) == 0xFC {
@ -332,11 +332,11 @@ impl M68kDecoder {
};
Ok(Instruction::MOVEC(target, creg, dir))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
} else {
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
Err(Error::processor(Exceptions::IllegalInstruction as u32))
}
},
OPCG_ADDQ_SUBQ => {
@ -354,12 +354,10 @@ impl M68kDecoder {
} else {
Ok(Instruction::SUBA(Target::Immediate(data), reg, size))
}
} else if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
} else {
if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
} else {
Ok(Instruction::SUB(Target::Immediate(data), target, size))
}
Ok(Instruction::SUB(Target::Immediate(data), target, size))
}
},
None => {
@ -402,11 +400,7 @@ impl M68kDecoder {
OPCG_DIV_OR => {
let size = get_size(ins);
if size.is_none() {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign))
} else if (ins & 0x1F0) == 0x100 {
if (ins & 0x1F0) == 0x100 {
let regx = get_high_reg(ins);
let regy = get_low_reg(ins);
@ -414,11 +408,15 @@ impl M68kDecoder {
false => Ok(Instruction::SBCD(Target::DirectDReg(regy), Target::DirectDReg(regx))),
true => Ok(Instruction::SBCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))),
}
} else {
} else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, size)?;
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::OR(from, to, size.unwrap()))
Ok(Instruction::OR(from, to, size))
} else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign))
}
},
OPCG_SUB => {
@ -472,7 +470,7 @@ impl M68kDecoder {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
Ok(Instruction::CMPA(target, reg, size))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
OPCG_MUL_AND => {
@ -486,24 +484,24 @@ impl M68kDecoder {
false => Ok(Instruction::ABCD(Target::DirectDReg(regy), Target::DirectDReg(regx))),
true => Ok(Instruction::ABCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))),
}
} else if (ins & 0b0001_0011_0000) == 0b0001_0000_0000 && !size.is_none() {
} else if (ins & 0b0001_0011_0000) == 0b0001_0000_0000 && size.is_some() {
let regx = get_high_reg(ins);
let regy = get_low_reg(ins);
match (ins & 0x00F8) >> 3 {
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if size.is_none() {
} else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size))
} else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::MULW(effective_addr, get_high_reg(ins), sign))
} else {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, size)?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size.unwrap()))
}
},
OPCG_ADD => {
@ -552,7 +550,7 @@ impl M68kDecoder {
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)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
None => {
@ -564,7 +562,7 @@ impl M68kDecoder {
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)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if self.cputype > M68kType::MC68020 {
// Bitfield instructions (MC68020+)
@ -591,10 +589,10 @@ impl M68kDecoder {
0b111 => Ok(Instruction::BFINS(reg, target, offset, width)),
0b110 => Ok(Instruction::BFSET(target, offset, width)),
0b000 => Ok(Instruction::BFTST(target, offset, width)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
Err(Error::processor(Exceptions::IllegalInstruction as u32))
}
},
}
@ -605,7 +603,7 @@ impl M68kDecoder {
OPCG_FLINE => {
Ok(Instruction::UnimplementedF(ins))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}

View File

@ -21,7 +21,7 @@ use crate::instructions::{
};
const DEV_NAME: &'static str = "m68k-cpu";
const DEV_NAME: &str = "m68k-cpu";
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Used {
@ -358,14 +358,14 @@ impl M68k {
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
let mask = self.set_bit_test_flags(src_val, bitnum, size);
src_val = src_val & !mask;
src_val &= !mask;
self.set_target_value(target, src_val, size, Used::Twice)?;
},
Instruction::BSET(bitnum, target, size) => {
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
let mut value = self.get_target_value(target, size, Used::Twice)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask;
value |= mask;
self.set_target_value(target, value, size, Used::Twice)?;
},
Instruction::BTST(bitnum, target, size) => {
@ -1562,7 +1562,7 @@ fn rotate_operation(value: u32, size: Size, dir: ShiftDirection, use_extend: Opt
}
},
ShiftDirection::Right => {
let bit = if (value & 0x01) != 0 { true } else { false };
let bit = (value & 0x01) != 0;
let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 };
((value >> 1) | mask, bit)
},

View File

@ -1,66 +1,66 @@
use std::fmt;
use std::fmt::{self, Write};
pub type Register = u8;
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Size {
Byte,
Word,
Long,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Sign {
Signed,
Unsigned,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Direction {
FromTarget,
ToTarget,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ShiftDirection {
Right,
Left,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum XRegister {
DReg(u8),
AReg(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BaseRegister {
None,
PC,
AReg(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct IndexRegister {
pub xreg: XRegister,
pub scale: u8,
pub size: Size,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RegOrImmediate {
DReg(u8),
Immediate(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControlRegister {
VBR,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Condition {
True,
False,
@ -80,7 +80,7 @@ pub enum Condition {
LessThanOrEqual,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Target {
Immediate(u32),
DirectDReg(Register),
@ -94,7 +94,7 @@ pub enum Target {
IndirectMemory(u32, Size),
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Instruction {
ABCD(Target, Target),
ADD(Target, Target, Size),
@ -318,7 +318,7 @@ fn fmt_index_disp(index: &Option<IndexRegister>) -> String {
Some(index) => {
let mut result = format!(", %{}", index.xreg);
if index.scale != 0 {
result += &format!("<< {}", index.scale);
write!(result, "<< {}", index.scale).unwrap();
}
result
},
@ -433,7 +433,7 @@ impl fmt::Display for Instruction {
Instruction::DBcc(cond, reg, offset) => write!(f, "db{}\t%d{}, {}", cond, reg, offset),
Instruction::DIVW(src, dest, sign) => write!(f, "div{}w\t{}, %d{}", sign, src, dest),
Instruction::DIVL(src, desth, destl, sign) => {
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or("".to_string());
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or_else(|| "".to_string());
write!(f, "div{}l\t{}, {}%d{}", sign, src, opt_reg, destl)
},
@ -478,7 +478,7 @@ impl fmt::Display for Instruction {
},
Instruction::MULW(src, dest, sign) => write!(f, "mul{}w\t{}, %d{}", sign, src, dest),
Instruction::MULL(src, desth, destl, sign) => {
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or("".to_string());
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or_else(|| "".to_string());
write!(f, "mul{}l\t{}, {}%d{}", sign, src, opt_reg, destl)
},

View File

@ -21,7 +21,7 @@ const FLAGS_ON_RESET: u16 = 0x2700;
#[repr(u16)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Flags {
Carry = 0x0001,
Overflow = 0x0002,
@ -36,7 +36,7 @@ pub enum Flags {
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Exceptions {
BusError = 2,
AddressError = 3,
@ -52,7 +52,7 @@ pub enum Exceptions {
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FunctionCode {
Reserved0 = 0,
UserData = 1,
@ -64,7 +64,7 @@ pub enum FunctionCode {
CpuSpace = 7,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Status {
Init,
Running,
@ -72,7 +72,7 @@ pub enum Status {
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InterruptPriority {
NoInterrupt = 0,
Level1 = 1,
@ -84,19 +84,19 @@ pub enum InterruptPriority {
Level7 = 7,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MemType {
Program,
Data,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MemAccess {
Read,
Write,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MemoryRequest {
pub i_n_bit: bool,
pub access: MemAccess,
@ -105,7 +105,7 @@ pub struct MemoryRequest {
pub address: u32,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct M68kState {
pub status: Status,
pub request: MemoryRequest,
@ -134,11 +134,11 @@ pub struct M68k {
pub timer: CpuTimer,
}
impl M68kState {
pub fn new() -> M68kState {
impl Default for M68kState {
fn default() -> M68kState {
M68kState {
status: Status::Init,
request: MemoryRequest::new(),
request: MemoryRequest::default(),
current_ipl: InterruptPriority::NoInterrupt,
pending_ipl: InterruptPriority::NoInterrupt,
@ -159,21 +159,21 @@ impl M68k {
M68k {
cputype,
frequency,
state: M68kState::new(),
state: M68kState::default(),
decoder: M68kDecoder::new(cputype, 0),
timing: M68kInstructionTiming::new(cputype, port.data_width()),
debugger: M68kDebugger::new(),
port: port,
timer: CpuTimer::new(),
debugger: M68kDebugger::default(),
port,
timer: CpuTimer::default(),
}
}
#[allow(dead_code)]
pub fn reset(&mut self) {
self.state = M68kState::new();
self.state = M68kState::default();
self.decoder = M68kDecoder::new(self.cputype, 0);
self.timing = M68kInstructionTiming::new(self.cputype, self.port.data_width());
self.debugger = M68kDebugger::new();
self.debugger = M68kDebugger::default();
}
pub fn dump_state(&mut self) {
@ -187,9 +187,9 @@ impl M68k {
println!(" SSP: {:#010x}", self.state.ssp);
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
println!("");
println!();
self.port.dump_memory(self.state.ssp as Address, 0x40);
println!("");
println!();
}
}
@ -226,8 +226,8 @@ impl FunctionCode {
}
}
impl MemoryRequest {
pub fn new() -> Self {
impl Default for MemoryRequest {
fn default() -> Self {
Self {
i_n_bit: false,
access: MemAccess::Read,
@ -236,7 +236,9 @@ impl MemoryRequest {
address: 0,
}
}
}
impl MemoryRequest {
pub fn get_type_code(&self) -> u16 {
let ins = match self.i_n_bit {
false => 0x0000,

View File

@ -143,7 +143,7 @@ mod decode_tests {
print!("FAILED");
print!("\nleft: {:?}, right: {:?}", data, case.data);
}
println!("");
println!();
},
Err(err) => {
println!("FAILED\n{:?}", err);
@ -181,7 +181,7 @@ mod decode_tests {
print!("FAILED");
print!("\nleft: {:#06x}, right: {:#06x}", data[0], case.data[0]);
}
println!("");
println!();
},
Err(err) => {
println!("FAILED\n{:?}", err);
@ -619,7 +619,7 @@ mod execute_tests {
print!("FAILED");
print!("\nleft: {:?}, right: {:?}", data, case.data);
}
println!("");
println!();
},
Err(err) => {
println!("FAILED\n{:?}", err);

View File

@ -3,7 +3,7 @@ use crate::M68kType;
use crate::instructions::{Size, Sign, Direction, Target, Instruction};
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct M68kInstructionTiming {
pub cputype: M68kType,
pub bus_size: Size,
@ -325,11 +325,12 @@ impl M68kInstructionTiming {
}
}
pub fn add_instruction_68020(&mut self, instruction: &Instruction) -> &mut Self {
match instruction {
// TODO implement
_ => self.add_internal(4),
}
pub fn add_instruction_68020(&mut self, _instruction: &Instruction) -> &mut Self {
//match instruction {
// // TODO implement
// _ => self.add_internal(4),
//}
self.add_internal(4)
}
pub fn calculate_clocks(&self, branched: bool, reps: u16) -> u16 {

View File

@ -5,20 +5,12 @@ use crate::state::Z80;
use crate::decode::Z80Decoder;
#[derive(Default)]
pub struct Z80Debugger {
pub enabled: bool,
pub breakpoints: Vec<u16>,
}
impl Z80Debugger {
pub fn new() -> Self {
Self {
enabled: false,
breakpoints: vec!(),
}
}
}
impl Debuggable for Z80 {
fn debugging_enabled(&mut self) -> bool {
self.debugger.enabled
@ -48,7 +40,7 @@ impl Debuggable for Z80 {
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
let mut decoder = Z80Decoder::new();
let mut decoder = Z80Decoder::default();
decoder.dump_disassembly(&mut self.port, addr as u16, count as u16);
}

View File

@ -4,19 +4,19 @@ use moa_core::{Error, Address, Addressable};
use crate::state::{Register, InterruptMode};
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Direction {
ToAcc,
FromAcc,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Size {
Byte,
Word,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Condition {
NotZero,
Zero,
@ -28,7 +28,7 @@ pub enum Condition {
Negative,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RegisterPair {
BC,
DE,
@ -39,13 +39,13 @@ pub enum RegisterPair {
IY,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IndexRegister {
IX,
IY,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IndexRegisterHalf {
IXH,
IXL,
@ -53,13 +53,13 @@ pub enum IndexRegisterHalf {
IYL,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SpecialRegister {
I,
R,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Target {
DirectReg(Register),
DirectRegHalf(IndexRegisterHalf),
@ -68,7 +68,7 @@ pub enum Target {
Immediate(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum LoadTarget {
DirectRegByte(Register),
DirectRegHalfByte(IndexRegisterHalf),
@ -85,7 +85,7 @@ pub enum LoadTarget {
pub type UndocumentedCopy = Option<Target>;
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Instruction {
ADCa(Target),
ADC16(RegisterPair, RegisterPair),
@ -179,8 +179,8 @@ pub struct Z80Decoder {
pub execution_time: u16,
}
impl Z80Decoder {
pub fn new() -> Self {
impl Default for Z80Decoder {
fn default() -> Self {
Self {
start: 0,
end: 0,

View File

@ -5,7 +5,7 @@ use crate::decode::{Condition, Instruction, LoadTarget, Target, RegisterPair, In
use crate::state::{Z80, Status, Flags, Register};
const DEV_NAME: &'static str = "z80-cpu";
const DEV_NAME: &str = "z80-cpu";
const FLAGS_NUMERIC: u8 = 0xC0;
const FLAGS_ARITHMETIC: u8 = 0x17;
@ -337,10 +337,10 @@ impl Z80 {
let parity = if count != 0 { Flags::Parity as u8 } else { 0 };
self.set_flags(mask, parity);
if self.decoder.instruction == Instruction::LDIR || self.decoder.instruction == Instruction::LDDR {
if count != 0 {
self.state.pc -= 2;
}
if (self.decoder.instruction == Instruction::LDIR || self.decoder.instruction == Instruction::LDDR)
&& count != 0
{
self.state.pc -= 2;
}
},
Instruction::NEG => {
@ -383,7 +383,7 @@ impl Z80 {
},
Instruction::RES(bit, target, opt_copy) => {
let mut value = self.get_target_value(target)?;
value = value & !(1 << bit);
value &= !(1 << bit);
self.set_target_value(target, value)?;
if let Some(target) = opt_copy {
self.set_target_value(target, value)?;
@ -504,7 +504,7 @@ impl Z80 {
},
Instruction::SET(bit, target, opt_copy) => {
let mut value = self.get_target_value(target)?;
value = value | (1 << bit);
value |= 1 << bit;
self.set_target_value(target, value)?;
if let Some(target) = opt_copy {
self.set_target_value(target, value)?;
@ -836,7 +836,7 @@ impl Z80 {
#[inline(always)]
fn set_flag(&mut self, flag: Flags, value: bool) {
self.state.reg[Register::F as usize] = self.state.reg[Register::F as usize] & !(flag as u8);
self.state.reg[Register::F as usize] &= !(flag as u8);
if value {
self.state.reg[Register::F as usize] |= flag as u8;
}

View File

@ -11,7 +11,7 @@ pub enum Z80Type {
Z80,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Status {
Init,
Running,
@ -19,7 +19,7 @@ pub enum Status {
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InterruptMode {
Mode0,
Mode01,
@ -29,7 +29,7 @@ pub enum InterruptMode {
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Flags {
Carry = 0x01,
AddSubtract = 0x02,
@ -42,7 +42,7 @@ pub enum Flags {
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Register {
B = 0,
C = 1,
@ -55,7 +55,7 @@ pub enum Register {
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Z80State {
pub status: Status,
pub interrupts_enabled: bool,
@ -73,8 +73,8 @@ pub struct Z80State {
pub r: u8,
}
impl Z80State {
pub fn new() -> Self {
impl Default for Z80State {
fn default() -> Self {
Self {
status: Status::Init,
interrupts_enabled: false,
@ -92,7 +92,9 @@ impl Z80State {
r: 0,
}
}
}
impl Z80State {
pub fn get_register(&mut self, reg: Register) -> u8 {
self.reg[reg as usize]
}
@ -118,10 +120,10 @@ impl Z80 {
Self {
cputype,
frequency,
state: Z80State::new(),
decoder: Z80Decoder::new(),
debugger: Z80Debugger::new(),
port: port,
state: Z80State::default(),
decoder: Z80Decoder::default(),
debugger: Z80Debugger::default(),
port,
reset: Signal::new(false),
bus_request: Signal::new(false),
}
@ -129,9 +131,9 @@ impl Z80 {
#[allow(dead_code)]
pub fn clear_state(&mut self) {
self.state = Z80State::new();
self.decoder = Z80Decoder::new();
self.debugger = Z80Debugger::new();
self.state = Z80State::default();
self.decoder = Z80Decoder::default();
self.debugger = Z80Debugger::default();
}
pub fn dump_state(&mut self) {
@ -147,9 +149,9 @@ impl Z80 {
println!("H: {:#04x} L: {:#04x} H': {:#04x} L': {:#04x}", self.state.reg[Register::H as usize], self.state.reg[Register::L as usize], self.state.shadow_reg[Register::H as usize], self.state.shadow_reg[Register::L as usize]);
println!("Current Instruction: {} {:?}", self.decoder.format_instruction_bytes(&mut self.port), self.decoder.instruction);
println!("");
println!();
self.port.dump_memory(self.state.sp as Address, 0x40);
println!("");
println!();
}
}

View File

@ -9,7 +9,7 @@ use moa_core::host::{Audio, ClockedQueue};
const SAMPLE_RATE: usize = 48000;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct AudioFrame {
data: Vec<(f32, f32)>,
}
@ -24,7 +24,7 @@ pub struct AudioSource {
impl AudioSource {
pub fn new(mixer: Arc<Mutex<AudioMixer>>) -> Self {
let queue = ClockedQueue::new();
let queue = ClockedQueue::default();
let (id, sample_rate, frame_size) = {
let mut mixer = mixer.lock().unwrap();
let id = mixer.add_source(queue.clone());
@ -283,7 +283,7 @@ impl CpalAudioOutput {
if let Some(frame) = result {
let (start, middle, end) = unsafe { frame.data.align_to::<f32>() };
if start.len() != 0 || end.len() != 0 {
if !start.is_empty() || !end.is_empty() {
warn!("audio: frame wasn't aligned");
}
let length = middle.len().min(data.len());

View File

@ -1,101 +0,0 @@
#[derive(Clone)]
pub struct CircularBuffer<T> {
pub inp: usize,
pub out: usize,
pub init: T,
pub buffer: Vec<T>,
}
impl<T: Copy> CircularBuffer<T> {
pub fn new(size: usize, init: T) -> Self {
Self {
inp: 0,
out: 0,
init,
buffer: vec![init; size],
}
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn clear(&mut self) {
self.inp = 0;
self.out = 0;
}
pub fn resize(&mut self, newlen: usize) {
if self.buffer.len() != newlen {
self.buffer = vec![self.init; newlen];
self.clear();
}
}
pub fn insert(&mut self, item: T) {
let next = self.next_in();
if next != self.out {
self.buffer[self.inp] = item;
self.inp = next;
}
}
pub fn drop_next(&mut self, mut count: usize) {
let avail = self.used_space();
if count > avail {
count = avail;
}
self.out += count;
if self.out >= self.buffer.len() {
self.out -= self.buffer.len();
}
}
pub fn is_full(&self) -> bool {
self.next_in() == self.out
}
pub fn used_space(&self) -> usize {
if self.inp >= self.out {
self.inp - self.out
} else {
self.buffer.len() - self.out + self.inp
}
}
pub fn free_space(&self) -> usize {
if self.out > self.inp {
self.out - self.inp - 1
} else {
self.buffer.len() - self.inp + self.out - 1
}
}
fn next_in(&self) -> usize {
if self.inp + 1 < self.buffer.len() {
self.inp + 1
} else {
0
}
}
}
impl<T: Copy> Iterator for CircularBuffer<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.out == self.inp {
None
} else {
let value = self.buffer[self.out];
self.out += 1;
if self.out >= self.buffer.len() {
self.out = 0;
}
Some(value)
}
}
}

View File

@ -1,6 +1,4 @@
pub mod circularbuf;
#[cfg(feature = "tty")]
pub mod tty;

View File

@ -1,7 +1,6 @@
use clap::Arg;
use moa_minifb;
use moa_genesis::{build_genesis, SegaGenesisOptions};
fn main() {
@ -10,7 +9,7 @@ fn main() {
.help("ROM file to load (must be flat binary)"))
.get_matches();
let mut options = SegaGenesisOptions::new();
let mut options = SegaGenesisOptions::default();
if let Some(filename) = matches.value_of("ROM") {
options.rom = filename.to_string();
}

View File

@ -1,5 +1,4 @@
use moa_minifb;
use moa_macintosh::build_macintosh_512k;
fn main() {

View File

@ -1,11 +1,10 @@
use std::sync::mpsc;
use moa_minifb;
use moa_peripherals_yamaha::{Ym2612, Sn76489};
use moa_core::host::gfx::{Frame, FrameQueue};
use moa_core::host::{Host, WindowUpdater, KeyboardUpdater, Key, KeyEvent, MouseUpdater, MouseState, MouseEvent};
use moa_core::host::{Host, WindowUpdater, KeyboardUpdater, Key, KeyEvent /*, MouseUpdater, MouseState, MouseEvent*/};
use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
@ -98,7 +97,7 @@ fn main() {
.get_matches();
moa_minifb::run(matches, |host| {
let mut system = System::new();
let mut system = System::default();
let queue = FrameQueue::new(384, 128);
let (sender, receiver) = mpsc::channel();
@ -112,7 +111,7 @@ fn main() {
let sn_sound = wrap_transmutable(Sn76489::create(host)?);
system.add_addressable_device(0x10, sn_sound)?;
host.add_window(Box::new(queue.clone()))?;
host.add_window(Box::new(queue))?;
host.register_keyboard(Box::new(SynthControlsUpdater(sender)))?;
//host.register_mouse(Box::new(SynthControlsUpdater(sender)))?;

View File

@ -1,7 +1,6 @@
use clap::Arg;
use moa_minifb;
use moa_trs80::{build_trs80, Trs80Options};
fn main() {
@ -14,7 +13,7 @@ fn main() {
.help("ROM file to load at the start of memory"))
.get_matches();
let mut options = Trs80Options::new();
let mut options = Trs80Options::default();
if let Some(filename) = matches.value_of("rom") {
options.rom = filename.to_string();
}

View File

@ -59,7 +59,7 @@ pub fn run<I>(matches: ArgMatches, init: I) where I: FnOnce(&mut MiniFrontendBui
}
pub fn run_inline<I>(matches: ArgMatches, init: I) where I: FnOnce(&mut MiniFrontendBuilder) -> Result<System, Error> {
let mut frontend = MiniFrontendBuilder::new();
let mut frontend = MiniFrontendBuilder::default();
let system = init(&mut frontend).unwrap();
frontend
@ -68,7 +68,7 @@ pub fn run_inline<I>(matches: ArgMatches, init: I) where I: FnOnce(&mut MiniFron
}
pub fn run_threaded<I>(matches: ArgMatches, init: I) where I: FnOnce(&mut MiniFrontendBuilder) -> Result<System, Error> + Send + 'static {
let frontend = Arc::new(Mutex::new(MiniFrontendBuilder::new()));
let frontend = Arc::new(Mutex::new(MiniFrontendBuilder::default()));
{
let frontend = frontend.clone();
@ -88,7 +88,7 @@ pub fn run_threaded<I>(matches: ArgMatches, init: I) where I: FnOnce(&mut MiniFr
}
fn wait_until_initialized(frontend: Arc<Mutex<MiniFrontendBuilder>>) {
while frontend.lock().unwrap().finalized == false {
while !frontend.lock().unwrap().finalized {
thread::sleep(Duration::from_millis(10));
}
}
@ -103,8 +103,8 @@ pub struct MiniFrontendBuilder {
pub finalized: bool,
}
impl MiniFrontendBuilder {
pub fn new() -> Self {
impl Default for MiniFrontendBuilder {
fn default() -> Self {
Self {
window: None,
controller: None,
@ -114,7 +114,9 @@ impl MiniFrontendBuilder {
finalized: false,
}
}
}
impl MiniFrontendBuilder {
pub fn finalize(&mut self) {
self.finalized = true;
}
@ -211,20 +213,24 @@ impl MiniFrontend {
.init().unwrap();
if matches.occurrences_of("debugger") > 0 {
system.as_mut().map(|system| system.enable_debugging());
if let Some(system) = system.as_mut() {
system.enable_debugging();
}
}
if matches.occurrences_of("disable-audio") <= 0 {
if matches.occurrences_of("disable-audio") == 0 {
self.audio = Some(CpalAudioOutput::create_audio_output(self.mixer.lock().unwrap().get_sink()));
}
let mut options = minifb::WindowOptions::default();
options.scale = match matches.value_of("scale").map(|s| u8::from_str_radix(s, 10).unwrap()) {
Some(1) => minifb::Scale::X1,
Some(2) => minifb::Scale::X2,
Some(4) => minifb::Scale::X4,
Some(8) => minifb::Scale::X8,
_ => minifb::Scale::X2,
let options = minifb::WindowOptions {
scale: match matches.value_of("scale").map(|s| s.parse::<u8>().unwrap()) {
Some(1) => minifb::Scale::X1,
Some(2) => minifb::Scale::X2,
Some(4) => minifb::Scale::X4,
Some(8) => minifb::Scale::X8,
_ => minifb::Scale::X2,
},
..Default::default()
};
let speed = match matches.value_of("speed") {
@ -271,9 +277,10 @@ impl MiniFrontend {
self.check_key(key, true);
// Process special keys
match key {
Key::D => { system.as_ref().map(|s| s.enable_debugging()); },
_ => { },
if let Key::D = key {
if let Some(system) = system.as_ref() {
system.enable_debugging();
}
}
}
}

View File

@ -30,8 +30,9 @@ const ATA_ST_ERROR: u8 = 0x01;
const ATA_SECTOR_SIZE: u32 = 512;
const DEV_NAME: &'static str = "ata";
const DEV_NAME: &str = "ata";
#[derive(Default)]
pub struct AtaDevice {
selected_sector: u32,
selected_count: u32,
@ -39,17 +40,7 @@ pub struct AtaDevice {
contents: Vec<u8>,
}
impl AtaDevice {
pub fn new() -> Self {
AtaDevice {
selected_sector: 0,
selected_count: 0,
last_error: 0,
contents: vec![],
}
}
pub fn load(&mut self, filename: &str) -> Result<(), Error> {
match fs::read(filename) {
Ok(contents) => {

View File

@ -12,7 +12,7 @@ const REG_INT_ENABLE: Address = 0x0E;
const REG_OUTPUT_A_NHS: Address = 0x0F;
const DEV_NAME: &'static str = "mos6522";
const DEV_NAME: &str = "mos6522";
pub struct Port {
@ -20,8 +20,8 @@ pub struct Port {
pub ddr: u8,
}
impl Port {
pub fn new() -> Self {
impl Default for Port {
fn default() -> Self {
Self {
data: 0xff,
ddr: 0,
@ -39,11 +39,11 @@ pub struct Mos6522 {
pub interrupt_enable: u8,
}
impl Mos6522 {
pub fn new() -> Self {
impl Default for Mos6522 {
fn default() -> Self {
Self {
port_a: ObservableSignal::new(Port::new()),
port_b: ObservableSignal::new(Port::new()),
port_a: ObservableSignal::new(Port::default()),
port_b: ObservableSignal::new(Port::default()),
peripheral_ctrl: 0,
interrupt: Signal::new(false),
interrupt_flags: 0,

View File

@ -65,8 +65,9 @@ const ISR_CH_A_RX_READY_FULL: u8 = 0x02;
const ISR_CH_A_TX_READY: u8 = 0x01;
const DEV_NAME: &'static str = "mc68681";
const DEV_NAME: &str = "mc68681";
#[derive(Default)]
pub struct MC68681Port {
tty: Option<Box<dyn Tty>>,
status: u8,
@ -78,18 +79,6 @@ pub struct MC68681Port {
}
impl MC68681Port {
pub fn new() -> MC68681Port {
MC68681Port {
tty: None,
status: 0,
tx_enabled: false,
rx_enabled: false,
input: 0,
}
}
pub fn connect(&mut self, pty: Box<dyn Tty>) -> Result<String, Error> {
let name = pty.device_name();
println!("{}: opening pts {}", DEV_NAME, name);
@ -180,12 +169,12 @@ pub struct MC68681 {
output_state: u8,
}
impl MC68681 {
pub fn new() -> Self {
impl Default for MC68681 {
fn default() -> Self {
MC68681 {
acr: 0,
port_a: MC68681Port::new(),
port_b: MC68681Port::new(),
port_a: MC68681Port::default(),
port_b: MC68681Port::default(),
int_mask: 0,
int_status: 0,
@ -202,7 +191,9 @@ impl MC68681 {
output_state: 0,
}
}
}
impl MC68681 {
fn set_interrupt_flag(&mut self, flag: u8, value: bool) {
self.int_status = (self.int_status & !flag) | (if value { flag } else { 0 });
}

View File

@ -5,7 +5,7 @@ use moa_core::host::{Host, Audio};
use moa_core::host::audio::{SquareWave};
const DEV_NAME: &'static str = "sn76489";
const DEV_NAME: &str = "sn76489";
#[derive(Clone)]
pub struct ToneGenerator {
@ -51,14 +51,16 @@ pub struct NoiseGenerator {
attenuation: f32,
}
impl NoiseGenerator {
pub fn new() -> Self {
impl Default for NoiseGenerator {
fn default() -> Self {
Self {
on: false,
attenuation: 0.0,
}
}
}
impl NoiseGenerator {
pub fn set_attenuation(&mut self, attenuation: u8) {
if attenuation == 0x0F {
self.on = false;
@ -99,7 +101,7 @@ impl Sn76489 {
first_byte: None,
source,
tones: vec![ToneGenerator::new(sample_rate); 3],
noise: NoiseGenerator::new(),
noise: NoiseGenerator::default(),
})
}
}
@ -113,7 +115,7 @@ impl Steppable for Sn76489 {
if samples > 0 {
//if available >= rate / 1000 {
let mut buffer = vec![0.0; samples];
for i in 0..samples {
for buffered_sample in buffer.iter_mut().take(samples) {
let mut sample = 0.0;
for ch in 0..3 {
@ -126,7 +128,7 @@ impl Steppable for Sn76489 {
sample += self.noise.get_sample();
}
buffer[i] = sample.clamp(-1.0, 1.0);
*buffered_sample = sample.clamp(-1.0, 1.0);
}
self.source.write_samples(system.clock, &buffer);
} else {

View File

@ -7,7 +7,7 @@ use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Tra
use moa_core::host::{Host, Audio};
use moa_core::host::audio::{SineWave};
const DEV_NAME: &'static str = "ym2612";
const DEV_NAME: &str = "ym2612";
const CHANNELS: usize = 8;
@ -101,22 +101,19 @@ impl Channel {
OperatorAlgorithm::A1 => {
let sample1 = self.operators[0].get_sample(0.0) + self.operators[1].get_sample(0.0);
let sample2 = self.operators[2].get_sample(sample1);
let sample3 = self.operators[3].get_sample(sample2);
sample3
self.operators[3].get_sample(sample2)
},
OperatorAlgorithm::A2 => {
let sample1 = self.operators[1].get_sample(0.0);
let sample2 = self.operators[2].get_sample(sample1);
let sample3 = self.operators[0].get_sample(0.0) + sample2;
let sample4 = self.operators[3].get_sample(sample3);
sample4
self.operators[3].get_sample(sample3)
},
OperatorAlgorithm::A3 => {
let sample1 = self.operators[0].get_sample(0.0);
let sample2 = self.operators[1].get_sample(sample1);
let sample3 = self.operators[2].get_sample(0.0);
let sample4 = self.operators[3].get_sample(sample2 + sample3);
sample4
self.operators[3].get_sample(sample2 + sample3)
},
OperatorAlgorithm::A4 => {
let sample1 = self.operators[0].get_sample(0.0);
@ -127,8 +124,7 @@ impl Channel {
},
OperatorAlgorithm::A5 => {
let sample1 = self.operators[0].get_sample(0.0);
let sample2 = self.operators[1].get_sample(sample1) + self.operators[2].get_sample(sample1) + self.operators[3].get_sample(sample1);
sample2
self.operators[1].get_sample(sample1) + self.operators[2].get_sample(sample1) + self.operators[3].get_sample(sample1)
},
OperatorAlgorithm::A6 => {
let sample1 = self.operators[0].get_sample(0.0);
@ -136,11 +132,10 @@ impl Channel {
sample2 + self.operators[2].get_sample(0.0) + self.operators[3].get_sample(0.0)
},
OperatorAlgorithm::A7 => {
let sample = self.operators[0].get_sample(0.0)
self.operators[0].get_sample(0.0)
+ self.operators[1].get_sample(0.0)
+ self.operators[2].get_sample(0.0)
+ self.operators[3].get_sample(0.0);
sample
+ self.operators[3].get_sample(0.0)
},
}
}
@ -240,7 +235,7 @@ impl Ym2612 {
self.channels[ch].operators[op].set_multiplier(frequency, multiplier)
},
reg if reg >= 0xA0 && reg <= 0xA2 => {
reg if (0xA0..=0xA2).contains(&reg) => {
let ch = (reg & 0x07) + (bank * 3);
self.channel_frequencies[ch].1 = (self.channel_frequencies[ch].1 & 0xFF00) | data as u16;
@ -249,13 +244,13 @@ impl Ym2612 {
self.channels[ch].set_frequency(frequency);
},
reg if reg >= 0xA4 && reg <= 0xA6 => {
reg if (0xA4..=0xA6).contains(&reg) => {
let ch = (reg & 0x07) - 4 + (bank * 3);
self.channel_frequencies[ch].1 = (self.channel_frequencies[ch].1 & 0xFF) | ((data as u16) & 0x07) << 8;
self.channel_frequencies[ch].0 = (data & 0x38) >> 3;
},
reg if reg >= 0xB0 && reg <= 0xB2 => {
reg if (0xB0..=0xB2).contains(&reg) => {
let ch = (reg & 0x07) + (bank * 3);
self.channels[ch].algorithm = match data & 0x07 {
0 => OperatorAlgorithm::A0,
@ -279,7 +274,7 @@ impl Ym2612 {
#[inline(always)]
pub fn fnumber_to_frequency(fnumber: (u8, u16)) -> f32 {
(fnumber.1 as f32 * 0.0264) * (2 as u32).pow(fnumber.0 as u32) as f32
(fnumber.1 as f32 * 0.0264) * 2_u32.pow(fnumber.0 as u32) as f32
}
#[inline(always)]
@ -313,7 +308,7 @@ impl Steppable for Ym2612 {
let samples = if available < rate / 1000 { available } else { rate / 1000 };
//if self.source.space_available() >= samples {
let mut buffer = vec![0.0; samples];
for i in 0..samples {
for buffered_sample in buffer.iter_mut().take(samples) {
let mut sample = 0.0;
for ch in 0..6 {
@ -330,9 +325,8 @@ impl Steppable for Ym2612 {
sample += self.channels[6].get_sample();
}
buffer[i] = sample.clamp(-1.0, 1.0);
*buffered_sample = sample.clamp(-1.0, 1.0);
}
//println!("synthesized: {:?}", buffer);
self.source.write_samples(system.clock, &buffer);
//}
@ -349,7 +343,7 @@ impl Addressable for Ym2612 {
match addr {
0 | 1 | 2 | 3 => {
// Read the status byte (busy/overflow)
data[0] = 0 | ((self.timer_a_overflow as u8) << 1) | (self.timer_b_overflow as u8);
data[0] = ((self.timer_a_overflow as u8) << 1) | (self.timer_b_overflow as u8);
}
_ => {
warn!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr);

View File

@ -1,42 +1,27 @@
use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Transmutable, warn, debug};
const DEV_NAME: &'static str = "z8530";
const DEV_NAME: &str = "z8530";
#[derive(Default)]
pub struct Z8530 {
}
impl Z8530 {
pub fn new() -> Self {
Self {
}
}
}
impl Addressable for Z8530 {
fn len(&self) -> usize {
0x10
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
match addr {
_ => {
warn!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr);
},
}
warn!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr);
debug!("{}: read from register {:x} of {:?}", DEV_NAME, addr, data);
Ok(())
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
debug!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]);
match addr {
_ => {
warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);
},
}
warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);
Ok(())
}
}
@ -44,7 +29,7 @@ impl Addressable for Z8530 {
impl Steppable for Z8530 {
fn step(&mut self, _system: &System) -> Result<ClockElapsed, Error> {
Ok(1_000_000_00)
Ok(1_000_000_000)
}
}

View File

@ -8,7 +8,7 @@ use moa_peripherals_motorola::MC68681;
pub fn build_computie<H: Host>(host: &H) -> Result<System, Error> {
let mut system = System::new();
let mut system = System::default();
let monitor = MemoryBlock::load("binaries/computie/monitor.bin")?;
system.add_addressable_device(0x00000000, wrap_transmutable(monitor))?;
@ -17,11 +17,11 @@ pub fn build_computie<H: Host>(host: &H) -> Result<System, Error> {
ram.load_at(0, "binaries/computie/kernel.bin")?;
system.add_addressable_device(0x00100000, wrap_transmutable(ram))?;
let mut ata = AtaDevice::new();
let mut ata = AtaDevice::default();
ata.load("binaries/computie/disk-with-partition-table.img")?;
system.add_addressable_device(0x00600000, wrap_transmutable(ata))?;
let mut serial = MC68681::new();
let mut serial = MC68681::default();
launch_terminal_emulator(serial.port_a.connect(host.create_pty()?)?);
launch_slip_connection(serial.port_b.connect(host.create_pty()?)?);
system.add_addressable_device(0x00700000, wrap_transmutable(serial))?;
@ -46,7 +46,7 @@ pub fn build_computie<H: Host>(host: &H) -> Result<System, Error> {
}
pub fn build_computie_k30<H: Host>(host: &H) -> Result<System, Error> {
let mut system = System::new();
let mut system = System::default();
let monitor = MemoryBlock::load("binaries/computie/monitor-68030.bin")?;
system.add_addressable_device(0x00000000, wrap_transmutable(monitor))?;
@ -55,11 +55,11 @@ pub fn build_computie_k30<H: Host>(host: &H) -> Result<System, Error> {
ram.load_at(0, "binaries/computie/kernel-68030.bin")?;
system.add_addressable_device(0x00100000, wrap_transmutable(ram))?;
let mut ata = AtaDevice::new();
let mut ata = AtaDevice::default();
ata.load("binaries/computie/disk-with-partition-table.img")?;
system.add_addressable_device(0x00600000, wrap_transmutable(ata))?;
let mut serial = MC68681::new();
let mut serial = MC68681::default();
launch_terminal_emulator(serial.port_a.connect(host.create_pty()?)?);
//launch_slip_connection(serial.port_b.connect(host.create_pty()?)?);
system.add_addressable_device(0x00700000, wrap_transmutable(serial))?;

View File

@ -16,7 +16,7 @@ const REG_S_CTRL2: Address = 0x19;
const REG_S_CTRL3: Address = 0x1F;
const DEV_NAME: &'static str = "genesis_controller";
const DEV_NAME: &str = "genesis_controller";
pub struct GenesisControllerPort {
/// Data contains bits:
@ -31,8 +31,8 @@ pub struct GenesisControllerPort {
s_ctrl: u8,
}
impl GenesisControllerPort {
pub fn new() -> Self {
impl Default for GenesisControllerPort {
fn default() -> Self {
Self {
buttons: HostData::new(0xffff),
ctrl: 0,
@ -41,7 +41,9 @@ impl GenesisControllerPort {
s_ctrl: 0,
}
}
}
impl GenesisControllerPort {
pub fn get_data(&mut self) -> u8 {
let inputs = self.buttons.get();
let th_state = (self.outputs & 0x40) != 0;
@ -118,19 +120,21 @@ pub struct GenesisControllers {
reset_timer: Clock,
}
impl GenesisControllers {
pub fn new() -> Self {
impl Default for GenesisControllers {
fn default() -> Self {
Self {
port_1: GenesisControllerPort::new(),
port_2: GenesisControllerPort::new(),
expansion: GenesisControllerPort::new(),
port_1: GenesisControllerPort::default(),
port_2: GenesisControllerPort::default(),
expansion: GenesisControllerPort::default(),
interrupt: HostData::new(false),
reset_timer: 0,
}
}
}
impl GenesisControllers {
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
let controller = GenesisControllers::new();
let controller = GenesisControllers::default();
let controller1 = Box::new(GenesisControllersUpdater(controller.port_1.buttons.clone(), controller.interrupt.clone()));
host.register_controller(ControllerDevice::A, controller1)?;

View File

@ -6,7 +6,7 @@ use moa_core::{warn, info};
use moa_core::{Bus, Signal, Error, Address, Addressable, Transmutable};
const DEV_NAME: &'static str = "coprocessor";
const DEV_NAME: &str = "coprocessor";
pub struct CoprocessorCoordinator {
bus_request: Signal<bool>,

View File

@ -59,10 +59,10 @@ const MODE4_BF_SHADOW_HIGHLIGHT: u8 = 0x08;
const DEV_NAME: &'static str = "ym7101";
const DEV_NAME: &str = "ym7101";
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DmaType {
None,
Memory,
@ -70,7 +70,7 @@ pub enum DmaType {
Copy,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Memory {
Vram,
Cram,
@ -97,8 +97,8 @@ pub struct Ym7101Memory {
pub ctrl_port_buffer: Option<u16>,
}
impl Ym7101Memory {
pub fn new() -> Self {
impl Default for Ym7101Memory {
fn default() -> Self {
Self {
vram: [0; 0x10000],
cram: [0; 128],
@ -119,8 +119,9 @@ impl Ym7101Memory {
ctrl_port_buffer: None,
}
}
}
impl Ym7101Memory {
#[inline(always)]
fn read_beu16(&self, target: Memory, addr: usize) -> u16 {
let addr = match target {
@ -148,7 +149,7 @@ impl Ym7101Memory {
pub fn setup_transfer(&mut self, first: u16, second: u16) {
self.ctrl_port_buffer = None;
self.transfer_type = ((((first & 0xC000) >> 14) | ((second & 0x00F0) >> 2))) as u8;
self.transfer_type = (((first & 0xC000) >> 14) | ((second & 0x00F0) >> 2)) as u8;
self.transfer_dest_addr = ((first & 0x3FFF) | ((second & 0x0003) << 14)) as u32;
self.transfer_target = match self.transfer_type & 0x0E {
0 => Memory::Vram,
@ -268,14 +269,14 @@ impl Ym7101Memory {
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ColourMode {
Normal,
Shadow,
Highlight,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Scroll {
ScrollA,
ScrollB,
@ -314,11 +315,11 @@ pub struct Ym7101State {
pub current_y: i32,
}
impl Ym7101State {
pub fn new() -> Self {
impl Default for Ym7101State {
fn default() -> Self {
Self {
status: 0x3400 | STATUS_FIFO_EMPTY,
memory: Ym7101Memory::new(),
memory: Ym7101Memory::default(),
mode_1: 0,
mode_2: 0,
@ -349,7 +350,9 @@ impl Ym7101State {
current_y: 0,
}
}
}
impl Ym7101State {
#[inline(always)]
fn hsync_int_enabled(&self) -> bool {
(self.mode_1 & MODE1_BF_HSYNC_INTERRUPT) != 0
@ -470,13 +473,11 @@ impl Ym7101State {
let offset = pattern_addr as usize + line * 4 + column;
let second = x % 2 == 1;
let value = if (!h_rev && !second) || (h_rev && second) {
if (!h_rev && !second) || (h_rev && second) {
(palette, self.memory.vram[offset] >> 4)
} else {
(palette, self.memory.vram[offset] & 0x0f)
};
value
}
}
pub fn draw_frame(&mut self, frame: &mut Frame) {
@ -685,10 +686,10 @@ impl Ym7101 {
Ym7101 {
queue,
state: Ym7101State::new(),
state: Ym7101State::default(),
sn_sound,
external_interrupt,
frame_complete: EdgeSignal::new(),
frame_complete: EdgeSignal::default(),
}
}
@ -779,8 +780,8 @@ impl Addressable for Ym7101 {
// Read from Control Port
0x04 | 0x05 | 0x06 | 0x07 => {
debug!("{}: read status byte {:x}", DEV_NAME, self.state.status);
for i in 0..data.len() {
data[i] = if (addr % 2) == 0 {
for item in data {
*item = if (addr % 2) == 0 {
(self.state.status >> 8) as u8
} else {
(self.state.status & 0x00FF) as u8
@ -873,18 +874,18 @@ impl Inspectable for Ym7101 {
impl Ym7101State {
pub fn dump_state(&self) {
println!("");
println!();
println!("Mode1: {:#04x}", self.mode_1);
println!("Mode2: {:#04x}", self.mode_2);
println!("Mode3: {:#04x}", self.mode_3);
println!("Mode4: {:#04x}", self.mode_4);
println!("");
println!();
println!("Scroll A : {:#06x}", self.scroll_a_addr);
println!("Window : {:#06x}", self.window_addr);
println!("Scroll B : {:#06x}", self.scroll_b_addr);
println!("HScroll : {:#06x}", self.hscroll_addr);
println!("Sprites : {:#06x}", self.sprites_addr);
println!("");
println!();
println!("DMA type : {:?}", self.memory.transfer_type);
println!("DMA Source: {:#06x}", self.memory.transfer_src_addr);
println!("DMA Dest : {:#06x}", self.memory.transfer_dest_addr);

View File

@ -3,7 +3,7 @@ use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
use moa_core::{System, Error, Signal, MemoryBlock, AddressRepeater, Bus, BusPort, Address, Addressable, Debuggable, wrap_transmutable};
use moa_core::{System, Error, Signal, MemoryBlock, Bus, BusPort, Address, Addressable, Debuggable, wrap_transmutable};
use moa_core::host::Host;
use moa_m68k::{M68k, M68kType};
@ -22,8 +22,8 @@ pub struct SegaGenesisOptions {
pub rom_data: Option<Vec<u8>>,
}
impl SegaGenesisOptions {
pub fn new() -> Self {
impl Default for SegaGenesisOptions {
fn default() -> Self {
Self {
rom: "".to_string(),
rom_data: None,
@ -32,7 +32,7 @@ impl SegaGenesisOptions {
}
pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) -> Result<System, Error> {
let mut system = System::new();
let mut system = System::default();
let rom_data = if options.rom_data.is_some() {
mem::take(&mut options.rom_data).unwrap()
@ -75,14 +75,14 @@ pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) ->
let coproc_register = wrap_transmutable(CoprocessorBankRegister::new(bank_register.clone()));
let coproc_area = wrap_transmutable(CoprocessorBankArea::new(bank_register, system.bus.clone()));
let coproc_bus = Rc::new(RefCell::new(Bus::new()));
let coproc_bus = Rc::new(RefCell::new(Bus::default()));
coproc_bus.borrow_mut().set_ignore_unmapped(true);
coproc_bus.borrow_mut().insert(0x0000, coproc_ram.clone());
coproc_bus.borrow_mut().insert(0x4000, coproc_ym_sound.clone());
coproc_bus.borrow_mut().insert(0x6000, coproc_register.clone());
coproc_bus.borrow_mut().insert(0x7f11, coproc_sn_sound.clone());
coproc_bus.borrow_mut().insert(0x8000, coproc_area);
let mut coproc = Z80::new(Z80Type::Z80, 3_579_545, BusPort::new(0, 16, 8, coproc_bus.clone()));
let mut coproc = Z80::new(Z80Type::Z80, 3_579_545, BusPort::new(0, 16, 8, coproc_bus));
coproc.set_debugging(true);
let mut reset = coproc.reset.clone();
let mut bus_request = coproc.bus_request.clone();

View File

@ -11,8 +11,9 @@ const ENABLE: u8 = 0x10;
const Q6: u8 = 0x40;
const Q7: u8 = 0x80;
const DEV_NAME: &'static str = "iwm";
const DEV_NAME: &str = "iwm";
#[derive(Default)]
pub struct IWM {
state: u8,
mode: u8,
@ -20,14 +21,6 @@ pub struct IWM {
}
impl IWM {
pub fn new() -> Self {
Self {
state: 0,
mode: 0,
handshake: 0,
}
}
pub fn flip_switches(&mut self, addr: Address) {
let mask = 1 << (addr >> 1);
@ -102,8 +95,8 @@ impl Addressable for IWM {
impl Steppable for IWM {
fn step(&mut self, _system: &System) -> Result<ClockElapsed, Error> {
Ok(1_000_000_00)
// TODO implement
Ok(1_000_000_000)
}
}

View File

@ -8,7 +8,7 @@ use moa_peripherals_mos::Mos6522;
use moa_peripherals_zilog::Z8530;
use crate::peripherals::iwm::IWM;
const DEV_NAME: &'static str = "mac";
const DEV_NAME: &str = "mac";
pub struct Mainboard {
@ -23,13 +23,13 @@ pub struct Mainboard {
impl Mainboard {
pub fn create(ram: TransmutableBox, rom: TransmutableBox) -> Result<Self, Error> {
let scc1 = Z8530::new();
let scc2 = Z8530::new();
let iwm = IWM::new();
let via = Mos6522::new();
let phase_read = PhaseRead::new();
let scc1 = Z8530::default();
let scc2 = Z8530::default();
let iwm = IWM::default();
let via = Mos6522::default();
let phase_read = PhaseRead::default();
let lower_bus = Rc::new(RefCell::new(Bus::new()));
let lower_bus = Rc::new(RefCell::new(Bus::default()));
let mainboard = Self {
lower_bus: lower_bus.clone(),
@ -72,17 +72,17 @@ impl Addressable for Mainboard {
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
if addr < 0x800000 {
self.lower_bus.borrow_mut().read(addr, data)
} else if addr >= 0x900000 && addr < 0xA00000 {
} else if (0x900000..0xA00000).contains(&addr) {
self.scc1.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xB00000 && addr < 0xC00000 {
} else if (0xB00000..0xC00000).contains(&addr) {
self.scc2.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xD00000 && addr < 0xE00000 {
} else if (0xD00000..0xE00000).contains(&addr) {
self.iwm.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xE80000 && addr < 0xF00000 {
} else if (0xE80000..0xF00000).contains(&addr) {
self.via.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xF00000 && addr < 0xF80000 {
} else if (0xF00000..0xF80000).contains(&addr) {
self.phase_read.read(addr, data)
} else if addr >= 0xF80000 && addr < 0xF80010 {
} else if (0xF80000..0xF80010).contains(&addr) {
// Debugger
Ok(())
} else {
@ -93,15 +93,15 @@ impl Addressable for Mainboard {
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
if addr < 0x800000 {
self.lower_bus.borrow_mut().write(addr, data)
} else if addr >= 0x900000 && addr < 0xA00000 {
} else if (0x900000..0xA00000).contains(&addr) {
self.scc1.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xB00000 && addr < 0xC00000 {
} else if (0xB00000..0xC00000).contains(&addr) {
self.scc2.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xD00000 && addr < 0xE00000 {
} else if (0xD00000..0xE00000).contains(&addr) {
self.iwm.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xE80000 && addr < 0xF00000 {
} else if (0xE80000..0xF00000).contains(&addr) {
self.via.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xF00000 && addr < 0xF80000 {
} else if (0xF00000..0xF80000).contains(&addr) {
self.phase_read.write(addr, data)
} else {
Err(Error::new(&format!("Error writing address {:#010x}", addr)))
@ -136,17 +136,11 @@ impl Transmutable for Mainboard {
#[derive(Default)]
pub struct PhaseRead {
}
impl PhaseRead {
pub fn new() -> Self {
Self {
}
}
}
impl Addressable for PhaseRead {
fn len(&self) -> usize {
0x80000

View File

@ -9,7 +9,7 @@ use crate::peripherals::mainboard::Mainboard;
pub fn build_macintosh_512k<H: Host>(host: &mut H) -> Result<System, Error> {
let mut system = System::new();
let mut system = System::default();
/*
use crate::peripherals::mos6522::Mos6522;

View File

@ -9,7 +9,7 @@ use super::keymap;
use super::charset::CharacterGenerator;
const DEV_NAME: &'static str = "model1";
const DEV_NAME: &str = "model1";
const SCREEN_SIZE: (u32, u32) = (384, 128);
pub struct Model1Peripherals {
@ -65,7 +65,7 @@ impl Addressable for Model1Peripherals {
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
if addr >= 0x20 && addr <= 0xA0 {
if (0x20..=0xA0).contains(&addr) {
let offset = addr - 0x20;
data[0] = 0;
if (offset & 0x01) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[0]; }
@ -77,7 +77,7 @@ impl Addressable for Model1Peripherals {
if (offset & 0x40) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[6]; }
if (offset & 0x80) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[7]; }
//info!("{}: read from keyboard {:x} of {:?}", DEV_NAME, addr, data);
} else if addr >= 0x420 && addr <= 0x820 {
} else if (0x420..=0x820).contains(&addr) {
data[0] = self.video_mem[addr as usize - 0x420];
} else {
warn!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr);
@ -88,7 +88,7 @@ impl Addressable for Model1Peripherals {
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
debug!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]);
if addr >= 0x420 && addr < 0x820 {
if (0x420..0x820).contains(&addr) {
self.video_mem[addr as usize - 0x420] = data[0];
} else {
warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);

View File

@ -13,8 +13,8 @@ pub struct Trs80Options {
pub frequency: u32,
}
impl Trs80Options {
pub fn new() -> Self {
impl Default for Trs80Options {
fn default() -> Self {
Self {
rom: "binaries/trs80/level2.rom".to_string(),
memory: 0xC000,
@ -25,7 +25,7 @@ impl Trs80Options {
pub fn build_trs80<H: Host>(host: &mut H, options: Trs80Options) -> Result<System, Error> {
let mut system = System::new();
let mut system = System::default();
let mut rom = MemoryBlock::new(vec![0; 0x3000]);
//rom.load_at(0x0000, "binaries/trs80/level1.rom")?;