mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-29 15:56:19 +00:00
Added Inspectable trait for getting debug data from peripherals
This commit is contained in:
parent
7fe83ad4a3
commit
31ff828f15
@ -92,6 +92,16 @@ impl Debugger {
|
|||||||
//self.port.dump_memory(self.state.ssp as Address, 0x40 as Address);
|
//self.port.dump_memory(self.state.ssp as Address, 0x40 as Address);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dp" | "dump_peripheral" => {
|
||||||
|
if args.len() < 2 {
|
||||||
|
println!("Usage: dp <device_name> [<device specific arguments>]");
|
||||||
|
} else {
|
||||||
|
let device = system.devices.get(args[1]).ok_or_else(|| Error::new(&format!("No device named {}", args[1])))?;
|
||||||
|
device.borrow_mut().as_inspectable()
|
||||||
|
.ok_or_else(|| Error::new("That device is not inspectable"))?
|
||||||
|
.inspect(system, &args[2..])?;
|
||||||
|
}
|
||||||
|
},
|
||||||
"dis" | "disassemble" => {
|
"dis" | "disassemble" => {
|
||||||
let addr = if args.len() > 1 {
|
let addr = if args.len() > 1 {
|
||||||
Address::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?
|
Address::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?
|
||||||
@ -156,7 +166,7 @@ impl Debugger {
|
|||||||
fn check_repeat_arg(&mut self, args: &[&str]) -> Result<(), Error> {
|
fn check_repeat_arg(&mut self, args: &[&str]) -> Result<(), Error> {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?;
|
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?;
|
||||||
self.last_command = Some("c".to_string());
|
self.last_command = Some(args[0].to_string());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -31,16 +31,6 @@ pub trait Interruptable {
|
|||||||
//fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error>;
|
//fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A device that can debugged using the built-in debugger
|
|
||||||
pub trait Debuggable {
|
|
||||||
fn add_breakpoint(&mut self, addr: Address);
|
|
||||||
fn remove_breakpoint(&mut self, addr: Address);
|
|
||||||
|
|
||||||
fn print_current_step(&mut self, system: &System) -> Result<(), Error>;
|
|
||||||
fn print_disassembly(&mut self, addr: Address, count: usize);
|
|
||||||
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A device that can be addressed to read data from or write data to the device.
|
/// A device that can be addressed to read data from or write data to the device.
|
||||||
pub trait Addressable {
|
pub trait Addressable {
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
@ -170,6 +160,22 @@ pub fn write_leu32(data: &mut [u8], value: u32) -> &mut [u8] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A device (cpu) that can debugged using the built-in debugger
|
||||||
|
pub trait Debuggable {
|
||||||
|
fn add_breakpoint(&mut self, addr: Address);
|
||||||
|
fn remove_breakpoint(&mut self, addr: Address);
|
||||||
|
|
||||||
|
fn print_current_step(&mut self, system: &System) -> Result<(), Error>;
|
||||||
|
fn print_disassembly(&mut self, addr: Address, count: usize);
|
||||||
|
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A device (peripheral) that can inspected using the built-in debugger
|
||||||
|
pub trait Inspectable {
|
||||||
|
fn inspect(&mut self, system: &System, args: &[&str]) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait Transmutable {
|
pub trait Transmutable {
|
||||||
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
||||||
None
|
None
|
||||||
@ -186,6 +192,10 @@ pub trait Transmutable {
|
|||||||
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
|
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_inspectable(&mut self) -> Option<&mut dyn Inspectable> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TransmutableBox = Rc<RefCell<Box<dyn Transmutable>>>;
|
pub type TransmutableBox = Rc<RefCell<Box<dyn Transmutable>>>;
|
||||||
|
@ -17,9 +17,11 @@ use crate::host::traits::{Host};
|
|||||||
pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
||||||
let mut system = System::new();
|
let mut system = System::new();
|
||||||
|
|
||||||
|
//let mut rom = MemoryBlock::load("binaries/genesis/GenTestV3.0.bin").unwrap();
|
||||||
|
let mut rom = MemoryBlock::load("binaries/genesis/ComradeOj's tiny demo.bin").unwrap();
|
||||||
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic The Hedgehog (W) (REV 00) [!].bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic The Hedgehog (W) (REV 00) [!].bin").unwrap();
|
||||||
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic The Hedgehog (W) (REV 01) [!].bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic The Hedgehog (W) (REV 01) [!].bin").unwrap();
|
||||||
let mut rom = MemoryBlock::load("binaries/genesis/Sonic the Hedgehog 2 (JUE) [!].bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic the Hedgehog 2 (JUE) [!].bin").unwrap();
|
||||||
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic the Hedgehog 3 (U) [!].bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Sonic the Hedgehog 3 (U) [!].bin").unwrap();
|
||||||
//let mut rom = MemoryBlock::load("binaries/genesis/Earthworm Jim (U) [h1].bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Earthworm Jim (U) [h1].bin").unwrap();
|
||||||
//let mut rom = MemoryBlock::load("binaries/genesis/Home Alone (beta).bin").unwrap();
|
//let mut rom = MemoryBlock::load("binaries/genesis/Home Alone (beta).bin").unwrap();
|
||||||
@ -47,7 +49,7 @@ pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
|||||||
let bus_request = coproc.bus_request.clone();
|
let bus_request = coproc.bus_request.clone();
|
||||||
|
|
||||||
system.add_addressable_device(0x00a00000, coproc_mem)?;
|
system.add_addressable_device(0x00a00000, coproc_mem)?;
|
||||||
system.add_device("coproc", wrap_transmutable(coproc))?;
|
//system.add_device("coproc", wrap_transmutable(coproc))?;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
|||||||
system.add_addressable_device(0x00a11000, wrap_transmutable(coproc)).unwrap();
|
system.add_addressable_device(0x00a11000, wrap_transmutable(coproc)).unwrap();
|
||||||
|
|
||||||
let vdp = genesis::ym7101::Ym7101::new(host, interrupt);
|
let vdp = genesis::ym7101::Ym7101::new(host, interrupt);
|
||||||
system.add_addressable_device(0x00c00000, wrap_transmutable(vdp)).unwrap();
|
system.add_peripheral("vdp", 0x00c00000, wrap_transmutable(vdp)).unwrap();
|
||||||
|
|
||||||
|
|
||||||
let mut cpu = M68k::new(M68kType::MC68000, 7_670_454, BusPort::new(0, 24, 16, system.bus.clone()));
|
let mut cpu = M68k::new(M68kType::MC68000, 7_670_454, BusPort::new(0, 24, 16, system.bus.clone()));
|
||||||
@ -79,6 +81,8 @@ pub fn build_genesis<H: Host>(host: &mut H) -> Result<System, Error> {
|
|||||||
|
|
||||||
//cpu.add_breakpoint(0x43c2);
|
//cpu.add_breakpoint(0x43c2);
|
||||||
|
|
||||||
|
//cpu.add_breakpoint(0x21a);
|
||||||
|
|
||||||
system.add_interruptable_device("cpu", wrap_transmutable(cpu)).unwrap();
|
system.add_interruptable_device("cpu", wrap_transmutable(cpu)).unwrap();
|
||||||
|
|
||||||
Ok(system)
|
Ok(system)
|
||||||
|
@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::devices::{Clock, ClockElapsed, Address, Addressable, Steppable, Transmutable, read_beu16, read_beu32, write_beu16};
|
use crate::devices::{Clock, ClockElapsed, Address, Addressable, Steppable, Inspectable, Transmutable, read_beu16, read_beu32, write_beu16};
|
||||||
use crate::host::traits::{Host, BlitableSurface, SharedData};
|
use crate::host::traits::{Host, BlitableSurface, SharedData};
|
||||||
use crate::host::gfx::{Frame, FrameSwapper};
|
use crate::host::gfx::{Frame, FrameSwapper};
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ const MODE1_BF_ENABLE_HV_COUNTER: u8 = 0x02;
|
|||||||
const MODE1_BF_HSYNC_INTERRUPT: u8 = 0x10;
|
const MODE1_BF_HSYNC_INTERRUPT: u8 = 0x10;
|
||||||
|
|
||||||
const MODE2_BF_V_CELL_MODE: u8 = 0x08;
|
const MODE2_BF_V_CELL_MODE: u8 = 0x08;
|
||||||
|
const MODE2_BF_DMA_ENABLED: u8 = 0x10;
|
||||||
const MODE2_BF_VSYNC_INTERRUPT: u8 = 0x20;
|
const MODE2_BF_VSYNC_INTERRUPT: u8 = 0x20;
|
||||||
|
|
||||||
const MODE3_BF_EXTERNAL_INTERRUPT: u8 = 0x08;
|
const MODE3_BF_EXTERNAL_INTERRUPT: u8 = 0x08;
|
||||||
@ -172,11 +173,11 @@ impl Ym7101State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_transfer_target_mut(&mut self) -> &mut [u8] {
|
pub fn get_transfer_target_mut(&mut self) -> (&mut [u8], usize) {
|
||||||
match self.transfer_target {
|
match self.transfer_target {
|
||||||
TargetType::Vram => &mut self.vram,
|
TargetType::Vram => (&mut self.vram, 0x10000),
|
||||||
TargetType::Cram => &mut self.cram,
|
TargetType::Cram => (&mut self.cram, 128),
|
||||||
TargetType::Vsram => &mut self.vsram,
|
TargetType::Vsram => (&mut self.vsram, 80),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +208,14 @@ impl Ym7101State {
|
|||||||
((self.regs[REG_WINDOW_ADDR] as u16) << 10) as u32
|
((self.regs[REG_WINDOW_ADDR] as u16) << 10) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_vram_sprites_addr(&self) -> u32 {
|
||||||
|
((self.regs[REG_SPRITES_ADDR] as u16) << 9) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_vram_hscroll_addr(&self) -> u32 {
|
||||||
|
((self.regs[REG_HSCROLL_ADDR] as u16) << 10) as u32
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_palette_colour(&self, palette: u8, colour: u8) -> u32 {
|
pub fn get_palette_colour(&self, palette: u8, colour: u8) -> u32 {
|
||||||
if colour == 0 {
|
if colour == 0 {
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
@ -305,7 +314,7 @@ impl Ym7101State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_sprites(&mut self, frame: &mut Frame) {
|
pub fn draw_sprites(&mut self, frame: &mut Frame) {
|
||||||
let sprite_table = (self.regs[REG_SPRITES_ADDR] as usize) << 9;
|
let sprite_table = self.get_vram_sprites_addr() as usize;
|
||||||
let (cells_h, cells_v) = self.get_screen_size();
|
let (cells_h, cells_v) = self.get_screen_size();
|
||||||
let (pos_limit_h, pos_limit_v) = (if cells_h == 32 { 383 } else { 447 }, if cells_v == 28 { 351 } else { 367 });
|
let (pos_limit_h, pos_limit_v) = (if cells_h == 32 { 383 } else { 447 }, if cells_v == 28 { 351 } else { 367 });
|
||||||
|
|
||||||
@ -323,7 +332,7 @@ impl Ym7101State {
|
|||||||
let (size_h, size_v) = (((size >> 2) & 0x03) as u16 + 1, (size & 0x03) as u16 + 1);
|
let (size_h, size_v) = (((size >> 2) & 0x03) as u16 + 1, (size & 0x03) as u16 + 1);
|
||||||
let h_rev = (pattern_name & 0x0800) != 0;
|
let h_rev = (pattern_name & 0x0800) != 0;
|
||||||
let v_rev = (pattern_name & 0x1000) != 0;
|
let v_rev = (pattern_name & 0x1000) != 0;
|
||||||
println!("i: {} ({} {}) {:x} ({}, {}) {:x}", i, h_pos, v_pos, size, size_h, size_v, pattern_name);
|
//println!("i: {} ({} {}) {:x} ({}, {}) {:x}", i, h_pos, v_pos, size, size_h, size_v, pattern_name);
|
||||||
|
|
||||||
for ih in 0..size_h {
|
for ih in 0..size_h {
|
||||||
for iv in 0..size_v {
|
for iv in 0..size_v {
|
||||||
@ -432,6 +441,10 @@ impl Transmutable for Ym7101 {
|
|||||||
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_inspectable(&mut self) -> Option<&mut dyn Inspectable> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Steppable for Ym7101 {
|
impl Steppable for Ym7101 {
|
||||||
@ -501,7 +514,7 @@ impl Steppable for Ym7101 {
|
|||||||
// Print Sprite
|
// Print Sprite
|
||||||
let mut swapper = self.swapper.lock().unwrap();
|
let mut swapper = self.swapper.lock().unwrap();
|
||||||
self.state.draw_background(&mut swapper.current);
|
self.state.draw_background(&mut swapper.current);
|
||||||
let sprite_table = (self.state.regs[REG_SPRITES_ADDR] as usize) << 9;
|
let sprite_table = self.get_vram_sprites_addr();
|
||||||
let (cells_h, cells_v) = self.state.get_screen_size();
|
let (cells_h, cells_v) = self.state.get_screen_size();
|
||||||
let sprite = 0;
|
let sprite = 0;
|
||||||
println!("{:?}", &self.state.vram[(sprite_table + (sprite * 8))..(sprite_table + (sprite * 8) + 8)].iter().map(|byte| format!("{:02x}", byte)).collect::<Vec<String>>());
|
println!("{:?}", &self.state.vram[(sprite_table + (sprite * 8))..(sprite_table + (sprite * 8) + 8)].iter().map(|byte| format!("{:02x}", byte)).collect::<Vec<String>>());
|
||||||
@ -530,7 +543,7 @@ impl Steppable for Ym7101 {
|
|||||||
//swapper.current.blit(16, 8, PatternIterator::new(&self.state, 0x405 * 32, 3, false, false), 8, 8);
|
//swapper.current.blit(16, 8, PatternIterator::new(&self.state, 0x405 * 32, 3, false, false), 8, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.state.transfer_run != DmaType::None {
|
if self.state.transfer_run != DmaType::None && (self.state.regs[REG_MODE_SET_2] & MODE2_BF_DMA_ENABLED) != 0 {
|
||||||
// TODO we will just do the full dma transfer here, but it really should be stepped
|
// TODO we will just do the full dma transfer here, but it really should be stepped
|
||||||
|
|
||||||
match self.state.transfer_run {
|
match self.state.transfer_run {
|
||||||
@ -553,9 +566,9 @@ impl Steppable for Ym7101 {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let addr = self.state.transfer_addr;
|
let addr = self.state.transfer_addr;
|
||||||
let target = self.state.get_transfer_target_mut();
|
let (target, length) = self.state.get_transfer_target_mut();
|
||||||
target[addr as usize] = data[0];
|
target[(addr as usize) % length] = data[0];
|
||||||
target[addr as usize + 1] = data[1];
|
target[(addr as usize + 1) % length] = data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
||||||
@ -606,9 +619,9 @@ impl Addressable for Ym7101 {
|
|||||||
0x00 | 0x02 => {
|
0x00 | 0x02 => {
|
||||||
{
|
{
|
||||||
let addr = self.state.transfer_addr;
|
let addr = self.state.transfer_addr;
|
||||||
let target = self.state.get_transfer_target_mut();
|
let (target, length) = self.state.get_transfer_target_mut();
|
||||||
for i in 0..data.len() {
|
for i in 0..data.len() {
|
||||||
data[i] = target[addr as usize + i];
|
data[i] = target[(addr as usize + i) % length];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
||||||
@ -636,13 +649,13 @@ impl Addressable for Ym7101 {
|
|||||||
self.state.transfer_fill = if data.len() >= 2 { read_beu16(data) } else { data[0] as u16 };
|
self.state.transfer_fill = if data.len() >= 2 { read_beu16(data) } else { data[0] as u16 };
|
||||||
self.state.set_dma_mode(DmaType::Fill);
|
self.state.set_dma_mode(DmaType::Fill);
|
||||||
} else {
|
} else {
|
||||||
debug!("{}: data port write {} bytes to {:?}:{:x} with {:?}", DEV_NAME, data.len(), self.state.transfer_target, self.state.transfer_addr, data);
|
info!("{}: data port write {} bytes to {:?}:{:x} with {:?}", DEV_NAME, data.len(), self.state.transfer_target, self.state.transfer_addr, data);
|
||||||
|
|
||||||
{
|
{
|
||||||
let addr = self.state.transfer_addr as usize;
|
let addr = self.state.transfer_addr as usize;
|
||||||
let target = self.state.get_transfer_target_mut();
|
let (target, length) = self.state.get_transfer_target_mut();
|
||||||
for i in 0..data.len() {
|
for i in 0..data.len() {
|
||||||
target[addr + i] = data[i];
|
target[(addr + i) % length] = data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32;
|
||||||
@ -651,7 +664,7 @@ impl Addressable for Ym7101 {
|
|||||||
|
|
||||||
// Write to Control Port
|
// Write to Control Port
|
||||||
0x04 | 0x06 => {
|
0x04 | 0x06 => {
|
||||||
debug!("{}: write {} bytes to port {:x} with data {:?}", DEV_NAME, data.len(), addr, data);
|
info!("{}: write {} bytes to port {:x} with data {:?}", DEV_NAME, data.len(), addr, data);
|
||||||
|
|
||||||
let value = read_beu16(data);
|
let value = read_beu16(data);
|
||||||
if (value & 0xC000) == 0x8000 {
|
if (value & 0xC000) == 0x8000 {
|
||||||
@ -679,3 +692,55 @@ impl Addressable for Ym7101 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Inspectable for Ym7101 {
|
||||||
|
fn inspect(&mut self, system: &System, args: &[&str]) -> Result<(), Error> {
|
||||||
|
let cmd = if args.len() > 0 { args[0] } else { "state" };
|
||||||
|
|
||||||
|
match cmd {
|
||||||
|
"" | "state" => {
|
||||||
|
self.state.dump_state();
|
||||||
|
},
|
||||||
|
"vram" => {
|
||||||
|
self.state.dump_vram();
|
||||||
|
},
|
||||||
|
_ => { },
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Ym7101State {
|
||||||
|
pub fn dump_state(&self) {
|
||||||
|
println!("");
|
||||||
|
println!("Mode1: {:#04x}", self.regs[REG_MODE_SET_1]);
|
||||||
|
println!("Mode2: {:#04x}", self.regs[REG_MODE_SET_2]);
|
||||||
|
println!("Mode3: {:#04x}", self.regs[REG_MODE_SET_3]);
|
||||||
|
println!("Mode4: {:#04x}", self.regs[REG_MODE_SET_4]);
|
||||||
|
println!("");
|
||||||
|
println!("Scroll A : {:#06x}", self.get_vram_scroll_a_addr());
|
||||||
|
println!("Window : {:#06x}", self.get_vram_window_addr());
|
||||||
|
println!("Scroll B : {:#06x}", self.get_vram_scroll_b_addr());
|
||||||
|
println!("HScroll : {:#06x}", self.get_vram_hscroll_addr());
|
||||||
|
println!("Sprites : {:#06x}", self.get_vram_sprites_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump_vram(&self) {
|
||||||
|
let mut count = 65536;
|
||||||
|
let mut addr = 0;
|
||||||
|
while count > 0 {
|
||||||
|
let mut line = format!("{:#010x}: ", addr);
|
||||||
|
|
||||||
|
let to = if count < 16 { count / 2 } else { 8 };
|
||||||
|
for _ in 0..to {
|
||||||
|
let word = ((self.vram[addr] as u16) << 8) | self.vram[addr + 1] as u16;
|
||||||
|
line += &format!("{:#06x} ", word);
|
||||||
|
addr += 2;
|
||||||
|
count -= 2;
|
||||||
|
}
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,14 @@ impl System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
|
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
|
||||||
|
self.add_peripheral(&format!("mem{:x}", addr), addr, device)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_peripheral(&mut self, name: &str, addr: Address, device: TransmutableBox) -> Result<(), Error> {
|
||||||
let length = device.borrow_mut().as_addressable().unwrap().len();
|
let length = device.borrow_mut().as_addressable().unwrap().len();
|
||||||
self.bus.borrow_mut().insert(addr, length, device.clone());
|
self.bus.borrow_mut().insert(addr, length, device.clone());
|
||||||
self.try_queue_device(device.clone());
|
self.try_queue_device(device.clone());
|
||||||
self.devices.insert(format!("mem{:x}", addr), device);
|
self.devices.insert(name.to_string(), device);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user