Skip to content

Commit

Permalink
add serial, sound and opl3 features. re-enable wasm32 build.
Browse files Browse the repository at this point in the history
  • Loading branch information
dbalsom committed Nov 30, 2024
1 parent 678ab0a commit 32ec4aa
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 514 deletions.
427 changes: 26 additions & 401 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,13 @@ opt-level = 3
opt-level = 3

[features]
default = ["ega", "vga"]
default = ["ega", "vga", "opl"]
devtools = ["martypc_desktop_wgpu/devtools"]
arduino_validator = ["marty_core/arduino_validator", "martypc_desktop_wgpu/arduino_validator"]
cpu_validator = ["marty_core/cpu_validator", "martypc_desktop_wgpu/cpu_validator"]
ega = ["marty_core/ega", "frontend_common/ega", "videocard_renderer/ega"]
vga = ["marty_core/vga", "frontend_common/vga", "videocard_renderer/vga"]
opl = ["marty_core/opl"]

[build-dependencies]
winres = "0.1"
Expand Down
37 changes: 26 additions & 11 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ license.workspace = true
[lib]
name = "marty_core"
path = "src/lib.rs"
crate-type = ["lib"]
crate-type = ["cdylib", "lib"]

[dependencies]
marty_common = { path = "../lib/common" }
anyhow = "1.0.58"
arraydeque = "0.4.5"
bytemuck = "1.13.1"

arraydeque = "0.5"
bytemuck = "1.19"
const_format = "0.2"
lazy_static = "1.4.0"
lazy_static = "1.5"
log = "0.4"
md5 = "0.7.0"
modular-bitfield = "0.11.2"
md5 = "0.7"
modular-bitfield = "0.11"
rand = "0.8.5"
regex = "1.5.5"
regex = "1.0"
ringbuf = "0.2.8"
serde = { version = "1.0.107", features = ["derive"] }
serde_derive = "1.0.107"
Expand All @@ -29,16 +29,26 @@ strum = "0.26"
strum_macros = "0.26"
toml = "0.5.10"
uuid = { version = "1.1.2", features = ["v4"] }
serialport.workspace = true
rodio.workspace = true
anyhow.workspace = true
serialport = { workspace = true, optional = true }
#rodio.workspace = true
fxhash.workspace = true
enum_dispatch.workspace = true
crossbeam-channel.workspace = true
fluxfox.workspace = true

