Compare commits

...

3 Commits

5 changed files with 110 additions and 38 deletions

86
Cargo.lock generated
View File

@ -42,9 +42,9 @@ dependencies = [
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f"
[[package]] [[package]]
name = "alsa" name = "alsa"
@ -106,9 +106,9 @@ dependencies = [
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.17" version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
@ -155,9 +155,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.92" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]] [[package]]
name = "arrayref" name = "arrayref"
@ -324,9 +324,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.34" version = "1.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -860,9 +860,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.0" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
[[package]] [[package]]
name = "hassle-rs" name = "hassle-rs"
@ -960,7 +960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.0", "hashbrown 0.15.1",
] ]
[[package]] [[package]]
@ -1046,9 +1046,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.161" version = "0.2.162"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -1673,9 +1673,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]] [[package]]
name = "polling" name = "polling"
version = "3.7.3" version = "3.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
@ -1881,9 +1881,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.38" version = "0.38.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
"errno", "errno",
@ -1892,6 +1892,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -1972,8 +1978,10 @@ dependencies = [
"pollster", "pollster",
"rtrb", "rtrb",
"rubato", "rubato",
"thread-priority",
"wgpu", "wgpu",
"winit", "winit",
"winver",
] ]
[[package]] [[package]]
@ -2100,24 +2108,38 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.66" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.66" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.87", "syn 2.0.87",
] ]
[[package]]
name = "thread-priority"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe075d7053dae61ac5413a34ea7d4913b6e6207844fd726bdd858b37ff72bf5"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"libc",
"log",
"rustversion",
"winapi",
]
[[package]] [[package]]
name = "tiny-skia" name = "tiny-skia"
version = "0.11.4" version = "0.11.4"
@ -2615,6 +2637,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.52.0" version = "0.52.0"
@ -2929,6 +2960,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winver"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e0e7162b9e282fd75a0a832cce93994bdb21208d848a418cd05a5fdd9b9ab33"
dependencies = [
"windows 0.48.0",
]
[[package]] [[package]]
name = "x11-dl" name = "x11-dl"
version = "2.21.0" version = "2.21.0"
@ -2988,9 +3028,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
[[package]] [[package]]
name = "xml-rs" name = "xml-rs"
version = "0.8.22" version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"

View File

@ -19,9 +19,13 @@ num-traits = "0.2"
pollster = "0.4" pollster = "0.4"
rtrb = "0.3" rtrb = "0.3"
rubato = "0.16" rubato = "0.16"
thread-priority = "1"
wgpu = "22.1" wgpu = "22.1"
winit = "0.30" winit = "0.30"
[target."cfg(windows)".dependencies]
winver = "1"
[build-dependencies] [build-dependencies]
cc = "1" cc = "1"

View File

