track RDP RDRAM writes (#259)
* track RDP RDRAM writes * more * more * more * more * more
This commit is contained in:
parent
17990dfebc
commit
656e390171
2
build.rs
2
build.rs
@ -101,6 +101,8 @@ fn main() {
|
||||
.allowlist_function("rdp_process_commands")
|
||||
.allowlist_function("rdp_check_callback")
|
||||
.allowlist_function("rdp_new_processor")
|
||||
.allowlist_function("rdp_check_framebuffers")
|
||||
.allowlist_function("rdp_full_sync")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
@ -64,6 +64,15 @@ static CALL_BACK callback;
|
||||
static GFX_INFO gfx_info;
|
||||
static uint32_t region;
|
||||
|
||||
static uint32_t depthbuffer_address;
|
||||
static uint32_t framebuffer_address;
|
||||
static uint32_t framebuffer_pixel_size;
|
||||
static uint32_t framebuffer_width;
|
||||
static uint32_t framebuffer_height;
|
||||
static uint8_t depthbuffer_enabled;
|
||||
static uint8_t *rdram_dirty;
|
||||
static uint64_t sync_signal;
|
||||
|
||||
static const unsigned cmd_len_lut[64] = {
|
||||
1,
|
||||
1,
|
||||
@ -234,10 +243,20 @@ void rdp_init(void *_window, GFX_INFO _gfx_info, bool _upscale, bool _integer_sc
|
||||
|
||||
callback.emu_running = true;
|
||||
callback.enable_speedlimiter = true;
|
||||
|
||||
sync_signal = 0;
|
||||
rdram_dirty = (uint8_t *)malloc(gfx_info.RDRAM_SIZE / 8);
|
||||
memset(rdram_dirty, 0, gfx_info.RDRAM_SIZE / 8);
|
||||
}
|
||||
|
||||
void rdp_close()
|
||||
{
|
||||
if (rdram_dirty)
|
||||
{
|
||||
free(rdram_dirty);
|
||||
rdram_dirty = nullptr;
|
||||
}
|
||||
|
||||
wsi->end_frame();
|
||||
|
||||
if (processor)
|
||||
@ -369,6 +388,21 @@ CALL_BACK rdp_check_callback()
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void rdp_check_framebuffers(uint32_t address)
|
||||
{
|
||||
if (sync_signal && rdram_dirty[address >> 3])
|
||||
{
|
||||
processor->wait_for_timeline(sync_signal);
|
||||
memset(rdram_dirty, 0, gfx_info.RDRAM_SIZE / 8);
|
||||
sync_signal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rdp_full_sync()
|
||||
{
|
||||
processor->wait_for_timeline(processor->signal_timeline());
|
||||
}
|
||||
|
||||
uint64_t rdp_process_commands()
|
||||
{
|
||||
uint64_t interrupt_timer = 0;
|
||||
@ -430,18 +464,69 @@ uint64_t rdp_process_commands()
|
||||
if (command >= 8)
|
||||
processor->enqueue_command(cmd_length * 2, &cmd_data[2 * cmd_cur]);
|
||||
|
||||
if (RDP::Op(command) == RDP::Op::SetScissor)
|
||||
if ((RDP::Op(command) >= RDP::Op::FillTriangle && RDP::Op(command) <= RDP::Op::ShadeTextureZBufferTriangle) ||
|
||||
RDP::Op(command) == RDP::Op::TextureRectangle ||
|
||||
RDP::Op(command) == RDP::Op::TextureRectangleFlip ||
|
||||
RDP::Op(command) == RDP::Op::FillRectangle)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
switch (framebuffer_pixel_size)
|
||||
{
|
||||
case 0:
|
||||
size = (framebuffer_width * framebuffer_height / 2) >> 3;
|
||||
break;
|
||||
case 1:
|
||||
size = (framebuffer_width * framebuffer_height) >> 3;
|
||||
break;
|
||||
case 2:
|
||||
size = (framebuffer_width * framebuffer_height * 2) >> 3;
|
||||
break;
|
||||
case 3:
|
||||
size = (framebuffer_width * framebuffer_height * 4) >> 3;
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t i = framebuffer_address; i < framebuffer_address + size; ++i)
|
||||
{
|
||||
rdram_dirty[i] = 1;
|
||||
}
|
||||
|
||||
if (depthbuffer_enabled)
|
||||
{
|
||||
size = (framebuffer_width * framebuffer_height * 2) >> 3;
|
||||
|
||||
for (uint32_t i = depthbuffer_address; i < depthbuffer_address + size; ++i)
|
||||
{
|
||||
rdram_dirty[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (RDP::Op(command) == RDP::Op::SetOtherModes)
|
||||
{
|
||||
depthbuffer_enabled = (w2 >> 5) & 1;
|
||||
}
|
||||
else if (RDP::Op(command) == RDP::Op::SetColorImage)
|
||||
{
|
||||
framebuffer_address = (w2 & 0x00FFFFFF) >> 3;
|
||||
framebuffer_pixel_size = (w1 >> 19) & 0x3;
|
||||
framebuffer_width = (w1 & 0x3FF) + 1;
|
||||
}
|
||||
else if (RDP::Op(command) == RDP::Op::SetMaskImage)
|
||||
{
|
||||
depthbuffer_address = (w2 & 0x00FFFFFF) >> 3;
|
||||
}
|
||||
else if (RDP::Op(command) == RDP::Op::SetScissor)
|
||||
{
|
||||
uint32_t upper_left_x = ((w1 >> 12) & 0xFFF) >> 2;
|
||||
uint32_t upper_left_y = (w1 & 0xFFF) >> 2;
|
||||
uint32_t lower_right_x = ((w2 >> 12) & 0xFFF) >> 2;
|
||||
uint32_t lower_right_y = (w2 & 0xFFF) >> 2;
|
||||
region = (lower_right_x - upper_left_x) * (lower_right_y - upper_left_y);
|
||||
framebuffer_height = lower_right_y;
|
||||
}
|
||||
if (RDP::Op(command) == RDP::Op::SyncFull)
|
||||
else if (RDP::Op(command) == RDP::Op::SyncFull)
|
||||
{
|
||||
processor->wait_for_timeline(processor->signal_timeline());
|
||||
|
||||
sync_signal = processor->signal_timeline();
|
||||
interrupt_timer = region;
|
||||
if (interrupt_timer == 0)
|
||||
interrupt_timer = 5000;
|
||||
|
||||
@ -34,6 +34,8 @@ extern "C"
|
||||
CALL_BACK rdp_check_callback();
|
||||
uint64_t rdp_process_commands();
|
||||
void rdp_new_processor(GFX_INFO _gfx_info, bool _upscale);
|
||||
void rdp_check_framebuffers(uint32_t address);
|
||||
void rdp_full_sync();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::device;
|
||||
use crate::ui;
|
||||
use std::alloc::{alloc_zeroed, Layout};
|
||||
|
||||
//const RDRAM_CONFIG_REG: u32 = 0;
|
||||
@ -46,6 +47,7 @@ pub fn read_mem(
|
||||
);
|
||||
let masked_address = address as usize & RDRAM_MASK;
|
||||
if address < device.rdram.size as u64 {
|
||||
ui::video::check_framebuffers(masked_address as u32);
|
||||
u32::from_ne_bytes(
|
||||
device.rdram.mem[masked_address..masked_address + 4]
|
||||
.try_into()
|
||||
@ -58,6 +60,7 @@ pub fn read_mem(
|
||||
|
||||
pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u32) {
|
||||
if address < device.rdram.size as u64 {
|
||||
ui::video::check_framebuffers(address as u32);
|
||||
let mut data = u32::from_ne_bytes(
|
||||
device.rdram.mem[address as usize..(address + 4) as usize]
|
||||
.try_into()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::device;
|
||||
use crate::ui;
|
||||
|
||||
const SP_MEM_ADDR_REG: u32 = 0;
|
||||
const SP_DRAM_ADDR_REG: u32 = 1;
|
||||
@ -146,6 +147,7 @@ fn do_dma(device: &mut device::Device, dma: RspDma) {
|
||||
let mut dram_addr = dma.dramaddr & 0xfffff8;
|
||||
let offset = dma.memaddr & 0x1000;
|
||||
|
||||
ui::video::check_framebuffers(dram_addr);
|
||||
if dma.dir == DmaDir::Read {
|
||||
let mut j = 0;
|
||||
while j < count {
|
||||
|
||||
@ -70,6 +70,8 @@ where
|
||||
}
|
||||
|
||||
pub fn create_savestate(device: &device::Device) {
|
||||
ui::video::full_sync();
|
||||
|
||||
let data: &[(&[u8], &str)] = &[
|
||||
(&postcard::to_stdvec(device).unwrap(), "device"),
|
||||
(&postcard::to_stdvec(&device.ui.saves).unwrap(), "saves"),
|
||||
|
||||
@ -67,6 +67,14 @@ pub fn update_screen() {
|
||||
unsafe { rdp_update_screen() }
|
||||
}
|
||||
|
||||
pub fn check_framebuffers(address: u32) {
|
||||
unsafe { rdp_check_framebuffers(address) }
|
||||
}
|
||||
|
||||
pub fn full_sync() {
|
||||
unsafe { rdp_full_sync() }
|
||||
}
|
||||
|
||||
pub fn load_state(device: &mut device::Device) {
|
||||
let gfx_info = GFX_INFO {
|
||||
RDRAM: device.rdram.mem.as_mut_ptr(),
|
||||
|
||||
Reference in New Issue
Block a user