Skip to content

Commit

Permalink
Implement basic wifi hle
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Mar 1, 2025
1 parent df63044 commit d322716
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 7 deletions.
5 changes: 4 additions & 1 deletion src/core/cycle_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::core::cpu_regs::CpuRegs;
use crate::core::emu::Emu;
use crate::core::graphics::gpu::Gpu;
use crate::core::hle::sound_nitro::SoundNitro;
use crate::core::hle::wifi_hle::WifiHle;
use crate::core::memory::cartridge::Cartridge;
use crate::core::memory::dma::Dma;
use crate::core::spu::Spu;
Expand Down Expand Up @@ -80,6 +81,7 @@ pub enum EventType {
SpuSample = 10,
TimerArm9 = 11,
TimerArm7 = 12,
WifiScanHle = 13,
}

pub struct CycleManager {
Expand Down Expand Up @@ -108,7 +110,7 @@ impl CycleManager {
}

pub fn check_events(&mut self, emu: &mut Emu) -> bool {
static LUT: [fn(&mut CycleManager, &mut Emu, u16); EventType::TimerArm7 as usize + 1] = [
static LUT: [fn(&mut CycleManager, &mut Emu, u16); EventType::WifiScanHle as usize + 1] = [
CpuRegs::on_interrupt_event::<{ ARM9 }>,
CpuRegs::on_interrupt_event::<{ ARM7 }>,
Gpu::on_scanline256_event,
Expand All @@ -122,6 +124,7 @@ impl CycleManager {
Spu::on_sample_event,
Timers::on_overflow_event::<{ ARM9 }>,
Timers::on_overflow_event::<{ ARM7 }>,
WifiHle::on_scan_event,
];

self.imm_events_swap.clear();
Expand Down
9 changes: 8 additions & 1 deletion src/core/hle/arm7_hle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::core::hle::power_manager_hle::PowerManagerHle;
use crate::core::hle::rtc_hle::RtcHle;
use crate::core::hle::sound_hle::SoundHle;
use crate::core::hle::touchscreen_hle::TouchscreenHle;
use crate::core::hle::wifi_hle::WifiHle;
use crate::core::CpuType::{ARM7, ARM9};
use bilge::prelude::*;
use std::cmp::Ordering;
Expand Down Expand Up @@ -56,6 +57,7 @@ pub struct Arm7Hle {
pub sound: SoundHle,
power_manager: PowerManagerHle,
cart: CartHle,
pub wifi: WifiHle,
}

impl Arm7Hle {
Expand All @@ -67,9 +69,14 @@ impl Arm7Hle {
sound: SoundHle::new(),
power_manager: PowerManagerHle::new(),
cart: CartHle::new(),
wifi: WifiHle::new(),
}
}

pub fn initialize(emu: &mut Emu) {
WifiHle::initialize(emu);
}

fn send_ipc_sync(val: u8, emu: &mut Emu) {
get_ipc_mut!(emu).sync_regs[ARM9].set_data_in(u4::new(val));
}
Expand Down Expand Up @@ -134,7 +141,7 @@ impl Arm7Hle {
}
IpcFifoTag::WirelessManager => {
if !message.err() {
// todo!()
self.wifi.ipc_recv(data, emu);
}
}
IpcFifoTag::Filesystem => {
Expand Down
1 change: 1 addition & 0 deletions src/core/hle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ mod rtc_hle;
mod sound_hle;
pub mod sound_nitro;
mod touchscreen_hle;
pub mod wifi_hle;
199 changes: 199 additions & 0 deletions src/core/hle/wifi_hle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
use crate::core::cycle_manager::{CycleManager, EventType};
use crate::core::emu::{get_arm7_hle_mut, get_cm_mut, get_mem_mut, Emu};
use crate::core::hle::arm7_hle::{Arm7Hle, IpcFifoTag};
use crate::core::CpuType::ARM7;

#[repr(u8)]
enum WMApiid {
Initialize = 0,
Reset = 1,
End = 2,
Enable = 3,
Disable = 4,
PowerOn = 5,
PowerOff = 6,
SetPParam = 7,
StartParent = 8,
EndParent = 9,
StartScan = 10,
EndScan = 11,
AsyncKindMax = 46,
Unknown = 255,
}

impl From<u8> for WMApiid {
fn from(value: u8) -> Self {
debug_assert!(value <= WMApiid::Unknown as u8);
unsafe { std::mem::transmute(value) }
}
}

#[repr(u8)]
enum WmState {
Ready = 0,
Stop = 1,
Idle = 2,
Class1 = 3,
TestMode = 4,
Scan = 5,
}

#[derive(Default)]
#[repr(C, align(4))]
struct WmArm7Buf {
status_ptr: u32,
_reserved: [u8; 4],
fifo_7_to_9: u32,
}

#[repr(C, align(4))]
struct WmStatus {
state: u16,
busy_app_iid: u16,
}

#[repr(C, align(4))]
struct WmCallback {
api_id: u16,
err_code: u16,
}

#[repr(u8)]
enum WmScanState {
ParentStart = 0,
BeaconSent = 2,
ScanStart = 3,
ParentNotFound = 4,
}

#[repr(C, align(4))]
struct WMStartScanReq {
api_id: u16,
channel: u16,
scan_buf_ptr: u32,
max_channel_time: u16,
}

#[derive(Default)]
#[repr(C, align(4))]
struct WMStartScanCallback {
api_id: u16,
err_code: u16,
wl_cmd_id: u16,
wl_result: u16,
state: u16,
mac_addr: [u8; 6],
channel: u16,
link_level: u16,
}

pub struct WifiHle {
msg_ptr: u32,
status_ptr: u32,
fifo_7_to_9_ptr: u32,
scan_channel: u16,
}

impl WifiHle {
pub(super) fn new() -> Self {
WifiHle {
msg_ptr: 0,
status_ptr: 0,
fifo_7_to_9_ptr: 0,
scan_channel: 0,
}
}

pub(super) fn initialize(emu: &mut Emu) {
const CHAN_MASK: u16 = 0x2082;
emu.mem_write::<{ ARM7 }, _>(0x027FFCFA, CHAN_MASK);
}

fn reply(&self, cmd: WMApiid, status: u16, emu: &mut Emu) {
let callback = WmCallback { api_id: cmd as u16, err_code: status };
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(self.fifo_7_to_9_ptr, &callback, emu);

Arm7Hle::send_ipc_fifo(IpcFifoTag::WirelessManager, self.fifo_7_to_9_ptr, false, emu);
}

pub(super) fn ipc_recv(&mut self, data: u32, emu: &mut Emu) {
self.msg_ptr = data;
let cmd = emu.mem_read::<{ ARM7 }, u16>(self.msg_ptr) & !0x8000;
if (cmd as u8) < WMApiid::AsyncKindMax as u8 {
match WMApiid::from(cmd as u8) {
WMApiid::Initialize => {
let arm7_buf_ptr = emu.mem_read::<{ ARM7 }, _>(self.msg_ptr + 4);
self.status_ptr = emu.mem_read::<{ ARM7 }, _>(self.msg_ptr + 8);
self.fifo_7_to_9_ptr = emu.mem_read::<{ ARM7 }, _>(self.msg_ptr + 12);

let arm7_buf = WmArm7Buf {
status_ptr: self.status_ptr,
fifo_7_to_9: self.fifo_7_to_9_ptr,
..Default::default()
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(arm7_buf_ptr, &arm7_buf, emu);

let status = WmStatus {
state: WmState::Idle as u16,
busy_app_iid: 0,
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(self.status_ptr, &status, emu);

self.reply(WMApiid::Initialize, 0, emu);
}
WMApiid::End => {
let status = WmStatus {
state: WmState::Ready as u16,
busy_app_iid: 0,
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(self.status_ptr, &status, emu);

self.reply(WMApiid::End, 0, emu);
}
WMApiid::StartScan => {
let req = get_mem_mut!(emu).read_struct::<{ ARM7 }, true, WMStartScanReq>(self.msg_ptr, emu);
self.scan_channel = req.channel;

let status = WmStatus {
state: WmState::Scan as u16,
busy_app_iid: 0,
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(self.status_ptr, &status, emu);

const MS_CYCLES: u32 = 34418;
get_cm_mut!(emu).schedule(req.max_channel_time as u32 * MS_CYCLES * 1024, EventType::WifiScanHle, 0);
return;
}
WMApiid::EndScan => {
let status = WmStatus {
state: WmState::Idle as u16,
busy_app_iid: 0,
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(self.status_ptr, &status, emu);

self.reply(WMApiid::EndScan, 0, emu);
}
_ => {}
}

emu.mem_write::<{ ARM7 }, u32>(self.status_ptr + 4, 0);
}

emu.mem_write::<{ ARM7 }, u16>(self.msg_ptr, cmd | 0x8000);
}

pub fn on_scan_event(_: &mut CycleManager, emu: &mut Emu, _: u16) {
let wifi = &get_arm7_hle_mut!(emu).wifi;
let callback = WMStartScanCallback {
state: WmScanState::ParentNotFound as u16,
channel: wifi.scan_channel,
link_level: 0,
..Default::default()
};
get_mem_mut!(emu).write_struct::<{ ARM7 }, true, _>(wifi.fifo_7_to_9_ptr, &callback, emu);
wifi.reply(WMApiid::StartScan, 0, emu);

emu.mem_write::<{ ARM7 }, u32>(wifi.status_ptr + 4, 0);
emu.mem_write::<{ ARM7 }, u16>(wifi.msg_ptr, 0x8000 | WMApiid::StartScan as u16);
}
}
15 changes: 15 additions & 0 deletions src/core/memory/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{utils, DEBUG_LOG};
use std::hint::unreachable_unchecked;
use std::intrinsics::unlikely;
use std::marker::PhantomData;
use std::mem;
use std::sync::atomic::AtomicU16;
use std::sync::Arc;
use CpuType::ARM7;
Expand Down Expand Up @@ -923,4 +924,18 @@ impl Memory {

MemoryMultipleMemsetIo::<CPU, TCM, T>::write(aligned_addr, value, size, emu);
}

pub fn read_struct<const CPU: CpuType, const TCM: bool, T>(&mut self, addr: u32, emu: &mut Emu) -> T
where
[(); size_of::<T>()]:,
{
let mut mem = [0; size_of::<T>()];
self.read_multiple_slice::<CPU, TCM, u8>(addr, emu, &mut mem);
unsafe { mem::transmute_copy(&mem) }
}

pub fn write_struct<const CPU: CpuType, const TCM: bool, T>(&mut self, addr: u32, value: &T, emu: &mut Emu) {
let slice = unsafe { core::slice::from_raw_parts(value as *const T as *const u8, size_of::<T>()) };
self.write_multiple_slice::<CPU, TCM, u8>(addr, emu, slice);
}
}
10 changes: 5 additions & 5 deletions src/jit/jit_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,11 @@ fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, guest_pc:

emit_func(asm, &mut block_asm);

// if DEBUG_LOG {
// block_asm.save_context();
// block_asm.call2(debug_after_exec_op::<CPU> as *const (), asm.jit_buf.current_pc, asm.jit_buf.current_inst().opcode);
// block_asm.restore_reg(Reg::CPSR);
// }
if DEBUG_LOG {
block_asm.save_context();
block_asm.call2(debug_after_exec_op::<CPU> as *const (), asm.jit_buf.current_pc, asm.jit_buf.current_inst().opcode);
block_asm.restore_reg(Reg::CPSR);
}
}

if last_inst_branch {
Expand Down
5 changes: 5 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::cartridge_io::CartridgeIo;
use crate::core::emu::{get_cm_mut, get_common_mut, get_cp15_mut, get_cpu_regs, get_jit_mut, get_mem_mut, get_mmu, get_regs_mut, get_spu_mut, Emu};
use crate::core::graphics::gpu::Gpu;
use crate::core::graphics::gpu_renderer::GpuRenderer;
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::memory::mmu::Mmu;
use crate::core::spu::{SoundSampler, Spu};
use crate::core::{spi, CpuType};
Expand Down Expand Up @@ -176,6 +177,10 @@ fn run_cpu(
get_spu_mut!(emu).audio_enabled = emu.settings.audio();
Spu::initialize_schedule(get_cm_mut!(emu));

if emu.settings.arm7_hle() == Arm7Emu::Hle {
Arm7Hle::initialize(emu);
}

let save_thread = thread::Builder::new()
.name("save".to_owned())
.spawn(move || {
Expand Down

0 comments on commit d322716

Please sign in to comment.