Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Feb 28, 2025
1 parent 1ff8724 commit 4b51f11
Show file tree
Hide file tree
Showing 23 changed files with 381 additions and 206 deletions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static_assertions = "1.1.0"
paste = "1.0.15"
enum_dispatch = "0.3.13"
bit-set = "0.8.0"
strum = "0.27.1"
strum_macros = "0.27.1"

[target.armv7-unknown-linux-gnueabihf.dependencies]
clap = { version = "4.5.17", features = ["cargo"] }
Expand Down
2 changes: 1 addition & 1 deletion src/core/cpu_regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl From<u8> for InterruptFlag {
}
}

struct InterruptFlags(u32);
pub struct InterruptFlags(pub u32);

impl Debug for InterruptFlags {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Expand Down
7 changes: 3 additions & 4 deletions src/core/graphics/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::core::memory::dma::DmaTransferMode;
use crate::core::CpuType;
use crate::core::CpuType::ARM9;
use crate::logging::debug_println;
use crate::settings::Arm7Emu;
use bilge::prelude::*;
use std::intrinsics::unlikely;
use std::ptr::NonNull;
Expand Down Expand Up @@ -80,7 +81,6 @@ pub struct Gpu {
pub pow_cnt1: u16,
pub disp_cap_cnt: u32,
frame_rate_counter: FrameRateCounter,
pub arm7_hle: bool,
pub v_count: u16,
pub gpu_2d_regs_a: Gpu2DRegisters,
pub gpu_2d_regs_b: Gpu2DRegisters,
Expand All @@ -95,7 +95,6 @@ impl Gpu {
pow_cnt1: 0,
disp_cap_cnt: 0,
frame_rate_counter: FrameRateCounter::new(fps),
arm7_hle: false,
v_count: 0,
gpu_2d_regs_a: Gpu2DRegisters::new(A),
gpu_2d_regs_b: Gpu2DRegisters::new(B),
Expand Down Expand Up @@ -199,7 +198,7 @@ impl Gpu {
gpu.v_count = 0;
gpu.get_renderer_mut().reload_registers();

if gpu.arm7_hle {
if emu.settings.arm7_hle() == Arm7Emu::Hle {
Arm7Hle::on_frame(emu);
}
}
Expand All @@ -220,7 +219,7 @@ impl Gpu {
gpu.disp_stat[i].set_h_blank_flag(u1::new(0));
}

if gpu.arm7_hle {
if emu.settings.arm7_hle() != Arm7Emu::AccurateLle {
get_arm7_hle_mut!(emu).on_scanline(gpu.v_count, emu);
}

Expand Down
132 changes: 85 additions & 47 deletions src/core/hle/arm7_hle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,53 @@ 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, Eq, PartialEq)]
#[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,
rtc: RtcHle,
touchscreen: TouchscreenHle,
pub(super) sound: SoundHle,
pub rtc: RtcHle,
pub touchscreen: TouchscreenHle,
pub sound: SoundHle,
power_manager: PowerManagerHle,
cart: CartHle,
pub cart: CartHle,
}

impl Arm7Hle {
Expand All @@ -35,91 +74,90 @@ 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);
fifo.cnt.set_send_full_status(true);
ipc.fifo[ARM9].cnt.set_recv_full(true);
} else {
fifo.queue.push_back(val);
fifo.queue.push_back(u32::from(IpcFifoMessage::new(u5::new(tag as u8), err, u26::new(data))));
if fifo.queue.len() == 1 {
get_cpu_regs_mut!(emu, ARM9).send_interrupt(InterruptFlag::IpcRecvFifoNotEmpty, emu);
ipc.fifo[ARM7].cnt.set_send_empty_status(false);
ipc.fifo[ARM9].cnt.set_recv_empty(false);
if 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 +167,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
20 changes: 9 additions & 11 deletions src/core/hle/cart_hle.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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;

pub(super) struct CartHle {
pub struct CartHle {
cmd: u32,
data_pos: u32,
buffer: u32,
Expand All @@ -14,7 +14,7 @@ impl CartHle {
CartHle { cmd: 0, data_pos: 0, buffer: 0 }
}

pub(super) fn ipc_recv(&mut self, data: u32, emu: &mut Emu) {
pub fn ipc_recv(&mut self, data: u32, emu: &mut Emu) {
if self.data_pos == 0 {
self.cmd = data;
}
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
Loading

0 comments on commit 4b51f11

Please sign in to comment.