From 5316a3572e8335b3d5bf2ba0fa57667b1913f465 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Tue, 6 May 2025 22:18:11 +0300 Subject: [PATCH] koshle: Update refsw2 and tacore --- vendor/emu/lxdream/tacore.cpp | 45 +- vendor/emu/refsw/TexUtils.cpp | 12 +- vendor/emu/refsw/TexUtils.h | 6 +- vendor/emu/refsw/gentable.h | 1456 ++++++++++++++++++++++++++++++ vendor/emu/refsw/gentable.py | 90 ++ vendor/emu/refsw/refsw_lists.cpp | 169 ++-- vendor/emu/refsw/refsw_lists.h | 18 +- vendor/emu/refsw/refsw_tile.cpp | 667 ++++++++------ vendor/emu/refsw/refsw_tile.h | 50 +- 9 files changed, 2083 insertions(+), 430 deletions(-) create mode 100644 vendor/emu/refsw/gentable.h create mode 100644 vendor/emu/refsw/gentable.py diff --git a/vendor/emu/lxdream/tacore.cpp b/vendor/emu/lxdream/tacore.cpp index d3b82efe..b2b82572 100644 --- a/vendor/emu/lxdream/tacore.cpp +++ b/vendor/emu/lxdream/tacore.cpp @@ -182,7 +182,8 @@ struct pvr2_ta_status { int32_t state; int32_t width, height; /* Tile resolution, ie 20x15 */ int32_t tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */ - uint32_t tilelist_size; /* Size of the tilelist segments */ + // uint32_t tilelist_size; /* Size of the tilelist segments */ + // this needs to be current_tile_size uint32_t tilelist_start; /* Initial address of the tilelist */ uint32_t polybuf_start; /* Initial bank address of the polygon buffer (ie &0x00F00000) */ int32_t current_vertex_type; @@ -208,6 +209,9 @@ struct pvr2_ta_status { struct tile_bounds last_triangle_bounds; struct pvr2_ta_vertex poly_vertex[8]; uint32_t debug_output; + + bool modifier_last_volume; + struct tile_bounds modifier_bounds; }; static struct pvr2_ta_status ta_status; @@ -253,13 +257,9 @@ void lxd_ta_init(u8* vram) { ta_status.clip.y2 = ta_status.height-1; uint32_t control = TA_ALLOC_CTRL; //MMIO_READ( PVR2, TA_TILECFG ); ta_status.tilelist_dir = (control >> 20) & 0x01; - ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ]; TA_ISP_CURRENT = TA_ISP_BASE; //MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) ); uint32_t plistpos = TA_NEXT_OPB_INIT >> 2; //MMIO_READ( PVR2, TA_LISTBASE ) - if( ta_status.tilelist_dir == TA_GROW_DOWN ) { - plistpos -= ta_status.tilelist_size; - } TA_NEXT_OPB = plistpos; //MMIO_WRITE( PVR2, TA_LISTPOS, plistpos ); ta_status.tilelist_start = plistpos; @@ -433,7 +433,9 @@ static uint32_t ta_alloc_tilelist( uint32_t reference ) { uint32_t limit = TA_OL_LIMIT >> 2;//MMIO_READ( PVR2, TA_LISTEND ) >> 2; uint32_t newposn; if( ta_status.tilelist_dir == TA_GROW_DOWN ) { - newposn = posn - ta_status.tilelist_size; + // printf("**TA WARNING**: Allocating tilelist in GROW_DOWN mode\n"); + posn -= ta_status.current_tile_size; + newposn = posn; if( posn == limit ) { PVRRAM(posn<<2) = 0xF0000000; PVRRAM(reference) = 0xE0000000 | (posn<<2); @@ -442,7 +444,7 @@ static uint32_t ta_alloc_tilelist( uint32_t reference ) { PVRRAM(reference) = 0xE0000000 | (posn<<2); return TA_NO_ALLOC; } else if( newposn <= limit ) { - } else if( newposn <= (limit + ta_status.tilelist_size) ) { + } else if( newposn <= (limit + ta_status.current_tile_size) ) { // asic_RaiseInterrupt(holly_MATR_NOMEM); pvr_queue_interrupt(ASIC_EVT_PVR_OPB_OUTOFMEM); printf("TA error: holly_MATR_NOMEM. Interrupt raised\n"); @@ -456,7 +458,7 @@ static uint32_t ta_alloc_tilelist( uint32_t reference ) { PVRRAM(reference) = 0xE0000000 | (posn<<2); return posn << 2; } else { - newposn = posn + ta_status.tilelist_size; + newposn = posn + ta_status.current_tile_size; if( posn == limit ) { PVRRAM(posn<<2) = 0xF0000000; PVRRAM(reference) = 0xE0000000 | (posn<<2); @@ -465,7 +467,7 @@ static uint32_t ta_alloc_tilelist( uint32_t reference ) { PVRRAM(reference) = 0xE0000000 | (posn<<2); return TA_NO_ALLOC; } else if( newposn >= limit ) { - } else if( newposn >= (limit - ta_status.tilelist_size) ) { + } else if( newposn >= (limit - ta_status.current_tile_size) ) { // asic_RaiseInterrupt(holly_MATR_NOMEM); pvr_queue_interrupt(ASIC_EVT_PVR_OPB_OUTOFMEM); printf("TA error: holly_MATR_NOMEM. Interrupt raised\n"); @@ -621,6 +623,17 @@ static void ta_commit_polygon( ) { if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0; if( polygon_bound.y2 >= ta_status.height ) polygon_bound.y2 = ta_status.height-1; + if (ta_status.current_vertex_type == TA_VERTEX_MOD_VOLUME) { + ta_status.modifier_bounds.x1 = MIN(ta_status.modifier_bounds.x1, polygon_bound.x1); + ta_status.modifier_bounds.x2 = MAX(ta_status.modifier_bounds.x2, polygon_bound.x2); + ta_status.modifier_bounds.y1 = MIN(ta_status.modifier_bounds.y1, polygon_bound.y1); + ta_status.modifier_bounds.y2 = MAX(ta_status.modifier_bounds.y2, polygon_bound.y2); + + if (ta_status.modifier_last_volume) { + polygon_bound = ta_status.modifier_bounds; + } + } + /* Set the "single tile" flag if it's entirely contained in 1 tile */ if( polygon_bound.x1 == polygon_bound.x2 && polygon_bound.y1 == polygon_bound.y2 ) { @@ -843,6 +856,14 @@ static void ta_parse_modifier_context( union ta_data *data ) { ta_status.vertex_count = 0; ta_status.max_vertex = 3; ta_status.poly_pointer = 0; + + if (ta_status.modifier_last_volume) { + ta_status.modifier_bounds.x1 = INT_MAX/32; + ta_status.modifier_bounds.y1 = INT_MAX/32; + ta_status.modifier_bounds.x2 = -1; + ta_status.modifier_bounds.y2 = -1; + } + ta_status.modifier_last_volume = data[0].i & TA_POLYCMD_FULLMOD; } /** @@ -1006,7 +1027,11 @@ static void ta_parse_vertex( union ta_data *data ) { vertex++; vertex->x = data[7].f; ta_status.vertex_count += 2; - ta_status.state = STATE_EXPECT_VERTEX_BLOCK2; + if (ta_status.current_vertex_type == TA_VERTEX_SPRITE || ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE) { + ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2; + } else { + ta_status.state = STATE_EXPECT_VERTEX_BLOCK2; + } break; } ta_status.vertex_count++; diff --git a/vendor/emu/refsw/TexUtils.cpp b/vendor/emu/refsw/TexUtils.cpp index 88e41a80..24ae4355 100644 --- a/vendor/emu/refsw/TexUtils.cpp +++ b/vendor/emu/refsw/TexUtils.cpp @@ -14,9 +14,9 @@ #endif u32 detwiddle[2][11][1024]; -u8 BM_SIN90[256]; -u8 BM_COS90[256]; -u8 BM_COS360[256]; +s8 BM_SIN90[256]; +s8 BM_COS90[256]; +s8 BM_COS360[256]; //input : address in the yyyyyxxxxx format //output : address in the xyxyxyxy format @@ -70,9 +70,9 @@ void BuildTables() } for (int i = 0; i < 256; i++) { - BM_SIN90[i] = 255 * sinf((i / 256.0f) * (M_PI / 2)); - BM_COS90[i] = 255 * cosf((i / 256.0f) * (M_PI / 2)); - BM_COS360[i] = 255 * cosf((i / 256.0f) * (2 * M_PI)); + BM_SIN90[i] = 127 * sinf((i / 256.0f) * (M_PI / 2)); + BM_COS90[i] = 127 * cosf((i / 256.0f) * (M_PI / 2)); + BM_COS360[i] = 127 * cosf((i / 256.0f) * (2 * M_PI)); } } \ No newline at end of file diff --git a/vendor/emu/refsw/TexUtils.h b/vendor/emu/refsw/TexUtils.h index 322b8828..8901e81e 100644 --- a/vendor/emu/refsw/TexUtils.h +++ b/vendor/emu/refsw/TexUtils.h @@ -8,9 +8,9 @@ #include extern u32 detwiddle[2][11][1024]; -extern u8 BM_SIN90[256]; -extern u8 BM_COS90[256]; -extern u8 BM_COS360[256]; +extern s8 BM_SIN90[256]; +extern s8 BM_COS90[256]; +extern s8 BM_COS360[256]; void BuildTables(); diff --git a/vendor/emu/refsw/gentable.h b/vendor/emu/refsw/gentable.h new file mode 100644 index 00000000..6a65fd57 --- /dev/null +++ b/vendor/emu/refsw/gentable.h @@ -0,0 +1,1456 @@ +PixelFlush_tsp_fp PixelFlush_tsp_table[2][2][2][2][2][4][2] = + { + { + { + { + { + { + { + &PixelFlush_tsp<0, 0, 0, 0, 0, 0, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 0, 1, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 0, 2, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 0, 3, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 0, 0, 0, 1, 0, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 1, 1, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 1, 2, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 0, 1, 3, 0>, + &PixelFlush_tsp<0, 0, 0, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<0, 0, 0, 1, 0, 0, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 0, 1, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 0, 2, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 0, 3, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 0, 0, 1, 1, 0, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 1, 1, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 1, 2, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 0, 1, 1, 3, 0>, + &PixelFlush_tsp<0, 0, 0, 1, 1, 3, 1>, + }, + }, + }, + }, + { + { + { + { + &PixelFlush_tsp<0, 0, 1, 0, 0, 0, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 0, 1, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 0, 2, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 0, 3, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 0, 1, 0, 1, 0, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 1, 1, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 1, 2, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 0, 1, 3, 0>, + &PixelFlush_tsp<0, 0, 1, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<0, 0, 1, 1, 0, 0, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 0, 1, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 0, 2, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 0, 3, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 0, 1, 1, 1, 0, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 1, 1, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 1, 2, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 0, 1, 1, 1, 3, 0>, + &PixelFlush_tsp<0, 0, 1, 1, 1, 3, 1>, + }, + }, + }, + }, + }, + { + { + { + { + { + &PixelFlush_tsp<0, 1, 0, 0, 0, 0, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 0, 1, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 0, 2, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 0, 3, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 1, 0, 0, 1, 0, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 1, 1, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 1, 2, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 0, 1, 3, 0>, + &PixelFlush_tsp<0, 1, 0, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<0, 1, 0, 1, 0, 0, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 0, 1, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 0, 2, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 0, 3, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 1, 0, 1, 1, 0, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 1, 1, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 1, 2, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 0, 1, 1, 3, 0>, + &PixelFlush_tsp<0, 1, 0, 1, 1, 3, 1>, + }, + }, + }, + }, + { + { + { + { + &PixelFlush_tsp<0, 1, 1, 0, 0, 0, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 0, 1, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 0, 2, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 0, 3, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 1, 1, 0, 1, 0, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 1, 1, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 1, 2, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 0, 1, 3, 0>, + &PixelFlush_tsp<0, 1, 1, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<0, 1, 1, 1, 0, 0, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 0, 1, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 0, 2, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 0, 3, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<0, 1, 1, 1, 1, 0, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 1, 1, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 1, 2, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<0, 1, 1, 1, 1, 3, 0>, + &PixelFlush_tsp<0, 1, 1, 1, 1, 3, 1>, + }, + }, + }, + }, + }, + }, + { + { + { + { + { + { + &PixelFlush_tsp<1, 0, 0, 0, 0, 0, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 0, 1, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 0, 2, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 0, 3, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 0, 0, 0, 1, 0, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 1, 1, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 1, 2, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 0, 1, 3, 0>, + &PixelFlush_tsp<1, 0, 0, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<1, 0, 0, 1, 0, 0, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 0, 1, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 0, 2, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 0, 3, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 0, 0, 1, 1, 0, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 1, 1, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 1, 2, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 0, 1, 1, 3, 0>, + &PixelFlush_tsp<1, 0, 0, 1, 1, 3, 1>, + }, + }, + }, + }, + { + { + { + { + &PixelFlush_tsp<1, 0, 1, 0, 0, 0, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 0, 1, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 0, 2, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 0, 3, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 0, 1, 0, 1, 0, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 1, 1, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 1, 2, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 0, 1, 3, 0>, + &PixelFlush_tsp<1, 0, 1, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<1, 0, 1, 1, 0, 0, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 0, 1, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 0, 2, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 0, 3, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 0, 1, 1, 1, 0, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 1, 1, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 1, 2, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 0, 1, 1, 1, 3, 0>, + &PixelFlush_tsp<1, 0, 1, 1, 1, 3, 1>, + }, + }, + }, + }, + }, + { + { + { + { + { + &PixelFlush_tsp<1, 1, 0, 0, 0, 0, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 0, 1, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 0, 2, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 0, 3, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 1, 0, 0, 1, 0, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 1, 1, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 1, 2, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 0, 1, 3, 0>, + &PixelFlush_tsp<1, 1, 0, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<1, 1, 0, 1, 0, 0, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 0, 1, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 0, 2, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 0, 3, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 1, 0, 1, 1, 0, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 1, 1, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 1, 2, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 0, 1, 1, 3, 0>, + &PixelFlush_tsp<1, 1, 0, 1, 1, 3, 1>, + }, + }, + }, + }, + { + { + { + { + &PixelFlush_tsp<1, 1, 1, 0, 0, 0, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 0, 1, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 0, 2, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 0, 3, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 1, 1, 0, 1, 0, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 1, 1, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 1, 2, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 0, 1, 3, 0>, + &PixelFlush_tsp<1, 1, 1, 0, 1, 3, 1>, + }, + }, + }, + { + { + { + &PixelFlush_tsp<1, 1, 1, 1, 0, 0, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 0, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 0, 1, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 0, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 0, 2, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 0, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 0, 3, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 0, 3, 1>, + }, + }, + { + { + &PixelFlush_tsp<1, 1, 1, 1, 1, 0, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 1, 0, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 1, 1, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 1, 1, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 1, 2, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 1, 2, 1>, + }, + { + &PixelFlush_tsp<1, 1, 1, 1, 1, 3, 0>, + &PixelFlush_tsp<1, 1, 1, 1, 1, 3, 1>, + }, + }, + }, + }, + }, + }, + } +; +TextureFilter_fp TextureFilter_table[2][2][2][2][2][4] = + { + { + { + { + { + { + &TextureFilter<0, 0, 0, 0, 0, 0>, + &TextureFilter<0, 0, 0, 0, 0, 1>, + &TextureFilter<0, 0, 0, 0, 0, 2>, + &TextureFilter<0, 0, 0, 0, 0, 3>, + }, + { + &TextureFilter<0, 0, 0, 0, 1, 0>, + &TextureFilter<0, 0, 0, 0, 1, 1>, + &TextureFilter<0, 0, 0, 0, 1, 2>, + &TextureFilter<0, 0, 0, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<0, 0, 0, 1, 0, 0>, + &TextureFilter<0, 0, 0, 1, 0, 1>, + &TextureFilter<0, 0, 0, 1, 0, 2>, + &TextureFilter<0, 0, 0, 1, 0, 3>, + }, + { + &TextureFilter<0, 0, 0, 1, 1, 0>, + &TextureFilter<0, 0, 0, 1, 1, 1>, + &TextureFilter<0, 0, 0, 1, 1, 2>, + &TextureFilter<0, 0, 0, 1, 1, 3>, + }, + }, + }, + { + { + { + &TextureFilter<0, 0, 1, 0, 0, 0>, + &TextureFilter<0, 0, 1, 0, 0, 1>, + &TextureFilter<0, 0, 1, 0, 0, 2>, + &TextureFilter<0, 0, 1, 0, 0, 3>, + }, + { + &TextureFilter<0, 0, 1, 0, 1, 0>, + &TextureFilter<0, 0, 1, 0, 1, 1>, + &TextureFilter<0, 0, 1, 0, 1, 2>, + &TextureFilter<0, 0, 1, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<0, 0, 1, 1, 0, 0>, + &TextureFilter<0, 0, 1, 1, 0, 1>, + &TextureFilter<0, 0, 1, 1, 0, 2>, + &TextureFilter<0, 0, 1, 1, 0, 3>, + }, + { + &TextureFilter<0, 0, 1, 1, 1, 0>, + &TextureFilter<0, 0, 1, 1, 1, 1>, + &TextureFilter<0, 0, 1, 1, 1, 2>, + &TextureFilter<0, 0, 1, 1, 1, 3>, + }, + }, + }, + }, + { + { + { + { + &TextureFilter<0, 1, 0, 0, 0, 0>, + &TextureFilter<0, 1, 0, 0, 0, 1>, + &TextureFilter<0, 1, 0, 0, 0, 2>, + &TextureFilter<0, 1, 0, 0, 0, 3>, + }, + { + &TextureFilter<0, 1, 0, 0, 1, 0>, + &TextureFilter<0, 1, 0, 0, 1, 1>, + &TextureFilter<0, 1, 0, 0, 1, 2>, + &TextureFilter<0, 1, 0, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<0, 1, 0, 1, 0, 0>, + &TextureFilter<0, 1, 0, 1, 0, 1>, + &TextureFilter<0, 1, 0, 1, 0, 2>, + &TextureFilter<0, 1, 0, 1, 0, 3>, + }, + { + &TextureFilter<0, 1, 0, 1, 1, 0>, + &TextureFilter<0, 1, 0, 1, 1, 1>, + &TextureFilter<0, 1, 0, 1, 1, 2>, + &TextureFilter<0, 1, 0, 1, 1, 3>, + }, + }, + }, + { + { + { + &TextureFilter<0, 1, 1, 0, 0, 0>, + &TextureFilter<0, 1, 1, 0, 0, 1>, + &TextureFilter<0, 1, 1, 0, 0, 2>, + &TextureFilter<0, 1, 1, 0, 0, 3>, + }, + { + &TextureFilter<0, 1, 1, 0, 1, 0>, + &TextureFilter<0, 1, 1, 0, 1, 1>, + &TextureFilter<0, 1, 1, 0, 1, 2>, + &TextureFilter<0, 1, 1, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<0, 1, 1, 1, 0, 0>, + &TextureFilter<0, 1, 1, 1, 0, 1>, + &TextureFilter<0, 1, 1, 1, 0, 2>, + &TextureFilter<0, 1, 1, 1, 0, 3>, + }, + { + &TextureFilter<0, 1, 1, 1, 1, 0>, + &TextureFilter<0, 1, 1, 1, 1, 1>, + &TextureFilter<0, 1, 1, 1, 1, 2>, + &TextureFilter<0, 1, 1, 1, 1, 3>, + }, + }, + }, + }, + }, + { + { + { + { + { + &TextureFilter<1, 0, 0, 0, 0, 0>, + &TextureFilter<1, 0, 0, 0, 0, 1>, + &TextureFilter<1, 0, 0, 0, 0, 2>, + &TextureFilter<1, 0, 0, 0, 0, 3>, + }, + { + &TextureFilter<1, 0, 0, 0, 1, 0>, + &TextureFilter<1, 0, 0, 0, 1, 1>, + &TextureFilter<1, 0, 0, 0, 1, 2>, + &TextureFilter<1, 0, 0, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<1, 0, 0, 1, 0, 0>, + &TextureFilter<1, 0, 0, 1, 0, 1>, + &TextureFilter<1, 0, 0, 1, 0, 2>, + &TextureFilter<1, 0, 0, 1, 0, 3>, + }, + { + &TextureFilter<1, 0, 0, 1, 1, 0>, + &TextureFilter<1, 0, 0, 1, 1, 1>, + &TextureFilter<1, 0, 0, 1, 1, 2>, + &TextureFilter<1, 0, 0, 1, 1, 3>, + }, + }, + }, + { + { + { + &TextureFilter<1, 0, 1, 0, 0, 0>, + &TextureFilter<1, 0, 1, 0, 0, 1>, + &TextureFilter<1, 0, 1, 0, 0, 2>, + &TextureFilter<1, 0, 1, 0, 0, 3>, + }, + { + &TextureFilter<1, 0, 1, 0, 1, 0>, + &TextureFilter<1, 0, 1, 0, 1, 1>, + &TextureFilter<1, 0, 1, 0, 1, 2>, + &TextureFilter<1, 0, 1, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<1, 0, 1, 1, 0, 0>, + &TextureFilter<1, 0, 1, 1, 0, 1>, + &TextureFilter<1, 0, 1, 1, 0, 2>, + &TextureFilter<1, 0, 1, 1, 0, 3>, + }, + { + &TextureFilter<1, 0, 1, 1, 1, 0>, + &TextureFilter<1, 0, 1, 1, 1, 1>, + &TextureFilter<1, 0, 1, 1, 1, 2>, + &TextureFilter<1, 0, 1, 1, 1, 3>, + }, + }, + }, + }, + { + { + { + { + &TextureFilter<1, 1, 0, 0, 0, 0>, + &TextureFilter<1, 1, 0, 0, 0, 1>, + &TextureFilter<1, 1, 0, 0, 0, 2>, + &TextureFilter<1, 1, 0, 0, 0, 3>, + }, + { + &TextureFilter<1, 1, 0, 0, 1, 0>, + &TextureFilter<1, 1, 0, 0, 1, 1>, + &TextureFilter<1, 1, 0, 0, 1, 2>, + &TextureFilter<1, 1, 0, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<1, 1, 0, 1, 0, 0>, + &TextureFilter<1, 1, 0, 1, 0, 1>, + &TextureFilter<1, 1, 0, 1, 0, 2>, + &TextureFilter<1, 1, 0, 1, 0, 3>, + }, + { + &TextureFilter<1, 1, 0, 1, 1, 0>, + &TextureFilter<1, 1, 0, 1, 1, 1>, + &TextureFilter<1, 1, 0, 1, 1, 2>, + &TextureFilter<1, 1, 0, 1, 1, 3>, + }, + }, + }, + { + { + { + &TextureFilter<1, 1, 1, 0, 0, 0>, + &TextureFilter<1, 1, 1, 0, 0, 1>, + &TextureFilter<1, 1, 1, 0, 0, 2>, + &TextureFilter<1, 1, 1, 0, 0, 3>, + }, + { + &TextureFilter<1, 1, 1, 0, 1, 0>, + &TextureFilter<1, 1, 1, 0, 1, 1>, + &TextureFilter<1, 1, 1, 0, 1, 2>, + &TextureFilter<1, 1, 1, 0, 1, 3>, + }, + }, + { + { + &TextureFilter<1, 1, 1, 1, 0, 0>, + &TextureFilter<1, 1, 1, 1, 0, 1>, + &TextureFilter<1, 1, 1, 1, 0, 2>, + &TextureFilter<1, 1, 1, 1, 0, 3>, + }, + { + &TextureFilter<1, 1, 1, 1, 1, 0>, + &TextureFilter<1, 1, 1, 1, 1, 1>, + &TextureFilter<1, 1, 1, 1, 1, 2>, + &TextureFilter<1, 1, 1, 1, 1, 3>, + }, + }, + }, + }, + }, + } +; +ColorCombiner_fp ColorCombiner_table[2][2][4] = + { + { + { + &ColorCombiner<0, 0, 0>, + &ColorCombiner<0, 0, 1>, + &ColorCombiner<0, 0, 2>, + &ColorCombiner<0, 0, 3>, + }, + { + &ColorCombiner<0, 1, 0>, + &ColorCombiner<0, 1, 1>, + &ColorCombiner<0, 1, 2>, + &ColorCombiner<0, 1, 3>, + }, + }, + { + { + &ColorCombiner<1, 0, 0>, + &ColorCombiner<1, 0, 1>, + &ColorCombiner<1, 0, 2>, + &ColorCombiner<1, 0, 3>, + }, + { + &ColorCombiner<1, 1, 0>, + &ColorCombiner<1, 1, 1>, + &ColorCombiner<1, 1, 2>, + &ColorCombiner<1, 1, 3>, + }, + }, + } +; +BlendingUnit_fp BlendingUnit_table[2][2][8][8] = + { + { + { + { + &BlendingUnit<0, 0, 0, 0>, + &BlendingUnit<0, 0, 0, 1>, + &BlendingUnit<0, 0, 0, 2>, + &BlendingUnit<0, 0, 0, 3>, + &BlendingUnit<0, 0, 0, 4>, + &BlendingUnit<0, 0, 0, 5>, + &BlendingUnit<0, 0, 0, 6>, + &BlendingUnit<0, 0, 0, 7>, + }, + { + &BlendingUnit<0, 0, 1, 0>, + &BlendingUnit<0, 0, 1, 1>, + &BlendingUnit<0, 0, 1, 2>, + &BlendingUnit<0, 0, 1, 3>, + &BlendingUnit<0, 0, 1, 4>, + &BlendingUnit<0, 0, 1, 5>, + &BlendingUnit<0, 0, 1, 6>, + &BlendingUnit<0, 0, 1, 7>, + }, + { + &BlendingUnit<0, 0, 2, 0>, + &BlendingUnit<0, 0, 2, 1>, + &BlendingUnit<0, 0, 2, 2>, + &BlendingUnit<0, 0, 2, 3>, + &BlendingUnit<0, 0, 2, 4>, + &BlendingUnit<0, 0, 2, 5>, + &BlendingUnit<0, 0, 2, 6>, + &BlendingUnit<0, 0, 2, 7>, + }, + { + &BlendingUnit<0, 0, 3, 0>, + &BlendingUnit<0, 0, 3, 1>, + &BlendingUnit<0, 0, 3, 2>, + &BlendingUnit<0, 0, 3, 3>, + &BlendingUnit<0, 0, 3, 4>, + &BlendingUnit<0, 0, 3, 5>, + &BlendingUnit<0, 0, 3, 6>, + &BlendingUnit<0, 0, 3, 7>, + }, + { + &BlendingUnit<0, 0, 4, 0>, + &BlendingUnit<0, 0, 4, 1>, + &BlendingUnit<0, 0, 4, 2>, + &BlendingUnit<0, 0, 4, 3>, + &BlendingUnit<0, 0, 4, 4>, + &BlendingUnit<0, 0, 4, 5>, + &BlendingUnit<0, 0, 4, 6>, + &BlendingUnit<0, 0, 4, 7>, + }, + { + &BlendingUnit<0, 0, 5, 0>, + &BlendingUnit<0, 0, 5, 1>, + &BlendingUnit<0, 0, 5, 2>, + &BlendingUnit<0, 0, 5, 3>, + &BlendingUnit<0, 0, 5, 4>, + &BlendingUnit<0, 0, 5, 5>, + &BlendingUnit<0, 0, 5, 6>, + &BlendingUnit<0, 0, 5, 7>, + }, + { + &BlendingUnit<0, 0, 6, 0>, + &BlendingUnit<0, 0, 6, 1>, + &BlendingUnit<0, 0, 6, 2>, + &BlendingUnit<0, 0, 6, 3>, + &BlendingUnit<0, 0, 6, 4>, + &BlendingUnit<0, 0, 6, 5>, + &BlendingUnit<0, 0, 6, 6>, + &BlendingUnit<0, 0, 6, 7>, + }, + { + &BlendingUnit<0, 0, 7, 0>, + &BlendingUnit<0, 0, 7, 1>, + &BlendingUnit<0, 0, 7, 2>, + &BlendingUnit<0, 0, 7, 3>, + &BlendingUnit<0, 0, 7, 4>, + &BlendingUnit<0, 0, 7, 5>, + &BlendingUnit<0, 0, 7, 6>, + &BlendingUnit<0, 0, 7, 7>, + }, + }, + { + { + &BlendingUnit<0, 1, 0, 0>, + &BlendingUnit<0, 1, 0, 1>, + &BlendingUnit<0, 1, 0, 2>, + &BlendingUnit<0, 1, 0, 3>, + &BlendingUnit<0, 1, 0, 4>, + &BlendingUnit<0, 1, 0, 5>, + &BlendingUnit<0, 1, 0, 6>, + &BlendingUnit<0, 1, 0, 7>, + }, + { + &BlendingUnit<0, 1, 1, 0>, + &BlendingUnit<0, 1, 1, 1>, + &BlendingUnit<0, 1, 1, 2>, + &BlendingUnit<0, 1, 1, 3>, + &BlendingUnit<0, 1, 1, 4>, + &BlendingUnit<0, 1, 1, 5>, + &BlendingUnit<0, 1, 1, 6>, + &BlendingUnit<0, 1, 1, 7>, + }, + { + &BlendingUnit<0, 1, 2, 0>, + &BlendingUnit<0, 1, 2, 1>, + &BlendingUnit<0, 1, 2, 2>, + &BlendingUnit<0, 1, 2, 3>, + &BlendingUnit<0, 1, 2, 4>, + &BlendingUnit<0, 1, 2, 5>, + &BlendingUnit<0, 1, 2, 6>, + &BlendingUnit<0, 1, 2, 7>, + }, + { + &BlendingUnit<0, 1, 3, 0>, + &BlendingUnit<0, 1, 3, 1>, + &BlendingUnit<0, 1, 3, 2>, + &BlendingUnit<0, 1, 3, 3>, + &BlendingUnit<0, 1, 3, 4>, + &BlendingUnit<0, 1, 3, 5>, + &BlendingUnit<0, 1, 3, 6>, + &BlendingUnit<0, 1, 3, 7>, + }, + { + &BlendingUnit<0, 1, 4, 0>, + &BlendingUnit<0, 1, 4, 1>, + &BlendingUnit<0, 1, 4, 2>, + &BlendingUnit<0, 1, 4, 3>, + &BlendingUnit<0, 1, 4, 4>, + &BlendingUnit<0, 1, 4, 5>, + &BlendingUnit<0, 1, 4, 6>, + &BlendingUnit<0, 1, 4, 7>, + }, + { + &BlendingUnit<0, 1, 5, 0>, + &BlendingUnit<0, 1, 5, 1>, + &BlendingUnit<0, 1, 5, 2>, + &BlendingUnit<0, 1, 5, 3>, + &BlendingUnit<0, 1, 5, 4>, + &BlendingUnit<0, 1, 5, 5>, + &BlendingUnit<0, 1, 5, 6>, + &BlendingUnit<0, 1, 5, 7>, + }, + { + &BlendingUnit<0, 1, 6, 0>, + &BlendingUnit<0, 1, 6, 1>, + &BlendingUnit<0, 1, 6, 2>, + &BlendingUnit<0, 1, 6, 3>, + &BlendingUnit<0, 1, 6, 4>, + &BlendingUnit<0, 1, 6, 5>, + &BlendingUnit<0, 1, 6, 6>, + &BlendingUnit<0, 1, 6, 7>, + }, + { + &BlendingUnit<0, 1, 7, 0>, + &BlendingUnit<0, 1, 7, 1>, + &BlendingUnit<0, 1, 7, 2>, + &BlendingUnit<0, 1, 7, 3>, + &BlendingUnit<0, 1, 7, 4>, + &BlendingUnit<0, 1, 7, 5>, + &BlendingUnit<0, 1, 7, 6>, + &BlendingUnit<0, 1, 7, 7>, + }, + }, + }, + { + { + { + &BlendingUnit<1, 0, 0, 0>, + &BlendingUnit<1, 0, 0, 1>, + &BlendingUnit<1, 0, 0, 2>, + &BlendingUnit<1, 0, 0, 3>, + &BlendingUnit<1, 0, 0, 4>, + &BlendingUnit<1, 0, 0, 5>, + &BlendingUnit<1, 0, 0, 6>, + &BlendingUnit<1, 0, 0, 7>, + }, + { + &BlendingUnit<1, 0, 1, 0>, + &BlendingUnit<1, 0, 1, 1>, + &BlendingUnit<1, 0, 1, 2>, + &BlendingUnit<1, 0, 1, 3>, + &BlendingUnit<1, 0, 1, 4>, + &BlendingUnit<1, 0, 1, 5>, + &BlendingUnit<1, 0, 1, 6>, + &BlendingUnit<1, 0, 1, 7>, + }, + { + &BlendingUnit<1, 0, 2, 0>, + &BlendingUnit<1, 0, 2, 1>, + &BlendingUnit<1, 0, 2, 2>, + &BlendingUnit<1, 0, 2, 3>, + &BlendingUnit<1, 0, 2, 4>, + &BlendingUnit<1, 0, 2, 5>, + &BlendingUnit<1, 0, 2, 6>, + &BlendingUnit<1, 0, 2, 7>, + }, + { + &BlendingUnit<1, 0, 3, 0>, + &BlendingUnit<1, 0, 3, 1>, + &BlendingUnit<1, 0, 3, 2>, + &BlendingUnit<1, 0, 3, 3>, + &BlendingUnit<1, 0, 3, 4>, + &BlendingUnit<1, 0, 3, 5>, + &BlendingUnit<1, 0, 3, 6>, + &BlendingUnit<1, 0, 3, 7>, + }, + { + &BlendingUnit<1, 0, 4, 0>, + &BlendingUnit<1, 0, 4, 1>, + &BlendingUnit<1, 0, 4, 2>, + &BlendingUnit<1, 0, 4, 3>, + &BlendingUnit<1, 0, 4, 4>, + &BlendingUnit<1, 0, 4, 5>, + &BlendingUnit<1, 0, 4, 6>, + &BlendingUnit<1, 0, 4, 7>, + }, + { + &BlendingUnit<1, 0, 5, 0>, + &BlendingUnit<1, 0, 5, 1>, + &BlendingUnit<1, 0, 5, 2>, + &BlendingUnit<1, 0, 5, 3>, + &BlendingUnit<1, 0, 5, 4>, + &BlendingUnit<1, 0, 5, 5>, + &BlendingUnit<1, 0, 5, 6>, + &BlendingUnit<1, 0, 5, 7>, + }, + { + &BlendingUnit<1, 0, 6, 0>, + &BlendingUnit<1, 0, 6, 1>, + &BlendingUnit<1, 0, 6, 2>, + &BlendingUnit<1, 0, 6, 3>, + &BlendingUnit<1, 0, 6, 4>, + &BlendingUnit<1, 0, 6, 5>, + &BlendingUnit<1, 0, 6, 6>, + &BlendingUnit<1, 0, 6, 7>, + }, + { + &BlendingUnit<1, 0, 7, 0>, + &BlendingUnit<1, 0, 7, 1>, + &BlendingUnit<1, 0, 7, 2>, + &BlendingUnit<1, 0, 7, 3>, + &BlendingUnit<1, 0, 7, 4>, + &BlendingUnit<1, 0, 7, 5>, + &BlendingUnit<1, 0, 7, 6>, + &BlendingUnit<1, 0, 7, 7>, + }, + }, + { + { + &BlendingUnit<1, 1, 0, 0>, + &BlendingUnit<1, 1, 0, 1>, + &BlendingUnit<1, 1, 0, 2>, + &BlendingUnit<1, 1, 0, 3>, + &BlendingUnit<1, 1, 0, 4>, + &BlendingUnit<1, 1, 0, 5>, + &BlendingUnit<1, 1, 0, 6>, + &BlendingUnit<1, 1, 0, 7>, + }, + { + &BlendingUnit<1, 1, 1, 0>, + &BlendingUnit<1, 1, 1, 1>, + &BlendingUnit<1, 1, 1, 2>, + &BlendingUnit<1, 1, 1, 3>, + &BlendingUnit<1, 1, 1, 4>, + &BlendingUnit<1, 1, 1, 5>, + &BlendingUnit<1, 1, 1, 6>, + &BlendingUnit<1, 1, 1, 7>, + }, + { + &BlendingUnit<1, 1, 2, 0>, + &BlendingUnit<1, 1, 2, 1>, + &BlendingUnit<1, 1, 2, 2>, + &BlendingUnit<1, 1, 2, 3>, + &BlendingUnit<1, 1, 2, 4>, + &BlendingUnit<1, 1, 2, 5>, + &BlendingUnit<1, 1, 2, 6>, + &BlendingUnit<1, 1, 2, 7>, + }, + { + &BlendingUnit<1, 1, 3, 0>, + &BlendingUnit<1, 1, 3, 1>, + &BlendingUnit<1, 1, 3, 2>, + &BlendingUnit<1, 1, 3, 3>, + &BlendingUnit<1, 1, 3, 4>, + &BlendingUnit<1, 1, 3, 5>, + &BlendingUnit<1, 1, 3, 6>, + &BlendingUnit<1, 1, 3, 7>, + }, + { + &BlendingUnit<1, 1, 4, 0>, + &BlendingUnit<1, 1, 4, 1>, + &BlendingUnit<1, 1, 4, 2>, + &BlendingUnit<1, 1, 4, 3>, + &BlendingUnit<1, 1, 4, 4>, + &BlendingUnit<1, 1, 4, 5>, + &BlendingUnit<1, 1, 4, 6>, + &BlendingUnit<1, 1, 4, 7>, + }, + { + &BlendingUnit<1, 1, 5, 0>, + &BlendingUnit<1, 1, 5, 1>, + &BlendingUnit<1, 1, 5, 2>, + &BlendingUnit<1, 1, 5, 3>, + &BlendingUnit<1, 1, 5, 4>, + &BlendingUnit<1, 1, 5, 5>, + &BlendingUnit<1, 1, 5, 6>, + &BlendingUnit<1, 1, 5, 7>, + }, + { + &BlendingUnit<1, 1, 6, 0>, + &BlendingUnit<1, 1, 6, 1>, + &BlendingUnit<1, 1, 6, 2>, + &BlendingUnit<1, 1, 6, 3>, + &BlendingUnit<1, 1, 6, 4>, + &BlendingUnit<1, 1, 6, 5>, + &BlendingUnit<1, 1, 6, 6>, + &BlendingUnit<1, 1, 6, 7>, + }, + { + &BlendingUnit<1, 1, 7, 0>, + &BlendingUnit<1, 1, 7, 1>, + &BlendingUnit<1, 1, 7, 2>, + &BlendingUnit<1, 1, 7, 3>, + &BlendingUnit<1, 1, 7, 4>, + &BlendingUnit<1, 1, 7, 5>, + &BlendingUnit<1, 1, 7, 6>, + &BlendingUnit<1, 1, 7, 7>, + }, + }, + }, + } +; +TextureFetch_fp TextureFetch_table[2][2][2][2][8] = + { + { + { + { + { + &TextureFetch<0, 0, 0, 0, 0>, + &TextureFetch<0, 0, 0, 0, 1>, + &TextureFetch<0, 0, 0, 0, 2>, + &TextureFetch<0, 0, 0, 0, 3>, + &TextureFetch<0, 0, 0, 0, 4>, + &TextureFetch<0, 0, 0, 0, 5>, + &TextureFetch<0, 0, 0, 0, 6>, + &TextureFetch<0, 0, 0, 0, 7>, + }, + { + &TextureFetch<0, 0, 0, 1, 0>, + &TextureFetch<0, 0, 0, 1, 1>, + &TextureFetch<0, 0, 0, 1, 2>, + &TextureFetch<0, 0, 0, 1, 3>, + &TextureFetch<0, 0, 0, 1, 4>, + &TextureFetch<0, 0, 0, 1, 5>, + &TextureFetch<0, 0, 0, 1, 6>, + &TextureFetch<0, 0, 0, 1, 7>, + }, + }, + { + { + &TextureFetch<0, 0, 1, 0, 0>, + &TextureFetch<0, 0, 1, 0, 1>, + &TextureFetch<0, 0, 1, 0, 2>, + &TextureFetch<0, 0, 1, 0, 3>, + &TextureFetch<0, 0, 1, 0, 4>, + &TextureFetch<0, 0, 1, 0, 5>, + &TextureFetch<0, 0, 1, 0, 6>, + &TextureFetch<0, 0, 1, 0, 7>, + }, + { + &TextureFetch<0, 0, 1, 1, 0>, + &TextureFetch<0, 0, 1, 1, 1>, + &TextureFetch<0, 0, 1, 1, 2>, + &TextureFetch<0, 0, 1, 1, 3>, + &TextureFetch<0, 0, 1, 1, 4>, + &TextureFetch<0, 0, 1, 1, 5>, + &TextureFetch<0, 0, 1, 1, 6>, + &TextureFetch<0, 0, 1, 1, 7>, + }, + }, + }, + { + { + { + &TextureFetch<0, 1, 0, 0, 0>, + &TextureFetch<0, 1, 0, 0, 1>, + &TextureFetch<0, 1, 0, 0, 2>, + &TextureFetch<0, 1, 0, 0, 3>, + &TextureFetch<0, 1, 0, 0, 4>, + &TextureFetch<0, 1, 0, 0, 5>, + &TextureFetch<0, 1, 0, 0, 6>, + &TextureFetch<0, 1, 0, 0, 7>, + }, + { + &TextureFetch<0, 1, 0, 1, 0>, + &TextureFetch<0, 1, 0, 1, 1>, + &TextureFetch<0, 1, 0, 1, 2>, + &TextureFetch<0, 1, 0, 1, 3>, + &TextureFetch<0, 1, 0, 1, 4>, + &TextureFetch<0, 1, 0, 1, 5>, + &TextureFetch<0, 1, 0, 1, 6>, + &TextureFetch<0, 1, 0, 1, 7>, + }, + }, + { + { + &TextureFetch<0, 1, 1, 0, 0>, + &TextureFetch<0, 1, 1, 0, 1>, + &TextureFetch<0, 1, 1, 0, 2>, + &TextureFetch<0, 1, 1, 0, 3>, + &TextureFetch<0, 1, 1, 0, 4>, + &TextureFetch<0, 1, 1, 0, 5>, + &TextureFetch<0, 1, 1, 0, 6>, + &TextureFetch<0, 1, 1, 0, 7>, + }, + { + &TextureFetch<0, 1, 1, 1, 0>, + &TextureFetch<0, 1, 1, 1, 1>, + &TextureFetch<0, 1, 1, 1, 2>, + &TextureFetch<0, 1, 1, 1, 3>, + &TextureFetch<0, 1, 1, 1, 4>, + &TextureFetch<0, 1, 1, 1, 5>, + &TextureFetch<0, 1, 1, 1, 6>, + &TextureFetch<0, 1, 1, 1, 7>, + }, + }, + }, + }, + { + { + { + { + &TextureFetch<1, 0, 0, 0, 0>, + &TextureFetch<1, 0, 0, 0, 1>, + &TextureFetch<1, 0, 0, 0, 2>, + &TextureFetch<1, 0, 0, 0, 3>, + &TextureFetch<1, 0, 0, 0, 4>, + &TextureFetch<1, 0, 0, 0, 5>, + &TextureFetch<1, 0, 0, 0, 6>, + &TextureFetch<1, 0, 0, 0, 7>, + }, + { + &TextureFetch<1, 0, 0, 1, 0>, + &TextureFetch<1, 0, 0, 1, 1>, + &TextureFetch<1, 0, 0, 1, 2>, + &TextureFetch<1, 0, 0, 1, 3>, + &TextureFetch<1, 0, 0, 1, 4>, + &TextureFetch<1, 0, 0, 1, 5>, + &TextureFetch<1, 0, 0, 1, 6>, + &TextureFetch<1, 0, 0, 1, 7>, + }, + }, + { + { + &TextureFetch<1, 0, 1, 0, 0>, + &TextureFetch<1, 0, 1, 0, 1>, + &TextureFetch<1, 0, 1, 0, 2>, + &TextureFetch<1, 0, 1, 0, 3>, + &TextureFetch<1, 0, 1, 0, 4>, + &TextureFetch<1, 0, 1, 0, 5>, + &TextureFetch<1, 0, 1, 0, 6>, + &TextureFetch<1, 0, 1, 0, 7>, + }, + { + &TextureFetch<1, 0, 1, 1, 0>, + &TextureFetch<1, 0, 1, 1, 1>, + &TextureFetch<1, 0, 1, 1, 2>, + &TextureFetch<1, 0, 1, 1, 3>, + &TextureFetch<1, 0, 1, 1, 4>, + &TextureFetch<1, 0, 1, 1, 5>, + &TextureFetch<1, 0, 1, 1, 6>, + &TextureFetch<1, 0, 1, 1, 7>, + }, + }, + }, + { + { + { + &TextureFetch<1, 1, 0, 0, 0>, + &TextureFetch<1, 1, 0, 0, 1>, + &TextureFetch<1, 1, 0, 0, 2>, + &TextureFetch<1, 1, 0, 0, 3>, + &TextureFetch<1, 1, 0, 0, 4>, + &TextureFetch<1, 1, 0, 0, 5>, + &TextureFetch<1, 1, 0, 0, 6>, + &TextureFetch<1, 1, 0, 0, 7>, + }, + { + &TextureFetch<1, 1, 0, 1, 0>, + &TextureFetch<1, 1, 0, 1, 1>, + &TextureFetch<1, 1, 0, 1, 2>, + &TextureFetch<1, 1, 0, 1, 3>, + &TextureFetch<1, 1, 0, 1, 4>, + &TextureFetch<1, 1, 0, 1, 5>, + &TextureFetch<1, 1, 0, 1, 6>, + &TextureFetch<1, 1, 0, 1, 7>, + }, + }, + { + { + &TextureFetch<1, 1, 1, 0, 0>, + &TextureFetch<1, 1, 1, 0, 1>, + &TextureFetch<1, 1, 1, 0, 2>, + &TextureFetch<1, 1, 1, 0, 3>, + &TextureFetch<1, 1, 1, 0, 4>, + &TextureFetch<1, 1, 1, 0, 5>, + &TextureFetch<1, 1, 1, 0, 6>, + &TextureFetch<1, 1, 1, 0, 7>, + }, + { + &TextureFetch<1, 1, 1, 1, 0>, + &TextureFetch<1, 1, 1, 1, 1>, + &TextureFetch<1, 1, 1, 1, 2>, + &TextureFetch<1, 1, 1, 1, 3>, + &TextureFetch<1, 1, 1, 1, 4>, + &TextureFetch<1, 1, 1, 1, 5>, + &TextureFetch<1, 1, 1, 1, 6>, + &TextureFetch<1, 1, 1, 1, 7>, + }, + }, + }, + }, + } +; diff --git a/vendor/emu/refsw/gentable.py b/vendor/emu/refsw/gentable.py new file mode 100644 index 00000000..c0f6415f --- /dev/null +++ b/vendor/emu/refsw/gentable.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import itertools + +def generate_table(name, parameters): + """ + Generates C++ code for PixelFlush_tsp_table given parameter ranges. + :param parameters: tuple of ints, the range for each template parameter + :return: string containing the C++ table declaration and initializer + """ + num_params = len(parameters) + # Construct the table dimensions + dims = ''.join(f'[{p}]' for p in parameters) + # Start building the initializer as a list of strings + lines = [] + + def recurse(level, indices, indent): + if level == num_params: + # Leaf: generate function pointer + params_list = ', '.join(str(i) for i in indices) + lines.append(f"{indent}&{name}<{params_list}>,") + else: + # Open brace for this dimension + lines.append(f"{indent}{{") + for i in range(parameters[level]): + recurse(level + 1, indices + [i], indent + ' ') + # Close brace + if level != 0: + lines.append(f"{indent}}},") + else: + lines.append(f"{indent}}}") + + # Table declaration + decl = f"{name}_fp {name}_table{dims} =" + lines.append(decl) + recurse(0, [], ' ') + lines.append(';') + + return '\n'.join(lines) + +if __name__ == '__main__': + # Example usage: each bool has 2 possibilities, some enums have more + bitwidths = ( + 1, # [pp_AlphaTest] + 1, # [entry->params.tsp[two_voume_index].UseAlpha] + 1, # [entry->params.isp.Texture] + 1, # [entry->params.isp.Offset] + 1, # [entry->params.tsp[two_voume_index].ColorClamp] + 2, # [entry->params.tsp[two_voume_index].FogCtrl] + 1, # [FPU_SHAD_SCALE.intensity_shadow] + ) + code = generate_table("PixelFlush_tsp", tuple(1 << bw for bw in bitwidths)) + print(code) + + bitwidths = ( + 1, # [entry->params.tsp[two_voume_index].IgnoreTexA] + 1, # [entry->params.tsp[two_voume_index].ClampU] + 1, # [entry->params.tsp[two_voume_index].ClampV] + 1, # [entry->params.tsp[two_voume_index].FlipU] + 1, # [entry->params.tsp[two_voume_index].FlipV] + 2, # [entry->params.tsp[two_voume_index].FilterMode] + ) + code = generate_table("TextureFilter", tuple(1 << bw for bw in bitwidths)) + print(code) + + bitwidths = ( + 1, # [entry->params.isp.Texture] + 1, # [entry->params.isp.Offset] + 2, # [entry->params.tsp[two_voume_index].ShadInstr ] + ) + code = generate_table("ColorCombiner", tuple(1 << bw for bw in bitwidths)) + print(code) + + bitwidths = ( + 1, # [entry->params.tsp[two_voume_index].SrcSelect] + 1, # [entry->params.tsp[two_voume_index].DstSelect] + 3, # [entry->params.tsp[two_voume_index].SrcInstr] + 3, # [entry->params.tsp[two_voume_index].DstInstr] + ) + code = generate_table("BlendingUnit", tuple(1 << bw for bw in bitwidths)) + print(code) + + bitwidths = ( + 1, # [entry->params.tcw[two_voume_index].VQ_Comp] + 1, # [entry->params.tcw[two_voume_index].MipMapped] + 1, # [entry->params.tcw[two_voume_index].ScanOrder] + 1, # [entry->params.tcw[two_voume_index].StrideSel] + 3, # [entry->params.tcw[two_voume_index].PixelFmt] + ) + code = generate_table("TextureFetch", tuple(1 << bw for bw in bitwidths)) + print(code) \ No newline at end of file diff --git a/vendor/emu/refsw/refsw_lists.cpp b/vendor/emu/refsw/refsw_lists.cpp index 90a6e720..a98ed734 100644 --- a/vendor/emu/refsw/refsw_lists.cpp +++ b/vendor/emu/refsw/refsw_lists.cpp @@ -81,34 +81,16 @@ #include "refsw_tile.h" -#define JLOG(...) -#define JLOG2(...) -#define V(x) x - -void log_vertex(const Vertex& v) { - JLOG(ll, - V(v.x), V(v.y), V(v.z), - V(v.col[0]), V(v.col[1]), V(v.col[2]), V(v.col[3]), V(v.spc[0]), V(v.spc[1]), V(v.spc[2]), V(v.spc[3]), V(v.u), V(v.v), - V(v.col1[0]), V(v.col1[1]), V(v.col1[2]), V(v.col1[3]), V(v.spc1[0]), V(v.spc1[1]), V(v.spc1[2]), V(v.spc1[3]), V(v.u1), V(v.v1) - ); -} - /* Main renderer class */ - void RenderTriangle(RenderMode render_mode, DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area) -{ - JLOG(ll, V(render_mode), V(tag), "tsp0", params->tsp[0].full, "tcw0", params->tcw[0].full, "tsp1", params->tsp[1].full, "tcw1", params->tcw[1].full); +{ + RasterizeTriangle_table[render_mode](params, tag, v1, v2, v3, v4, area); - log_vertex(v1); - log_vertex(v2); - log_vertex(v3); - if (v4) { - log_vertex(*v4); + if (render_mode == RM_TRANSLUCENT_PRESORT) { + RenderParamTags(area->left, area->top); } - - RasterizeTriangle(render_mode, params, tag, v1, v2, v3, v4, area); if (render_mode == RM_MODIFIER) { @@ -138,6 +120,7 @@ u32 ReadRegionArrayEntry(u32 base, RegionArrayEntry* entry) u32 rv; if (fmt_v1) { + entry->control.pre_sort = ISP_FEED_CFG.pre_sort; entry->puncht.full = 0x80000000; rv = 5 * 4; } @@ -160,13 +143,13 @@ u32 ReadRegionArrayEntry(u32 base, RegionArrayEntry* entry) } ISP_BACKGND_T_type CoreTagFromDesc(u32 cache_bypass, u32 shadow, u32 skip, u32 param_offs_in_words, u32 tag_offset) { - ISP_BACKGND_T_type rv { - .tag_offset = tag_offset, - .param_offs_in_words = param_offs_in_words, - .skip = skip, - .shadow = shadow, - .cache_bypass = cache_bypass - }; + ISP_BACKGND_T_type rv; + rv.full = 0; + rv.tag_offset = tag_offset; + rv.param_offs_in_words = param_offs_in_words; + rv.skip = skip; + rv.shadow = shadow; + rv.cache_bypass = cache_bypass; return rv; } @@ -174,8 +157,6 @@ ISP_BACKGND_T_type CoreTagFromDesc(u32 cache_bypass, u32 shadow, u32 skip, u32 p // render a triangle strip object list entry void RenderTriangleStrip(RenderMode render_mode, ObjectListEntry obj, taRECT* rect) { - JLOG(ll, V(render_mode), "obj", obj.full); - Vertex vtx[8]; DrawParameters params; @@ -204,7 +185,6 @@ void RenderTriangleStrip(RenderMode render_mode, ObjectListEntry obj, taRECT* re // render a triangle array object list entry void RenderTriangleArray(RenderMode render_mode, ObjectListEntry obj, taRECT* rect) { - JLOG(ll, V(render_mode), "obj", obj.full); auto triangles = obj.tarray.prims + 1; u32 param_base = PARAM_BASE & 0xF00000; @@ -222,8 +202,6 @@ void RenderTriangleArray(RenderMode render_mode, ObjectListEntry obj, taRECT* re parameter_tag_t tag = CoreTagFromDesc(params.isp.CacheBypass, obj.tstrip.shadow, obj.tstrip.skip, (tag_address - param_base)/4, 0).full; - assert(!(tag & TAG_INVALID)); - RenderTriangle(render_mode, ¶ms, tag, vtx[0], vtx[1], vtx[2], nullptr, rect); } } @@ -231,8 +209,6 @@ void RenderTriangleArray(RenderMode render_mode, ObjectListEntry obj, taRECT* re // render a quad array object list entry void RenderQuadArray(RenderMode render_mode, ObjectListEntry obj, taRECT* rect) { - JLOG(ll, V(render_mode), "obj", obj.full); - auto quads = obj.qarray.prims + 1; u32 param_base = PARAM_BASE & 0xF00000; @@ -301,22 +277,12 @@ void RenderCORE() { } u32 base = REGION_BASE; - JLOG(ll, V(REGION_BASE)); - RegionArrayEntry entry; // Parse region array do { auto step = ReadRegionArrayEntry(base, &entry); - JLOG2(llrrae, "ReadRegionArrayEntry", V(base), - "control", entry.control.full, - "opaque", entry.opaque.full, - "opaque_mod", entry.opaque_mod.full, - "trans", entry.trans.full, - "trans_mod", entry.trans_mod.full, - "puncht", entry.puncht.full); - base += step; taRECT rect; @@ -328,6 +294,7 @@ void RenderCORE() { parameter_tag_t bgTag; + ClearFpuCache(); // register BGPOLY to fpu { bgTag = ISP_BACKGND_T.full; @@ -338,85 +305,102 @@ void RenderCORE() { { // Clear Param + Z + stencil buffers ClearBuffers(bgTag, ISP_BACKGND_D.f, 0); + } else { + ClearParamStatusBuffer(); } // Render OPAQ to TAGS if (!entry.opaque.empty) { - JLOG2(llo, "opaque", V(entry.opaque.ptr_in_words)); RenderObjectList(RM_OPAQUE, entry.opaque.ptr_in_words * 4, &rect); + + if (!entry.opaque_mod.empty) + { + RenderObjectList(RM_MODIFIER, entry.opaque_mod.ptr_in_words * 4, &rect); + } } - // Render TAGS to ACCUM - RenderParamTags(RM_OPAQUE, rect.left, rect.top); + RenderParamTags(rect.left, rect.top); // render PT to TAGS if (!entry.puncht.empty) { PeelBuffersPTInitial(FLT_MAX); + + ClearMoreToDraw(); - do { + // Render to TAGS + RenderObjectList(RM_PUNCHTHROUGH_PASS0, entry.puncht.ptr_in_words * 4, &rect); + + // keep reference Z buffer + PeelBuffersPT(); + + // Render TAGS to ACCUM, making Z holes as-needed + RenderParamTags(rect.left, rect.top); + + while (GetMoreToDraw()) { ClearMoreToDraw(); // Render to TAGS - { - JLOG2(llo, "puncht", V(entry.puncht.ptr_in_words)); - RenderObjectList(RM_PUNCHTHROUGH, entry.puncht.ptr_in_words * 4, &rect); - } + RenderObjectList(RM_PUNCHTHROUGH_PASSN, entry.puncht.ptr_in_words * 4, &rect); + if (!GetMoreToDraw()) + break; + + ClearMoreToDraw(); // keep reference Z buffer PeelBuffersPT(); // Render TAGS to ACCUM, making Z holes as-needed - RenderParamTags(RM_PUNCHTHROUGH, rect.left, rect.top); - - // Copy TAGB=TAGA buffers, clear TAGA - PeelBuffersPTAfterHoles(); - - } while (GetMoreToDraw() != 0); - } - - - //TODO: Actually render OPAQ modvol affected pixels - if (!entry.opaque_mod.empty) - { - JLOG2(llo, "opaque_mod", V(entry.opaque_mod.ptr_in_words)); - RenderObjectList(RM_MODIFIER, entry.opaque_mod.ptr_in_words * 4, &rect); - RenderParamTags(RM_OP_PT_MV, rect.left, rect.top); + RenderParamTags(rect.left, rect.top); + } + if (!entry.opaque_mod.empty) + { + RenderObjectList(RM_MODIFIER, entry.opaque_mod.ptr_in_words * 4, &rect); + RenderParamTags(rect.left, rect.top); + } } // layer peeling rendering if (!entry.trans.empty) { - // clear the param buffer - ClearParamBuffer(TAG_INVALID); + if (entry.control.pre_sort) { + // clear the param buffer + ClearParamStatusBuffer(); - do - { - // prepare for a new pass - ClearMoreToDraw(); + // render to TAGS + { + RenderObjectList(RM_TRANSLUCENT_PRESORT, entry.trans.ptr_in_words * 4, &rect); + } + + // what happens with modvols here? + // if (!entry.trans_mod.empty) + // { + // RenderObjectList(RM_MODIFIER, entry.trans_mod.ptr_in_words * 4, &rect); + // } + } else { + do + { + // prepare for a new pass + ClearMoreToDraw(); - if (!ISP_FEED_CFG.pre_sort) { // copy depth test to depth reference buffer, clear depth test buffer, clear stencil PeelBuffers(FLT_MAX, 0); - } - // render to TAGS - { - JLOG2(llo, "trans", V(entry.trans.ptr_in_words)); - RenderObjectList(RM_TRANSLUCENT, entry.trans.ptr_in_words * 4, &rect); - } + // render to TAGS + { + RenderObjectList(RM_TRANSLUCENT_AUTOSORT, entry.trans.ptr_in_words * 4, &rect); + } - if (!entry.trans_mod.empty) - { - JLOG2(llo, "trans_mod", V(entry.trans_mod.ptr_in_words)); - RenderObjectList(RM_MODIFIER, entry.trans_mod.ptr_in_words * 4, &rect); - } + if (!entry.trans_mod.empty) + { + RenderObjectList(RM_MODIFIER, entry.trans_mod.ptr_in_words * 4, &rect); + } - // render TAGS to ACCUM - // also marks TAGS as invalid, but keeps the index for coplanar sorting - RenderParamTags(RM_TRANSLUCENT, rect.left, rect.top); - } while (GetMoreToDraw() != 0); + // render TAGS to ACCUM + RenderParamTags(rect.left, rect.top); + } while (GetMoreToDraw() != 0); + } } // Copy to vram @@ -469,9 +453,6 @@ void RenderCORE() { } } } - - // clear the tsp cache - ClearFpuEntries(); } while (!entry.control.last_region); } diff --git a/vendor/emu/refsw/refsw_lists.h b/vendor/emu/refsw/refsw_lists.h index 1cfce22f..7b1aebb7 100644 --- a/vendor/emu/refsw/refsw_lists.h +++ b/vendor/emu/refsw/refsw_lists.h @@ -26,13 +26,23 @@ struct DrawParameters enum RenderMode { RM_OPAQUE, - RM_PUNCHTHROUGH, - RM_OP_PT_MV, // OP and PT with modvol - RM_TRANSLUCENT, + RM_PUNCHTHROUGH_PASS0, + RM_PUNCHTHROUGH_PASSN, + RM_PUNCHTHROUGH_MV, // PT MODVOL 2nd pass + RM_TRANSLUCENT_AUTOSORT, + RM_TRANSLUCENT_PRESORT, RM_MODIFIER, }; -#define TAG_INVALID (1 << 31) +struct TagState { + union { + struct { + bool valid: 1; + bool rendered: 1; + }; + uint8_t raw; + }; +}; typedef u32 parameter_tag_t; diff --git a/vendor/emu/refsw/refsw_tile.cpp b/vendor/emu/refsw/refsw_tile.cpp index b57a6bcb..eb2bba80 100644 --- a/vendor/emu/refsw/refsw_tile.cpp +++ b/vendor/emu/refsw/refsw_tile.cpp @@ -14,20 +14,25 @@ #include #include #include +#include #include "refsw_tile.h" #include "TexUtils.h" +#include + +TagState tagStatus[MAX_RENDER_PIXELS]; parameter_tag_t tagBuffer[2] [MAX_RENDER_PIXELS]; StencilType stencilBuffer[MAX_RENDER_PIXELS]; u32 colorBuffer1 [MAX_RENDER_PIXELS]; u32 colorBuffer2 [MAX_RENDER_PIXELS]; -ZType depthBuffer[2] [MAX_RENDER_PIXELS]; +ZType depthBuffer[3] [MAX_RENDER_PIXELS]; -u32 tagBufferA; -u32 tagBufferB; -u32 depthBufferA; -u32 depthBufferB; +constexpr const u32 tagBufferA = 0; +constexpr const u32 tagBufferB = 1; +constexpr const u32 depthBufferA = 0; +constexpr const u32 depthBufferB = 1; +constexpr const u32 depthBufferC = 2; static float mmin(float a, float b, float c, float d) { @@ -54,74 +59,53 @@ f32 mask_w(f32 w) { void ClearBuffers(u32 paramValue, float depthValue, u32 stencilValue) { - depthBufferA = 0; - depthBufferB = 1; - - tagBufferA = 0; - tagBufferB = 1; - auto zb = depthBuffer[depthBufferA]; auto stencil = stencilBuffer; - auto pb = tagBuffer[tagBufferA]; + auto pb = tagBuffer[tagBufferA];; for (int i = 0; i < MAX_RENDER_PIXELS; i++) { zb[i] = mask_w(depthValue); stencil[i] = stencilValue; pb[i] = paramValue; + tagStatus[i] = { true, false }; } } -void ClearParamBuffer(parameter_tag_t paramValue) { - tagBufferA = 0; - tagBufferB = 1; - - auto pb = tagBuffer[tagBufferA]; +void ClearParamStatusBuffer() { + auto ts = tagStatus; for (int i = 0; i < MAX_RENDER_PIXELS; i++) { - pb[i] = paramValue; + ts[i] = { false, false }; } } void PeelBuffersPTInitial(float depthValue) { - tagBufferA = 1; - tagBufferB = 0; - - auto zb2 = depthBuffer[depthBufferB]; + memcpy(depthBuffer[depthBufferC], depthBuffer[depthBufferA], sizeof(ZType) * MAX_RENDER_PIXELS); + auto ts = tagStatus; for (int i = 0; i < MAX_RENDER_PIXELS; i++) { - zb2[i] = mask_w(depthValue);// set the "furthest" test to furthest value possible - tagBuffer[tagBufferA][i] = TAG_INVALID; + ts[i] = { false, false }; + stencilBuffer[i] = 0; } } void PeelBuffersPT() { - auto zb = depthBuffer[depthBufferA]; - auto zb2 = depthBuffer[depthBufferB]; - - for (int i = 0; i < MAX_RENDER_PIXELS; i++) { - zb2[i] = zb[i]; // keep old zb for - } -} - -void PeelBuffersPTAfterHoles() { - std::swap(tagBufferB, tagBufferA); - for (int i = 0; i < MAX_RENDER_PIXELS; i++) { - tagBuffer[tagBufferA][i] = TAG_INVALID; - } + memcpy(depthBuffer[depthBufferB], depthBuffer[depthBufferA], sizeof(ZType) * MAX_RENDER_PIXELS); + memcpy(tagBuffer[tagBufferB], tagBuffer[tagBufferA], sizeof(parameter_tag_t) * MAX_RENDER_PIXELS); } void PeelBuffers(float depthValue, u32 stencilValue) { - std::swap(depthBufferB, depthBufferA); - std::swap(tagBufferB, tagBufferA); + memcpy(depthBuffer[depthBufferB], depthBuffer[depthBufferA], sizeof(ZType) * MAX_RENDER_PIXELS); + memcpy(tagBuffer[tagBufferB], tagBuffer[tagBufferA], sizeof(parameter_tag_t) * MAX_RENDER_PIXELS); + auto zb = depthBuffer[depthBufferA]; - auto zb2 = depthBuffer[depthBufferB]; auto stencil = stencilBuffer; for (int i = 0; i < MAX_RENDER_PIXELS; i++) { zb[i] = mask_w(depthValue); // set the "closest" test to furthest value possible - tagBuffer[tagBufferA][i] = TAG_INVALID; + tagStatus[i] = { false, false }; stencil[i] = stencilValue; } } @@ -164,7 +148,8 @@ bool GetMoreToDraw() // Render to ACCUM from TAG buffer // TAG holds references to trianes, ACCUM is the tile framebuffer -void RenderParamTags(RenderMode rm, int tileX, int tileY) { +template +void RenderParamTags(int tileX, int tileY) { float halfpixel = HALF_OFFSET.tsp_pixel_half_offset ? 0.5f : 0; taRECT rect; rect.left = tileX; @@ -176,39 +161,45 @@ void RenderParamTags(RenderMode rm, int tileX, int tileY) { for (int x = 0; x < 32; x++) { auto index = y * 32 + x; auto tag = tagBuffer[tagBufferA][index]; - ISP_BACKGND_T_type t { .full = tag & ~TAG_INVALID }; + ISP_BACKGND_T_type t { .full = tag }; bool InVolume = (stencilBuffer[index] & 0b001) == 0b001 && t.shadow; - bool TagValid = !(tag & TAG_INVALID); + bool TagValid = tagStatus[index].valid; - if (TagValid || (rm == RM_OP_PT_MV && InVolume)) { - auto Entry = GetFpuEntry(&rect, rm, t); + if (rm == RM_PUNCHTHROUGH_MV && !InVolume) { + continue; + } + + if (rm == RM_PUNCHTHROUGH_PASS0 || rm == RM_PUNCHTHROUGH_PASSN) { + InVolume = false; + } + + if (TagValid) { + const auto& Entry = GetFpuEntry(&rect, rm, t); auto invW = Entry.ips.invW.Ip(x + halfpixel, y + halfpixel); - bool AlphaTestPassed = PixelFlush_tsp(rm == RM_PUNCHTHROUGH, &Entry, x + halfpixel, y + halfpixel, index, invW, InVolume); + bool AlphaTestPassed = PixelFlush_tsp(rm == RM_PUNCHTHROUGH_PASS0 || rm == RM_PUNCHTHROUGH_PASSN, &Entry, x + halfpixel, y + halfpixel, index, invW, InVolume); - auto pb = tagBuffer[tagBufferA] + index; - - *pb |= TAG_INVALID; - - // can only happen when rm == RM_PUNCHTHROUGH - if (!AlphaTestPassed) { - MoreToDraw = true; - // Feedback Channel - depthBuffer[depthBufferA][index] = ISP_BACKGND_D.f; + if (rm == RM_PUNCHTHROUGH_PASS0 || rm == RM_PUNCHTHROUGH_PASSN) { + // can only happen when rm == RM_PUNCHTHROUGH + if (!AlphaTestPassed) { + MoreToDraw = true; + // Feedback Channel + depthBuffer[depthBufferA][index] = depthBuffer[depthBufferC][index]; + } else { + tagStatus[index].rendered = true; + } } } } } } -void ClearFpuEntries() { - -} - -f32 f16(u16 v) -{ - u32 z=v<<16; - return *(f32*)&z; -} +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); +template void RenderParamTags(int tileX, int tileY); #define vert_packed_color_(to,src) \ { \ @@ -313,25 +304,29 @@ u32 decode_pvr_vertices(DrawParameters* params, pvr32addr_t base, u32 skip, u32 return base; } -FpuEntry GetFpuEntry(taRECT *rect, RenderMode render_mode, ISP_BACKGND_T_type core_tag) +struct { + FpuEntry entry; + u32 tag; +} fpuCache[32]; + +const FpuEntry& GetFpuEntry(taRECT *rect, RenderMode render_mode, ISP_BACKGND_T_type core_tag) { - FpuEntry entry = {}; + if (fpuCache[core_tag.param_offs_in_words & 31].tag == core_tag.full) { + return fpuCache[core_tag.param_offs_in_words & 31].entry; + } + FpuEntry &entry = fpuCache[core_tag.param_offs_in_words & 31].entry; Vertex vtx[3]; decode_pvr_vertices(&entry.params, PARAM_BASE + core_tag.param_offs_in_words * 4, core_tag.skip, core_tag.shadow & ~FPU_SHAD_SCALE.intensity_shadow, vtx, 3, core_tag.tag_offset); entry.ips.Setup(rect, &entry.params, vtx[0], vtx[1], vtx[2], core_tag.shadow & ~FPU_SHAD_SCALE.intensity_shadow); - return entry; + fpuCache[core_tag.param_offs_in_words & 31].tag = core_tag.full; + + return fpuCache[core_tag.param_offs_in_words & 31].entry ; } -// Lookup/create cached TSP parameters, and call PixelFlush_tsp -bool PixelFlush_tsp(bool pp_AlphaTest, FpuEntry* entry, float x, float y, u32 index, float invW, bool InVolume) -{ - u32 two_voume_index = InVolume & !FPU_SHAD_SCALE.intensity_shadow; - return PixelFlush_tsp(entry->params.tsp[two_voume_index].UseAlpha, entry->params.isp.Texture, entry->params.isp.Offset, entry->params.tsp[two_voume_index].ColorClamp, entry->params.tsp[two_voume_index].FogCtrl, - entry->params.tsp[two_voume_index].IgnoreTexA, entry->params.tsp[two_voume_index].ClampU, entry->params.tsp[two_voume_index].ClampV, entry->params.tsp[two_voume_index].FlipU, entry->params.tsp[two_voume_index].FlipV, entry->params.tsp[two_voume_index].FilterMode, entry->params.tsp[two_voume_index].ShadInstr, - pp_AlphaTest, entry->params.tsp[two_voume_index].SrcSelect, entry->params.tsp[two_voume_index].DstSelect, entry->params.tsp[two_voume_index].SrcInstr, entry->params.tsp[two_voume_index].DstInstr, - entry, x, y, 1/invW, InVolume, index); +void ClearFpuCache() { + memset(fpuCache, 0, sizeof(fpuCache)); } // this is disabled for now, as it breaks game scenes @@ -343,8 +338,146 @@ bool IsTopLeft(float x, float y) { return true; } + +// Depth processing for a pixel -- render_mode 0: OPAQ, 1: PT, 2: TRANS +template +inline __attribute__((always_inline)) void PixelFlush_isp(u32 depth_mode, u32 ZWriteDis, float x, float y, float invW, u32 index, parameter_tag_t tag) +{ + auto pb = tagBuffer[tagBufferA] + index; + auto ts = tagStatus + index; + auto pb2 = tagBuffer[tagBufferB] + index; + auto zb = depthBuffer[depthBufferA] + index; + auto zb2 = depthBuffer[depthBufferB] + index; + auto stencil = stencilBuffer + index; + + auto mode = depth_mode; + + if (render_mode == RM_PUNCHTHROUGH_PASS0 || render_mode == RM_PUNCHTHROUGH_PASSN) + mode = 6; + else if (render_mode == RM_TRANSLUCENT_AUTOSORT) + mode = 3; + else if (render_mode == RM_MODIFIER) + mode = 6; + + switch(mode) { + // never + case 0: return; break; + // less + case 1: if (invW >= *zb) return; break; + // equal + case 2: if (invW != *zb) return; break; + // less or equal + case 3: if (invW > *zb) { + if (render_mode == RM_TRANSLUCENT_AUTOSORT) { + MoreToDraw = true; + } + return; + }break; + // greater + case 4: if (invW <= *zb) return; break; + // not equal + case 5: if (invW == *zb) return; break; + // greater or equal + case 6: if (invW < *zb) return; break; + // always + case 7: break; + } + + switch (render_mode) + { + // OPAQ + case RM_OPAQUE: + { + // Z pre-pass only + if (!ZWriteDis) { + *zb = mask_w(invW); + } + *pb = tag; + ts->valid = 1; + } + break; + + case RM_MODIFIER: + { + // Flip on Z pass + + *stencil ^= 0b0010; + + // This pixel has valid stencil for summary + *stencil |= 0b100; + } + break; + + case RM_PUNCHTHROUGH_PASS0: + { + *zb = mask_w(invW); + *pb = tag; + + ts->valid = 1; + } + break; + // PT + case RM_PUNCHTHROUGH_PASSN: + { + if (ts->rendered) + return; + + if (invW > *zb2) + return; + + if (invW == *zb2) { + auto tagRendered = *pb2; + + if (tag <= tagRendered) + return; + } + + MoreToDraw = true; + + *zb = mask_w(invW); + *pb = tag; + } + break; + + // Layer Peeling. zb2 holds the reference depth, zb is used to find closest to reference + case RM_TRANSLUCENT_PRESORT: + { + if (!ZWriteDis) { + *zb = mask_w(invW); + } + *pb = tag; + ts->valid = true; + } + break; + case RM_TRANSLUCENT_AUTOSORT: + { + if (invW < *zb2) + return; + + if (invW == *zb2) { + auto tagRendered = *pb2; + + if (tag >= tagRendered) + return; + } + + *zb = mask_w(invW); + + if (ts->valid) { + MoreToDraw = true; + } + ts->valid = true; + *pb = tag; + } + break; + + case RM_PUNCHTHROUGH_MV: die("this is invalid here"); break; + } +} + // Rasterize a single triangle to ISP (or ISP+TSP for PT) -void RasterizeTriangle(RenderMode render_mode, DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area) +template +void RasterizeTriangle(DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area) { const int stride_bytes = STRIDE_PIXEL_OFFSET * 4; //Plane equation @@ -444,14 +577,7 @@ void RasterizeTriangle(RenderMode render_mode, DrawParameters* params, parameter if (inTriangle) { u32 index = y * 32 + x; float invW = Z.Ip(x_ps, y_ps); - PixelFlush_isp(render_mode, params->isp.DepthMode, params->isp.ZWriteDis, x_ps, y_ps, invW, index, tag); - - if (render_mode == RM_TRANSLUCENT && ISP_FEED_CFG.pre_sort && !(tagBuffer[tagBufferA][index] & TAG_INVALID)) { - ISP_BACKGND_T_type t { .full = tagBuffer[tagBufferA][index] }; - auto Entry = GetFpuEntry(area, RM_TRANSLUCENT, t); - PixelFlush_tsp(false, &Entry, x_ps, y_ps, index, invW, false); - tagBuffer[tagBufferA][index] |= TAG_INVALID; - } + PixelFlush_isp(params->isp.DepthMode, params->isp.ZWriteDis, x_ps, y_ps, invW, index, tag); } x_ps = x_ps + 1; @@ -460,15 +586,25 @@ void RasterizeTriangle(RenderMode render_mode, DrawParameters* params, parameter y_ps = y_ps + 1; } } - + +void (*RasterizeTriangle_table[7])(DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area) = { + &RasterizeTriangle, + &RasterizeTriangle, + &RasterizeTriangle, + &RasterizeTriangle, + &RasterizeTriangle, + &RasterizeTriangle, + &RasterizeTriangle +}; + u8* GetColorOutputBuffer() { return (u8*)colorBuffer1; } // Clamp and flip a texture coordinate -static int ClampFlip( bool pp_Clamp, bool pp_Flip - , int coord, int size) { +template +inline __attribute__((always_inline)) int ClampFlip(int coord, int size) { if (pp_Clamp) { // clamp if (coord < 0) { coord = 0; @@ -561,7 +697,8 @@ static Color TextureFetchOld(TSP tsp, TCW tcw, int u, int v) { } #endif -u32 ExpandToARGB8888(u32 color, u32 mode, bool ScanOrder /* TODO: Expansion Patterns */) { +template +inline __attribute__((always_inline)) u32 ExpandToARGB8888(u32 color, u32 mode) { switch(mode) { case 0: return ARGB1555_32(color); @@ -572,27 +709,29 @@ u32 ExpandToARGB8888(u32 color, u32 mode, bool ScanOrder /* TODO: Expansion Patt return 0xDEADBEEF; } -u32 TexAddressGen(TCW tcw) { +template +inline __attribute__((always_inline)) u32 TexAddressGen(TCW tcw) { u32 base_address = tcw.TexAddr << 3; - if (tcw.VQ_Comp) { + if (VQ_Comp) { base_address += 256 * 4 * 2; } return base_address; } -u32 TexOffsetGen(TSP tsp, TCW tcw, bool ScanOrder, int u, int v, u32 stride, u32 MipLevel) { +template +inline __attribute__((always_inline)) u32 TexOffsetGen(TSP tsp, int u, int v, u32 stride, u32 MipLevel) { u32 mip_offset; - if (tcw.MipMapped) { + if (MipMapped) { mip_offset = MipPoint[3 + tsp.TexU - MipLevel]; } else { mip_offset = 0; } - if (tcw.VQ_Comp || !ScanOrder) { - if (tcw.MipMapped) { + if (VQ_Comp || !ScanOrder) { + if (MipMapped) { return mip_offset + twop(u, v, (tsp.TexU - MipLevel), (tsp.TexU - MipLevel)); } else { return mip_offset + twop(u, v, tsp.TexU, tsp.TexV); @@ -603,26 +742,27 @@ u32 TexOffsetGen(TSP tsp, TCW tcw, bool ScanOrder, int u, int v, u32 stride, u32 } // 4.1 format -u32 fBitsPerPixel(TCW tcw) { - u32 rv; - if (tcw.PixelFmt == PixelPal8) { +template +inline constexpr u32 fBitsPerPixel() { + u32 rv = 16; + if (PixelFmt == PixelPal8) { rv = 8; } - else if (tcw.PixelFmt == PixelPal4) { + else if (PixelFmt == PixelPal4) { rv = 4; } else { rv = 16; } - if (tcw.VQ_Comp) { + if (VQ_Comp) { return 8 * 2 / (64 / rv); // 8 bpp / (pixels per 64 bits) } else { return rv * 2; } } -u64 VQLookup(u32 start_address, u64 memtel, u32 offset) { +inline __attribute__((always_inline)) u64 VQLookup(u32 start_address, u64 memtel, u32 offset) { u8* memtel8 = (u8*)&memtel; u64 *vq_book = (u64*)&emu_vram[start_address & (VRAM_MASK-7)]; @@ -630,14 +770,16 @@ u64 VQLookup(u32 start_address, u64 memtel, u32 offset) { return vq_book[index]; } -u32 TexStride(u32 TexU, u32 StrideSel, u32 ScanOrder, u32 MipLevel) { +template +inline __attribute__((always_inline)) u32 TexStride(u32 TexU, u32 MipLevel) { if (StrideSel && ScanOrder) return (TEXT_CONTROL&31)*32; else return (8U << TexU) >> MipLevel; } -u32 DecodeTextel(u32 PixelFmt, u32 PalSelect, u64 memtel, u32 offset) { +template +inline __attribute__((always_inline)) u32 DecodeTextel(u32 PalSelect, u64 memtel, u32 offset) { auto memtel_32 = (u32*)&memtel; auto memtel_16 = (u16*)&memtel; auto memtel_8 = (u8*)&memtel; @@ -673,7 +815,8 @@ u32 DecodeTextel(u32 PixelFmt, u32 PalSelect, u64 memtel, u32 offset) { return 0xDEADBEEF; } -u32 GetExpandFormat(u32 PixelFmt) { +template +inline __attribute__((always_inline)) u32 GetExpandFormat() { if (PixelFmt == PixelPal4 || PixelFmt == PixelPal8) { return PAL_RAM_CTRL&3; } else if (PixelFmt == PixelBumpMap || PixelFmt == PixelYUV) { @@ -682,6 +825,7 @@ u32 GetExpandFormat(u32 PixelFmt) { return PixelFmt & 3; } } + Color MipDebugColor[11] = { {.raw = 0xFF000060}, {.raw = 0xFF000090}, @@ -699,42 +843,42 @@ Color MipDebugColor[11] = { {.raw = 0xFFF0F0F0}, }; +template static Color TextureFetch(TSP tsp, TCW tcw, int u, int v, u32 MipLevel) { - - u32 PixelFmt = tcw.PixelFmt; - if (MipLevel == (tsp.TexU + 3)) { - if (PixelFmt == PixelYUV) { - PixelFmt = Pixel565; - } - } + // TODO: implement this + // if (MipLevel == (tsp.TexU + 3)) { + // if (PixelFmt == PixelYUV) { + // PixelFmt = Pixel565; + // } + // } // These are fixed to zero for pal4/pal8 - u32 ScanOrder = tcw.ScanOrder & ~(PixelFmt == PixelPal4 || PixelFmt == PixelPal8); - u32 StrideSel = tcw.StrideSel & ~(PixelFmt == PixelPal4 || PixelFmt == PixelPal8); + constexpr u32 ScanOrder = ScanOrder_ & ~(PixelFmt == PixelPal4 || PixelFmt == PixelPal8); + constexpr u32 StrideSel = StrideSel_ & ~(PixelFmt == PixelPal4 || PixelFmt == PixelPal8); - u32 stride = TexStride(tsp.TexU, StrideSel, ScanOrder, MipLevel); + u32 stride = TexStride(tsp.TexU, MipLevel); u32 start_address = tcw.TexAddr << 3; - auto fbpp = fBitsPerPixel(tcw); + auto fbpp = fBitsPerPixel(); - auto base_address = TexAddressGen(tcw); - auto offset = TexOffsetGen(tsp, tcw, ScanOrder, u, v, stride, MipLevel); + auto base_address = TexAddressGen(tcw); + auto offset = TexOffsetGen(tsp, u, v, stride, MipLevel); u64 memtel = (u64&)emu_vram[(base_address + offset * fbpp / 16) & (VRAM_MASK-7)]; - if (tcw.VQ_Comp) { + if (VQ_Comp) { memtel = VQLookup(start_address, memtel, offset * fbpp / 16); } - u32 textel = DecodeTextel(PixelFmt, tcw.PalSelect, memtel, offset); + u32 textel = DecodeTextel(tcw.PalSelect, memtel, offset); - u32 expand_format = GetExpandFormat(PixelFmt); + u32 expand_format = GetExpandFormat(); - textel = ExpandToARGB8888(textel, expand_format, tcw.ScanOrder); + textel = ExpandToARGB8888(textel, expand_format); // auto old = TextureFetch2(texture, u, v); // if (textel != old.raw) { @@ -754,10 +898,11 @@ static Color TextureFetch(TSP tsp, TCW tcw, int u, int v, u32 MipLevel) { u32 to_u8_256(u8 v) { return v + (v >> 7); } +using TextureFetch_fp = decltype(&TextureFetch); + // Fetch pixels from UVs, interpolate -static Color TextureFilter( - bool pp_IgnoreTexA, bool pp_ClampU, bool pp_ClampV, bool pp_FlipU, bool pp_FlipV, u32 pp_FilterMode, - TSP tsp, TCW tcw, float u, float v, u32 MipLevel, f32 dTrilinear) { +template +static Color TextureFilter(TSP tsp, TCW tcw, float u, float v, u32 MipLevel, f32 dTrilinear, TextureFetch_fp fetch) { int halfpixel = HALF_OFFSET.texure_pixel_half_offset ? -127 : 0; if (MipLevel >= (tsp.TexU + 3)) { @@ -776,10 +921,10 @@ static Color TextureFilter( int ui = u * sizeU * 256 + halfpixel; int vi = v * sizeV * 256 + halfpixel; - auto offset00 = TextureFetch(tsp, tcw, ClampFlip(pp_ClampU, pp_FlipU, (ui >> 8) + 1, sizeU), ClampFlip(pp_ClampV, pp_FlipV, (vi >> 8) + 1, sizeV), MipLevel); - auto offset01 = TextureFetch(tsp, tcw, ClampFlip(pp_ClampU, pp_FlipU, (ui >> 8) + 0, sizeU), ClampFlip(pp_ClampV, pp_FlipV, (vi >> 8) + 1, sizeV), MipLevel); - auto offset10 = TextureFetch(tsp, tcw, ClampFlip(pp_ClampU, pp_FlipU, (ui >> 8) + 1, sizeU), ClampFlip(pp_ClampV, pp_FlipV, (vi >> 8) + 0, sizeV), MipLevel); - auto offset11 = TextureFetch(tsp, tcw, ClampFlip(pp_ClampU, pp_FlipU, (ui >> 8) + 0, sizeU), ClampFlip(pp_ClampV, pp_FlipV, (vi >> 8) + 0, sizeV), MipLevel); + auto offset00 = fetch(tsp, tcw, ClampFlip((ui >> 8) + 1, sizeU), ClampFlip((vi >> 8) + 1, sizeV), MipLevel); + auto offset01 = fetch(tsp, tcw, ClampFlip((ui >> 8) + 0, sizeU), ClampFlip((vi >> 8) + 1, sizeV), MipLevel); + auto offset10 = fetch(tsp, tcw, ClampFlip((ui >> 8) + 1, sizeU), ClampFlip((vi >> 8) + 0, sizeV), MipLevel); + auto offset11 = fetch(tsp, tcw, ClampFlip((ui >> 8) + 0, sizeU), ClampFlip((vi >> 8) + 0, sizeV), MipLevel); Color textel = {0xAF674839}; @@ -792,17 +937,18 @@ static Color TextureFilter( } else if (pp_FilterMode == 1) { // Bilinear filtering int ublend = to_u8_256(ui & 255); - int vblend = (vi & 255); + int vblend = to_u8_256(vi & 255); int nublend = 256 - ublend; int nvblend = 256 - vblend; for (int i = 0; i < 4; i++) { - textel.bgra[i] = - (offset00.bgra[i] * ublend * vblend) / 65536 + - (offset01.bgra[i] * nublend * vblend) / 65536 + - (offset10.bgra[i] * ublend * nvblend) / 65536 + - (offset11.bgra[i] * nublend * nvblend) / 65536; + textel.bgra[i] = ( + (offset00.bgra[i] * ublend * vblend) + + (offset01.bgra[i] * nublend * vblend) + + (offset10.bgra[i] * ublend * nvblend) + + (offset11.bgra[i] * nublend * nvblend) + ) / 65536; }; } else { // trilinear filtering A and B @@ -819,9 +965,8 @@ static Color TextureFilter( } // Combine Base, Textel and Offset colors -static Color ColorCombiner( - bool pp_Texture, bool pp_Offset, u32 pp_ShadInstr, - Color base, Color textel, Color offset) { +template +static Color ColorCombiner(Color base, Color textel, Color offset) { Color rv = base; if (pp_Texture) @@ -884,10 +1029,15 @@ static Color BumpMapper(Color textel, Color offset) { u8 K3 = offset.g; u8 Q = offset.b; - u8 S = offset.b; - u8 R = offset.g; + u8 R = textel.b; + u8 S = textel.g; - u8 I = u8(K1 + K2*BM_SIN90[S]/256 + K3*BM_COS90[S]*BM_COS360[(R - Q) & 255]/256/256); + s32 I = (K1*127*127 + K2*BM_SIN90[S]*127 + K3*BM_COS90[S]*BM_COS360[(R - Q) & 255])/127/127; + if (I < 0) { + I = 0; + } else if (I > 255) { + I = 255; + } Color res; res.b = 255; @@ -898,9 +1048,8 @@ static Color BumpMapper(Color textel, Color offset) { } // Interpolate the base color, also cheap shadows modifier -static Color InterpolateBase( - bool pp_UseAlpha, bool pp_CheapShadows, - const PlaneStepper3* Col, float x, float y, float W, bool InVolume) { +template +inline __attribute__((always_inline)) Color InterpolateBase(const PlaneStepper3* Col, float x, float y, float W, bool InVolume) { Color rv; u32 mult = 256; @@ -910,10 +1059,10 @@ static Color InterpolateBase( } } - rv.bgra[0] = 0.5f + Col[0].Ip(x, y, W) * mult / 256; - rv.bgra[1] = 0.5f + Col[1].Ip(x, y, W) * mult / 256; - rv.bgra[2] = 0.5f + Col[2].Ip(x, y, W) * mult / 256; - rv.bgra[3] = 0.5f + Col[3].Ip(x, y, W) * mult / 256; + rv.bgra[0] = 0.5f + Col[0].IpU8(x, y, W) * mult / 256; + rv.bgra[1] = 0.5f + Col[1].IpU8(x, y, W) * mult / 256; + rv.bgra[2] = 0.5f + Col[2].IpU8(x, y, W) * mult / 256; + rv.bgra[3] = 0.5f + Col[3].IpU8(x, y, W) * mult / 256; if (!pp_UseAlpha) { @@ -924,8 +1073,8 @@ static Color InterpolateBase( } // Interpolate the offset color, also cheap shadows modifier -static Color InterpolateOffs(bool pp_CheapShadows, - const PlaneStepper3* Ofs, float x, float y, float W, bool InVolume) { +template +inline __attribute__((always_inline)) Color InterpolateOffs(const PlaneStepper3* Ofs, float x, float y, float W, bool InVolume) { Color rv; u32 mult = 256; @@ -935,18 +1084,17 @@ static Color InterpolateOffs(bool pp_CheapShadows, } } - rv.bgra[0] = 0.5f + Ofs[0].Ip(x, y, W) * mult / 256; - rv.bgra[1] = 0.5f + Ofs[1].Ip(x, y, W) * mult / 256; - rv.bgra[2] = 0.5f + Ofs[2].Ip(x, y, W) * mult / 256; - rv.bgra[3] = 0.5f + Ofs[3].Ip(x, y, W); + rv.bgra[0] = 0.5f + Ofs[0].IpU8(x, y, W) * mult / 256; + rv.bgra[1] = 0.5f + Ofs[1].IpU8(x, y, W) * mult / 256; + rv.bgra[2] = 0.5f + Ofs[2].IpU8(x, y, W) * mult / 256; + rv.bgra[3] = 0.5f + Ofs[3].IpU8(x, y, W); return rv; } // select/calculate blend coefficient for the blend unit -static Color BlendCoefs( - u32 pp_AlphaInst, bool srcOther, - Color src, Color dst) { +template +inline __attribute__((always_inline)) Color BlendCoefs(Color src, Color dst) { Color rv; switch(pp_AlphaInst>>1) { @@ -969,16 +1117,15 @@ static Color BlendCoefs( } // Blending Unit implementation. Alpha blend, accum buffers and such -static bool BlendingUnit( - bool pp_AlphaTest, u32 pp_SrcSel, u32 pp_DstSel, u32 pp_SrcInst, u32 pp_DstInst, - u32 index, Color col) +template +static void BlendingUnit(u32 index, Color col) { Color rv; Color src = {.raw = pp_SrcSel ? colorBuffer2[index] : col.raw }; Color dst = {.raw = pp_DstSel ? colorBuffer2[index] : colorBuffer1[index] }; - Color src_blend = BlendCoefs(pp_SrcInst, false, src, dst); - Color dst_blend = BlendCoefs(pp_DstInst, true, src, dst); + Color src_blend = BlendCoefs(src, dst); + Color dst_blend = BlendCoefs(src, dst); for (int j = 0; j < 4; j++) { @@ -987,17 +1134,9 @@ static bool BlendingUnit( (pp_DstSel ? colorBuffer2[index] : colorBuffer1[index]) = rv.raw; - if (!pp_AlphaTest || src.a >= PT_ALPHA_REF) - { - return true; - } - else - { - return false; - } } -static u8 LookupFogTable(float invW) { +inline __attribute__((always_inline)) u8 LookupFogTable(float invW) { u8* fog_density=(u8*)&FOG_DENSITY; float fog_den_mant=fog_density[1]/128.0f; //bit 7 -> x. bit, so [6:0] -> fraction -> /128 s32 fog_den_exp=(s8)fog_density[0]; @@ -1033,7 +1172,8 @@ static u8 LookupFogTable(float invW) { } // Color Clamp and Fog a pixel -static Color FogUnit(bool pp_Offset, bool pp_ColorClamp, u32 pp_FogCtrl, Color col, float invW, u8 offs_a) { +template +inline __attribute__((always_inline)) Color FogUnit(Color col, float invW, u8 offs_a) { if (pp_ColorClamp) { Color clamp_max = { FOG_CLAMP_MAX }; Color clamp_min = { FOG_CLAMP_MIN }; @@ -1093,7 +1233,7 @@ static Color FogUnit(bool pp_Offset, bool pp_ColorClamp, u32 pp_FogCtrl, Color c return col; } -void DumpTexture(TSP tsp, TCW tcw) { +void DumpTexture(TSP tsp, TCW tcw, TextureFetch_fp fetch) { char tex_dump[256]; int max_mipmap = 0; int texU = tsp.TexU + 3; @@ -1110,7 +1250,7 @@ void DumpTexture(TSP tsp, TCW tcw) { for (int t = 0; t < height; t++) { for (int s = 0; s < width; s++) { - tex[t * width + s] = TextureFetch(tsp, tcw, s, t, mip); + tex[t * width + s] = fetch(tsp, tcw, s, t, mip); std::swap(tex[t * width + s].r, tex[t * width + s].b); } } @@ -1120,17 +1260,19 @@ void DumpTexture(TSP tsp, TCW tcw) { } } const char* dump_textures = nullptr; +using BlendingUnit_fp = decltype(&BlendingUnit<0,0,0,0>); +using ColorCombiner_fp = decltype(&ColorCombiner<0,0,0>); +using TextureFilter_fp = decltype(&TextureFilter<0,0,0,0,0,0>); // Implement the full texture/shade pipeline for a pixel -bool PixelFlush_tsp( - bool pp_UseAlpha, bool pp_Texture, bool pp_Offset, bool pp_ColorClamp, u32 pp_FogCtrl, bool pp_IgnoreAlpha, bool pp_ClampU, bool pp_ClampV, bool pp_FlipU, bool pp_FlipV, u32 pp_FilterMode, u32 pp_ShadInstr, bool pp_AlphaTest, u32 pp_SrcSel, u32 pp_DstSel, u32 pp_SrcInst, u32 pp_DstInst, - const FpuEntry *entry, float x, float y, float W, bool InVolume, u32 index) +template +static bool PixelFlush_tsp(const FpuEntry *entry, float x, float y, float W, bool InVolume, u32 index, TextureFetch_fp fetch, TextureFilter_fp filter, ColorCombiner_fp combiner, BlendingUnit_fp blending) { - u32 two_voume_index = InVolume & !FPU_SHAD_SCALE.intensity_shadow; + u32 two_voume_index = InVolume & !pp_CheapShadows; auto cb = (Color*)colorBuffer1 + index; Color base = { 0 }, textel = { 0 }, offs = { 0 }; - base = InterpolateBase(pp_UseAlpha, FPU_SHAD_SCALE.intensity_shadow, entry->ips.Col[two_voume_index], x, y, W, InVolume); + base = InterpolateBase(entry->ips.Col[two_voume_index], x, y, W, InVolume); float dTrilinear; u32 MipLevel; @@ -1143,7 +1285,7 @@ bool PixelFlush_tsp( if (dumps.count(uid) == 0) { dumps.insert(uid); - DumpTexture(entry->params.tsp[two_voume_index], entry->params.tcw[two_voume_index]); + DumpTexture(entry->params.tsp[two_voume_index], entry->params.tcw[two_voume_index], fetch); } } float u = entry->ips.U[two_voume_index].Ip(x, y, W); @@ -1169,9 +1311,17 @@ bool PixelFlush_tsp( MipLevel = 0; } - textel = TextureFilter(pp_IgnoreAlpha, pp_ClampU, pp_ClampV, pp_FlipU, pp_FlipV, pp_FilterMode, entry->params.tsp[two_voume_index], entry->params.tcw[two_voume_index], u, v, MipLevel, dTrilinear); + textel = filter(entry->params.tsp[two_voume_index], entry->params.tcw[two_voume_index], u, v, MipLevel, dTrilinear, fetch); if (pp_Offset) { - offs = InterpolateOffs(FPU_SHAD_SCALE.intensity_shadow, entry->ips.Ofs[two_voume_index], x, y, W, InVolume); + offs = InterpolateOffs(entry->ips.Ofs[two_voume_index], x, y, W, InVolume); + } + } + + if (pp_AlphaTest) { + if (textel.a < PT_ALPHA_REF) { + return false; + } else { + textel.a = 255; } } @@ -1179,133 +1329,62 @@ bool PixelFlush_tsp( if (pp_Texture && pp_Offset && entry->params.tcw[two_voume_index].PixelFmt == PixelBumpMap) { col = BumpMapper(textel, offs); } else { - col = ColorCombiner(pp_Texture, pp_Offset, pp_ShadInstr, base, textel, offs); + col = combiner(base, textel, offs); } - col = FogUnit(pp_Offset, pp_ColorClamp, pp_FogCtrl, col, 1/W, offs.a); + col = FogUnit(col, 1/W, offs.a); // if (pp_Texture) { // col = MipDebugColor[10-MipLevel]; // } else { // col = { .raw = 0 }; // } - return BlendingUnit(pp_AlphaTest, pp_SrcSel, pp_DstSel, pp_SrcInst, pp_DstInst, index, col); + blending(index, col); + return true; } +using PixelFlush_tsp_fp = decltype(&PixelFlush_tsp<0,0,0,0,0,0,0>); -// Depth processing for a pixel -- render_mode 0: OPAQ, 1: PT, 2: TRANS -void PixelFlush_isp(RenderMode render_mode, u32 depth_mode, u32 ZWriteDis, float x, float y, float invW, u32 index, parameter_tag_t tag) +#include "gentable.h" + +// Lookup/create cached TSP parameters, and call PixelFlush_tsp +bool PixelFlush_tsp(bool pp_AlphaTest, const FpuEntry* entry, float x, float y, u32 index, float invW, bool InVolume) { - auto pb = tagBuffer[tagBufferA] + index; - auto pb2 = tagBuffer[tagBufferB] + index; - auto zb = depthBuffer[depthBufferA] + index; - auto zb2 = depthBuffer[depthBufferB] + index; - auto stencil = stencilBuffer + index; + u32 two_voume_index = InVolume & !FPU_SHAD_SCALE.intensity_shadow; - auto mode = depth_mode; - - if (render_mode == RM_PUNCHTHROUGH) - mode = 6; // TODO: FIXME - else if (render_mode == RM_TRANSLUCENT && !ISP_FEED_CFG.pre_sort) - mode = 3; - else if (render_mode == RM_MODIFIER) - mode = 6; - - switch(mode) { - // never - case 0: return; break; - // less - case 1: if (invW >= *zb) return; break; - // equal - case 2: if (invW != *zb) return; break; - // less or equal - case 3: if (invW > *zb) { - if (render_mode == RM_TRANSLUCENT && !ISP_FEED_CFG.pre_sort) { - MoreToDraw = true; - } - return; - }break; - // greater - case 4: if (invW <= *zb) return; break; - // not equal - case 5: if (invW == *zb) return; break; - // greater or equal - case 6: if (invW < *zb) return; break; - // always - case 7: break; - } + auto fetch = TextureFetch_table + [entry->params.tcw[two_voume_index].VQ_Comp] + [entry->params.tcw[two_voume_index].MipMapped] + [entry->params.tcw[two_voume_index].ScanOrder] + [entry->params.tcw[two_voume_index].StrideSel] + [entry->params.tcw[two_voume_index].PixelFmt]; - switch (render_mode) - { - // OPAQ - case RM_OPAQUE: - { - // Z pre-pass only - if (!ZWriteDis) { - *zb = mask_w(invW); - } - *pb = tag; - } - break; + auto filter = TextureFilter_table + [entry->params.tsp[two_voume_index].IgnoreTexA] + [entry->params.tsp[two_voume_index].ClampU] + [entry->params.tsp[two_voume_index].ClampV] + [entry->params.tsp[two_voume_index].FlipU] + [entry->params.tsp[two_voume_index].FlipV] + [entry->params.tsp[two_voume_index].FilterMode]; - case RM_MODIFIER: - { - // Flip on Z pass + auto combiner = ColorCombiner_table + [entry->params.isp.Texture] + [entry->params.isp.Offset] + [entry->params.tsp[two_voume_index].ShadInstr]; - *stencil ^= 0b0010; + auto blending = BlendingUnit_table + [entry->params.tsp[two_voume_index].SrcSelect] + [entry->params.tsp[two_voume_index].DstSelect] + [entry->params.tsp[two_voume_index].SrcInstr] + [entry->params.tsp[two_voume_index].DstInstr]; + + auto pixel = PixelFlush_tsp_table + [pp_AlphaTest] + [entry->params.tsp[two_voume_index].UseAlpha] + [entry->params.isp.Texture] + [entry->params.isp.Offset] + [entry->params.tsp[two_voume_index].ColorClamp] + [entry->params.tsp[two_voume_index].FogCtrl] + [FPU_SHAD_SCALE.intensity_shadow]; - // This pixel has valid stencil for summary - *stencil |= 0b100; - } - break; - - // PT - case RM_PUNCHTHROUGH: - { - - if (invW > *zb2) - return; - - if (invW == *zb2) { - auto tagRendered = *pb2 & ~TAG_INVALID; - - if (tag <= tagRendered) - return; - } - - *zb = mask_w(invW); - *pb = tag; - } - break; - - // Layer Peeling. zb2 holds the reference depth, zb is used to find closest to reference - case RM_TRANSLUCENT: - { - if (!ISP_FEED_CFG.pre_sort) { - if (invW < *zb2) - return; - - if (invW == *zb2) { - auto tagRendered = *pb2 & ~TAG_INVALID; - - if (tag >= tagRendered) - return; - } - - *zb = mask_w(invW); - - if (!(*pb & TAG_INVALID)) { - MoreToDraw = true; - } - *pb = tag; - } else { - if (!ZWriteDis) { - *zb = mask_w(invW); - } - *pb = tag; - } - } - break; - - case RM_OP_PT_MV: die("this is invalid here"); break; - } + return pixel(entry, x, y, 1/invW, InVolume, index, fetch, filter, combiner, blending); } \ No newline at end of file diff --git a/vendor/emu/refsw/refsw_tile.h b/vendor/emu/refsw/refsw_tile.h index b57fc360..606cda4a 100644 --- a/vendor/emu/refsw/refsw_tile.h +++ b/vendor/emu/refsw/refsw_tile.h @@ -39,6 +39,10 @@ struct PlaneStepper3 float C = ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)); + if (C == 0) { + C = 1; // avoid divide by zero + } + ddx = -Aa / C; ddy = -Ba / C; @@ -54,6 +58,16 @@ struct PlaneStepper3 { return Ip(x, y) * W; } + + float IpU8(float x, float y, float W) const + { + float rv = Ip(x, y, W); + + if (rv < 0) rv = 0; + if (rv > 255) rv = 255; + + return rv; + } }; /* @@ -87,8 +101,8 @@ struct IPs3 } if (TwoVolumes) { - U[1].Setup(rect, v1, v2, v3, v1.u * v1.z, v2.u1 * v2.z, v3.u1 * v3.z); - V[1].Setup(rect, v1, v2, v3, v1.v * v1.z, v2.v1 * v2.z, v3.v1 * v3.z); + U[1].Setup(rect, v1, v2, v3, v1.u1 * v1.z, v2.u1 * v2.z, v3.u1 * v3.z); + V[1].Setup(rect, v1, v2, v3, v1.v1 * v1.z, v2.v1 * v2.z, v3.v1 * v3.z); if (params->isp.Gouraud) { for (int i = 0; i < 4; i++) Col[1][i].Setup(rect, v1, v2, v3, v1.col1[i] * v1.z, v2.col1[i] * v2.z, v3.col1[i] * v3.z); @@ -128,10 +142,9 @@ extern u32 colorBuffer1 [MAX_RENDER_PIXELS]; extern const char* dump_textures; void ClearBuffers(u32 paramValue, float depthValue, u32 stencilValue); -void ClearParamBuffer(parameter_tag_t paramValue); +void ClearParamStatusBuffer(); void PeelBuffers(float depthValue, u32 stencilValue); void PeelBuffersPT(); -void PeelBuffersPTAfterHoles(); void PeelBuffersPTInitial(float depthValue); void SummarizeStencilOr(); void SummarizeStencilAnd(); @@ -140,31 +153,29 @@ bool GetMoreToDraw(); // Render to ACCUM from TAG buffer // TAG holds references to triangles, ACCUM is the tile framebuffer -void RenderParamTags(RenderMode rm, int tileX, int tileY); -void ClearFpuEntries(); +template +void RenderParamTags(int tileX, int tileY); -f32 f16(u16 v); +inline __attribute__((always_inline)) f32 f16(u16 v) +{ + u32 z=v<<16; + return *(f32*)&z; +} //decode a vertex in the native pvr format void decode_pvr_vertex(DrawParameters* params, pvr32addr_t ptr,Vertex* cv, u32 shadow); // decode an object (params + vertexes) u32 decode_pvr_vertices(DrawParameters* params, pvr32addr_t base, u32 skip, u32 two_volumes, Vertex* vtx, int count, int offset); -FpuEntry GetFpuEntry(taRECT *rect, RenderMode render_mode, ISP_BACKGND_T_type core_tag); +const FpuEntry& GetFpuEntry(taRECT *rect, RenderMode render_mode, ISP_BACKGND_T_type core_tag); // Lookup/create cached TSP parameters, and call PixelFlush_tsp -bool PixelFlush_tsp(bool pp_AlphaTest, FpuEntry* entry, float x, float y, u32 index, float invW, bool InVolume); +bool PixelFlush_tsp(bool pp_AlphaTest, const FpuEntry* entry, float x, float y, u32 index, float invW, bool InVolume); // Rasterize a single triangle to ISP (or ISP+TSP for PT) -void RasterizeTriangle(RenderMode render_mode, DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area); + +extern void (*RasterizeTriangle_table[])(DrawParameters* params, parameter_tag_t tag, const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex* v4, taRECT* area); + u8* GetColorOutputBuffer(); -// Implement the full texture/shade pipeline for a pixel -bool PixelFlush_tsp( - bool pp_UseAlpha, bool pp_Texture, bool pp_Offset, bool pp_ColorClamp, u32 pp_FogCtrl, bool pp_IgnoreAlpha, bool pp_ClampU, bool pp_ClampV, bool pp_FlipU, bool pp_FlipV, u32 pp_FilterMode, u32 pp_ShadInstr, bool pp_AlphaTest, u32 pp_SrcSel, u32 pp_DstSel, u32 pp_SrcInst, u32 pp_DstInst, - const FpuEntry *entry, float x, float y, float W, bool InVolume, u32 index); - -// Depth processing for a pixel -- render_mode 0: OPAQ, 1: PT, 2: TRANS -void PixelFlush_isp(RenderMode render_mode, u32 depth_mode, u32 ZWriteDis, float x, float y, float invW, u32 index, parameter_tag_t tag); - /* Main renderer class @@ -180,4 +191,5 @@ void RenderTriangleArray(RenderMode render_mode, ObjectListEntry obj, taRECT* re void RenderQuadArray(RenderMode render_mode, ObjectListEntry obj, taRECT* rect); void RenderObjectList(RenderMode render_mode, pvr32addr_t base, taRECT* rect); void RenderCORE(); -void Hackpresent(); \ No newline at end of file +void Hackpresent(); +void ClearFpuCache(); \ No newline at end of file