[dependencies.opl3-rs]
git = "https://github.com/dbalsom/opl3-rs.git"
branch = "main"
optional = true

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
fluxfox = { workspace = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
wasm-bindgen = { version = "0.2", optional = true }
wasm-bindgen-futures = { version = "0.4", optional = true }
fluxfox = { workspace = true, default-features=false, features = ["wasm", "zip", "mfi"] }

[dev-dependencies]
criterion = "0.5"
Expand All @@ -52,6 +62,11 @@ name = "cpu_bench"
harness = false

[features]
default = ["ega", "vga", "sound", "serial", "opl"]
sound = []
serial = ["serialport"]
opl = ["dep:opl3-rs"]
wasm = []
arduino_validator = []
cpu_validator = []
ega = []
Expand Down
18 changes: 18 additions & 0 deletions core/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::{env, process::Command};

fn main() {
println!("cargo:rerun-if-changed=build.rs");
if let Ok(target) = env::var("TARGET") {
if target == "wasm32-unknown-emscripten" {
// Run the emsdk_env.bat script
let status = Command::new("cmd")
.args(["/C", "path\\to\\emsdk_env.bat"])
.status()
.expect("Failed to run emsdk_env.bat");

if !status.success() {
panic!("emsdk_env.bat script failed to execute successfully");
}
}
}
}
52 changes: 40 additions & 12 deletions core/src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,27 @@

#![allow(dead_code)]

use crate::devices::pit::SPEAKER_SAMPLE_RATE;
use anyhow::Error;
use crossbeam_channel::unbounded;

use fxhash::FxHashMap;
use std::{collections::VecDeque, fmt, io::Write, path::Path};

#[cfg(feature = "sound")]
use crate::device_traits::sounddevice::SoundDevice;
#[cfg(feature = "sound")]
use crate::devices::pit::SPEAKER_SAMPLE_RATE;
#[cfg(feature = "sound")]
use crossbeam_channel::unbounded;

use crate::{
bytequeue::*,
device_traits::{
sounddevice::SoundDevice,
videocard::{ClockingMode, VideoCard, VideoCardDispatch, VideoCardId, VideoCardInterface, VideoType},
device_traits::videocard::{
ClockingMode,
VideoCard,
VideoCardDispatch,
VideoCardId,
VideoCardInterface,
VideoType,
},
devices::{
cga::CGACard,
Expand All @@ -69,28 +79,33 @@ use crate::{
tracelogger::TraceLogger,
};

#[cfg(feature = "opl")]
use crate::devices::adlib::AdLibCard;
#[cfg(feature = "ega")]
use crate::devices::ega::EGACard;
#[cfg(feature = "vga")]
use crate::devices::vga::VGACard;
#[cfg(feature = "sound")]
use crate::machine_types::SoundType;
#[cfg(feature = "sound")]
use crate::sound::{SoundOutputConfig, SoundSourceDescriptor};

use crate::{
cpu_common::CpuType,
device_traits::videocard::VideoCardSubType,
devices::{
a0::A0Register,
adlib::AdLibCard,
cartridge_slots::CartridgeSlot,
game_port::GamePort,
lotech_ems::LotechEmsCard,
lpt_card::ParallelController,
tga::TGACard,
},
machine_types::{EmsType, FdcType, MachineType, SoundType},
sound::{SoundOutputConfig, SoundSourceDescriptor},
machine_types::{EmsType, FdcType, MachineType},
syntax_token::SyntaxFormatType,
};

pub const NO_IO_BYTE: u8 = 0xFF; // This is the byte read from a unconnected IO address.
pub const NO_IO_BYTE: u8 = 0xFF; // This is the byte read from an unconnected IO address.
pub const OPEN_BUS_BYTE: u8 = 0xFF; // This is the byte read from an unmapped memory address.

const ADDRESS_SPACE: usize = 0x10_0000;
Expand Down Expand Up @@ -180,6 +195,8 @@ impl DeviceRunContext {

#[derive(Default)]
pub struct InstalledDevicesResult {
pub dummy: bool,
#[cfg(feature = "sound")]
pub sound_sources: Vec<SoundSourceDescriptor>,
}

Expand Down Expand Up @@ -412,6 +429,7 @@ pub struct BusInterface {
ems: Option<LotechEmsCard>,
cart_slot: Option<CartridgeSlot>,
game_port: Option<GamePort>,
#[cfg(feature = "opl")]
adlib: Option<AdLibCard>,

videocards: FxHashMap<VideoCardId, VideoCardDispatch>,
Expand Down Expand Up @@ -590,6 +608,7 @@ impl Default for BusInterface {
ems: None,
cart_slot: None,
game_port: None,
#[cfg(feature = "sound")]
adlib: None,
videocards: FxHashMap::default(),
videocard_ids: Vec::new(),
Expand Down Expand Up @@ -1780,7 +1799,7 @@ impl BusInterface {
&mut self,
machine_desc: &MachineDescriptor,
machine_config: &MachineConfiguration,
sound_config: &SoundOutputConfig,
#[cfg(feature = "sound")] sound_config: &SoundOutputConfig,
terminal_port: Option<u16>,
) -> Result<InstalledDevicesResult, Error> {
let mut installed_devices = InstalledDevicesResult::new();
Expand Down Expand Up @@ -1844,6 +1863,7 @@ impl BusInterface {
}

// Create the crossbeam channel for the PIT to send sound samples to the sound output thread.
#[cfg(feature = "sound")]
let pit_sample_sender = if machine_config.speaker {
// Add this sound source.
let (s, r) = unbounded();
Expand All @@ -1858,6 +1878,8 @@ impl BusInterface {
else {
None
};
#[cfg(not(feature = "sound"))]
let pit_sample_sender = None;

// Create the PIT. One PIT will always exist, but it may be an 8253 or 8254.
// Pick the device type from MachineDesc.
Expand Down Expand Up @@ -2016,6 +2038,7 @@ impl BusInterface {
}

// Create sound cards
#[cfg(feature = "sound")]
for (_i, card) in machine_config.sound.iter().enumerate() {
#[allow(irrefutable_let_patterns)]
if let SoundType::AdLib = card.sound_type {
Expand Down Expand Up @@ -2312,6 +2335,7 @@ impl BusInterface {
}

// Run the adlib card {
#[cfg(feature = "opl")]
if let Some(adlib) = &mut self.adlib {
adlib.run(us);
}
Expand Down Expand Up @@ -2622,7 +2646,9 @@ impl BusInterface {
}
}
}
IoDeviceType::Sound => {
IoDeviceType::Sound =>
{
#[cfg(feature = "opl")]
if let Some(adlib) = &mut self.adlib {
byte = Some(adlib.read_u8(port, nul_delta));
}
Expand Down Expand Up @@ -2792,7 +2818,9 @@ impl BusInterface {
}
}
}
IoDeviceType::Sound => {
IoDeviceType::Sound =>
{
#[cfg(feature = "opl")]
if let Some(adlib) = &mut self.adlib {
IoDevice::write_u8(adlib, port, data, None, nul_delta);
}
Expand Down
1 change: 1 addition & 0 deletions core/src/device_traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@
*/

#[cfg(feature = "sound")]
pub mod sounddevice;
pub mod videocard;
2 changes: 2 additions & 0 deletions core/src/device_traits/sounddevice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
must implement.
*/

#[cfg(feature = "opl")]
use crate::devices::adlib::AdLibCard;

use enum_dispatch::enum_dispatch;

pub type AudioSample = f32;
Expand Down
1 change: 1 addition & 0 deletions core/src/devices/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/

pub mod a0;
#[cfg(feature = "opl")]
pub mod adlib;
pub mod cartridge_slots;
pub mod cga;
Expand Down
12 changes: 12 additions & 0 deletions core/src/devices/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ pub type SerialPortDisplayState = BTreeMap<&'static str, SyntaxToken>;
pub struct SerialPortDescriptor {
pub id: usize,
pub name: String,
#[cfg(feature = "serial")]
pub brige_port_id: Option<usize>,
}

Expand Down Expand Up @@ -258,8 +259,11 @@ pub struct SerialPort {
us_per_byte: f64,

// Serial port bridge
#[cfg(feature = "serial")]
bridge_port_id: Option<usize>,
#[cfg(feature = "serial")]
bridge_port: Option<Box<dyn serialport::SerialPort>>,
#[cfg(feature = "serial")]
bridge_buf: Vec<u8>,
}

Expand Down Expand Up @@ -295,8 +299,11 @@ impl Default for SerialPort {
tx_timer: 0.0,
us_per_byte: 833.333, // 9600 baud

#[cfg(feature = "serial")]
bridge_port_id: None,
#[cfg(feature = "serial")]
bridge_port: None,
#[cfg(feature = "serial")]
bridge_buf: vec![0; 1000],
}
}
Expand Down Expand Up @@ -761,6 +768,7 @@ impl SerialPort {
}
}

#[cfg(feature = "serial")]
fn bridge_port(&mut self, port_name: String, port_id: usize) -> anyhow::Result<bool> {
let port_result = serialport::new(port_name.clone(), 9600)
.timeout(std::time::Duration::from_millis(5))
Expand Down Expand Up @@ -882,6 +890,7 @@ impl SerialPortController {
ports.push(SerialPortDescriptor {
id: i,
name: port.name.clone(),
#[cfg(feature = "serial")]
brige_port_id: port.bridge_port_id,
});
}
Expand Down Expand Up @@ -922,6 +931,7 @@ impl SerialPortController {
}

/// Bridge the specified serial port
#[cfg(feature = "serial")]
pub fn bridge_port(&mut self, port: usize, host_port_name: String, host_port_id: usize) -> anyhow::Result<bool> {
self.port[port].bridge_port(host_port_name, host_port_id)
}
Expand Down Expand Up @@ -961,6 +971,7 @@ impl SerialPortController {
// Is there a byte waiting to be sent in the tx holding register?
if !port.tx_holding_empty {
// If we have bridged this serial port, send the byte to the tx queue
#[cfg(feature = "serial")]
if let Some(_) = &port.bridge_port {
//log::trace!("{}: Sending byte: {:02X}", port.name, port.tx_holding_reg);
port.tx_queue.push_back(port.tx_holding_reg);
Expand Down Expand Up @@ -991,6 +1002,7 @@ impl SerialPortController {
/// The update function is called per-frame, instead of within the emulation loop.
/// This allows bridging realtime events with virtual device.
pub fn update(&mut self) {
#[cfg(feature = "serial")]
for port in &mut self.port {
match &mut port.bridge_port {
Some(bridge_port) => {
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub mod keys;
pub mod machine;
pub mod machine_config;
pub mod memerror;
#[cfg(feature = "sound")]
pub mod sound;
pub mod syntax_token;
pub mod tracelogger;
Expand Down
Loading

0 comments on commit 32ec4aa

Please sign in to comment.