#include "render_pass_ot.hpp" #include #include static uint32_t ram[2*1024*1024/4]; static uint32_t aperture[256/4]; extern "C" { int g_psx_render_pass_active=1; uint32_t memory_get_ram_bytes(){return sizeof ram;} int psx_mod_gpu_dma_memory_contains(uint32_t p,uint32_t bytes){return bytes && psx_mod_gpu_dma_aperture_offset_for(p,bytes,sizeof aperture,nullptr);} uint32_t psx_mod_read_word(uint32_t p){p&=0x1FFFFFFF;return p>=0x800000 ? aperture[(p-0x800000)/4] : ram[p/4];} void psx_mod_write_word(uint32_t p,uint32_t v){p&=0x1FFFFFFF;if(p>=0x800000)aperture[(p-0x800000)/4]=v;else ram[p/4]=v;} // Parser lengths used by these fixtures. Runtime supplies its actual GPU decoder. int gpu_gp0_command_word_count(uint8_t op) { if(op==0x20)return 4;if(op==0xA0)return 3;if(op==0x48)return -1; if(op==0 || (op>=0xE1 && op<=0xE6))return 1; return 0; } } static void check(bool ok,const char* name){if(!ok){std::fprintf(stderr,"FAIL: %s\n",name);std::exit(1);}} static void put(uint32_t p,uint32_t v){psx_mod_write_word(p,v);} static uint32_t get(uint32_t p){return psx_mod_read_word(p);} int main() { constexpr uint32_t slot=0x10000,world=0x20000,late=0x21000,next=0x22000; put(slot,world);put(world,0x00FFFFFF); PSXOTReplay ot;check(ot.capture(slot,1),"capture heads"); put(slot,late);put(late,0x01000000|world);put(late+4,0xE1000123); check(ot.preserve_late(),"capture late prefix"); put(slot,next);put(late,0);put(late+4,0);ot.apply_late(); check(get(slot)==late && get(late)==(0x01000000|next) && get(late+4)==0xE1000123,"late follows regenerated world"); put(slot,late);put(late,late);check(!ot.preserve_late(),"cycle bounded"); PSXOTReplay hud; check(hud.capture_new_list(slot),"standalone late HUD head"); put(slot,late);put(late,0x01FFFFFF);put(late+4,0xE1000123); check(hud.preserve_late(),"capture complete HUD prefix"); put(slot,0xFFFFFF);put(late,0);put(late+4,0);hud.apply_late(); check(get(slot)==late && get(late)==0x01FFFFFF && get(late+4)==0xE1000123,"restore standalone HUD"); constexpr uint32_t p=0x30000; put(p,0x07FFFFFF);put(p+4,0x20010203);put(p+8,0xE3000042); put(p+12,0xE4000012);put(p+16,0xE50000AB); put(p+20,0xE3000000|(256u<<10));put(p+24,0xE400013F|(495u<<10)); put(p+28,0xE5000000|(258u<<11)); check(PSXOTReplay::retarget_y(p,256,0,240),"retarget packet stream"); check(get(p+8)==0xE3000042 && get(p+12)==0xE4000012 && get(p+16)==0xE50000AB,"coordinate payload is never decoded as opcode"); check(get(p+20)==0xE3000000 && get(p+24)==(0xE400013F|(239u<<10)) && get(p+28)==(0xE5000000|(2u<<11)),"environment preserves crop and shake"); put(p,0x02031000);put(p+4,0xE3000000);put(p+8,0xE400013F|(239u<<10)); put(0x31000,0x01FFFFFF);put(0x31004,0xF1000000); check(!PSXOTReplay::retarget_y(p,0,256,240) && get(p+4)==0xE3000000,"invalid tail makes no partial edits"); put(p,0x07FFFFFF);put(p+4,0xA0000000);put(p+8,0);put(p+12,0x00010002); put(p+16,0xE3000123);put(p+20,0xE3000000);put(p+24,0xE400013F|(239u<<10));put(p+28,0xE5000000); check(PSXOTReplay::retarget_y(p,0,256,240) && get(p+16)==0xE3000123,"image data is not a command"); // Native widescreen terrain uses a real allocated GPU-DMA aperture. // Apply the same parsed environment edits, with no unrelated memory access. put(slot,0x800000);put(0x800000,0x02FFFFFF); put(0x800004,0xE3000000);put(0x800008,0xE5000000); check(PSXOTReplay::retarget_y(slot,0,256,240) && get(0x800004)==(0xE3000000|(256u<<10)),"allocated terrain aperture retargets"); put(slot,0x800100); check(!PSXOTReplay::retarget_y(slot,0,256,240),"unallocated aperture tail refused"); check(!psx_mod_gpu_dma_memory_contains(0x1FC00000,4),"BIOS is never an aperture alias"); put(slot,0x8000FC);put(0x8000FC,0x02FFFFFF); check(!PSXOTReplay::retarget_y(slot,0,256,240),"packet spanning aperture end refused before edits"); g_psx_render_pass_active=0; check(!PSXOTReplay::retarget_y(p,256,0,240),"outside sandbox refused"); std::puts("ALL PASS"); }