Compare commits

...

21 Commits

Author SHA1 Message Date
Logan McNaughton 581cc0b9aa cargo update 2025-11-05 15:16:57 +01:00
Logan McNaughton 6f6e21c718 tweak build options 2025-11-05 15:12:12 +01:00
Logan McNaughton 181774a1de pass netplay_id to workflow 2025-11-04 15:38:30 +01:00
Logan McNaughton 002fbbe8a4 set netplay id from environment (#606) 2025-11-04 08:27:32 +01:00
Logan McNaughton ab630cc8cb Use skia backend for gui (#605)
* Use skia backend for gui

* more

* use clang-cl

* more

* more
2025-11-03 23:07:10 +01:00
Logan McNaughton 06f9c56a79 bump to 1.1.10 2025-10-30 22:52:34 +01:00
Logan McNaughton c3f4b11519 update sdl3 2025-10-30 22:47:45 +01:00
Logan McNaughton 921a0d5362 Rust 1.91 (#599) 2025-10-30 20:14:39 +01:00
Logan McNaughton 24fc5b9638 update parallel-rdp 2025-10-30 13:59:20 +01:00
dependabot[bot] 1559856483 Bump signpath/github-action-submit-signing-request from 1.3 to 2.0 (#597)
Bumps [signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request) from 1.3 to 2.0.
- [Release notes](https://github.com/signpath/github-action-submit-signing-request/releases)
- [Commits](https://github.com/signpath/github-action-submit-signing-request/compare/v1.3...v2.0)

---
updated-dependencies:
- dependency-name: signpath/github-action-submit-signing-request
  dependency-version: '2.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 08:36:02 +01:00
dependabot[bot] 1deb91fc1e Bump actions/upload-artifact from 4 to 5 (#596)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 06:01:31 +01:00
Logan McNaughton 726a58f854 cargo update 2025-10-26 13:45:56 +01:00
Logan McNaughton fe0297690f pump events during vi (#593)
* pump events during vi

* add var

* more

* more
2025-10-26 13:42:25 +01:00
Logan McNaughton 847df61526 Add pause between key bindings (#594) 2025-10-26 13:33:40 +01:00
Logan McNaughton 6de8128f5b cargo update 2025-10-12 12:30:57 +02:00
Logan McNaughton 6c09176d12 add .srm for GB saves 2025-10-11 19:32:35 +02:00
Logan McNaughton 2050098735 fix out of bounds access (#590) 2025-10-06 09:02:50 +02:00
Logan McNaughton d3ecc37da6 fix compare interrupt issue (#588) 2025-10-01 10:05:03 +02:00
Logan McNaughton a0237e9f7d bump to 1.1.9 2025-09-28 10:00:37 +02:00
Logan McNaughton d6d608b674 Revert "more audio cleanup"
This reverts commit f3271cba63.
2025-09-28 09:59:02 +02:00
Logan McNaughton f254bec968 bump to 1.1.8 2025-09-27 21:33:21 +02:00
16 changed files with 1149 additions and 1148 deletions
+13 -5
View File
@@ -48,7 +48,7 @@ jobs:
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev \
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev libfreetype-dev libfontconfig-dev
version: ${{ matrix.target }}-1.0
- name: Install LLVM and Clang
uses: KyleMayes/install-llvm-action@v2
@@ -60,8 +60,10 @@ jobs:
cargo build --release -v --target=${{ matrix.target }}
mkdir output
cp target/${{ matrix.target }}/release/gopher64 output/gopher64-${{ matrix.arch }}
env:
NETPLAY_ID: ${{ secrets.NETPLAY_ID }}
- name: Upload file
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: gopher64-${{ matrix.arch }}
path: output/gopher64-${{ matrix.arch }}
@@ -102,15 +104,19 @@ jobs:
cargo build --release -v --target=${{ matrix.target }}
mkdir output
cp target/${{ matrix.target }}/release/gopher64.exe output/gopher64-${{ matrix.arch }}.exe
env:
CC: clang-cl
CXX: clang-cl
NETPLAY_ID: ${{ secrets.NETPLAY_ID }}
- name: Upload unsigned artifact
id: upload-unsigned-artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: gopher64-${{ matrix.arch }}
path: output/gopher64-${{ matrix.arch }}.exe
- name: SignPath
if: ${{ github.ref_type == 'tag' }}
uses: signpath/github-action-submit-signing-request@v1.3
uses: signpath/github-action-submit-signing-request@v2.0
with:
api-token: "${{ secrets.SIGNPATH_API_TOKEN }}"
organization-id: "${{ secrets.SIGNPATH_ORG_ID }}"
@@ -121,6 +127,7 @@ jobs:
wait-for-completion: false
build-macos:
if: false
runs-on: macos-15
strategy:
fail-fast: false
@@ -145,8 +152,9 @@ jobs:
cp target/${{ matrix.target }}/release/gopher64 output/gopher64-${{ matrix.arch }}
env:
AR: ar
NETPLAY_ID: ${{ secrets.NETPLAY_ID }}
- name: Upload file
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: gopher64-${{ matrix.arch }}
path: output/gopher64-${{ matrix.arch }}
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev \
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev libfreetype-dev libfontconfig-dev
version: lint-1.0
- name: Install LLVM and Clang
uses: KyleMayes/install-llvm-action@v2
Generated
+1080 -1124
View File
File diff suppressed because it is too large Load Diff
+8 -5
View File
@@ -1,25 +1,25 @@
[package]
name = "gopher64"
version = "1.1.7"
version = "1.1.10"
edition = "2024"
rust-version = "1.90"
rust-version = "1.91"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dirs = "6.0"
zip = "5.1"
zip = "6.0"
governor = "0.10"
sevenz-rust2 = { version = "0.19", default-features = false }
chrono = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-big-array = "0.5"
slint = { version = "1.12", default-features = false, features = ["compat-1-2", "std", "backend-winit", "renderer-femtovg-wgpu"] }
slint = { version = "1.12", default-features = false, features = ["compat-1-2", "std", "backend-winit", "renderer-skia-vulkan"] }
open = "5.3"
sha2 = "0.10"
sdl3-sys = { version = "0.5", features = ["build-from-source-static"] }
sdl3-ttf-sys = { version = "0.2", features = ["build-static-vendored", "no-sdlttf-harfbuzz", "no-sdlttf-plutosvg"] }
sdl3-ttf-sys = { version = "0.2", features = ["build-from-source-static", "no-sdlttf-harfbuzz", "no-sdlttf-plutosvg"] }
rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "tokio"] }
tokio = {version = "1.46", features = ["rt-multi-thread", "macros"] }
spin_sleep = "1.3"
@@ -45,7 +45,10 @@ cc = { version = "1.2", features = ["parallel"] }
[profile.release]
panic = "abort"
lto = "thin"
strip = true
[profile.release-with-debug]
inherits = "release"
debug = true
strip = false
panic = "unwind"
+3
View File
@@ -193,5 +193,8 @@ fn main() {
let git_hash = String::from_utf8(git_output.stdout).unwrap();
println!("cargo:rustc-env=GIT_HASH={git_hash}");
let netplay_id = std::env::var("NETPLAY_ID").unwrap_or("gopher64".to_string());
println!("cargo:rustc-env=NETPLAY_ID={netplay_id}");
println!("cargo:rustc-env=N64_STACK_SIZE={}", 8 * 1024 * 1024);
}
+8 -4
View File
@@ -711,7 +711,8 @@ uint64_t rdp_process_commands()
uint32_t offset_address = (rdp_device.frame_buffer_info.framebuffer_address + pixel_size(rdp_device.frame_buffer_info.framebuffer_pixel_size, rdp_device.frame_buffer_info.framebuffer_y_offset * rdp_device.frame_buffer_info.framebuffer_width)) >> 3;
if (offset_address < rdram_dirty.size() && !rdram_dirty[offset_address])
{
std::fill_n(rdram_dirty.begin() + offset_address, (pixel_size(rdp_device.frame_buffer_info.framebuffer_pixel_size, rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) + 7) >> 3, true);
uint32_t end_addr = std::min(offset_address + ((pixel_size(rdp_device.frame_buffer_info.framebuffer_pixel_size, rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) + 7) >> 3), static_cast<uint32_t>(rdram_dirty.size()));
std::fill(rdram_dirty.begin() + offset_address, rdram_dirty.begin() + end_addr, true);
}
if (rdp_device.frame_buffer_info.depth_buffer_enabled)
@@ -719,7 +720,8 @@ uint64_t rdp_process_commands()
offset_address = (rdp_device.frame_buffer_info.depthbuffer_address + pixel_size(2, rdp_device.frame_buffer_info.framebuffer_y_offset * rdp_device.frame_buffer_info.framebuffer_width)) >> 3;
if (offset_address < rdram_dirty.size() && !rdram_dirty[offset_address])
{
std::fill_n(rdram_dirty.begin() + offset_address, (pixel_size(2, rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) + 7) >> 3, true);
uint32_t end_addr = std::min(offset_address + ((pixel_size(2, rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) + 7) >> 3), static_cast<uint32_t>(rdram_dirty.size()));
std::fill(rdram_dirty.begin() + offset_address, rdram_dirty.begin() + end_addr, true);
}
}
}
@@ -732,7 +734,8 @@ uint64_t rdp_process_commands()
if (offset_address < rdram_dirty.size() && !rdram_dirty[offset_address])
{
uint32_t lower_right_t = (w2 & 0xFFF) >> 2;
std::fill_n(rdram_dirty.begin() + offset_address, (pixel_size(rdp_device.frame_buffer_info.texture_pixel_size, (lower_right_t - upper_left_t) * rdp_device.frame_buffer_info.texture_width) + 7) >> 3, true);
uint32_t end_addr = std::min(offset_address + ((pixel_size(rdp_device.frame_buffer_info.texture_pixel_size, (lower_right_t - upper_left_t) * rdp_device.frame_buffer_info.texture_width) + 7) >> 3), static_cast<uint32_t>(rdram_dirty.size()));
std::fill(rdram_dirty.begin() + offset_address, rdram_dirty.begin() + end_addr, true);
}
}
break;
@@ -744,7 +747,8 @@ uint64_t rdp_process_commands()
if (offset_address < rdram_dirty.size() && !rdram_dirty[offset_address])
{
uint32_t lower_right_s = ((w2 >> 12) & 0xFFF);
std::fill_n(rdram_dirty.begin() + offset_address, (pixel_size(rdp_device.frame_buffer_info.texture_pixel_size, lower_right_s - upper_left_s) + 7) >> 3, true);
uint32_t end_addr = std::min(offset_address + ((pixel_size(rdp_device.frame_buffer_info.texture_pixel_size, lower_right_s - upper_left_s) + 7) >> 3), static_cast<uint32_t>(rdram_dirty.size()));
std::fill(rdram_dirty.begin() + offset_address, rdram_dirty.begin() + end_addr, true);
}
}
break;
+1 -1
View File
@@ -1,2 +1,2 @@
[toolchain]
channel = "1.90.0"
channel = "1.91.0"
+1
View File
@@ -322,6 +322,7 @@ impl Device {
pif: pif::Pif {
rom: [0; 1984],
ram: [0; 64],
input_gathered: false,
channels: [pif::PifChannel {
tx: None,
tx_buf: None,
-1
View File
@@ -18,7 +18,6 @@ pub fn check_pending_interrupts(device: &mut device::Device) {
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] = device::cop0::COP0_CAUSE_IP2;
} else if device.cpu.cop0.pending_compare_interrupt {
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] = device::cop0::COP0_CAUSE_IP7;
device.cpu.cop0.pending_compare_interrupt = false;
}
if (device.cpu.cop0.regs[device::cop0::COP0_STATUS_REG as usize]
+4
View File
@@ -8,6 +8,7 @@ pub struct Pif {
#[serde(with = "serde_big_array::BigArray")]
pub ram: [u8; 64],
pub channels: [PifChannel; 5],
pub input_gathered: bool,
}
#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
@@ -95,6 +96,9 @@ fn process_channel(device: &mut device::Device, channel: usize) -> usize {
}
pub fn update_pif_ram(device: &mut device::Device) -> u64 {
unsafe { sdl3_sys::events::SDL_PumpEvents() };
device.pif.input_gathered = true;
let mut active_channels = 0;
for k in 0..PIF_CHANNELS_COUNT {
active_channels += process_channel(device, k)
+4
View File
@@ -159,6 +159,10 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
if device.netplay.is_none() && paused {
ui::video::pause_loop();
} else if !device.pif.input_gathered {
unsafe { sdl3_sys::events::SDL_PumpEvents() }; // in case the game isn't prompting for input
} else {
device.pif.input_gathered = false;
}
/*
+14
View File
@@ -86,6 +86,20 @@ pub fn play_audio(device: &device::Device, dram_addr: usize, length: u64) {
let audio_queued =
unsafe { sdl3_sys::audio::SDL_GetAudioStreamQueued(device.ui.audio.audio_stream) } as f64;
let acceptable_latency = (device.ai.freq as f64 * 0.2) * 4.0;
let min_latency = (device.ai.freq as f64 * 0.02) * 4.0;
if audio_queued < min_latency {
let silence_buffer: Vec<u8> = vec![0; min_latency as usize & !3];
if !unsafe {
sdl3_sys::audio::SDL_PutAudioStreamData(
device.ui.audio.audio_stream,
silence_buffer.as_ptr() as *const std::ffi::c_void,
silence_buffer.len() as i32,
)
} {
panic!("Could not play audio");
}
}
if audio_queued < acceptable_latency
&& !unsafe {
+1 -1
View File
@@ -472,7 +472,7 @@ fn open_rom(app: &AppWindow, usb: ui::Usb) {
select_gb_ram[i] = Some(
rfd::AsyncFileDialog::new()
.set_title(format!("GB RAM P{}", i + 1))
.add_filter("GB RAM files", &["sav", "ram", "SAV", "RAM"])
.add_filter("GB RAM files", &["sav", "ram", "srm", "SAV", "RAM", "SRM"])
.pick_file(),
);
}
+7 -2
View File
@@ -385,8 +385,6 @@ pub fn get_controller_paths(game_ui: &ui::Ui) -> Vec<Option<String>> {
}
pub fn get(ui: &ui::Ui, channel: usize) -> InputData {
unsafe { sdl3_sys::events::SDL_PumpEvents() };
let profile_name = ui.config.input.input_profile_binding[channel].clone();
let profile = ui.config.input.input_profiles.get(&profile_name).unwrap();
let mut keys = 0;
@@ -702,6 +700,13 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, d
}
}
}
ui::video::draw_text(
format!("Binding set for {key}").as_str(),
renderer,
text_engine,
font,
);
std::thread::sleep(std::time::Duration::from_millis(200));
}
close_controllers(open_joysticks, open_controllers);
+3 -3
View File
@@ -111,7 +111,7 @@ impl NetplayPages for NetplayJoin {
fn populate_server_names<T: ComponentHandle + NetplayPages + 'static>(weak: slint::Weak<T>) {
let task = reqwest::Client::new()
.get("https://dispatch.gopher64.com/getRegions")
.header("netplay-id", EMU_NAME)
.header("netplay-id", env!("NETPLAY_ID"))
.send();
tokio::spawn(async move {
let mut local_servers: Vec<(String, String)> = vec![];
@@ -296,7 +296,7 @@ pub fn setup_create_window(
let task = reqwest::Client::new()
.get("https://dispatch.gopher64.com/createServer")
.query(&[("region", server_url.strip_prefix("dispatcher:").unwrap())])
.header("netplay-id", EMU_NAME)
.header("netplay-id", env!("NETPLAY_ID"))
.send();
let netplay_read_sender = netplay_read_sender.clone();
let netplay_write_receiver = netplay_write_receiver.resubscribe();
@@ -448,7 +448,7 @@ fn show_netplay_error(message: String) {
fn update_sessions(weak: slint::Weak<NetplayJoin>) {
let task = reqwest::Client::new()
.get("https://dispatch.gopher64.com/getServers")
.header("netplay-id", EMU_NAME)
.header("netplay-id", env!("NETPLAY_ID"))
.send();
tokio::spawn(async move {
let mut dispatcher_servers = std::collections::HashMap::new();