Change to a command based storage card
This commit is contained in:
parent
8c0b923455
commit
0b1a8e1398
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -178,9 +178,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
|
||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@ -190,9 +190,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
|
||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@ -205,15 +205,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
|
||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
|
||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -345,9 +345,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
@ -436,6 +436,7 @@ name = "m68k_emu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"bitvec",
|
||||
"derive-try-from-primitive",
|
||||
"elf",
|
||||
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.66"
|
||||
bitflags = "1.3.2"
|
||||
bitvec = "1.0.0"
|
||||
derive-try-from-primitive = "1.0.0"
|
||||
elf = "0.7.0"
|
||||
|
131
src/storage.rs
131
src/storage.rs
@ -1,62 +1,80 @@
|
||||
use std::{fmt::Display, fs::File, io::Read};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use human_repr::HumanCount;
|
||||
use nullable_result::NullableResult;
|
||||
use serde::Deserialize;
|
||||
use toml::Value;
|
||||
|
||||
use crate::{
|
||||
card::{u32_get_be_byte, u32_set_be_byte, Card},
|
||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card},
|
||||
m68k::BusError,
|
||||
register,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use bitflags::bitflags;
|
||||
use human_repr::HumanCount;
|
||||
use nullable_result::NullableResult;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{Read, Seek, SeekFrom},
|
||||
};
|
||||
use toml::Value;
|
||||
|
||||
const SECTOR_SIZE: usize = 256;
|
||||
const SECTOR_SIZE: u64 = 512;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Config {
|
||||
image: Option<String>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct Status: u16 {
|
||||
const BUSY = 0b00000001;
|
||||
const DATA_READY = 0b00000010;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Storage {
|
||||
data: Vec<u8>,
|
||||
file: Option<(File, String)>,
|
||||
read_data: VecDeque<u8>,
|
||||
sector: u32,
|
||||
offset: usize,
|
||||
file_name: Option<String>,
|
||||
count: u32,
|
||||
status: Status,
|
||||
}
|
||||
|
||||
// Registers
|
||||
// 0x0-0x4: Sector
|
||||
// 0x4-0x8: Sector count
|
||||
// 0x8-0xA: Command (W) / Status(R)
|
||||
// 0xA-0xC: Data
|
||||
|
||||
impl Card for Storage {
|
||||
fn new(data: Value) -> anyhow::Result<Self> {
|
||||
let file_name = data.try_into::<Config>()?.image;
|
||||
let mut data = Vec::new();
|
||||
if let Some(file_name) = file_name.as_ref() {
|
||||
File::open(file_name)
|
||||
.map_err(|e| anyhow!("Could not open disk image file {} ({})", file_name, e))?
|
||||
.read_to_end(&mut data)
|
||||
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", file_name, e))?;
|
||||
};
|
||||
let file = file_name
|
||||
.as_ref()
|
||||
.map(|file_name| {
|
||||
File::open(file_name)
|
||||
.map_err(|e| anyhow!("Could not open disk image file {} ({})", file_name, e))
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
data,
|
||||
file_name,
|
||||
file: file.zip(file_name),
|
||||
read_data: VecDeque::new(),
|
||||
sector: 0,
|
||||
offset: 0,
|
||||
count: 0,
|
||||
status: Status::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
||||
match address {
|
||||
0x0..=0x3 => NullableResult::Ok(u32_get_be_byte(self.sector, address)),
|
||||
0x4 => {
|
||||
let byte = self
|
||||
.data
|
||||
.get(self.sector as usize * SECTOR_SIZE + self.offset as usize)
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
self.offset += 1;
|
||||
NullableResult::Ok(byte)
|
||||
0x4..=0x7 => NullableResult::Ok(u32_get_be_byte(self.count, address - 0x4)),
|
||||
0x8..=0x9 => NullableResult::Ok(u16_get_be_byte(self.status.bits(), address - 0x8)),
|
||||
0xA..=0xB => {
|
||||
if self.read_data.len() == 1 {
|
||||
self.status.set(Status::DATA_READY, false);
|
||||
}
|
||||
NullableResult::Ok(self.read_data.pop_front().unwrap_or(0))
|
||||
}
|
||||
0xFF => NullableResult::Ok(4),
|
||||
_ => NullableResult::Null,
|
||||
@ -64,33 +82,40 @@ impl Card for Storage {
|
||||
}
|
||||
|
||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
||||
if let 0x0..=0x3 = address {
|
||||
self.sector = u32_set_be_byte(self.sector, address, data);
|
||||
self.offset = 0;
|
||||
match address {
|
||||
0x0..=0x3 => {
|
||||
self.sector = u32_set_be_byte(self.sector, address, data);
|
||||
}
|
||||
0x4..=0x7 => {
|
||||
self.count = u32_set_be_byte(self.count, address - 0x4, data);
|
||||
}
|
||||
// More commands to be added later
|
||||
#[allow(clippy::single_match)]
|
||||
0x9 => match data {
|
||||
0x0 => {
|
||||
if let Some((file, _)) = &mut self.file {
|
||||
file.seek(SeekFrom::Start(self.sector as u64 * SECTOR_SIZE))
|
||||
.unwrap();
|
||||
let mut buf = Vec::new();
|
||||
buf.resize(self.count as usize * SECTOR_SIZE as usize, 0);
|
||||
file.read_exact(&mut buf).unwrap();
|
||||
self.read_data.extend(buf);
|
||||
self.status.set(Status::DATA_READY, true);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
NullableResult::Ok(())
|
||||
}
|
||||
|
||||
fn cmd(&mut self, cmd: &[&str]) -> anyhow::Result<()> {
|
||||
if cmd[0] == "load" && cmd.len() >= 2 {
|
||||
let mut file = File::open(cmd[1])
|
||||
let file = File::open(cmd[1])
|
||||
.map_err(|e| anyhow!("Couldn't open disk image file {} ({})", cmd[1], e))?;
|
||||
self.data.clear();
|
||||
file.read_to_end(&mut self.data)
|
||||
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", cmd[1], e))?;
|
||||
self.file_name = Some(cmd[1].into());
|
||||
self.file = Some((file, cmd[1].into()));
|
||||
println!("Read disk image file {}", cmd[1]);
|
||||
} else if cmd[0] == "reload" {
|
||||
if let Some(file_name) = &self.file_name {
|
||||
let mut file = File::open(cmd[1])
|
||||
.map_err(|e| anyhow!("Couldn't open disk image file {} ({})", cmd[1], e))?;
|
||||
self.data.clear();
|
||||
file.read_to_end(&mut self.data)
|
||||
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", cmd[1], e))?;
|
||||
println!("Reloaded disk image file {}", file_name);
|
||||
} else {
|
||||
println!("No disk image file to reload");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -99,11 +124,11 @@ impl Card for Storage {
|
||||
impl Display for Storage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Storage card, ")?;
|
||||
if let Some(name) = self.file_name.as_ref() {
|
||||
if let Some((file, file_name)) = self.file.as_ref() {
|
||||
f.write_fmt(format_args!(
|
||||
"disk image {} ({})",
|
||||
name,
|
||||
self.data.len().human_count_bytes(),
|
||||
file_name,
|
||||
file.metadata().unwrap().len().human_count_bytes(),
|
||||
))
|
||||
} else {
|
||||
f.write_str("no disk image")
|
||||
|
Loading…
Reference in New Issue
Block a user