mirror of
https://github.com/transistorfet/moa.git
synced 2025-01-02 06:30:45 +00:00
Fixed all clippy warnings
This commit is contained in:
parent
0ac3f48b64
commit
7bdd63bc76
1
.clippy.toml
Normal file
1
.clippy.toml
Normal file
@ -0,0 +1 @@
|
||||
msrv = "1.60.0"
|
@ -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(())
|
||||
|
@ -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>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ErrorType {
|
||||
Assertion,
|
||||
Emulator,
|
||||
|
@ -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),
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Key {
|
||||
A,
|
||||
B,
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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, ®)?, 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, ®)?, 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)))
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
},
|
||||
|
@ -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)
|
||||
},
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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!();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
pub mod circularbuf;
|
||||
|
||||
#[cfg(feature = "tty")]
|
||||
pub mod tty;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
use moa_minifb;
|
||||
use moa_macintosh::build_macintosh_512k;
|
||||
|
||||
fn main() {
|
||||
|
@ -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)))?;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
|
@ -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 });
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(®) => {
|
||||
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(®) => {
|
||||
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(®) => {
|
||||
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);
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))?;
|
||||
|
@ -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)?;
|
||||
|
@ -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>,
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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")?;
|
||||
|
Loading…
Reference in New Issue
Block a user