Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Feb 23, 2025
1 parent 1ff8724 commit 9b4a747
Show file tree
Hide file tree
Showing 15 changed files with 242 additions and 124 deletions.
9 changes: 7 additions & 2 deletions src/core/graphics/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ use crate::core::graphics::gpu_2d::Gpu2DEngine::{A, B};
use crate::core::graphics::gpu_3d::registers_3d::Gpu3DRegisters;
use crate::core::graphics::gpu_renderer::GpuRenderer;
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::ipc::ARM7_NEEDED;
use crate::core::memory::dma::DmaTransferMode;
use crate::core::CpuType;
use crate::core::CpuType::ARM9;
use crate::core::CpuType::{ARM7, ARM9};
use crate::logging::debug_println;
use bilge::prelude::*;
use std::intrinsics::unlikely;
use std::ptr::NonNull;
use std::sync::atomic::{AtomicU16, Ordering};
use std::sync::Arc;
use std::time::Instant;
use std::thread;
use std::time::{Duration, Instant};

pub const DISPLAY_WIDTH: usize = 256;
pub const DISPLAY_HEIGHT: usize = 192;
Expand Down Expand Up @@ -202,6 +204,9 @@ impl Gpu {
if gpu.arm7_hle {
Arm7Hle::on_frame(emu);
}
if gpu.frame_rate_counter.frame_counter & 15 == 0 {
unsafe { ARM7_NEEDED = true };
}
}
_ => {}
}
Expand Down
118 changes: 75 additions & 43 deletions src/core/hle/arm7_hle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,45 @@ use crate::core::hle::touchscreen_hle::TouchscreenHle;
use crate::core::CpuType::{ARM7, ARM9};
use bilge::prelude::*;
use std::cmp::Ordering;
use std::mem;

#[derive(Debug)]
#[repr(u8)]
pub enum IpcFifoTag {
Ex = 0,
User0 = 1,
User1 = 2,
System = 3,
Nvram = 4,
Rtc = 5,
Touchpanel = 6,
Sound = 7,
PowerManager = 8,
Mic = 9,
WirelessManager = 10,
Filesystem = 11,
Os = 12,
Cartridge = 13,
Card = 14,
ControlDrivingWirelessLib = 15,
CartridgeEx = 16,
Max = 32,
}

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

#[bitsize(32)]
#[derive(FromBits)]
pub struct IpcFifoMessage {
pub tag: u5,
pub err: bool,
pub data: u26,
}

