Compare commits

..

No commits in common. "259503e505caa9ac15c1cc92e2976ac6de378e7f" and "ac4446b0551353f0f8bb00c27ca316d645c91791" have entirely different histories.

15 changed files with 621 additions and 932 deletions

1391
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -21,11 +21,11 @@ nokhwa = { version = "0.10", features = [
"input-avfoundation",
], optional = true }
send_wrapper = { version = "0.6.0", optional = true }
winit = { version = "0.29.15", features = ["rwh_05"] }
winit_input_helper = "0.16"
winit = { version = "0.29", features = ["rwh_05"] }
winit_input_helper = "0.15"
raw-window-handle = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
image = { version = "0.25.1", default-features = false, features = ["png"] }
image = { version = "0.24", default-features = false, features = ["png"] }
bytemuck = "1.14"
chrono = "0.4"
log = { workspace = true }

View file

@ -3,7 +3,7 @@ use cpal::{
Stream,
};
use futures::executor;
use gb_emu_lib::connect::{AsyncConsumer, AudioOutput, DownsampleType};
use gb_emu_lib::connect::{AudioOutput, DownsampleType};
use crate::access_config;

View file

@ -27,7 +27,7 @@ nih_plug = { workspace = true, features = [
"vst3",
], optional = true }
baseview = { workspace = true, optional = true }
async-ringbuf = { version = "0.2.1", optional = true }
async-ringbuf = { version = "0.1", optional = true }
futures = { version = "0.3", optional = true }
keyboard-types = { version = "0.6.2", optional = true }
raw-window-handle = { workspace = true }

View file

