From 5278c301ef9284a694a913f3b840cb24f72f1ee7 Mon Sep 17 00:00:00 2001 From: transistor Date: Fri, 30 Sep 2022 11:24:11 -0700 Subject: [PATCH] Added .smd file decoding --- emulator/core/src/memory.rs | 4 ++ emulator/frontends/minifb/src/controllers.rs | 4 +- emulator/systems/genesis/src/lib.rs | 1 + emulator/systems/genesis/src/system.rs | 14 ++++--- emulator/systems/genesis/src/utils.rs | 43 ++++++++++++++++++++ todo.txt | 7 +++- 6 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 emulator/systems/genesis/src/utils.rs diff --git a/emulator/core/src/memory.rs b/emulator/core/src/memory.rs index 0573b13..6ff2310 100644 --- a/emulator/core/src/memory.rs +++ b/emulator/core/src/memory.rs @@ -42,6 +42,10 @@ impl MemoryBlock { pub fn read_only(&mut self) { self.read_only = true; } + + pub fn resize(&mut self, new_size: usize) { + self.contents.resize(new_size, 0); + } } impl Addressable for MemoryBlock { diff --git a/emulator/frontends/minifb/src/controllers.rs b/emulator/frontends/minifb/src/controllers.rs index 5983946..00060f9 100644 --- a/emulator/frontends/minifb/src/controllers.rs +++ b/emulator/frontends/minifb/src/controllers.rs @@ -5,8 +5,8 @@ use moa_core::host::ControllerEvent; pub fn map_controller_a(key: MiniKey, state: bool) -> Option { match key { MiniKey::A => { Some(ControllerEvent::ButtonA(state)) }, - MiniKey::B => { Some(ControllerEvent::ButtonB(state)) }, - MiniKey::C => { Some(ControllerEvent::ButtonC(state)) }, + MiniKey::O => { Some(ControllerEvent::ButtonB(state)) }, + MiniKey::E => { Some(ControllerEvent::ButtonC(state)) }, MiniKey::Up => { Some(ControllerEvent::DpadUp(state)) }, MiniKey::Down => { Some(ControllerEvent::DpadDown(state)) }, MiniKey::Left => { Some(ControllerEvent::DpadLeft(state)) }, diff --git a/emulator/systems/genesis/src/lib.rs b/emulator/systems/genesis/src/lib.rs index 2de56d8..a72c6ae 100644 --- a/emulator/systems/genesis/src/lib.rs +++ b/emulator/systems/genesis/src/lib.rs @@ -1,5 +1,6 @@ pub mod peripherals; +pub mod utils; mod system; pub use crate::system::{SegaGenesisOptions, build_genesis}; diff --git a/emulator/systems/genesis/src/system.rs b/emulator/systems/genesis/src/system.rs index 0df0ddb..65867ed 100644 --- a/emulator/systems/genesis/src/system.rs +++ b/emulator/systems/genesis/src/system.rs @@ -11,6 +11,7 @@ use moa_z80::{Z80, Z80Type}; use moa_peripherals_yamaha::Ym2612; use moa_peripherals_yamaha::Sn76489; +use crate::utils; use crate::peripherals::ym7101::Ym7101; use crate::peripherals::controllers::GenesisControllers; use crate::peripherals::coprocessor::{CoprocessorCoordinator, CoprocessorBankRegister, CoprocessorBankArea}; @@ -33,12 +34,13 @@ impl SegaGenesisOptions { pub fn build_genesis(host: &mut H, mut options: SegaGenesisOptions) -> Result { let mut system = System::new(); - let rom = if options.rom_data.is_some() { - let data = mem::take(&mut options.rom_data).unwrap(); - MemoryBlock::new(data) + let rom_data = if options.rom_data.is_some() { + mem::take(&mut options.rom_data).unwrap() } else { - MemoryBlock::load(&options.rom).unwrap() + utils::load_rom_file(&options.rom)? }; + + let rom = MemoryBlock::new(rom_data); //let mut rom = MemoryBlock::load("binaries/genesis/GenTestV3.0.bin").unwrap(); //let mut rom = MemoryBlock::load("binaries/genesis/HDRV_Genesis_Test_v1_4.bin").unwrap(); //let mut rom = MemoryBlock::load("binaries/genesis/ComradeOj's tiny demo.bin").unwrap(); @@ -58,8 +60,8 @@ pub fn build_genesis(host: &mut H, mut options: SegaGenesisOptions) -> let rom_end = rom.len(); system.add_addressable_device(0x00000000, wrap_transmutable(rom)).unwrap(); - let nvram = MemoryBlock::new(vec![0; 0x00010000]); - system.add_addressable_device(rom_end as Address, wrap_transmutable(nvram)).unwrap(); + let cartridge_nvram = MemoryBlock::new(vec![0; 0x400000 - rom_end]); + system.add_addressable_device(rom_end as Address, wrap_transmutable(cartridge_nvram)).unwrap(); let ram = MemoryBlock::new(vec![0; 0x00010000]); system.add_addressable_device(0x00ff0000, wrap_transmutable(ram)).unwrap(); diff --git a/emulator/systems/genesis/src/utils.rs b/emulator/systems/genesis/src/utils.rs new file mode 100644 index 0000000..0e3f709 --- /dev/null +++ b/emulator/systems/genesis/src/utils.rs @@ -0,0 +1,43 @@ + +use std::fs; + +use moa_core::Error; + +const SMD_HEADER: usize = 512; +const SMD_BLOCK_SIZE: usize = 16384; +const SMD_MAGIC: &[u8] = &[0xAA, 0xBB]; + +pub fn smd_to_bin(input: Vec) -> Result, Error> { + let mut output = vec![0; input.len() - SMD_HEADER]; + + if &input[8..10] != SMD_MAGIC { + return Err(Error::new(&format!("smd: magic not found: {:?}", &input[8..10]))); + } + + let calculated_blocks = (input.len() - SMD_HEADER) / SMD_BLOCK_SIZE; + + for block in 0..calculated_blocks { + let offset = block * SMD_BLOCK_SIZE; + let odds = &input[SMD_HEADER + offset..]; + let evens = &input[SMD_HEADER + offset + (SMD_BLOCK_SIZE / 2)..]; + + for i in 0..(SMD_BLOCK_SIZE / 2) { + output[offset + i * 2] = evens[i]; + output[offset + i * 2 + 1] = odds[i]; + } + } + + Ok(output) +} + +pub fn load_rom_file(filename: &str) -> Result, Error> { + let mut contents = fs::read(filename).map_err(|_| Error::new(&format!("Error reading contents of {}", filename)))?; + + if filename.ends_with(".smd") { + contents = smd_to_bin(contents)?; + } + + Ok(contents) +} + + diff --git a/todo.txt b/todo.txt index 6f5fc8c..bfdcb94 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,9 @@ +* make the keys easier to config... + +* add log crate to core +* can you make the debugger more accessible, so a web interface could access the data and display it, in light of the fact that println isn't available in wasm + Web Assembly: * the frame rate is pretty bad. It's definitely faster with a smaller window * can you limit the size of the window that pixels generates? @@ -11,8 +16,6 @@ Web Assembly: * can you make the web interface nicer with like... a picture of a genesis or something -* EarthwormJim, Mortal Kombat 2, and a few others, that were working are now not working, possibly due to the tests (it fixed some things and broke others) - It's possible that some of the errors are coming from the Z80 and coprocessor interactions. Try running tests agains Z80 * fix audio, and/or make it possible to disable audio processing/simulation for one or both sound chips (might be nice to have sn76489 but not ym2612)