diff --git a/parallel-rdp/interface.cpp b/parallel-rdp/interface.cpp index 11bc25f1..17abcdfe 100644 --- a/parallel-rdp/interface.cpp +++ b/parallel-rdp/interface.cpp @@ -56,12 +56,12 @@ typedef struct { uint32_t depthbuffer_address; uint32_t framebuffer_address; + uint32_t texture_address; uint32_t framebuffer_pixel_size; uint32_t framebuffer_width; + uint32_t texture_pixel_size; + uint32_t texture_width; uint32_t framebuffer_height; - uint32_t framebuffer_size; - uint32_t depthbuffer_size; - uint8_t depthbuffer_enabled; } FrameBufferInfo; typedef struct @@ -492,24 +492,45 @@ void rdp_load_state(const uint8_t *state) memcpy(&rdp_device, state, sizeof(RDP_DEVICE)); } -void calculate_buffer_size() +uint32_t texture_size(uint32_t area) +{ + switch (rdp_device.frame_buffer_info.texture_pixel_size) + { + case 0: + return (area / 2) >> 3; + case 1: + return (area) >> 3; + case 2: + return (area * 2) >> 3; + case 3: + return (area * 4) >> 3; + default: + printf("Invalid texture pixel size: %u\n", rdp_device.frame_buffer_info.texture_pixel_size); + return 0; + } +} + +uint32_t framebuffer_size() { switch (rdp_device.frame_buffer_info.framebuffer_pixel_size) { case 0: - rdp_device.frame_buffer_info.framebuffer_size = (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height / 2) >> 3; - break; + return (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height / 2) >> 3; case 1: - rdp_device.frame_buffer_info.framebuffer_size = (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) >> 3; - break; + return (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height) >> 3; case 2: - rdp_device.frame_buffer_info.framebuffer_size = (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 2) >> 3; - break; + return (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 2) >> 3; case 3: - rdp_device.frame_buffer_info.framebuffer_size = (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 4) >> 3; - break; + return (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 4) >> 3; + default: + printf("Invalid framebuffer pixel size: %u\n", rdp_device.frame_buffer_info.framebuffer_pixel_size); + return 0; } - rdp_device.frame_buffer_info.depthbuffer_size = (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 2) >> 3; +} + +uint32_t depthbuffer_size() +{ + return (rdp_device.frame_buffer_info.framebuffer_width * rdp_device.frame_buffer_info.framebuffer_height * 2) >> 3; } uint64_t rdp_process_commands() @@ -573,37 +594,64 @@ uint64_t rdp_process_commands() if (command >= 8) processor->enqueue_command(cmd_length * 2, &rdp_device.cmd_data[2 * rdp_device.cmd_cur]); - 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) + switch (RDP::Op(command)) { + 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: if (!rdram_dirty[rdp_device.frame_buffer_info.framebuffer_address]) { - std::fill_n(rdram_dirty.begin() + rdp_device.frame_buffer_info.framebuffer_address, rdp_device.frame_buffer_info.framebuffer_size, true); + std::fill_n(rdram_dirty.begin() + rdp_device.frame_buffer_info.framebuffer_address, framebuffer_size(), true); } - if (rdp_device.frame_buffer_info.depthbuffer_enabled && !rdram_dirty[rdp_device.frame_buffer_info.depthbuffer_address]) + if (rdp_device.frame_buffer_info.depthbuffer_address < rdram_dirty.size() && !rdram_dirty[rdp_device.frame_buffer_info.depthbuffer_address]) { - std::fill_n(rdram_dirty.begin() + rdp_device.frame_buffer_info.depthbuffer_address, rdp_device.frame_buffer_info.depthbuffer_size, true); + std::fill_n(rdram_dirty.begin() + rdp_device.frame_buffer_info.depthbuffer_address, depthbuffer_size(), true); } - } - else if (RDP::Op(command) == RDP::Op::SetOtherModes) + break; + case RDP::Op::LoadTLut: + case RDP::Op::LoadTile: + if (!rdram_dirty[rdp_device.frame_buffer_info.texture_address]) + { + uint32_t lower_right_t = (w2 & 0xFFF) >> 2; + std::fill_n(rdram_dirty.begin() + + rdp_device.frame_buffer_info.texture_address, + texture_size(rdp_device.frame_buffer_info.texture_width * lower_right_t), true); + } + break; + case RDP::Op::LoadBlock: { - rdp_device.frame_buffer_info.depthbuffer_enabled = (w2 >> 5) & 1; + uint32_t upper_left_s = ((w1 >> 12) & 0xFFF) >> 2; + uint32_t offset_address = rdp_device.frame_buffer_info.texture_address + texture_size(upper_left_s); + if (!rdram_dirty[offset_address]) + { + uint32_t lower_right_s = ((w2 >> 12) & 0xFFF) >> 2; + std::fill_n(rdram_dirty.begin() + offset_address, texture_size(lower_right_s - upper_left_s), true); + } + break; } - else if (RDP::Op(command) == RDP::Op::SetColorImage) - { + case RDP::Op::SetColorImage: rdp_device.frame_buffer_info.framebuffer_address = (w2 & 0x00FFFFFF) >> 3; rdp_device.frame_buffer_info.framebuffer_pixel_size = (w1 >> 19) & 0x3; rdp_device.frame_buffer_info.framebuffer_width = (w1 & 0x3FF) + 1; - calculate_buffer_size(); - } - else if (RDP::Op(command) == RDP::Op::SetMaskImage) - { + break; + case RDP::Op::SetMaskImage: rdp_device.frame_buffer_info.depthbuffer_address = (w2 & 0x00FFFFFF) >> 3; - } - else if (RDP::Op(command) == RDP::Op::SetScissor) + break; + case RDP::Op::SetTextureImage: + rdp_device.frame_buffer_info.texture_address = (w2 & 0x00FFFFFF) >> 3; + rdp_device.frame_buffer_info.texture_pixel_size = (w1 >> 19) & 0x3; + rdp_device.frame_buffer_info.texture_width = (w1 & 0x3FF) + 1; + break; + case RDP::Op::SetScissor: { uint32_t upper_left_x = ((w1 >> 12) & 0xFFF) >> 2; uint32_t upper_left_y = (w1 & 0xFFF) >> 2; @@ -619,14 +667,14 @@ uint64_t rdp_process_commands() } rdp_device.frame_buffer_info.framebuffer_height = lower_right_y; - calculate_buffer_size(); + break; } - else if (RDP::Op(command) == RDP::Op::SyncFull) - { + case RDP::Op::SyncFull: sync_signal = processor->signal_timeline(); interrupt_timer = rdp_device.region; if (interrupt_timer == 0) interrupt_timer = 5000; + break; } rdp_device.cmd_cur += cmd_length;