pub struct Arm7Hle {
firmware: FirmwareHle,
Expand All @@ -35,91 +74,84 @@ impl Arm7Hle {
get_ipc_mut!(emu).sync_regs[ARM9].set_data_in(u4::new(val));
}

pub(super) fn send_ipc_fifo(service: u32, data: u32, flag: u32, emu: &mut Emu) {
let val = (service & 0x1F) | (data << 6) | ((flag & 0x1) << 5);

let fifo = &mut get_ipc_mut!(emu).fifo[ARM7];
pub fn send_ipc_fifo(tag: IpcFifoTag, data: u32, err: bool, emu: &mut Emu) {
let ipc = get_ipc_mut!(emu);
let fifo = &mut ipc.fifo[ARM7];
if fifo.queue.len() == 16 {
fifo.cnt.set_err(true);
} else {
fifo.queue.push_back(val);
if fifo.queue.len() == 1 {
fifo.queue.push_back(u32::from(IpcFifoMessage::new(u5::new(tag as u8), err, u26::new(data))));
if fifo.queue.len() == 1 && ipc.fifo[ARM9].cnt.recv_not_empty_irq() {
get_cpu_regs_mut!(emu, ARM9).send_interrupt(InterruptFlag::IpcRecvFifoNotEmpty, emu);
}
}
}

pub fn ipc_recv(&mut self, emu: &mut Emu) {
let val = *get_ipc!(emu).fifo[ARM9].queue.front();
get_ipc_mut!(emu).fifo[ARM9].queue.pop_front();
if get_ipc!(emu).fifo[ARM9].queue.is_empty() && get_ipc!(emu).fifo[ARM9].cnt.send_empty_irq() {
let ipc = get_ipc_mut!(emu);
let val = *ipc.fifo[ARM9].queue.front();
ipc.fifo[ARM9].queue.pop_front();
if ipc.fifo[ARM9].queue.is_empty() && ipc.fifo[ARM9].cnt.send_empty_irq() {
get_cpu_regs_mut!(emu, ARM9).send_interrupt(InterruptFlag::IpcSendFifoEmpty, emu);
}

let service = val & 0x1F;
let data = val >> 6;
let flag = ((val >> 5) & 0x1) != 0;
let message = IpcFifoMessage::from(val);
let tag = IpcFifoTag::from(u8::from(message.tag()));
let data = u32::from(message.data());

match service {
0x4 => {
if !flag {
match tag {
IpcFifoTag::Nvram => {
if !message.err() {
self.firmware.ipc_recv(data, emu);
}
}
0x5 => {
if !flag {
IpcFifoTag::Rtc => {
if !message.err() {
self.rtc.ipc_recv(data, emu);
}
}
0x6 => {
if !flag {
IpcFifoTag::Touchpanel => {
if !message.err() {
self.touchscreen.ipc_recv(data, emu);
}
}
0x7 => {
self.sound.ipc_recv(data, emu);
}
0x8 => {
if !flag {
IpcFifoTag::Sound => self.sound.ipc_recv(data, emu),
IpcFifoTag::PowerManager => {
if !message.err() {
self.power_manager.ipc_recv(data, emu);
}
}
0x9 => {
// Mic
if !flag {
IpcFifoTag::Mic => {
if !message.err() {
// todo!()
}
}
0xA => {
// Wifi
if !flag {
IpcFifoTag::WirelessManager => {
if !message.err() {
// todo!()
}
}
0xB => {
if flag {
IpcFifoTag::Filesystem => {
if message.err() {
self.cart.ipc_recv(data, emu);
}
}
0xC => {
IpcFifoTag::Os => {
if data == 0x1000 {
Self::send_ipc_fifo(0xC, 0x1000, 0, emu);
Self::send_ipc_fifo(IpcFifoTag::Os, 0x1000, false, emu);
}
}
0xD => {
// Cart
IpcFifoTag::Cartridge => {
if (data & 0x3F) == 1 {
Self::send_ipc_fifo(0xD, 0x1, 0, emu);
Self::send_ipc_fifo(IpcFifoTag::Cartridge, 0x1, false, emu);
}
}
0xF => {
IpcFifoTag::ControlDrivingWirelessLib => {
if data == 0x10000 {
Self::send_ipc_fifo(0xF, 0x10000, 0, emu);
Self::send_ipc_fifo(IpcFifoTag::ControlDrivingWirelessLib, 0x10000, false, emu);
}
}
_ => {
todo!("hle: Unknown ipc request {:x} service {:x} data {:x} flag {}", val, service, data, flag)
}
_ => todo!("hle: ipc request {val:x} tag {tag:?} data {data:x} err {}", message.err()),
}
}

Expand All @@ -129,7 +161,7 @@ impl Arm7Hle {
Ordering::Less => Self::send_ipc_sync(data_in + 1, emu),
Ordering::Equal => {
Self::send_ipc_sync(0, emu);
emu.mem_write::<{ ARM7 }, u32>(0x027FFF8C, 0x0000FFF0);
emu.mem_write::<{ ARM7 }, u32>(0x027FFF8C, 0x3fff0);
}
_ => {}
}
Expand Down
16 changes: 7 additions & 9 deletions src/core/hle/cart_hle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::core::emu::{get_common, get_common_mut, Emu};
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::hle::arm7_hle::{Arm7Hle, IpcFifoTag};
use crate::core::CpuType::ARM7;
use crate::logging::debug_println;

Expand All @@ -23,7 +23,7 @@ impl CartHle {
0 => {
if self.data_pos == 1 {
self.buffer = data;
Arm7Hle::send_ipc_fifo(0xB, 0x1, 1, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Filesystem, 0x1, true, emu);
self.data_pos = 0;
return;
}
Expand All @@ -34,7 +34,7 @@ impl CartHle {
let save_size_shift = (save_param >> 8) & 0xFF;
get_common_mut!(emu).cartridge.io.resize_save_file(1 << save_size_shift);
}
Arm7Hle::send_ipc_fifo(0xB, 0x1, 1, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Filesystem, 0x1, true, emu);
self.data_pos = 0;
return;
}
Expand All @@ -48,7 +48,7 @@ impl CartHle {
emu.mem_write::<{ ARM7 }, u8>(dst + i, cartridge_io.read_save_buf((offset + i) & (cartridge_io.save_file_size - 1)));
}

Arm7Hle::send_ipc_fifo(0xB, 0x1, 1, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Filesystem, 0x1, true, emu);
self.data_pos = 0;
return;
}
Expand All @@ -64,18 +64,16 @@ impl CartHle {
let cartridge_io = &mut get_common_mut!(emu).cartridge.io;
cartridge_io.write_save_buf_slice(offset & (cartridge_io.save_file_size - 1), &buf);

Arm7Hle::send_ipc_fifo(0xB, 0x1, 1, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Filesystem, 0x1, true, emu);
self.data_pos = 0;
return;
}
9 => {
Arm7Hle::send_ipc_fifo(0xB, 0x1, 1, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Filesystem, 0x1, true, emu);
self.data_pos = 0;
return;
}
_ => {
debug_println!("cart save: unknown cmd {:x}", self.cmd);
}
_ => debug_println!("cart save: unknown cmd {:x}", self.cmd),
}

self.data_pos += 1;
Expand Down
18 changes: 9 additions & 9 deletions src/core/hle/firmware_hle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::core::emu::Emu;
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::hle::arm7_hle::{Arm7Hle, IpcFifoTag};
use crate::core::spi;
use crate::core::CpuType::ARM7;

Expand All @@ -26,17 +26,17 @@ impl FirmwareHle {
let cmd = (self.data[0] >> 8) - 0x20;
match cmd {
0 => {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A000, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A000, false, emu);
}
1 => {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A100, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A100, false, emu);
}
2 => {
let addr = (((self.data[0] as u32) & 0xFF) << 24) | ((self.data[1] as u32) << 8) | (((self.data[2] as u32) >> 8) & 0xFF);
if (0x02000000..0x02800000).contains(&addr) {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A200, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A200, false, emu);
} else {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A202, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A202, false, emu);
}
}
3 => {
Expand All @@ -50,17 +50,17 @@ impl FirmwareHle {
emu.mem_write::<{ ARM7 }, _>(addr + i, val);
}

Arm7Hle::send_ipc_fifo(0x4, 0x0300A300, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A300, false, emu);
} else {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A302, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A302, false, emu);
}
}
5 => {
let addr = ((self.data[3] as u32) << 16) | self.data[4] as u32;
if (0x02000000..0x02800000).contains(&addr) {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A500, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A500, false, emu);
} else {
Arm7Hle::send_ipc_fifo(0x4, 0x0300A502, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Nvram, 0x0300A502, false, emu);
}
}
_ => {}
Expand Down
12 changes: 6 additions & 6 deletions src/core/hle/power_manager_hle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::core::emu::Emu;
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::hle::arm7_hle::{Arm7Hle, IpcFifoTag};

pub(super) struct PowerManagerHle {
data: [u16; 16],
Expand All @@ -24,19 +24,19 @@ impl PowerManagerHle {
let cmd = (self.data[0] >> 8) - 0x60;
match cmd {
1 => {
Arm7Hle::send_ipc_fifo(0x8, 0x0300E300, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::PowerManager, 0x0300E300, false, emu);
}
3 => {
Arm7Hle::send_ipc_fifo(0x8, 0x0300E300, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::PowerManager, 0x0300E300, false, emu);
}
4 => {
Arm7Hle::send_ipc_fifo(0x8, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::PowerManager, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), false, emu);
}
5 => {
Arm7Hle::send_ipc_fifo(0x8, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::PowerManager, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), false, emu);
}
6 => {
Arm7Hle::send_ipc_fifo(0x8, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::PowerManager, 0x03008000 | (((self.data[1] as u32 + 0x70) & 0xFF) << 8), false, emu);
}
_ => {}
}
Expand Down
10 changes: 5 additions & 5 deletions src/core/hle/rtc_hle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::core::emu::{io_rtc_mut, Emu};
use crate::core::hle::arm7_hle::Arm7Hle;
use crate::core::hle::arm7_hle::{Arm7Hle, IpcFifoTag};
use crate::core::CpuType::ARM7;

pub(super) struct RtcHle;
Expand All @@ -13,7 +13,7 @@ impl RtcHle {
let cmd = (data >> 8) & 0x7F;

if (2..=15).contains(&cmd) || (26..=34).contains(&cmd) || (cmd >= 42) {
Arm7Hle::send_ipc_fifo(0x5, 0x8001 | (cmd << 8), 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Rtc, 0x8001 | (cmd << 8), false, emu);
return;
}

Expand All @@ -26,23 +26,23 @@ impl RtcHle {
for i in 0..7 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9000, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Rtc, 0x9000, false, emu);
}
0x11 => {
// read date
rtc.update_date_time();
for i in 0..4 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9100, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Rtc, 0x9100, false, emu);
}
0x12 => {
// read time
rtc.update_date_time();
for i in 4..7 {
emu.mem_write::<{ ARM7 }, _>(0x027FFDE8 + i, rtc.date_time[i as usize]);
}
Arm7Hle::send_ipc_fifo(0x5, 0x9200, 0, emu);
Arm7Hle::send_ipc_fifo(IpcFifoTag::Rtc, 0x9200, false, emu);
}
_ => {}
}
Expand Down
Loading

0 comments on commit 9b4a747

Please sign in to comment.