mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c3f4b11519 | |||
| 921a0d5362 | |||
| 24fc5b9638 | |||
| 1559856483 | |||
| 1deb91fc1e | |||
| 726a58f854 | |||
| fe0297690f | |||
| 847df61526 | |||
| 6de8128f5b | |||
| 6c09176d12 | |||
| 2050098735 | |||
| d3ecc37da6 | |||
| a0237e9f7d | |||
| d6d608b674 | |||
| f254bec968 | |||
| bd4aff2b2c | |||
| 0bf70a77ea | |||
| e23e7f33c1 | |||
| 9d0516545e | |||
| e3023a902f | |||
| 431c7c2a8d | |||
| cf99539f85 | |||
| c2493b829e | |||
| 2f25de55d7 | |||
| 116ffe9845 | |||
| f3271cba63 | |||
| 9037680cda | |||
| fc41e26a6d | |||
| d1f28bb7a8 | |||
| 9db831fdef | |||
| 004b603e96 | |||
| 8661e2c9b1 | |||
| c712f2a288 |
@@ -61,7 +61,7 @@ jobs:
|
||||
mkdir output
|
||||
cp target/${{ matrix.target }}/release/gopher64 output/gopher64-${{ matrix.arch }}
|
||||
- name: Upload file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: gopher64-${{ matrix.arch }}
|
||||
path: output/gopher64-${{ matrix.arch }}
|
||||
@@ -104,13 +104,13 @@ jobs:
|
||||
cp target/${{ matrix.target }}/release/gopher64.exe output/gopher64-${{ matrix.arch }}.exe
|
||||
- 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 }}"
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
env:
|
||||
AR: ar
|
||||
- name: Upload file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: gopher64-${{ matrix.arch }}
|
||||
path: output/gopher64-${{ matrix.arch }}
|
||||
|
||||
Generated
+772
-737
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -1,16 +1,16 @@
|
||||
[package]
|
||||
name = "gopher64"
|
||||
version = "1.1.6"
|
||||
version = "1.1.9"
|
||||
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.18", default-features = false }
|
||||
sevenz-rust2 = { version = "0.19", default-features = false }
|
||||
chrono = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
@@ -26,7 +26,7 @@ spin_sleep = "1.3"
|
||||
encoding_rs = "0.8"
|
||||
mimalloc = "0.1"
|
||||
regex = "1.11"
|
||||
tokio-tungstenite = "0.27"
|
||||
tokio-tungstenite = "0.28"
|
||||
futures = "0.3"
|
||||
socket2 = { version = "0.6", features = ["all"] }
|
||||
rand_chacha = "0.9"
|
||||
|
||||
@@ -73,7 +73,6 @@ fn main() {
|
||||
|
||||
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
let profile = std::env::var("PROFILE").unwrap();
|
||||
let opt_flag = if arch == "x86_64" {
|
||||
"-march=x86-64-v3"
|
||||
} else if arch == "aarch64" {
|
||||
@@ -96,11 +95,10 @@ fn main() {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if profile == "release" {
|
||||
volk_build.flag("-flto=thin");
|
||||
rdp_build.flag("-flto=thin");
|
||||
simd_build.flag("-flto=thin");
|
||||
}
|
||||
volk_build.flag("-flto=thin");
|
||||
rdp_build.flag("-flto=thin");
|
||||
simd_build.flag("-flto=thin");
|
||||
|
||||
volk_build.compile("volk");
|
||||
rdp_build.compile("parallel-rdp");
|
||||
|
||||
|
||||
+47
-27
@@ -64,6 +64,7 @@ typedef struct
|
||||
uint32_t texture_pixel_size;
|
||||
uint32_t texture_width;
|
||||
uint32_t framebuffer_height;
|
||||
bool depth_buffer_enabled;
|
||||
} FrameBufferInfo;
|
||||
|
||||
typedef struct
|
||||
@@ -274,6 +275,11 @@ void rdp_new_processor(GFX_INFO _gfx_info)
|
||||
flags |= RDP::COMMAND_PROCESSOR_FLAG_SUPER_SAMPLED_DITHER_BIT;
|
||||
flags |= RDP::COMMAND_PROCESSOR_FLAG_UPSCALING_4X_BIT;
|
||||
}
|
||||
else if (gfx_info.upscale == 8)
|
||||
{
|
||||
flags |= RDP::COMMAND_PROCESSOR_FLAG_SUPER_SAMPLED_DITHER_BIT;
|
||||
flags |= RDP::COMMAND_PROCESSOR_FLAG_UPSCALING_8X_BIT;
|
||||
}
|
||||
|
||||
processor = new RDP::CommandProcessor(wsi->get_device(), gfx_info.RDRAM, 0, gfx_info.RDRAM_SIZE, gfx_info.RDRAM_SIZE / 2, flags);
|
||||
}
|
||||
@@ -570,17 +576,18 @@ void rdp_check_framebuffers(uint32_t address, uint32_t length)
|
||||
{
|
||||
address >>= 3;
|
||||
length = (length + 7) >> 3;
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
|
||||
if (address >= rdram_dirty.size())
|
||||
return;
|
||||
|
||||
uint32_t end_addr = std::min(address + length, static_cast<uint32_t>(rdram_dirty.size()));
|
||||
|
||||
auto it = std::find(rdram_dirty.begin() + address, rdram_dirty.begin() + end_addr, true);
|
||||
if (it != rdram_dirty.begin() + end_addr)
|
||||
{
|
||||
if (address + i >= rdram_dirty.size())
|
||||
return;
|
||||
if (rdram_dirty[address + i])
|
||||
{
|
||||
processor->wait_for_timeline(sync_signal);
|
||||
rdram_dirty.assign(gfx_info.RDRAM_SIZE >> 3, false);
|
||||
sync_signal = 0;
|
||||
return;
|
||||
}
|
||||
processor->wait_for_timeline(sync_signal);
|
||||
rdram_dirty.assign(gfx_info.RDRAM_SIZE >> 3, false);
|
||||
sync_signal = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,21 +696,14 @@ uint64_t rdp_process_commands()
|
||||
|
||||
switch (RDP::Op(command))
|
||||
{
|
||||
case RDP::Op::FillZBufferTriangle:
|
||||
case RDP::Op::TextureZBufferTriangle:
|
||||
case RDP::Op::ShadeZBufferTriangle:
|
||||
case RDP::Op::ShadeTextureZBufferTriangle:
|
||||
{
|
||||
uint32_t 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);
|
||||
}
|
||||
}
|
||||
case RDP::Op::FillTriangle:
|
||||
case RDP::Op::FillZBufferTriangle:
|
||||
case RDP::Op::TextureTriangle:
|
||||
case RDP::Op::TextureZBufferTriangle:
|
||||
case RDP::Op::ShadeTriangle:
|
||||
case RDP::Op::ShadeZBufferTriangle:
|
||||
case RDP::Op::ShadeTextureTriangle:
|
||||
case RDP::Op::ShadeTextureZBufferTriangle:
|
||||
case RDP::Op::TextureRectangle:
|
||||
case RDP::Op::TextureRectangleFlip:
|
||||
case RDP::Op::FillRectangle:
|
||||
@@ -711,7 +711,18 @@ 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)
|
||||
{
|
||||
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])
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -723,19 +734,21 @@ 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;
|
||||
case RDP::Op::LoadBlock:
|
||||
{
|
||||
uint32_t upper_left_s = ((w1 >> 12) & 0xFFF) >> 2;
|
||||
uint32_t upper_left_t = (w1 & 0xFFF) >> 2;
|
||||
uint32_t upper_left_s = ((w1 >> 12) & 0xFFF);
|
||||
uint32_t upper_left_t = (w1 & 0xFFF);
|
||||
uint32_t offset_address = (rdp_device.frame_buffer_info.texture_address + pixel_size(rdp_device.frame_buffer_info.texture_pixel_size, upper_left_s + upper_left_t * rdp_device.frame_buffer_info.texture_width)) >> 3;
|
||||
if (offset_address < rdram_dirty.size() && !rdram_dirty[offset_address])
|
||||
{
|
||||
uint32_t lower_right_s = ((w2 >> 12) & 0xFFF) >> 2;
|
||||
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 lower_right_s = ((w2 >> 12) & 0xFFF);
|
||||
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;
|
||||
@@ -771,6 +784,13 @@ uint64_t rdp_process_commands()
|
||||
rdp_device.frame_buffer_info.framebuffer_height = lower_right_y - upper_left_y;
|
||||
}
|
||||
break;
|
||||
case RDP::Op::SetOtherModes:
|
||||
{
|
||||
uint8_t cycle_type = (w1 >> 20) & 3;
|
||||
uint8_t depth_read_write = (w2 >> 4) & 3;
|
||||
rdp_device.frame_buffer_info.depth_buffer_enabled = ((cycle_type & 2) == 0) && (depth_read_write != 0);
|
||||
}
|
||||
break;
|
||||
case RDP::Op::SyncFull:
|
||||
sync_signal = processor->signal_timeline();
|
||||
|
||||
|
||||
Submodule parallel-rdp/parallel-rdp-standalone updated: ba3293573d...091c7fec1c
+1
-1
@@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "1.90.0"
|
||||
channel = "1.91.0"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -22,8 +22,8 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
|
||||
let data = std::str::from_utf8(
|
||||
&device.cart.is_viewer_buffer[0x20_usize..(0x20 + length) as usize],
|
||||
);
|
||||
if data.is_ok() {
|
||||
print!("{}", data.unwrap());
|
||||
if let Ok(data) = data {
|
||||
print!("{}", data);
|
||||
}
|
||||
} else {
|
||||
let mut data = u32::from_be_bytes(
|
||||
|
||||
+10
-5
@@ -1,6 +1,6 @@
|
||||
use crate::device;
|
||||
|
||||
const MI_INIT_MODE_REG: u32 = 0;
|
||||
pub const MI_INIT_MODE_REG: u32 = 0;
|
||||
const MI_VERSION_REG: u32 = 1;
|
||||
pub const MI_INTR_REG: u32 = 2;
|
||||
pub const MI_INTR_MASK_REG: u32 = 3;
|
||||
@@ -29,7 +29,7 @@ const MI_CLR_DP: u32 = 1 << 10;
|
||||
const MI_SET_DP: u32 = 1 << 11;
|
||||
|
||||
/* mode read */
|
||||
const MI_INIT_MODE: u32 = 1 << 7;
|
||||
pub const MI_INIT_MODE: u32 = 1 << 7;
|
||||
const MI_EBUS_MODE: u32 = 1 << 8;
|
||||
const MI_RDRAM_MODE: u32 = 1 << 9;
|
||||
|
||||
@@ -42,7 +42,7 @@ const MI_CLR_DP_INTR: u32 = 1 << 11;
|
||||
const MI_CLR_RDRAM: u32 = 1 << 12;
|
||||
const MI_SET_RDRAM: u32 = 1 << 13;
|
||||
|
||||
const MI_INIT_LENGTH_MASK: u32 = 0b1111111;
|
||||
pub const MI_INIT_LENGTH_MASK: u32 = 0b1111111;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Mi {
|
||||
@@ -78,11 +78,16 @@ fn update_init_mode(device: &mut device::Device, w: u32) {
|
||||
device.mi.regs[MI_INIT_MODE_REG as usize] |= w & MI_INIT_LENGTH_MASK;
|
||||
|
||||
if w & MI_CLR_INIT != 0 {
|
||||
for i in 0..(0x3F00000 >> 16) {
|
||||
device.memory.memory_map_write[i] = device::rdram::write_mem;
|
||||
}
|
||||
device.mi.regs[MI_INIT_MODE_REG as usize] &= !MI_INIT_MODE
|
||||
}
|
||||
if w & MI_SET_INIT != 0 {
|
||||
panic!("MI_SET_INIT not implemented")
|
||||
//device.mi.regs[MI_INIT_MODE_REG as usize] |= MI_INIT_MODE
|
||||
for i in 0..(0x3F00000 >> 16) {
|
||||
device.memory.memory_map_write[i] = device::rdram::write_mem_repeat;
|
||||
}
|
||||
device.mi.regs[MI_INIT_MODE_REG as usize] |= MI_INIT_MODE
|
||||
}
|
||||
if w & MI_CLR_EBUS != 0 {
|
||||
device.mi.regs[MI_INIT_MODE_REG as usize] &= !MI_EBUS_MODE
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -85,6 +85,39 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
|
||||
.copy_from_slice(&data.to_ne_bytes());
|
||||
}
|
||||
|
||||
pub fn write_mem_repeat(device: &mut device::Device, address: u64, value: u32, mask: u32) {
|
||||
if mask != 0xFFFFFFFF {
|
||||
panic!("RDRAM write_mem_repeat called with mask {:#x}", mask);
|
||||
}
|
||||
|
||||
let repeat_length = (device.mi.regs[device::mi::MI_INIT_MODE_REG as usize]
|
||||
& device::mi::MI_INIT_LENGTH_MASK)
|
||||
+ 1;
|
||||
|
||||
if !repeat_length.is_multiple_of(4) {
|
||||
panic!(
|
||||
"RDRAM write_mem_repeat called with non-word-aligned length {}",
|
||||
repeat_length
|
||||
);
|
||||
}
|
||||
|
||||
ui::video::check_framebuffers(address as u32, repeat_length);
|
||||
|
||||
for i in (0..repeat_length as u64).step_by(4) {
|
||||
device
|
||||
.rdram
|
||||
.mem
|
||||
.get_mut((address + i) as usize..(address + i) as usize + 4)
|
||||
.unwrap_or(&mut [0; 4])
|
||||
.copy_from_slice(&value.to_ne_bytes());
|
||||
}
|
||||
|
||||
device.mi.regs[device::mi::MI_INIT_MODE_REG as usize] &= !device::mi::MI_INIT_MODE;
|
||||
for i in 0..(0x3F00000 >> 16) {
|
||||
device.memory.memory_map_write[i] = device::rdram::write_mem;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_regs(
|
||||
device: &mut device::Device,
|
||||
address: u64,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,9 +15,7 @@ pub struct Dirs {
|
||||
}
|
||||
|
||||
pub struct Audio {
|
||||
pub audio_device_spec: sdl3_sys::audio::SDL_AudioSpec,
|
||||
pub audio_stream: *mut sdl3_sys::audio::SDL_AudioStream,
|
||||
pub audio_device: u32,
|
||||
pub gain: f32,
|
||||
}
|
||||
|
||||
@@ -183,9 +181,7 @@ impl Ui {
|
||||
game_id: String::new(),
|
||||
game_hash: String::new(),
|
||||
audio: Audio {
|
||||
audio_device_spec: Default::default(),
|
||||
audio_stream: std::ptr::null_mut(),
|
||||
audio_device: 0,
|
||||
gain: 1.0,
|
||||
},
|
||||
video: Video {
|
||||
|
||||
+9
-34
@@ -3,32 +3,6 @@ use crate::ui;
|
||||
|
||||
pub fn init(ui: &mut ui::Ui, frequency: u64) {
|
||||
ui::sdl_init(sdl3_sys::init::SDL_INIT_AUDIO);
|
||||
|
||||
let device_audio_spec = sdl3_sys::audio::SDL_AudioSpec {
|
||||
format: sdl3_sys::audio::SDL_AUDIO_S16LE,
|
||||
freq: 48000,
|
||||
channels: 2,
|
||||
};
|
||||
ui.audio.audio_device = unsafe {
|
||||
sdl3_sys::audio::SDL_OpenAudioDevice(
|
||||
sdl3_sys::audio::SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
|
||||
&device_audio_spec,
|
||||
)
|
||||
};
|
||||
if ui.audio.audio_device == 0 {
|
||||
panic!("Could not open audio device");
|
||||
}
|
||||
|
||||
if !unsafe {
|
||||
sdl3_sys::audio::SDL_GetAudioDeviceFormat(
|
||||
ui.audio.audio_device,
|
||||
&mut ui.audio.audio_device_spec,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
} {
|
||||
panic!("Could not get audio device format");
|
||||
}
|
||||
|
||||
init_game_audio(ui, frequency);
|
||||
}
|
||||
|
||||
@@ -40,25 +14,26 @@ pub fn init_game_audio(ui: &mut ui::Ui, frequency: u64) {
|
||||
};
|
||||
|
||||
ui.audio.audio_stream = unsafe {
|
||||
sdl3_sys::audio::SDL_CreateAudioStream(&game_audio_spec, &ui.audio.audio_device_spec)
|
||||
sdl3_sys::audio::SDL_OpenAudioDeviceStream(
|
||||
sdl3_sys::audio::SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
|
||||
&game_audio_spec,
|
||||
None,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if ui.audio.audio_stream.is_null() {
|
||||
return;
|
||||
panic!("Could not create audio stream");
|
||||
}
|
||||
if !unsafe {
|
||||
sdl3_sys::audio::SDL_SetAudioStreamGain(ui.audio.audio_stream, ui.audio.gain)
|
||||
&& sdl3_sys::audio::SDL_BindAudioStream(ui.audio.audio_device, ui.audio.audio_stream)
|
||||
&& sdl3_sys::audio::SDL_ResumeAudioStreamDevice(ui.audio.audio_stream)
|
||||
} {
|
||||
panic!("Could not bind audio stream");
|
||||
panic!("Could not resume audio stream");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(ui: &mut ui::Ui) {
|
||||
close_game_audio(ui);
|
||||
unsafe {
|
||||
sdl3_sys::audio::SDL_CloseAudioDevice(ui.audio.audio_device);
|
||||
ui.audio.audio_device = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close_game_audio(ui: &mut ui::Ui) {
|
||||
|
||||
+3
-2
@@ -111,6 +111,7 @@ fn settings_window(app: &AppWindow, config: &ui::config::Config) {
|
||||
1 => 0,
|
||||
2 => 1,
|
||||
4 => 2,
|
||||
8 => 3,
|
||||
_ => 0,
|
||||
};
|
||||
app.set_resolution(combobox_value);
|
||||
@@ -249,7 +250,7 @@ pub fn save_settings(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
config.emulation.overclock = app.get_overclock_n64_cpu();
|
||||
config.emulation.disable_expansion_pak = app.get_disable_expansion_pak();
|
||||
config.emulation.usb = app.get_emulate_usb();
|
||||
let upscale_values = [1, 2, 4];
|
||||
let upscale_values = [1, 2, 4, 8];
|
||||
config.video.upscale = upscale_values[app.get_resolution() as usize];
|
||||
|
||||
config.input.emulate_vru = app.get_emulate_vru();
|
||||
@@ -471,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(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export component Settings inherits Page {
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
model: ["1x", "2x", "4x"];
|
||||
model: ["1x", "2x", "4x", "8x"];
|
||||
current-index: SettingsData.resolution;
|
||||
selected => {
|
||||
SettingsData.resolution = self.current-index;
|
||||
|
||||
+7
-2
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user