Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16613fb982 |
Generated
+772
-384
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -4,13 +4,12 @@ description = "An emulator for the Virtual Boy."
|
||||
repository = "https://git.virtual-boy.com/PVB/lemur"
|
||||
publish = false
|
||||
license = "MIT"
|
||||
version = "0.10.2"
|
||||
version = "0.9.2"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
atoi = "2"
|
||||
audioadapter-buffers = "2"
|
||||
atomic = "0.6"
|
||||
bitflags = { version = "2", features = ["serde"] }
|
||||
bytemuck = { version = "1", features = ["derive"] }
|
||||
@@ -25,7 +24,7 @@ egui-wgpu = { version = "0.33", features = ["winit"] }
|
||||
fxprof-processed-profile = "0.8"
|
||||
fixed = { version = "1.28", features = ["num-traits"] }
|
||||
gilrs = { version = "0.11", features = ["serde-serialize"] }
|
||||
gimli = "0.33"
|
||||
gimli = "0.32"
|
||||
hex = "0.4"
|
||||
image = { version = "0.25", default-features = false, features = ["png"] }
|
||||
itertools = "0.14"
|
||||
@@ -37,9 +36,9 @@ object = "0.38"
|
||||
oneshot = "0.1"
|
||||
pollster = "0.4"
|
||||
rand = "0.9"
|
||||
rfd = "0.17"
|
||||
rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "async-std"]}
|
||||
rtrb = "0.3"
|
||||
rubato = "1"
|
||||
rubato = "0.16"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
thread-priority = "3"
|
||||
|
||||
+13
-13
@@ -10,30 +10,30 @@ RUN apt-get update && \
|
||||
apt-get install -y ca-certificates
|
||||
COPY llvm.sources /etc/apt/sources.list.d/llvm.sources
|
||||
RUN apt-get update && \
|
||||
apt-get install -y bash bzip2 clang-21 git lld-21 llvm-21 make patch xz-utils && \
|
||||
ln -s $(which clang-21) /usr/bin/clang && \
|
||||
ln -s $(which clang++-21) /usr/bin/clang++ && \
|
||||
ln -s $(which ld64.lld-21) /usr/bin/ld64.lld && \
|
||||
apt-get install -y bash bzip2 clang-20 git lld-20 llvm-20 make patch xz-utils && \
|
||||
ln -s $(which clang-20) /usr/bin/clang && \
|
||||
ln -s $(which clang++-20) /usr/bin/clang++ && \
|
||||
ln -s $(which ld64.lld-20) /usr/bin/ld64.lld && \
|
||||
SDK_VERSION=14.5 UNATTENDED=1 ENABLE_COMPILER_RT_INSTALL=1 TARGET_DIR=/osxcross ./build.sh
|
||||
|
||||
FROM rust:1.93-bookworm
|
||||
FROM rust:1.91-bookworm
|
||||
ADD --chmod=644 "https://apt.llvm.org/llvm-snapshot.gpg.key" /etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||
COPY llvm.sources /etc/apt/sources.list.d/llvm.sources
|
||||
RUN rustup target add x86_64-pc-windows-msvc && \
|
||||
rustup target add x86_64-apple-darwin && \
|
||||
rustup target add aarch64-apple-darwin && \
|
||||
apt-get update && \
|
||||
apt-get install -y clang-21 lld-21 libc6-dev libasound2-dev libudev-dev genisoimage mingw-w64 && \
|
||||
apt-get install -y clang-20 lld-20 libc6-dev libasound2-dev libudev-dev genisoimage mingw-w64 && \
|
||||
cargo install cargo-bundle xwin && \
|
||||
xwin --accept-license splat --output xwin && \
|
||||
rm -rf .xwin-cache && \
|
||||
ln -s $(which clang-21) /usr/bin/clang && \
|
||||
ln -s $(which clang++-21) /usr/bin/clang++
|
||||
ln -s $(which clang-20) /usr/bin/clang && \
|
||||
ln -s $(which clang++-20) /usr/bin/clang++
|
||||
COPY --from=osxcross /osxcross /osxcross
|
||||
|
||||
ENV PATH="/osxcross/bin:$PATH" \
|
||||
LD_LIBRARY_PATH="/osxcross/lib" \
|
||||
CC="clang-21" CXX="clang++-21" AR="llvm-ar-21" \
|
||||
CC="clang-20" CXX="clang++-20" AR="llvm-ar-20" \
|
||||
CC_x86_64-apple-darwin="o64-clang" \
|
||||
CXX_x86_64-apple-darwin="o64-clang++" \
|
||||
CC_aarch64-apple-darwin="oa64-clang" \
|
||||
@@ -43,11 +43,11 @@ ENV PATH="/osxcross/bin:$PATH" \
|
||||
SHROOMS_CFLAGS_x86_64-pc-windows-msvc="-flto" \
|
||||
CFLAGS_x86_64-pc-windows-msvc="-I/xwin/crt/include -I/xwin/sdk/include/ucrt -I/xwin/sdk/include/um -I/xwin/sdk/include/shared" \
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS="-Lnative=/xwin/crt/lib/x86_64 -Lnative=/xwin/sdk/lib/um/x86_64 -Lnative=/xwin/sdk/lib/ucrt/x86_64 -Clinker-plugin-lto -Clink-arg=-fuse-ld=lld" \
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER="lld-link-21" \
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER="lld-link-20" \
|
||||
CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER="o64-clang" \
|
||||
CARGO_TARGET_X86_64_APPLE_DARWIN_AR="llvm-ar-21" \
|
||||
CARGO_TARGET_X86_64_APPLE_DARWIN_AR="llvm-ar-20" \
|
||||
CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER="oa64-clang" \
|
||||
CARGO_TARGET_AARCH64_APPLE_DARWIN_AR="llvm-ar-21" \
|
||||
RC_PATH="llvm-rc-21" \
|
||||
CARGO_TARGET_AARCH64_APPLE_DARWIN_AR="llvm-ar-20" \
|
||||
RC_PATH="llvm-rc-20" \
|
||||
MACOSX_DEPLOYMENT_TARGET="14.5"
|
||||
ENTRYPOINT ["bash"]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Types: deb deb-src
|
||||
URIs: http://apt.llvm.org/bookworm/
|
||||
Suites: llvm-toolchain-bookworm-21
|
||||
Suites: llvm-toolchain-bookworm-20
|
||||
Components: main
|
||||
|
||||
+2
-3
@@ -382,8 +382,7 @@ impl WgpuState {
|
||||
});
|
||||
|
||||
let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference:
|
||||
wgpu::PowerPreference::from_env().unwrap_or(wgpu::PowerPreference::LowPower),
|
||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||
compatible_surface: None,
|
||||
force_fallback_adapter: false,
|
||||
}))
|
||||
@@ -440,7 +439,7 @@ impl Viewport {
|
||||
egui_extras::install_image_loaders(&ctx);
|
||||
|
||||
let wgpu_config = egui_wgpu::WgpuConfiguration {
|
||||
present_mode: wgpu::PresentMode::AutoVsync,
|
||||
present_mode: wgpu::PresentMode::AutoNoVsync,
|
||||
wgpu_setup: egui_wgpu::WgpuSetup::Existing(egui_wgpu::WgpuSetupExisting {
|
||||
instance: wgpu.instance.clone(),
|
||||
adapter: wgpu.adapter.clone(),
|
||||
|
||||
+33
-38
@@ -1,17 +1,17 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use audioadapter_buffers::direct::InterleavedSlice;
|
||||
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
use rubato::Resampler;
|
||||
use itertools::Itertools;
|
||||
use rubato::{FastFixedOut, Resampler};
|
||||
use tracing::error;
|
||||
|
||||
pub struct Audio {
|
||||
#[allow(unused)]
|
||||
stream: cpal::Stream,
|
||||
sampler: rubato::Async<f32>,
|
||||
input_buffer: Vec<f32>,
|
||||
output_buffer: Vec<f32>,
|
||||
sampler: FastFixedOut<f32>,
|
||||
input_buffer: Vec<Vec<f32>>,
|
||||
output_buffer: Vec<Vec<f32>>,
|
||||
sample_sink: rtrb::Producer<f32>,
|
||||
}
|
||||
|
||||
@@ -32,18 +32,17 @@ impl Audio {
|
||||
let mut config = config.with_max_sample_rate().config();
|
||||
let resample_ratio = config.sample_rate.0 as f64 / VB_FREQUENCY as f64;
|
||||
let chunk_size = (834.0 * resample_ratio) as usize;
|
||||
let sampler = rubato::Async::new_poly(
|
||||
let sampler = FastFixedOut::new(
|
||||
resample_ratio,
|
||||
64.0,
|
||||
rubato::PolynomialDegree::Cubic,
|
||||
chunk_size,
|
||||
2,
|
||||
rubato::FixedAsync::Output,
|
||||
)?;
|
||||
config.buffer_size = cpal::BufferSize::Fixed(sampler.output_frames_max() as u32);
|
||||
|
||||
let input_buffer = Vec::with_capacity(sampler.nbr_channels() * sampler.input_frames_max());
|
||||
let output_buffer = vec![0.0; sampler.nbr_channels() * sampler.output_frames_max()];
|
||||
let input_buffer = sampler.input_buffer_allocate(true);
|
||||
let output_buffer = sampler.output_buffer_allocate(true);
|
||||
let (sample_sink, mut sample_source) =
|
||||
rtrb::RingBuffer::new(sampler.output_frames_max() * 4);
|
||||
|
||||
@@ -79,38 +78,34 @@ impl Audio {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update(&mut self, mut samples: &[f32]) {
|
||||
while self.input_buffer.len() + samples.len() >= self.sampler.input_frames_next() * 2 {
|
||||
let samples_needed =
|
||||
(self.sampler.input_frames_next() * 2).saturating_sub(self.input_buffer.len());
|
||||
let (current_samples, future_samples) = samples.split_at(samples_needed);
|
||||
self.input_buffer.extend_from_slice(current_samples);
|
||||
samples = future_samples;
|
||||
|
||||
let buffer_in =
|
||||
InterleavedSlice::new(&self.input_buffer, 2, self.sampler.input_frames_next())
|
||||
pub fn update(&mut self, samples: &[f32]) {
|
||||
for sample in samples.chunks_exact(2) {
|
||||
for (channel, value) in self.input_buffer.iter_mut().zip(sample) {
|
||||
channel.push(*value);
|
||||
}
|
||||
if self.input_buffer[0].len() >= self.sampler.input_frames_next() {
|
||||
let (_, output_samples) = self
|
||||
.sampler
|
||||
.process_into_buffer(&self.input_buffer, &mut self.output_buffer, None)
|
||||
.unwrap();
|
||||
let mut buffer_out = InterleavedSlice::new_mut(
|
||||
&mut self.output_buffer,
|
||||
2,
|
||||
self.sampler.output_frames_next(),
|
||||
)
|
||||
.unwrap();
|
||||
let (_, output_samples) = self
|
||||
.sampler
|
||||
.process_into_buffer(&buffer_in, &mut buffer_out, None)
|
||||
.unwrap();
|
||||
let chunk = match self.sample_sink.write_chunk_uninit(output_samples * 2) {
|
||||
Ok(c) => c,
|
||||
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
||||
self.sample_sink.write_chunk_uninit(n).unwrap()
|
||||
}
|
||||
};
|
||||
chunk.fill_from_iter(self.output_buffer[..output_samples * 2].iter().copied());
|
||||
|
||||
self.input_buffer.clear();
|
||||
let chunk = match self.sample_sink.write_chunk_uninit(output_samples * 2) {
|
||||
Ok(c) => c,
|
||||
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
||||
self.sample_sink.write_chunk_uninit(n).unwrap()
|
||||
}
|
||||
};
|
||||
let interleaved = self.output_buffer[0]
|
||||
.iter()
|
||||
.interleave(self.output_buffer[1].iter())
|
||||
.cloned();
|
||||
chunk.fill_from_iter(interleaved);
|
||||
|
||||
for channel in &mut self.input_buffer {
|
||||
channel.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.input_buffer.extend_from_slice(samples);
|
||||
|
||||
while self.sample_sink.slots() < self.sampler.output_frames_max() * 2 {
|
||||
std::thread::sleep(Duration::from_micros(500));
|
||||
|
||||
@@ -245,12 +245,9 @@ impl ParseContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_inline<'a>(
|
||||
ctx: &mut ParseContext<'a>,
|
||||
node: gimli::EntriesTreeNode<'a, '_, Reader<'a>>,
|
||||
) -> Result<()> {
|
||||
fn parse_inline(ctx: &mut ParseContext, node: gimli::EntriesTreeNode<Reader>) -> Result<()> {
|
||||
if node.entry().tag() == gimli::DW_TAG_inlined_subroutine
|
||||
&& let Some(attr) = node.entry().attr_value(gimli::DW_AT_abstract_origin)
|
||||
&& let Some(attr) = node.entry().attr_value(gimli::DW_AT_abstract_origin)?
|
||||
&& let Some(name) = ctx.name_attr(attr)?
|
||||
{
|
||||
let name = Arc::new(name);
|
||||
|
||||
+1
-1
@@ -683,7 +683,7 @@ impl ShortcutProvider {
|
||||
else {
|
||||
return true;
|
||||
};
|
||||
if *key != shortcut.logical_key || !modifiers.contains(shortcut.modifiers) {
|
||||
if shortcut.logical_key != *key || !shortcut.modifiers.contains(*modifiers) {
|
||||
return true;
|
||||
}
|
||||
if matches!(command, Command::FastForward(_)) {
|
||||
|
||||
Reference in New Issue
Block a user