@ -8,7 +8,7 @@ use imgui::{FontSource, MouseCursor, SuspendedContext, WindowToken};
use imgui_wgpu::{Renderer, RendererConfig}; use imgui_wgpu::{Renderer, RendererConfig};
use imgui_winit_support::WinitPlatform; use imgui_winit_support::WinitPlatform;
use pollster::block_on; use pollster::block_on;
#[cfg(target_os = "windows")] #[cfg(windows)]
use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _}; use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _};
use winit::{ use winit::{
dpi::{LogicalSize, PhysicalSize, Size}, dpi::{LogicalSize, PhysicalSize, Size},
@ -23,7 +23,7 @@ pub struct WindowStateBuilder<'a> {
impl<'a> WindowStateBuilder<'a> { impl<'a> WindowStateBuilder<'a> {
pub fn new(event_loop: &'a ActiveEventLoop) -> Self { pub fn new(event_loop: &'a ActiveEventLoop) -> Self {
let attributes = Window::default_attributes(); let attributes = Window::default_attributes();
#[cfg(target_os = "windows")] #[cfg(windows)]
let attributes = attributes.with_corner_preference(CornerPreference::DoNotRound); let attributes = attributes.with_corner_preference(CornerPreference::DoNotRound);
Self { Self {
event_loop, event_loop,
@ -63,8 +63,17 @@ pub struct WindowState {
impl WindowState { impl WindowState {
fn new(event_loop: &ActiveEventLoop, attributes: WindowAttributes) -> Self { fn new(event_loop: &ActiveEventLoop, attributes: WindowAttributes) -> Self {
let backends = wgpu::Backends::PRIMARY;
#[cfg(windows)]
let backends = if winver::WindowsVersion::detect().is_some_and(|v| v.major >= 10) {
// DX12 is faster than GL, so don't use GL on windows versions which support DX12.
// When wgpu switches to default to DX12, this can be removed.
backends - wgpu::Backends::GL
} else {
backends
};
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::PRIMARY, backends,
..Default::default() ..Default::default()
}); });

View File

@ -3,7 +3,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
mpsc::{self, TryRecvError}, mpsc::{self, RecvError, TryRecvError},
Arc, Arc,
}, },
}; };
@ -94,19 +94,33 @@ impl Emulator {
let mut eye_contents = vec![0u8; 384 * 224 * 2]; let mut eye_contents = vec![0u8; 384 * 224 * 2];
let mut audio_samples = vec![]; let mut audio_samples = vec![];
loop { loop {
let mut idle = true;
if self.running.load(Ordering::Acquire) { if self.running.load(Ordering::Acquire) {
idle = false;
self.sim.emulate_frame(); self.sim.emulate_frame();
} }
if let Some(renderer) = &mut self.renderer { if let Some(renderer) = &mut self.renderer {
if self.sim.read_pixels(&mut eye_contents) { if self.sim.read_pixels(&mut eye_contents) {
idle = false;
renderer.render(&eye_contents); renderer.render(&eye_contents);
} }
} }
self.sim.read_samples(&mut audio_samples); self.sim.read_samples(&mut audio_samples);
if !audio_samples.is_empty() { if !audio_samples.is_empty() {
idle = false;
self.audio.update(&audio_samples); self.audio.update(&audio_samples);
audio_samples.clear(); audio_samples.clear();
} }
if idle {
// The game is paused, and we have output all the video/audio we have.
// Block the thread until a new command comes in.
match self.commands.recv() {
Ok(command) => self.handle_command(command),
Err(RecvError) => {
return;
}
}
}
loop { loop {
match self.commands.try_recv() { match self.commands.try_recv() {
Ok(command) => self.handle_command(command), Ok(command) => self.handle_command(command),

View File

@ -1,9 +1,10 @@
use std::{path::PathBuf, process, thread}; use std::{path::PathBuf, process};
use anyhow::Result; use anyhow::Result;
use app::App; use app::App;
use clap::Parser; use clap::Parser;
use emulator::EmulatorBuilder; use emulator::EmulatorBuilder;
use thread_priority::{ThreadBuilder, ThreadPriority};
use winit::event_loop::{ControlFlow, EventLoop}; use winit::event_loop::{ControlFlow, EventLoop};
mod app; mod app;
@ -26,16 +27,20 @@ fn main() -> Result<()> {
if let Some(path) = args.rom { if let Some(path) = args.rom {
builder = builder.with_rom(&path); builder = builder.with_rom(&path);
} }
thread::spawn(move || {
let mut emulator = match builder.build() { ThreadBuilder::default()
Ok(e) => e, .name("Emulator".to_owned())
Err(err) => { .priority(ThreadPriority::Max)
eprintln!("Error initializing emulator: {err}"); .spawn_careless(move || {
process::exit(1); let mut emulator = match builder.build() {
} Ok(e) => e,
}; Err(err) => {
emulator.run(); eprintln!("Error initializing emulator: {err}");
}); process::exit(1);
}
};
emulator.run();
})?;
let event_loop = EventLoop::with_user_event().build().unwrap(); let event_loop = EventLoop::with_user_event().build().unwrap();
event_loop.set_control_flow(ControlFlow::Poll); event_loop.set_control_flow(ControlFlow::Poll);