@ -1,7 +1,4 @@
use async_ringbuf::{
traits::{AsyncConsumer, Observer},
AsyncHeapCons,
};
use async_ringbuf::AsyncHeapConsumer;
use baseview::Size;
use futures::executor;
use gb_emu_lib::{
@ -54,7 +51,7 @@ struct EmuParams {
}
struct EmuVars {
rx: AsyncHeapCons<[f32; 2]>,
rx: AsyncHeapConsumer<[f32; 2]>,
emulator_core: EmulatorCore<[u8; 4]>,
serial_tx: Sender<u8>,
}
@ -327,7 +324,6 @@ impl Plugin for GameboyEmu {
.with_show_bootrom(!will_skip_bootrom);
EmulatorCore::init(false, receiver, options)
.expect("couldn't initialize emulator core!")
};
emulator_core.run_until_buffer_full();

View file

@ -9,19 +9,19 @@ identifier = "com.alexjanka.TWINC.gui"
osx_file_extensions = [[["Game Boy ROM", "Viewer"], ["gb", "gbc"]]]
[features]
default = ["macos-ui", "crossplatform-ui"]
default = ["macos-ui", "crossplatform-ui", "force-crossplatform-ui"]
macos-ui = ["cacao", "objc", "uuid"]
crossplatform-ui = ["gtk", "adw", "glib-build-tools"]
force-crossplatform-ui = ["crossplatform-ui"]
[dependencies]
adw = { version = "0.7.0", package = "libadwaita", features = [
adw = { version = "0.6.0", package = "libadwaita", features = [
"v1_4",
"gtk_v4_6",
"gtk_v4_12",
], optional = true }
frontend-common = { workspace = true }
gb-emu-lib = { workspace = true }
gtk = { version = "0.9.0", package = "gtk4", features = [
gtk = { version = "0.8.0", package = "gtk4", features = [
"v4_12",
], optional = true }
twinc_emu_vst = { path = "../gb-vst", default-features = false }
@ -40,4 +40,4 @@ uuid = { version = "1.6", features = ["v4", "fast-rng"], optional = true }
[build-dependencies]
glib-build-tools = { version = "0.20.0", optional = true }
glib-build-tools = { version = "0.19.0", optional = true }

View file

@ -301,14 +301,7 @@ impl CacaoWindowManager {
if state {
let is_running = self.is_emulator_running();
if is_running {
let new_layer_window: Sender<RendererMessage<[u8; 4]>> =
match new_layer_window(self) {
Ok(t) => t,
Err(e) => {
log::error!("couldn't create tile window: {e:?}");
return;
}
};
let new_layer_window = new_layer_window(self);
if let Some(ref handles) = self.handles {
handles
.sender
@ -323,13 +316,7 @@ impl CacaoWindowManager {
if state {
let is_running = self.is_emulator_running();
if is_running {
let new_tile_window = match new_tile_window(self) {
Ok(t) => t,
Err(e) => {
log::error!("couldn't create tile window: {e:?}");
return;
}
};
let new_tile_window = new_tile_window(self);
if let Some(ref handles) = self.handles {
handles
.sender

View file

@ -170,13 +170,7 @@ impl Dispatcher for TwincUiApp {
let (output, stream) = audio::create_output(false);
let mut window_manager = self.current_game.write().unwrap();
window_manager.update_handles(sender, stream);
let mut core = match frontend_common::run(prepared, &mut *window_manager, output) {
Ok(c) => c,
Err(e) => {
log::error!("couldn't create emulator core: {e:?}");
return;
}
};
let mut core = frontend_common::run(prepared, &mut *window_manager, output);
let handle = std::thread::Builder::new()
.name(String::from("EmuCore"))
.spawn(move || loop {

View file

@ -4,7 +4,6 @@ use std::path::PathBuf;
use cacao::button::Button;
use cacao::filesystem::FileSelectPanel;
use cacao::image::{Image, ImageView};
use cacao::input::TextField;
use cacao::layout::{Layout, LayoutConstraint};
use cacao::select::Select;
@ -206,7 +205,7 @@ pub struct PickerView<T>
where
T: ToString,
{
pub _view: View,
pub view: View,
pub select: Select,
pub title: Label,
_p: PhantomData<T>,
@ -244,7 +243,7 @@ where
]);
Self {
_view: view,
view,
select,
title,
_p: PhantomData,
@ -486,43 +485,3 @@ impl StepperViewToggle {
self.enabled = !self.enabled;
}
}
pub struct ImageViewWrapper {
view: View,
image_view: ImageView,
_image: Image,
}
impl ImageViewWrapper {
pub fn new(image: Image) -> Self {
let view = View::new();
let image_view = ImageView::new();
image_view.set_image(&image);
view.add_subview(&image_view);
LayoutConstraint::activate(&[
image_view
.leading
.constraint_equal_to(&view.leading)
.offset(10.),
image_view.top.constraint_equal_to(&view.top).offset(10.),
image_view
.bottom
.constraint_equal_to(&view.bottom)
.offset(-10.),
]);
Self {
view,
image_view,
_image: image,
}
}
pub fn view(&self) -> &View {
&self.view
}
pub fn image_view(&self) -> &ImageView {
&self.image_view
}
}

View file

@ -4,7 +4,7 @@ version = "0.5.1"
edition = "2021"
[features]
default = ["config", "librashader", "wgpu-renderer"]
default = []
clocked-serial = []
librashader = [
"dep:librashader",
@ -34,9 +34,9 @@ error-colour = []
[dependencies]
rand = "0.8.5"
async-ringbuf = "0.2.1"
futures = "0.3.30"
itertools = "0.13.0"
async-ringbuf = "0.1"
futures = "0.3"
itertools = "0.12"
serde = { version = "1.0", features = ["derive"] }
serde_with = "3.0"
bytemuck = "1.14"
@ -51,16 +51,13 @@ librashader-common = { workspace = true, optional = true }
directories = { version = "5.0", optional = true }
ron = { version = "0.8", optional = true }
lazy_static = "1.4"
wgpu = { version = "22.0.0", optional = true }
wgpu = { version = "0.20", optional = true }
thiserror = { workspace = true }
log = { workspace = true }
anyhow = "1.0.86"
[build-dependencies]
naga = { version = "22.0.0", optional = true, features = [
"wgsl-in",
"spv-out",
] }
naga = { version = "0.19", optional = true, features = ["wgsl-in", "spv-out"] }
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
ash-molten = { version = "0.19.0", optional = true }
ash-molten = { version = "0.16.0", optional = true }

View file

@ -1,11 +1,8 @@
use async_ringbuf::{traits::Split, AsyncHeapCons, AsyncHeapProd, AsyncHeapRb};
use std::fs;
use std::path::PathBuf;
use std::sync::mpsc::Sender;
use std::sync::{Arc, RwLock};
pub use async_ringbuf::traits::consumer::AsyncConsumer;
pub use crate::error::RomHeaderError;
pub use crate::processor::memory::mmio::gpu::Colour;
pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState};
@ -16,6 +13,7 @@ pub use crate::processor::memory::rom::{
};
pub use crate::processor::memory::Rom;
pub use crate::{HEIGHT, WIDTH};
use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};
#[derive(Debug)]
pub enum EmulatorMessage<ColourFormat>
@ -100,7 +98,7 @@ pub struct ResolutionData {
pub struct AudioOutput {
pub sample_rate: f32,
pub send_rb: AsyncHeapProd<[f32; 2]>,
pub send_rb: AsyncHeapProducer<[f32; 2]>,
pub downsample_type: DownsampleType,
}
@ -109,7 +107,7 @@ impl AudioOutput {
sample_rate: f32,
buffers_per_frame: usize,
downsample_type: DownsampleType,
) -> (Self, AsyncHeapCons<[f32; 2]>) {
) -> (Self, AsyncHeapConsumer<[f32; 2]>) {
let rb_len = (sample_rate as usize / 60) / buffers_per_frame;
let rb = AsyncHeapRb::<[f32; 2]>::new(rb_len);

View file

@ -7,7 +7,6 @@ use crate::{
processor::memory::addresses::{AddressMarker, AudioAddress, WaveRamAddress},
util::{get_bit, set_or_clear_bit},
};
use async_ringbuf::traits::{AsyncProducer, Observer};
use futures::executor;
use itertools::izip;

View file

@ -97,7 +97,6 @@ impl RendererBackend for WgpuBackend {
required_features: wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
required_limits: wgpu::Limits::default(),
label: None,
memory_hints: wgpu::MemoryHints::default(),
},
None,
)

View file

@ -6,14 +6,14 @@ use gb_emu_lib::connect::{EmulatorCoreTrait, RomFile};
mod common;
#[test]
fn cpu_instrs() -> anyhow::Result<()> {
fn cpu_instrs() -> Result<(), String> {
run_blargg_test("cpu_instrs\n\n01:ok 02:ok 03:ok 04:ok 05:ok 06:ok 07:ok 08:ok 09:ok 10:ok 11:ok \n\nPassed all tests", include_bytes!(
"../../test-roms/blargg/cpu_instrs/cpu_instrs.gb"
),None)
}
#[test]
fn instr_timing() -> anyhow::Result<()> {
fn instr_timing() -> Result<(), String> {
run_blargg_test(
"instr_timing\n\n\nPassed",
include_bytes!("../../test-roms/blargg/instr_timing/instr_timing.gb"),
@ -22,7 +22,7 @@ fn instr_timing() -> anyhow::Result<()> {
}
#[test]
fn mem_timing() -> anyhow::Result<()> {
fn mem_timing() -> Result<(), String> {
run_blargg_test(
"mem_timing\n\n\nPassed",
include_bytes!("../../test-roms/blargg/mem_timing/mem_timing.gb"),
@ -30,17 +30,11 @@ fn mem_timing() -> anyhow::Result<()> {
)
}
#[derive(Debug, thiserror::Error)]
enum TestError {
#[error("Timeout")]
Timeout(String),
}
fn run_blargg_test<const N: usize>(
correct_output: &str,
rom: &[u8; N],
extra_end: Option<Vec<&str>>,
) -> anyhow::Result<()> {
) -> Result<(), String> {
let mut emu = emulator_setup(RomFile::Raw(rom.to_vec()))?;
let mut end_strings = extra_end.unwrap_or_default();
@ -60,7 +54,7 @@ fn run_blargg_test<const N: usize>(
}
}
if began.elapsed() > timeout {
return Err(TestError::Timeout(format!("Test timed out: output was {chars}")).into());
return Err(format!("Test timed out: output was {chars}"));
}
}

View file

@ -1,5 +1,6 @@
use std::sync::mpsc::{channel, Receiver, Sender};
use async_ringbuf::AsyncHeapConsumer;
use gb_emu_lib::{
connect::{AudioOutput, EmulatorMessage, EmulatorOptions, RomFile},
EmulatorCore,
@ -7,14 +8,16 @@ use gb_emu_lib::{
pub struct TestEmulator {
pub core: EmulatorCore<[u8; 4]>,
pub _sender: Sender<EmulatorMessage<[u8; 4]>>,
pub _audio_rx: async_ringbuf::AsyncHeapCons<[f32; 2]>,
pub sender: Sender<EmulatorMessage<[u8; 4]>>,
pub audio_rx: AsyncHeapConsumer<[f32; 2]>,
pub serial_rx: Receiver<u8>,
}
pub fn emulator_setup(rom_file: RomFile) -> anyhow::Result<TestEmulator> {
pub fn emulator_setup(rom_file: RomFile) -> Result<TestEmulator, String> {
let (sender, receiver) = channel::<EmulatorMessage<[u8; 4]>>();
let rom = rom_file.load(gb_emu_lib::connect::SramType::None)?;
let rom = rom_file
.load(gb_emu_lib::connect::SramType::None)
.map_err(|_e| String::from("Error reading ROM: {_e:?}"))?;
let (audio_output, audio_rx) = AudioOutput::new(
48000.,
1,
@ -37,12 +40,14 @@ pub fn emulator_setup(rom_file: RomFile) -> anyhow::Result<TestEmulator> {
include_bytes!("../../../sameboy-bootroms/dmg_boot.bin").to_vec(),
)));
let core = EmulatorCore::init(true, receiver, options)?;
sender.send(EmulatorMessage::Start)?;
let core = EmulatorCore::init(true, receiver, options);
sender
.send(EmulatorMessage::Start)
.map_err(|_e| String::from("Error sending message: {_e:?}"))?;
Ok(TestEmulator {
core,
_sender: sender,
_audio_rx: audio_rx,
sender,
audio_rx,
serial_rx,
})
}