mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 10:59:16 -04:00
Qualify remaining shaded polygon command variants
(cherry picked from commit 086a513fb1)
This commit is contained in:
committed by
Alexandros Mandravillis
parent
942ad0a210
commit
2bf27fe2c1
@@ -0,0 +1,32 @@
|
||||
# Source shaded textured polygon variants
|
||||
|
||||
Pepsiman's successive 39 and 31 scope stops expose incomplete flag-family
|
||||
admission. Alongside the confirmed untextured triangle correction, this
|
||||
fixture qualifies the remaining shaded textured polygon variants 35/36/37
|
||||
and 3D/3F, retaining already admitted 34/3C/3E as source controls.
|
||||
|
||||
The existing renderer and work projector own raw texture, modulation,
|
||||
semitransparency, Gouraud interpolation, masking, cache and split-quad work.
|
||||
The production change only admits the qualified opcodes. It does not change
|
||||
packet lengths, rendering, timing, movie input, geometry guards or reset
|
||||
policy. These variants were not each independently encountered in the title;
|
||||
their admission is supported by the complete authored source matrix.
|
||||
|
||||
The CPU/MMIO driver seeds mixed transparent, mask-bit and ordinary texture
|
||||
and destination pixels, then draws two identical polygons without clearing
|
||||
the texture cache or framebuffer. It covers eight opcodes, three texture
|
||||
depths, four blend modes, four mask modes, dithering off/on and disjoint or
|
||||
overlapping texture targets. The source owns all CPU loads/stores and GPU
|
||||
dispatches. Declared waits restore draw credit between dispatches.
|
||||
|
||||
All 1536 complete final VRAM images match stock Octoshock 2.3. The passive
|
||||
observer preserves each image and authored program identity, and records
|
||||
4608 command/cache work values across both repeated triangles or split
|
||||
quads. O0/O2 native fixtures match every image and work value. Before the
|
||||
admission change, the native fixture stops at 35 after 192 opcode 34 controls.
|
||||
|
||||
The golden manifest binds source lineage a15b31a, stock core, passive observer
|
||||
and authored driver. No retail data or emulator states are included. Run
|
||||
CTest -R tas_gpu_shaded_texture_family. This is source-profile qualification;
|
||||
full unchanged Pepsiman and Tekken replays and the Pepsiman ending witness
|
||||
remain separate acceptance gates. No whole-game or hardware claim follows.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Source shaded-triangle family
|
||||
|
||||
Pepsiman qualification 16 clears the shaded-quad admission boundary and
|
||||
matches all 5269 captured source RAM/clock returns. It then stops when the
|
||||
source-profile table rejects GP0 31 at clock 2982504064. The diagnostic's
|
||||
draw mode 0218 is context, not an established draw-mode defect.
|
||||
|
||||
The renderer and work projector already implement the shared shaded-triangle
|
||||
flags. This correction admits opcodes 31/32/33 alongside 30. The low bit is
|
||||
ignored for these untextured commands; bit 1 selects semitransparency. Packet
|
||||
length, command dispatch, work calculation and rasterization are unchanged.
|
||||
Other family and lifecycle guards remain in place.
|
||||
|
||||
An authored CPU/MMIO fixture covers all four opcodes, four blend modes, four
|
||||
mask modes and dithering off/on. Its 128 complete final VRAM images match
|
||||
stock Octoshock 2.3; the passive observer preserves each image and provides
|
||||
128 command-work values. Both native O0/O2 builds match every image and work
|
||||
value. All 64 ignored-bit source alias pairs agree. Before correction the
|
||||
native fixture stops at opcode 31 after the 32 opcode 30 controls.
|
||||
|
||||
The fixture manifest binds source lineage a15b31a, stock core, observer and
|
||||
authored driver. No retail data or emulator states are included. Run CTest
|
||||
-R tas_gpu_shaded_triangle. Full unchanged Pepsiman and Tekken regressions
|
||||
remain separate acceptance gates; this is source compatibility evidence,
|
||||
not a whole-game or PS1 hardware accuracy claim.
|
||||
@@ -413,6 +413,26 @@ if(BUILD_TESTING)
|
||||
add_test(NAME tas_gpu_polygon_order_${_mode} COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../runtime/tests/test_source_gpu_polygon_order_contracts.py
|
||||
$<TARGET_FILE:tas_gpu_polygon_order_${_mode}>)
|
||||
add_executable(tas_gpu_shaded_texture_family_${_mode}
|
||||
../runtime/tests/test_source_gpu_shaded_texture_family.c
|
||||
../runtime/src/gpu_sw_renderer.c
|
||||
../runtime/src/gpu_vram_dirty.c ../runtime/src/psx_sha256.c)
|
||||
target_include_directories(tas_gpu_shaded_texture_family_${_mode} PRIVATE ../runtime/include)
|
||||
target_compile_options(tas_gpu_shaded_texture_family_${_mode} PRIVATE -${_mode} -UNDEBUG)
|
||||
target_link_libraries(tas_gpu_shaded_texture_family_${_mode} PRIVATE m)
|
||||
add_test(NAME tas_gpu_shaded_texture_family_${_mode} COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../runtime/tests/test_source_gpu_shaded_texture_family_contracts.py
|
||||
$<TARGET_FILE:tas_gpu_shaded_texture_family_${_mode}>)
|
||||
add_executable(tas_gpu_shaded_triangle_${_mode}
|
||||
../runtime/tests/test_source_gpu_shaded_triangle.c
|
||||
../runtime/src/gpu_sw_renderer.c
|
||||
../runtime/src/gpu_vram_dirty.c ../runtime/src/psx_sha256.c)
|
||||
target_include_directories(tas_gpu_shaded_triangle_${_mode} PRIVATE ../runtime/include)
|
||||
target_compile_options(tas_gpu_shaded_triangle_${_mode} PRIVATE -${_mode} -UNDEBUG)
|
||||
target_link_libraries(tas_gpu_shaded_triangle_${_mode} PRIVATE m)
|
||||
add_test(NAME tas_gpu_shaded_triangle_${_mode} COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../runtime/tests/test_source_gpu_shaded_triangle_contracts.py
|
||||
$<TARGET_FILE:tas_gpu_shaded_triangle_${_mode}>)
|
||||
add_executable(tas_gpu_shaded_quad_${_mode}
|
||||
../runtime/tests/test_source_gpu_shaded_quad.c
|
||||
../runtime/src/gpu_sw_renderer.c
|
||||
|
||||
@@ -54,9 +54,9 @@ static inline unsigned source_gpu_polygon_stride(unsigned opcode) {
|
||||
static inline int source_gpu_polygon_supported(unsigned opcode) {
|
||||
switch(opcode) {
|
||||
case 0x20:case 0x21:case 0x22:case 0x23:
|
||||
case 0x28:case 0x29:case 0x2a:case 0x2b:case 0x30:case 0x38:case 0x39:case 0x3a:case 0x3b:
|
||||
case 0x28:case 0x29:case 0x2a:case 0x2b:case 0x30:case 0x31:case 0x32:case 0x33:case 0x38:case 0x39:case 0x3a:case 0x3b:
|
||||
case 0x24:case 0x25:case 0x26:case 0x27:case 0x2c:case 0x2d:case 0x2e:case 0x2f:
|
||||
case 0x34:case 0x3c:case 0x3e:return 1;
|
||||
case 0x34:case 0x35:case 0x36:case 0x37:case 0x3c:case 0x3d:case 0x3e:case 0x3f:return 1;
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
#include "source_gpu_command_projection.h"
|
||||
#include "gpu_sw_renderer.h"
|
||||
#include "psx_sha256.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static uint16_t vram[1024*512];
|
||||
int g_ws_bd_stretch_on,g_ws_bd_stretch_pct;
|
||||
int psx_ws_prim_in_backdrop(void){abort();}
|
||||
static void run(unsigned op,unsigned mode,unsigned blend,unsigned mask,unsigned dither,unsigned feedback) {
|
||||
memset(vram,0,sizeof(vram));unsigned ty=feedback?0:256,page=(feedback?0:16)|(mode<<7)|(blend<<5);
|
||||
for(unsigned y=0;y<128;y++)for(unsigned x=0;x<256;x++)vram[(y+ty)*1024+x]=(uint16_t)((x+y)%13==0?0:((x*37+y*113+1)&32767)|((x&1)?32768:0));
|
||||
for(unsigned i=0;i<256;i++)vram[400*1024+i]=(uint16_t)(i%17==0?0:((i*97+1)&32767)|((i&1)?32768:0));
|
||||
if(!feedback)for(unsigned y=0;y<32;y++)for(unsigned x=0;x<32;x++)vram[y*1024+x]=(uint16_t)(((x*19+y*57+123)&32767)|((x&1)?32768:0));
|
||||
int x[]={4,28,8,32},y[]={4,6,20,22};uint32_t colors[]={0xe3942b,0x285eb0,0x76c341,0x8ce921},uv[]={0x0301,0x65f7,0x7d0e,0x165f},words[12];
|
||||
unsigned vertices=(op&8)?4:3;
|
||||
for(unsigned i=0;i<vertices;i++){words[i*3]=colors[i]|(i?0:op<<24);words[i*3+1]=(unsigned)x[i]|(unsigned)y[i]<<16;words[i*3+2]=uv[i]|((i==0?400u<<6:i==1?page:0)<<16);}
|
||||
SourceGPUCommandProjection s;source_gpu_command_cold(&s);s.budget=256;s.clip_x1=1023;s.clip_y1=511;s.mask_bits=mask;s.draw_mode=page|dither<<9;
|
||||
sw_renderer_init(vram);sw_source_texture_control(0,0);sw_set_draw_area(0,0,1023,511);sw_set_mask_bits(mask&1,!!(mask&2));sw_set_semi_transparency(!!(op&2),blend);
|
||||
printf("op%02x-m%u-b%u-k%u-d%u-f%u",op,mode,blend,mask,dither,feedback);
|
||||
for(unsigned pass=0;pass<2;pass++)for(unsigned second=0;second<((op&8)?2u:1u);second++) {
|
||||
unsigned start=second?9:0,end=second?12:9;
|
||||
for(unsigned i=start;i<end;i++)if(!source_gpu_command_write(&s,words[i])){fprintf(stderr,"rejected opcode %02X\n",op);exit(1);}
|
||||
unsigned kind=(op&8)?(second?SOURCE_GPU_DISPATCH_QUAD_SECOND:SOURCE_GPU_DISPATCH_QUAD_FIRST):SOURCE_GPU_DISPATCH_COMMAND;
|
||||
if(s.dispatch.kind!=kind || s.dispatch.count!=end || s.phase!=((op&8)&&!second?2u:0u) || s.count)abort();
|
||||
if(!second)sw_source_texture_control(3,page);
|
||||
SourceGPUTexture texture={0};texture.page=page;texture.clut=400u<<6;texture.raw=!!(op&1);texture.load_clut=!second;
|
||||
for(unsigned i=0;i<3;i++)texture.uv[i]=uv[i+second];
|
||||
int extra=-1;if(!sw_draw_source_triangle(x+second,y+second,colors+second,1,dither,0,0,&texture,&extra) || extra<0)abort();
|
||||
s.budget-=extra;printf(" %d",256-s.budget);
|
||||
if(!source_gpu_command_update(&s,s.last_update+100000))abort();
|
||||
}
|
||||
uint8_t hash[32];psx_sha256_compute((uint8_t*)vram,sizeof(vram),hash);printf(" ");for(unsigned i=0;i<32;i++)printf("%02x",hash[i]);puts("");
|
||||
}
|
||||
int main(void){unsigned ops[]={0x34,0x35,0x36,0x37,0x3c,0x3d,0x3e,0x3f};for(unsigned o=0;o<8;o++)for(unsigned m=0;m<3;m++)for(unsigned b=0;b<4;b++)for(unsigned k=0;k<4;k++)for(unsigned d=0;d<2;d++)for(unsigned f=0;f<2;f++)run(ops[o],m,b,k,d,f);return 0;}
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Full stock shaded textured polygon images and source command/cache work."""
|
||||
from pathlib import Path
|
||||
import json,os,subprocess,sys
|
||||
fixture=json.loads(Path(__file__).with_name('source_gpu_shaded_texture_family_fixtures.json').read_text())
|
||||
env={k:v for k,v in os.environ.items() if not k.startswith('PSX_')}
|
||||
result=subprocess.run([sys.argv[1]],capture_output=True,text=True,env=env,timeout=90)
|
||||
assert result.returncode==0,(result.returncode,result.stderr)
|
||||
rows=[line.split() for line in result.stdout.splitlines()]
|
||||
assert len(rows)==len(fixture['cases'])==1536
|
||||
for row,case in zip(rows,fixture['cases']):
|
||||
assert row[0]==case['case'] and [int(x) for x in row[1:-1]]==case['work'] and row[-1]==case['source_vram_sha256'],(row,case)
|
||||
assert sum(len(x['work']) for x in fixture['cases'])==4608
|
||||
print('1536 stock complete VRAM images and 4608 command/cache work values PASS')
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "source_gpu_command_projection.h"
|
||||
#include "gpu_sw_renderer.h"
|
||||
#include "psx_sha256.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static uint16_t vram[1024*512];
|
||||
int g_ws_bd_stretch_on,g_ws_bd_stretch_pct;
|
||||
int psx_ws_prim_in_backdrop(void){abort();}
|
||||
static void run(unsigned op,unsigned blend,unsigned mask,unsigned dither) {
|
||||
memset(vram,0,sizeof(vram));
|
||||
for(unsigned y=0;y<32;y++)for(unsigned x=0;x<32;x++)vram[y*1024+x]=(uint16_t)(((x*37+y*113+1)&32767)|((x&1)?32768:0));
|
||||
int x[]={4,28,8},y[]={4,6,20};uint32_t colors[]={0xe3942b,0x285eb0,0x76c341},words[6];
|
||||
for(unsigned i=0;i<3;i++){words[i*2]=colors[i]|(i?0:op<<24);words[i*2+1]=(unsigned)x[i]|(unsigned)y[i]<<16;}
|
||||
SourceGPUCommandProjection s;source_gpu_command_cold(&s);s.budget=256;s.clip_x1=1023;s.clip_y1=511;s.mask_bits=mask;s.draw_mode=blend<<5|dither<<9;
|
||||
for(unsigned i=0;i<6;i++)if(!source_gpu_command_write(&s,words[i])){fprintf(stderr,"rejected opcode %02X\n",op);exit(1);}
|
||||
if(s.dispatch.kind!=SOURCE_GPU_DISPATCH_COMMAND || s.dispatch.count!=6 || s.phase || s.count)abort();int work=256-s.budget;
|
||||
sw_renderer_init(vram);sw_source_texture_control(0,0);sw_set_draw_area(0,0,1023,511);sw_set_mask_bits(mask&1,!!(mask&2));sw_set_semi_transparency(!!(op&2),blend);
|
||||
int extra=-1;if(!sw_draw_source_triangle(x,y,colors,1,dither,0,0,NULL,&extra) || extra)abort();
|
||||
uint8_t hash[32];psx_sha256_compute((uint8_t*)vram,sizeof(vram),hash);
|
||||
printf("op%02x-b%u-k%u-d%u %d ",op,blend,mask,dither,work);for(unsigned i=0;i<32;i++)printf("%02x",hash[i]);puts("");
|
||||
}
|
||||
int main(void){for(unsigned op=0x30;op<=0x33;op++)for(unsigned b=0;b<4;b++)for(unsigned k=0;k<4;k++)for(unsigned d=0;d<2;d++)run(op,b,k,d);return 0;}
|
||||
@@ -0,0 +1,12 @@
|
||||
"""Original-source shaded triangle complete images and command work."""
|
||||
from pathlib import Path
|
||||
import json,os,subprocess,sys
|
||||
fixture=json.loads(Path(__file__).with_name('source_gpu_shaded_triangle_fixtures.json').read_text())
|
||||
env={k:v for k,v in os.environ.items() if not k.startswith('PSX_')}
|
||||
result=subprocess.run([sys.argv[1]],capture_output=True,text=True,env=env,timeout=90)
|
||||
assert result.returncode==0,(result.returncode,result.stderr)
|
||||
rows=[line.split() for line in result.stdout.splitlines()]
|
||||
assert len(rows)==len(fixture['cases'])==128
|
||||
for row,case in zip(rows,fixture['cases']):
|
||||
assert row[0]==case['case'] and int(row[1])==case['work'] and row[2]==case['source_vram_sha256'],(row,case)
|
||||
print('128 stock complete VRAM images and 128 command work values PASS')
|
||||
Reference in New Issue
Block a user