nkeynes@189 | 1 | /**
|
nkeynes@200 | 2 | * $Id: tacore.c,v 1.6 2006-08-06 04:01:37 nkeynes Exp $
|
nkeynes@189 | 3 | *
|
nkeynes@189 | 4 | * PVR2 Tile Accelerator implementation
|
nkeynes@189 | 5 | *
|
nkeynes@189 | 6 | * Copyright (c) 2005 Nathan Keynes.
|
nkeynes@189 | 7 | *
|
nkeynes@189 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@189 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@189 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@189 | 11 | * (at your option) any later version.
|
nkeynes@189 | 12 | *
|
nkeynes@189 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@189 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@189 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@189 | 16 | * GNU General Public License for more details.
|
nkeynes@189 | 17 | */
|
nkeynes@189 | 18 | #include "pvr2.h"
|
nkeynes@189 | 19 | #include "asic.h"
|
nkeynes@189 | 20 |
|
nkeynes@189 | 21 | #define STATE_IDLE 0
|
nkeynes@189 | 22 | #define STATE_IN_LIST 1
|
nkeynes@194 | 23 | #define STATE_IN_POLYGON 2
|
nkeynes@194 | 24 | #define STATE_EXPECT_POLY_BLOCK2 3
|
nkeynes@194 | 25 | #define STATE_EXPECT_VERTEX_BLOCK2 4
|
nkeynes@194 | 26 | #define STATE_ERROR 5
|
nkeynes@189 | 27 | #define STATE_EXPECT_END_VERTEX_BLOCK2 7
|
nkeynes@189 | 28 |
|
nkeynes@189 | 29 | #define TA_CMD(i) ( (i) >> 29 )
|
nkeynes@189 | 30 | #define TA_CMD_END_LIST 0
|
nkeynes@189 | 31 | #define TA_CMD_CLIP 1
|
nkeynes@189 | 32 | #define TA_CMD_POLYGON_CONTEXT 4
|
nkeynes@189 | 33 | #define TA_CMD_SPRITE_CONTEXT 5
|
nkeynes@189 | 34 | #define TA_CMD_VERTEX 7
|
nkeynes@189 | 35 |
|
nkeynes@189 | 36 | #define TA_LIST_NONE -1
|
nkeynes@189 | 37 | #define TA_LIST_OPAQUE 0
|
nkeynes@189 | 38 | #define TA_LIST_OPAQUE_MOD 1
|
nkeynes@189 | 39 | #define TA_LIST_TRANS 2
|
nkeynes@189 | 40 | #define TA_LIST_TRANS_MOD 3
|
nkeynes@189 | 41 | #define TA_LIST_PUNCH_OUT 4
|
nkeynes@189 | 42 | #define TA_IS_MODIFIER_LIST(list) (list == TA_LIST_OPAQUE_MOD || list == TA_LIST_TRANS_MOD)
|
nkeynes@189 | 43 |
|
nkeynes@189 | 44 | #define TA_GROW_UP 0
|
nkeynes@189 | 45 | #define TA_GROW_DOWN 1
|
nkeynes@189 | 46 |
|
nkeynes@189 | 47 | #define TA_VERTEX_NONE -1
|
nkeynes@189 | 48 | #define TA_VERTEX_PACKED 0x00
|
nkeynes@189 | 49 | #define TA_VERTEX_TEX_PACKED 0x08
|
nkeynes@189 | 50 | #define TA_VERTEX_TEX_SPEC_PACKED 0x0C
|
nkeynes@189 | 51 | #define TA_VERTEX_TEX_UV16_PACKED 0x09
|
nkeynes@189 | 52 | #define TA_VERTEX_TEX_UV16_SPEC_PACKED 0x0D
|
nkeynes@189 | 53 | #define TA_VERTEX_FLOAT 0x10
|
nkeynes@189 | 54 | #define TA_VERTEX_TEX_FLOAT 0x18
|
nkeynes@189 | 55 | #define TA_VERTEX_TEX_SPEC_FLOAT 0x1C
|
nkeynes@189 | 56 | #define TA_VERTEX_TEX_UV16_FLOAT 0x19
|
nkeynes@189 | 57 | #define TA_VERTEX_TEX_UV16_SPEC_FLOAT 0x1D
|
nkeynes@189 | 58 | #define TA_VERTEX_INTENSITY 0x20
|
nkeynes@189 | 59 | #define TA_VERTEX_TEX_INTENSITY 0x28
|
nkeynes@189 | 60 | #define TA_VERTEX_TEX_SPEC_INTENSITY 0x2C
|
nkeynes@189 | 61 | #define TA_VERTEX_TEX_UV16_INTENSITY 0x29
|
nkeynes@189 | 62 | #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY 0x2D
|
nkeynes@189 | 63 | #define TA_VERTEX_PACKED_MOD 0x40
|
nkeynes@189 | 64 | #define TA_VERTEX_TEX_PACKED_MOD 0x48
|
nkeynes@189 | 65 | #define TA_VERTEX_TEX_SPEC_PACKED_MOD 0x4C
|
nkeynes@189 | 66 | #define TA_VERTEX_TEX_UV16_PACKED_MOD 0x49
|
nkeynes@189 | 67 | #define TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD 0x4D
|
nkeynes@189 | 68 | #define TA_VERTEX_INTENSITY_MOD 0x60
|
nkeynes@189 | 69 | #define TA_VERTEX_TEX_INTENSITY_MOD 0x68
|
nkeynes@189 | 70 | #define TA_VERTEX_TEX_SPEC_INTENSITY_MOD 0x6C
|
nkeynes@189 | 71 | #define TA_VERTEX_TEX_UV16_INTENSITY_MOD 0x69
|
nkeynes@189 | 72 | #define TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD 0x6D
|
nkeynes@189 | 73 | #define TA_VERTEX_SPRITE 0x80
|
nkeynes@189 | 74 | #define TA_VERTEX_TEX_SPRITE 0x88
|
nkeynes@189 | 75 | #define TA_VERTEX_MOD_VOLUME 0x81
|
nkeynes@189 | 76 |
|
nkeynes@189 | 77 | #define TA_IS_NORMAL_POLY() (ta_status.current_vertex_type < TA_VERTEX_SPRITE)
|
nkeynes@189 | 78 |
|
nkeynes@189 | 79 | static int strip_lengths[4] = {3,4,6,8}; /* in vertexes */
|
nkeynes@189 | 80 | #define TA_POLYCMD_LISTTYPE(i) ( ((i) >> 24) & 0x0F )
|
nkeynes@194 | 81 | #define TA_POLYCMD_USELENGTH(i) ( i & 0x00800000 )
|
nkeynes@189 | 82 | #define TA_POLYCMD_LENGTH(i) strip_lengths[((i >> 18) & 0x03)]
|
nkeynes@189 | 83 | #define TA_POLYCMD_CLIP(i) ((i>>16)&0x03)
|
nkeynes@189 | 84 | #define TA_POLYCMD_COLOURFMT(i) (i & 0x00000030)
|
nkeynes@189 | 85 | #define TA_POLYCMD_COLOURFMT_ARGB32 0x00000000
|
nkeynes@189 | 86 | #define TA_POLYCMD_COLOURFMT_FLOAT 0x00000010
|
nkeynes@189 | 87 | #define TA_POLYCMD_COLOURFMT_INTENSITY 0x00000020
|
nkeynes@189 | 88 | #define TA_POLYCMD_COLOURFMT_LASTINT 0x00000030
|
nkeynes@189 | 89 |
|
nkeynes@189 | 90 | #define TA_POLYCMD_MODIFIED 0x00000080
|
nkeynes@189 | 91 | #define TA_POLYCMD_FULLMOD 0x00000040
|
nkeynes@189 | 92 | #define TA_POLYCMD_TEXTURED 0x00000008
|
nkeynes@189 | 93 | #define TA_POLYCMD_SPECULAR 0x00000004
|
nkeynes@189 | 94 | #define TA_POLYCMD_SHADED 0x00000002
|
nkeynes@189 | 95 | #define TA_POLYCMD_UV16 0x00000001
|
nkeynes@189 | 96 |
|
nkeynes@189 | 97 | #define TA_POLYCMD_IS_SPECULAR(i) ((i & 0x0000000C)==0x0000000C) /* Only applies to textured polys */
|
nkeynes@189 | 98 | #define TA_POLYCMD_IS_FULLMOD(i) ((i & 0x000000C0)==0x000000C0)
|
nkeynes@189 | 99 |
|
nkeynes@189 | 100 |
|
nkeynes@189 | 101 | #define TA_IS_END_VERTEX(i) (i & 0x10000000)
|
nkeynes@189 | 102 |
|
nkeynes@199 | 103 | /** Note these are not the IEEE 754 definitions - the TA treats NANs
|
nkeynes@199 | 104 | * as if they were INFs of the appropriate sign.
|
nkeynes@199 | 105 | */
|
nkeynes@199 | 106 | #define TA_IS_INF(f) (((*((uint32_t *)&f)) & 0xFF800000) == 0x7F800000)
|
nkeynes@199 | 107 | #define TA_IS_NINF(f) (((*((uint32_t *)&f)) & 0xFF800000) == 0xFF800000)
|
nkeynes@199 | 108 |
|
nkeynes@189 | 109 | #define MIN3( x1, x2, x3 ) ( (x1)<(x2)? ((x1)<(x3)?(x1):(x3)) : ((x2)<(x3)?(x2):(x3)) )
|
nkeynes@189 | 110 | #define MAX3( x1, x2, x3 ) ( (x1)>(x2)? ((x1)>(x3)?(x1):(x3)) : ((x2)>(x3)?(x2):(x3)) )
|
nkeynes@189 | 111 |
|
nkeynes@189 | 112 | #define TILESLOT( x, y ) (ta_status.current_tile_matrix + (ta_status.current_tile_size * (y * ta_status.width+ x) << 2))
|
nkeynes@189 | 113 |
|
nkeynes@189 | 114 | extern char *video_base;
|
nkeynes@189 | 115 | #define PVRRAM(addr) (*(uint32_t *)(video_base + ((addr)&PVR2_RAM_MASK)))
|
nkeynes@189 | 116 |
|
nkeynes@189 | 117 | struct pvr2_ta_vertex {
|
nkeynes@189 | 118 | float x,y,z;
|
nkeynes@189 | 119 | uint32_t detail[8]; /* 0-8 detail words */
|
nkeynes@189 | 120 | };
|
nkeynes@189 | 121 |
|
nkeynes@189 | 122 | struct tile_bounds {
|
nkeynes@189 | 123 | int x1, y1, x2, y2;
|
nkeynes@189 | 124 | };
|
nkeynes@189 | 125 |
|
nkeynes@189 | 126 | struct pvr2_ta_status {
|
nkeynes@189 | 127 | int state;
|
nkeynes@189 | 128 | int width, height; /* Tile resolution, ie 20x15 */
|
nkeynes@189 | 129 | int tilelist_dir; /* Growth direction of the tilelist, 0 = up, 1 = down */
|
nkeynes@189 | 130 | uint32_t tilelist_size; /* Size of the tilelist segments */
|
nkeynes@193 | 131 | uint32_t tilelist_start; /* Initial address of the tilelist */
|
nkeynes@189 | 132 | int current_vertex_type;
|
nkeynes@193 | 133 | gboolean accept_vertexes;
|
nkeynes@189 | 134 | int vertex_count; /* index of last start-vertex seen, or -1 if no vertexes
|
nkeynes@189 | 135 | * are present
|
nkeynes@189 | 136 | */
|
nkeynes@189 | 137 | int max_vertex; /* Maximum number of vertexes in the current polygon (3/4/6/8) */
|
nkeynes@189 | 138 | int current_list_type;
|
nkeynes@189 | 139 | uint32_t current_tile_matrix; /* Memory location of the first tile for the current list. */
|
nkeynes@189 | 140 | uint32_t current_tile_size; /* Size of the tile matrix space in 32-bit words (0/8/16/32)*/
|
nkeynes@189 | 141 | uint32_t intensity1, intensity2;
|
nkeynes@198 | 142 | struct tile_bounds clip;
|
nkeynes@189 | 143 | /**
|
nkeynes@189 | 144 | * Current working object
|
nkeynes@189 | 145 | */
|
nkeynes@189 | 146 | int poly_context_size;
|
nkeynes@189 | 147 | int poly_vertex_size;
|
nkeynes@189 | 148 | int poly_parity;
|
nkeynes@189 | 149 | uint32_t poly_context[5];
|
nkeynes@189 | 150 | uint32_t poly_pointer;
|
nkeynes@189 | 151 | struct tile_bounds last_triangle_bounds;
|
nkeynes@189 | 152 | struct pvr2_ta_vertex poly_vertex[8];
|
nkeynes@189 | 153 | int debug_output;
|
nkeynes@189 | 154 | };
|
nkeynes@189 | 155 |
|
nkeynes@189 | 156 | static struct pvr2_ta_status ta_status;
|
nkeynes@189 | 157 |
|
nkeynes@189 | 158 | static int tilematrix_sizes[4] = {0,8,16,32};
|
nkeynes@189 | 159 |
|
nkeynes@189 | 160 | /**
|
nkeynes@189 | 161 | * Convenience union - ta data is either 32-bit integer or 32-bit float.
|
nkeynes@189 | 162 | */
|
nkeynes@189 | 163 | union ta_data {
|
nkeynes@189 | 164 | unsigned int i;
|
nkeynes@189 | 165 | float f;
|
nkeynes@189 | 166 | };
|
nkeynes@189 | 167 |
|
nkeynes@189 | 168 |
|
nkeynes@189 | 169 | void pvr2_ta_reset() {
|
nkeynes@189 | 170 | ta_status.state = STATE_ERROR; /* State not valid until initialized */
|
nkeynes@189 | 171 | ta_status.debug_output = 0;
|
nkeynes@189 | 172 | }
|
nkeynes@189 | 173 |
|
nkeynes@193 | 174 | void pvr2_ta_save_state( FILE *f )
|
nkeynes@193 | 175 | {
|
nkeynes@193 | 176 | fwrite( &ta_status, sizeof(ta_status), 1, f );
|
nkeynes@193 | 177 | }
|
nkeynes@193 | 178 |
|
nkeynes@193 | 179 | int pvr2_ta_load_state( FILE *f )
|
nkeynes@193 | 180 | {
|
nkeynes@193 | 181 | if( fread( &ta_status, sizeof(ta_status), 1, f ) != 1 )
|
nkeynes@193 | 182 | return 1;
|
nkeynes@193 | 183 | return 0;
|
nkeynes@193 | 184 | }
|
nkeynes@193 | 185 |
|
nkeynes@189 | 186 | void pvr2_ta_init() {
|
nkeynes@189 | 187 | ta_status.state = STATE_IDLE;
|
nkeynes@189 | 188 | ta_status.current_list_type = -1;
|
nkeynes@189 | 189 | ta_status.current_vertex_type = -1;
|
nkeynes@189 | 190 | ta_status.poly_parity = 0;
|
nkeynes@189 | 191 | ta_status.vertex_count = 0;
|
nkeynes@189 | 192 | ta_status.max_vertex = 3;
|
nkeynes@189 | 193 | ta_status.last_triangle_bounds.x1 = -1;
|
nkeynes@193 | 194 | ta_status.accept_vertexes = TRUE;
|
nkeynes@198 | 195 | ta_status.clip.x1 = 0;
|
nkeynes@198 | 196 | ta_status.clip.y1 = 0;
|
nkeynes@198 | 197 |
|
nkeynes@189 | 198 | uint32_t size = MMIO_READ( PVR2, TA_TILESIZE );
|
nkeynes@189 | 199 | ta_status.width = (size & 0xFFFF) + 1;
|
nkeynes@189 | 200 | ta_status.height = (size >> 16) + 1;
|
nkeynes@198 | 201 | ta_status.clip.x2 = ta_status.width-1;
|
nkeynes@198 | 202 | ta_status.clip.y2 = ta_status.height-1;
|
nkeynes@189 | 203 | uint32_t control = MMIO_READ( PVR2, TA_TILECFG );
|
nkeynes@189 | 204 | ta_status.tilelist_dir = (control >> 20) & 0x01;
|
nkeynes@189 | 205 | ta_status.tilelist_size = tilematrix_sizes[ (control & 0x03) ];
|
nkeynes@189 | 206 | MMIO_WRITE( PVR2, TA_POLYPOS, MMIO_READ( PVR2, TA_POLYBASE ) );
|
nkeynes@189 | 207 | uint32_t plistpos = MMIO_READ( PVR2, TA_LISTBASE ) >> 2;
|
nkeynes@189 | 208 | if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
|
nkeynes@189 | 209 | plistpos -= ta_status.tilelist_size;
|
nkeynes@189 | 210 | }
|
nkeynes@189 | 211 | MMIO_WRITE( PVR2, TA_LISTPOS, plistpos );
|
nkeynes@193 | 212 | ta_status.tilelist_start = plistpos;
|
nkeynes@189 | 213 | }
|
nkeynes@189 | 214 |
|
nkeynes@189 | 215 | static uint32_t parse_float_colour( float a, float r, float g, float b ) {
|
nkeynes@200 | 216 | int ai,ri,gi,bi;
|
nkeynes@200 | 217 |
|
nkeynes@200 | 218 | if( TA_IS_INF(a) ) {
|
nkeynes@200 | 219 | ai = 255;
|
nkeynes@200 | 220 | } else {
|
nkeynes@200 | 221 | ai = 256 * CLAMP(a,0.0,1.0) - 1;
|
nkeynes@200 | 222 | if( ai < 0 ) ai = 0;
|
nkeynes@200 | 223 | }
|
nkeynes@200 | 224 | if( TA_IS_INF(r) ) {
|
nkeynes@200 | 225 | ri = 255;
|
nkeynes@200 | 226 | } else {
|
nkeynes@200 | 227 | ri = 256 * CLAMP(r,0.0,1.0) - 1;
|
nkeynes@200 | 228 | if( ri < 0 ) ri = 0;
|
nkeynes@200 | 229 | }
|
nkeynes@200 | 230 | if( TA_IS_INF(g) ) {
|
nkeynes@200 | 231 | gi = 255;
|
nkeynes@200 | 232 | } else {
|
nkeynes@200 | 233 | gi = 256 * CLAMP(g,0.0,1.0) - 1;
|
nkeynes@200 | 234 | if( gi < 0 ) gi = 0;
|
nkeynes@200 | 235 | }
|
nkeynes@200 | 236 | if( TA_IS_INF(b) ) {
|
nkeynes@200 | 237 | bi = 255;
|
nkeynes@200 | 238 | } else {
|
nkeynes@200 | 239 | bi = 256 * CLAMP(b,0.0,1.0) - 1;
|
nkeynes@200 | 240 | if( bi < 0 ) bi = 0;
|
nkeynes@200 | 241 | }
|
nkeynes@200 | 242 | return (ai << 24) | (ri << 16) | (gi << 8) | bi;
|
nkeynes@189 | 243 | }
|
nkeynes@189 | 244 |
|
nkeynes@189 | 245 | static uint32_t parse_intensity_colour( uint32_t base, float intensity )
|
nkeynes@189 | 246 | {
|
nkeynes@189 | 247 | unsigned int i = (unsigned int)(256 * CLAMP(intensity, 0.0,1.0));
|
nkeynes@189 | 248 |
|
nkeynes@189 | 249 | return
|
nkeynes@189 | 250 | (((((base & 0xFF) * i) & 0xFF00) |
|
nkeynes@189 | 251 | (((base & 0xFF00) * i) & 0xFF0000) |
|
nkeynes@189 | 252 | (((base & 0xFF0000) * i) & 0xFF000000)) >> 8) |
|
nkeynes@189 | 253 | base & 0xFF000000;
|
nkeynes@189 | 254 | }
|
nkeynes@189 | 255 |
|
nkeynes@189 | 256 | /**
|
nkeynes@189 | 257 | * Initialize the specified TA list.
|
nkeynes@189 | 258 | */
|
nkeynes@189 | 259 | static void ta_init_list( unsigned int listtype ) {
|
nkeynes@189 | 260 | int config = MMIO_READ( PVR2, TA_TILECFG );
|
nkeynes@189 | 261 | int tile_matrix = MMIO_READ( PVR2, TA_TILEBASE );
|
nkeynes@193 | 262 | int list_end = MMIO_READ( PVR2, TA_LISTEND );
|
nkeynes@193 | 263 |
|
nkeynes@193 | 264 | ta_status.current_tile_matrix = tile_matrix;
|
nkeynes@193 | 265 |
|
nkeynes@193 | 266 | /* If the list grows down, the end must be < tile matrix start.
|
nkeynes@193 | 267 | * If it grows up, the end must be > tile matrix start.
|
nkeynes@193 | 268 | * Don't ask me why, it just does...
|
nkeynes@193 | 269 | */
|
nkeynes@193 | 270 | if( ((ta_status.tilelist_dir == TA_GROW_DOWN && list_end <= tile_matrix) ||
|
nkeynes@193 | 271 | (ta_status.tilelist_dir == TA_GROW_UP && list_end >= tile_matrix )) &&
|
nkeynes@193 | 272 | listtype <= TA_LIST_PUNCH_OUT ) {
|
nkeynes@189 | 273 | int i;
|
nkeynes@189 | 274 | uint32_t *p;
|
nkeynes@189 | 275 | for( i=0; i < listtype; i++ ) {
|
nkeynes@189 | 276 | int size = tilematrix_sizes[(config & 0x03)] << 2;
|
nkeynes@193 | 277 | ta_status.current_tile_matrix += ta_status.width * ta_status.height * size;
|
nkeynes@189 | 278 | config >>= 4;
|
nkeynes@189 | 279 | }
|
nkeynes@189 | 280 | ta_status.current_tile_size = tilematrix_sizes[(config & 0x03)];
|
nkeynes@189 | 281 |
|
nkeynes@189 | 282 | /* Initialize each tile to 0xF0000000 */
|
nkeynes@189 | 283 | if( ta_status.current_tile_size != 0 ) {
|
nkeynes@193 | 284 | p = (uint32_t *)(video_base + ta_status.current_tile_matrix);
|
nkeynes@189 | 285 | for( i=0; i< ta_status.width * ta_status.height; i++ ) {
|
nkeynes@189 | 286 | *p = 0xF0000000;
|
nkeynes@189 | 287 | p += ta_status.current_tile_size;
|
nkeynes@189 | 288 | }
|
nkeynes@189 | 289 | }
|
nkeynes@193 | 290 | } else {
|
nkeynes@193 | 291 | ta_status.current_tile_size = 0;
|
nkeynes@189 | 292 | }
|
nkeynes@193 | 293 |
|
nkeynes@193 | 294 | if( tile_matrix == list_end ) {
|
nkeynes@193 | 295 | ta_status.current_tile_size = 0;
|
nkeynes@193 | 296 | }
|
nkeynes@193 | 297 |
|
nkeynes@189 | 298 | ta_status.state = STATE_IN_LIST;
|
nkeynes@189 | 299 | ta_status.current_list_type = listtype;
|
nkeynes@189 | 300 | ta_status.last_triangle_bounds.x1 = -1;
|
nkeynes@189 | 301 | }
|
nkeynes@189 | 302 |
|
nkeynes@189 | 303 | static int list_events[5] = {EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE,
|
nkeynes@189 | 304 | EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE,
|
nkeynes@189 | 305 | EVENT_PVR_PUNCHOUT_DONE };
|
nkeynes@189 | 306 |
|
nkeynes@189 | 307 | static void ta_end_list() {
|
nkeynes@189 | 308 | if( ta_status.current_list_type != TA_LIST_NONE ) {
|
nkeynes@189 | 309 | asic_event( list_events[ta_status.current_list_type] );
|
nkeynes@194 | 310 | if( ta_status.state == STATE_IN_POLYGON ) {
|
nkeynes@194 | 311 | asic_event( EVENT_TA_ERROR );
|
nkeynes@194 | 312 | asic_event( EVENT_PVR_BAD_INPUT );
|
nkeynes@194 | 313 | }
|
nkeynes@189 | 314 | ta_status.current_list_type = TA_LIST_NONE;
|
nkeynes@189 | 315 | ta_status.current_vertex_type = -1;
|
nkeynes@189 | 316 | ta_status.state = STATE_IDLE;
|
nkeynes@189 | 317 | }
|
nkeynes@189 | 318 | }
|
nkeynes@189 | 319 |
|
nkeynes@189 | 320 | /**
|
nkeynes@189 | 321 | * Write data out to the polygon buffer.
|
nkeynes@189 | 322 | * If the end-of-buffer is reached, asserts EVENT_PVR_PRIM_ALLOC_FAIL
|
nkeynes@189 | 323 | * @param data to be written
|
nkeynes@189 | 324 | * @param length Number of 32-bit words to write.
|
nkeynes@189 | 325 | * @return number of words actually written
|
nkeynes@189 | 326 | */
|
nkeynes@189 | 327 | static int ta_write_polygon_buffer( uint32_t *data, int length )
|
nkeynes@189 | 328 | {
|
nkeynes@189 | 329 | int rv;
|
nkeynes@189 | 330 | int posn = MMIO_READ( PVR2, TA_POLYPOS );
|
nkeynes@189 | 331 | int end = MMIO_READ( PVR2, TA_POLYEND );
|
nkeynes@189 | 332 | uint32_t *target = (uint32_t *)(video_base + posn);
|
nkeynes@189 | 333 | for( rv=0; rv < length; rv++ ) {
|
nkeynes@189 | 334 | if( posn == end ) {
|
nkeynes@189 | 335 | asic_event( EVENT_PVR_PRIM_ALLOC_FAIL );
|
nkeynes@189 | 336 | asic_event( EVENT_TA_ERROR );
|
nkeynes@189 | 337 | // ta_status.state = STATE_ERROR;
|
nkeynes@189 | 338 | break;
|
nkeynes@189 | 339 | }
|
nkeynes@189 | 340 | *target++ = *data++;
|
nkeynes@189 | 341 | posn += 4;
|
nkeynes@189 | 342 | }
|
nkeynes@189 | 343 |
|
nkeynes@189 | 344 | MMIO_WRITE( PVR2, TA_POLYPOS, posn );
|
nkeynes@189 | 345 | return rv;
|
nkeynes@189 | 346 | }
|
nkeynes@189 | 347 |
|
nkeynes@193 | 348 | #define TA_NO_ALLOC 0xFFFFFFFF
|
nkeynes@193 | 349 |
|
nkeynes@189 | 350 | /**
|
nkeynes@193 | 351 | * Allocate a new tile list block from the grow space and update the
|
nkeynes@193 | 352 | * word at reference to be a link to the new block.
|
nkeynes@189 | 353 | */
|
nkeynes@193 | 354 | static uint32_t ta_alloc_tilelist( uint32_t reference ) {
|
nkeynes@189 | 355 | uint32_t posn = MMIO_READ( PVR2, TA_LISTPOS );
|
nkeynes@193 | 356 | uint32_t limit = MMIO_READ( PVR2, TA_LISTEND ) >> 2;
|
nkeynes@189 | 357 | uint32_t newposn;
|
nkeynes@193 | 358 | uint32_t result;
|
nkeynes@189 | 359 | if( ta_status.tilelist_dir == TA_GROW_DOWN ) {
|
nkeynes@189 | 360 | newposn = posn - ta_status.tilelist_size;
|
nkeynes@193 | 361 | if( posn == limit ) {
|
nkeynes@193 | 362 | PVRRAM(posn<<2) = 0xF0000000;
|
nkeynes@193 | 363 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 364 | return TA_NO_ALLOC;
|
nkeynes@193 | 365 | } else if( posn < limit ) {
|
nkeynes@193 | 366 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 367 | return TA_NO_ALLOC;
|
nkeynes@193 | 368 | } else if( newposn <= limit ) {
|
nkeynes@193 | 369 | } else if( newposn <= (limit + ta_status.tilelist_size) ) {
|
nkeynes@193 | 370 | asic_event( EVENT_TA_ERROR );
|
nkeynes@193 | 371 | asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
|
nkeynes@193 | 372 | MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
|
nkeynes@193 | 373 | } else {
|
nkeynes@193 | 374 | MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
|
nkeynes@193 | 375 | }
|
nkeynes@193 | 376 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 377 | return posn << 2;
|
nkeynes@189 | 378 | } else {
|
nkeynes@189 | 379 | newposn = posn + ta_status.tilelist_size;
|
nkeynes@193 | 380 | if( posn == limit ) {
|
nkeynes@193 | 381 | PVRRAM(posn<<2) = 0xF0000000;
|
nkeynes@193 | 382 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 383 | return TA_NO_ALLOC;
|
nkeynes@193 | 384 | } else if ( posn > limit ) {
|
nkeynes@193 | 385 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 386 | return TA_NO_ALLOC;
|
nkeynes@193 | 387 | } else if( newposn >= limit ) {
|
nkeynes@193 | 388 | } else if( newposn >= (limit - ta_status.tilelist_size) ) {
|
nkeynes@193 | 389 | asic_event( EVENT_TA_ERROR );
|
nkeynes@193 | 390 | asic_event( EVENT_PVR_MATRIX_ALLOC_FAIL );
|
nkeynes@193 | 391 | MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
|
nkeynes@193 | 392 | } else {
|
nkeynes@193 | 393 | MMIO_WRITE( PVR2, TA_LISTPOS, newposn );
|
nkeynes@193 | 394 | }
|
nkeynes@193 | 395 | PVRRAM(reference) = 0xE0000000 | (posn<<2);
|
nkeynes@193 | 396 | return posn << 2;
|
nkeynes@189 | 397 | }
|
nkeynes@189 | 398 | }
|
nkeynes@189 | 399 |
|
nkeynes@189 | 400 | /**
|
nkeynes@189 | 401 | * Write a tile entry out to the matrix.
|
nkeynes@189 | 402 | */
|
nkeynes@189 | 403 | static int ta_write_tile_entry( int x, int y, uint32_t tile_entry ) {
|
nkeynes@189 | 404 | uint32_t tile = TILESLOT(x,y);
|
nkeynes@193 | 405 | uint32_t tilestart = tile;
|
nkeynes@189 | 406 | uint32_t value;
|
nkeynes@189 | 407 | uint32_t lasttri = 0;
|
nkeynes@189 | 408 | int i,l;
|
nkeynes@189 | 409 |
|
nkeynes@189 | 410 | if( (tile_entry & 0x80000000) &&
|
nkeynes@189 | 411 | ta_status.last_triangle_bounds.x1 != -1 &&
|
nkeynes@189 | 412 | ta_status.last_triangle_bounds.x1 <= x &&
|
nkeynes@189 | 413 | ta_status.last_triangle_bounds.x2 >= x &&
|
nkeynes@189 | 414 | ta_status.last_triangle_bounds.y1 <= y &&
|
nkeynes@189 | 415 | ta_status.last_triangle_bounds.y2 >= y ) {
|
nkeynes@189 | 416 | /* potential for triangle stacking */
|
nkeynes@189 | 417 | lasttri = tile_entry & 0xE1E00000;
|
nkeynes@189 | 418 | }
|
nkeynes@189 | 419 |
|
nkeynes@189 | 420 |
|
nkeynes@189 | 421 | if( PVRRAM(tile) == 0xF0000000 ) {
|
nkeynes@189 | 422 | PVRRAM(tile) = tile_entry;
|
nkeynes@189 | 423 | PVRRAM(tile+4) = 0xF0000000;
|
nkeynes@189 | 424 | return;
|
nkeynes@189 | 425 | }
|
nkeynes@189 | 426 |
|
nkeynes@189 | 427 | while(1) {
|
nkeynes@189 | 428 | value = PVRRAM(tile);
|
nkeynes@189 | 429 | for( i=1; i<ta_status.current_tile_size; i++ ) {
|
nkeynes@189 | 430 | tile += 4;
|
nkeynes@189 | 431 | uint32_t nextval = PVRRAM(tile);
|
nkeynes@189 | 432 | if( nextval == 0xF0000000 ) {
|
nkeynes@189 | 433 | if( lasttri != 0 && lasttri == (value&0xE1E00000) ) {
|
nkeynes@189 | 434 | int count = (value & 0x1E000000) + 0x02000000;
|
nkeynes@189 | 435 | if( count < 0x20000000 ) {
|
nkeynes@189 | 436 | PVRRAM(tile-4) = (value & 0xE1FFFFFF) | count;
|
nkeynes@189 | 437 | return;
|
nkeynes@189 | 438 | }
|
nkeynes@189 | 439 | }
|
nkeynes@189 | 440 | if( i < ta_status.current_tile_size-1 ) {
|
nkeynes@189 | 441 | PVRRAM(tile) = tile_entry;
|
nkeynes@189 | 442 | PVRRAM(tile+4) = 0xF0000000;
|
nkeynes@189 | 443 | return;
|
nkeynes@189 | 444 | }
|
nkeynes@189 | 445 | }
|
nkeynes@189 | 446 | value = nextval;
|
nkeynes@189 | 447 | }
|
nkeynes@189 | 448 |
|
nkeynes@189 | 449 | if( value == 0xF0000000 ) {
|
nkeynes@193 | 450 | tile = ta_alloc_tilelist(tile);
|
nkeynes@193 | 451 | if( tile != TA_NO_ALLOC ) {
|
nkeynes@193 | 452 | PVRRAM(tile) = tile_entry;
|
nkeynes@193 | 453 | PVRRAM(tile+4) = 0xF0000000;
|
nkeynes@193 | 454 | }
|
nkeynes@189 | 455 | return;
|
nkeynes@189 | 456 | } else if( (value & 0xFF000000) == 0xE0000000 ) {
|
nkeynes@193 | 457 | value &= 0x00FFFFFF;
|
nkeynes@193 | 458 | if( value == tilestart )
|
nkeynes@193 | 459 | return 0; /* Loop */
|
nkeynes@193 | 460 | tilestart = tile = value;
|
nkeynes@189 | 461 | } else {
|
nkeynes@189 | 462 | /* This should never happen */
|
nkeynes@189 | 463 | return 0;
|
nkeynes@189 | 464 | }
|
nkeynes@189 | 465 | }
|
nkeynes@189 | 466 | }
|
nkeynes@189 | 467 |
|
nkeynes@189 | 468 | /**
|
nkeynes@189 | 469 | * Write a completed polygon out to the memory buffers
|
nkeynes@189 | 470 | * OPTIMIZEME: This is not terribly efficient at the moment.
|
nkeynes@189 | 471 | */
|
nkeynes@189 | 472 | static void ta_commit_polygon( ) {
|
nkeynes@189 | 473 | int i, x, y;
|
nkeynes@189 | 474 | int tx[ta_status.vertex_count], ty[ta_status.vertex_count];
|
nkeynes@189 | 475 | struct tile_bounds triangle_bound[ta_status.vertex_count - 2];
|
nkeynes@189 | 476 | struct tile_bounds polygon_bound;
|
nkeynes@189 | 477 | uint32_t poly_context[5];
|
nkeynes@189 | 478 |
|
nkeynes@189 | 479 | if( ta_status.vertex_count < 2 ) {
|
nkeynes@189 | 480 | return; /* No polygons - ignore */
|
nkeynes@189 | 481 | }
|
nkeynes@189 | 482 | memcpy( poly_context, ta_status.poly_context, ta_status.poly_context_size * 4 );
|
nkeynes@189 | 483 |
|
nkeynes@189 | 484 | /* Compute the tile coordinates for each vertex (need to be careful with
|
nkeynes@189 | 485 | * clamping here)
|
nkeynes@189 | 486 | */
|
nkeynes@189 | 487 | for( i=0; i<ta_status.vertex_count; i++ ) {
|
nkeynes@199 | 488 | if( ta_status.poly_vertex[i].x < 0.0 || TA_IS_NINF(ta_status.poly_vertex[i].x) ) {
|
nkeynes@189 | 489 | tx[i] = -1;
|
nkeynes@199 | 490 | } else if( ta_status.poly_vertex[i].x > (float)INT_MAX || TA_IS_INF(ta_status.poly_vertex[i].x) ) {
|
nkeynes@189 | 491 | tx[i] = INT_MAX/32;
|
nkeynes@189 | 492 | } else {
|
nkeynes@189 | 493 | tx[i] = (int)(ta_status.poly_vertex[i].x / 32.0);
|
nkeynes@189 | 494 | }
|
nkeynes@199 | 495 | if( ta_status.poly_vertex[i].y < 0.0 || TA_IS_NINF(ta_status.poly_vertex[i].y)) {
|
nkeynes@189 | 496 | ty[i] = -1;
|
nkeynes@199 | 497 | } else if( ta_status.poly_vertex[i].y > (float)INT_MAX || TA_IS_INF(ta_status.poly_vertex[i].y) ) {
|
nkeynes@189 | 498 | ty[i] = INT_MAX/32;
|
nkeynes@189 | 499 | } else {
|
nkeynes@189 | 500 | ty[i] = (int)(ta_status.poly_vertex[i].y / 32.0);
|
nkeynes@189 | 501 | }
|
nkeynes@189 | 502 |
|
nkeynes@189 | 503 | }
|
nkeynes@189 | 504 |
|
nkeynes@189 | 505 | /* Compute bounding box for each triangle individually, as well
|
nkeynes@189 | 506 | * as the overall polygon.
|
nkeynes@189 | 507 | */
|
nkeynes@189 | 508 |
|
nkeynes@189 | 509 | for( i=0; i<ta_status.vertex_count-2; i++ ) {
|
nkeynes@189 | 510 | triangle_bound[i].x1 = MIN3(tx[i],tx[i+1],tx[i+2]);
|
nkeynes@189 | 511 | triangle_bound[i].x2 = MAX3(tx[i],tx[i+1],tx[i+2]);
|
nkeynes@189 | 512 | triangle_bound[i].y1 = MIN3(ty[i],ty[i+1],ty[i+2]);
|
nkeynes@189 | 513 | triangle_bound[i].y2 = MAX3(ty[i],ty[i+1],ty[i+2]);
|
nkeynes@189 | 514 | if( i == 0 ) {
|
nkeynes@189 | 515 | polygon_bound.x1 = triangle_bound[0].x1;
|
nkeynes@189 | 516 | polygon_bound.y1 = triangle_bound[0].y1;
|
nkeynes@189 | 517 | polygon_bound.x2 = triangle_bound[0].x2;
|
nkeynes@189 | 518 | polygon_bound.y2 = triangle_bound[0].y2;
|
nkeynes@189 | 519 | } else {
|
nkeynes@189 | 520 | polygon_bound.x1 = MIN(polygon_bound.x1, triangle_bound[i].x1);
|
nkeynes@189 | 521 | polygon_bound.x2 = MAX(polygon_bound.x2, triangle_bound[i].x2);
|
nkeynes@189 | 522 | polygon_bound.y1 = MIN(polygon_bound.y1, triangle_bound[i].y1);
|
nkeynes@189 | 523 | polygon_bound.y2 = MAX(polygon_bound.y2, triangle_bound[i].y2);
|
nkeynes@189 | 524 | }
|
nkeynes@189 | 525 | }
|
nkeynes@189 | 526 |
|
nkeynes@189 | 527 | /* If the polygon is actually entirely out of the frustum, clip it entirely */
|
nkeynes@189 | 528 | if( polygon_bound.x2 < 0 || polygon_bound.x1 > ta_status.width ||
|
nkeynes@189 | 529 | polygon_bound.y2 < 0 || polygon_bound.y1 > ta_status.height ) {
|
nkeynes@189 | 530 | return;
|
nkeynes@189 | 531 | }
|
nkeynes@189 | 532 |
|
nkeynes@189 | 533 | /* Clamp the polygon bounds to the frustum */
|
nkeynes@189 | 534 | if( polygon_bound.x1 < 0 ) polygon_bound.x1 = 0;
|
nkeynes@189 | 535 | if( polygon_bound.x2 >= ta_status.width ) polygon_bound.x2 = ta_status.width-1;
|
nkeynes@189 | 536 | if( polygon_bound.y1 < 0 ) polygon_bound.y1 = 0;
|
nkeynes@189 | 537 | if( polygon_bound.y2 >= ta_status.width ) polygon_bound.y2 = ta_status.height-1;
|
nkeynes@189 | 538 |
|
nkeynes@189 | 539 | /* Set the "single tile" flag if it's entirely contained in 1 tile */
|
nkeynes@189 | 540 | if( polygon_bound.x1 == polygon_bound.x2 &&
|
nkeynes@189 | 541 | polygon_bound.y1 == polygon_bound.y2 ) {
|
nkeynes@189 | 542 | poly_context[0] |= 0x00200000;
|
nkeynes@189 | 543 | }
|
nkeynes@189 | 544 |
|
nkeynes@189 | 545 | /* Ok, we're good to go - write out the polygon first */
|
nkeynes@189 | 546 | uint32_t tile_entry = MMIO_READ( PVR2, TA_POLYPOS ) >> 2 | ta_status.poly_pointer;
|
nkeynes@189 | 547 |
|
nkeynes@189 | 548 | int status = ta_write_polygon_buffer( poly_context, ta_status.poly_context_size );
|
nkeynes@189 | 549 | if( status == 0 ) {
|
nkeynes@189 | 550 | /* No memory available - abort */
|
nkeynes@189 | 551 | return;
|
nkeynes@189 | 552 | } else {
|
nkeynes@189 | 553 | for( i=0; i<ta_status.vertex_count && status != 0; i++ ) {
|
nkeynes@189 | 554 | status = ta_write_polygon_buffer( (uint32_t *)(&ta_status.poly_vertex[i]), 3 + ta_status.poly_vertex_size );
|
nkeynes@189 | 555 | }
|
nkeynes@189 | 556 | }
|
nkeynes@189 | 557 |
|
nkeynes@193 | 558 | if( ta_status.current_tile_size == 0 ) {
|
nkeynes@193 | 559 | /* No memory for tile entry, so don't write anything */
|
nkeynes@193 | 560 | return;
|
nkeynes@193 | 561 | }
|
nkeynes@193 | 562 |
|
nkeynes@189 | 563 | /* And now the tile entries. Triangles are different from everything else */
|
nkeynes@189 | 564 | if( ta_status.vertex_count == 3 ) {
|
nkeynes@189 | 565 | tile_entry |= 0x80000000;
|
nkeynes@189 | 566 | for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
|
nkeynes@189 | 567 | for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
|
nkeynes@189 | 568 | ta_write_tile_entry( x,y,tile_entry );
|
nkeynes@189 | 569 | }
|
nkeynes@189 | 570 | }
|
nkeynes@189 | 571 | ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
|
nkeynes@189 | 572 | ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
|
nkeynes@189 | 573 | ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
|
nkeynes@189 | 574 | ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
|
nkeynes@189 | 575 | } else if( ta_status.current_vertex_type == TA_VERTEX_SPRITE ||
|
nkeynes@189 | 576 | ta_status.current_vertex_type == TA_VERTEX_TEX_SPRITE ) {
|
nkeynes@189 | 577 | tile_entry |= 0xA0000000;
|
nkeynes@189 | 578 | for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
|
nkeynes@189 | 579 | for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
|
nkeynes@189 | 580 | ta_write_tile_entry( x,y,tile_entry );
|
nkeynes@189 | 581 | }
|
nkeynes@189 | 582 | }
|
nkeynes@189 | 583 | ta_status.last_triangle_bounds.x1 = polygon_bound.x1;
|
nkeynes@189 | 584 | ta_status.last_triangle_bounds.y1 = polygon_bound.y1;
|
nkeynes@189 | 585 | ta_status.last_triangle_bounds.x2 = polygon_bound.x2;
|
nkeynes@189 | 586 | ta_status.last_triangle_bounds.y2 = polygon_bound.y2;
|
nkeynes@189 | 587 | } else {
|
nkeynes@189 | 588 | for( y=polygon_bound.y1; y<=polygon_bound.y2; y++ ) {
|
nkeynes@189 | 589 | for( x=polygon_bound.x1; x<=polygon_bound.x2; x++ ) {
|
nkeynes@189 | 590 | uint32_t entry = tile_entry;
|
nkeynes@189 | 591 | for( i=0; i<ta_status.vertex_count-2; i++ ) {
|
nkeynes@189 | 592 | if( triangle_bound[i].x1 <= x && triangle_bound[i].x2 >= x &&
|
nkeynes@189 | 593 | triangle_bound[i].y1 <= y && triangle_bound[i].y2 >= y ) {
|
nkeynes@189 | 594 | entry |= (0x40000000>>i);
|
nkeynes@189 | 595 | }
|
nkeynes@189 | 596 | }
|
nkeynes@189 | 597 | ta_write_tile_entry( x, y, entry );
|
nkeynes@189 | 598 | }
|
nkeynes@189 | 599 | }
|
nkeynes@189 | 600 | ta_status.last_triangle_bounds.x1 = -1;
|
nkeynes@189 | 601 | }
|
nkeynes@189 | 602 | }
|
nkeynes@189 | 603 |
|
nkeynes@189 | 604 | /**
|
nkeynes@189 | 605 | * Variant of ta_split_polygon called when vertex_count == max_vertex, but
|
nkeynes@189 | 606 | * the client hasn't sent the LAST VERTEX flag. Commit the poly as normal
|
nkeynes@189 | 607 | * first, then start a new poly with the first 2 vertexes taken from the
|
nkeynes@189 | 608 | * current one.
|
nkeynes@189 | 609 | */
|
nkeynes@189 | 610 | static void ta_split_polygon() {
|
nkeynes@189 | 611 | ta_commit_polygon();
|
nkeynes@189 | 612 | if( TA_IS_NORMAL_POLY() ) {
|
nkeynes@189 | 613 | /* This only applies to ordinary polys - Sprites + modifier lists are
|
nkeynes@189 | 614 | * handled differently
|
nkeynes@189 | 615 | */
|
nkeynes@189 | 616 | if( ta_status.vertex_count == 3 ) {
|
nkeynes@189 | 617 | /* Triangles use an odd/even scheme */
|
nkeynes@189 | 618 | if( ta_status.poly_parity == 0 ) {
|
nkeynes@189 | 619 | memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[2],
|
nkeynes@189 | 620 | sizeof(struct pvr2_ta_vertex) );
|
nkeynes@189 | 621 | ta_status.poly_parity = 1;
|
nkeynes@189 | 622 | } else {
|
nkeynes@189 | 623 | memcpy( &ta_status.poly_vertex[1], &ta_status.poly_vertex[2],
|
nkeynes@189 | 624 | sizeof(struct pvr2_ta_vertex) );
|
nkeynes@189 | 625 | ta_status.poly_parity = 0;
|
nkeynes@189 | 626 | }
|
nkeynes@189 | 627 | } else {
|
nkeynes@189 | 628 | /* Everything else just uses the last 2 vertexes in order */
|
nkeynes@189 | 629 | memcpy( &ta_status.poly_vertex[0], &ta_status.poly_vertex[ta_status.vertex_count-2],
|
nkeynes@189 | 630 | sizeof(struct pvr2_ta_vertex)*2 );
|
nkeynes@189 | 631 | ta_status.poly_parity = 0;
|
nkeynes@189 | 632 | }
|
nkeynes@189 | 633 | ta_status.vertex_count = 2;
|
nkeynes@189 | 634 | } else {
|
nkeynes@189 | 635 | ta_status.vertex_count = 0;
|
nkeynes@189 | 636 | }
|
nkeynes@189 | 637 | }
|
nkeynes@189 | 638 |
|
nkeynes@189 | 639 | /**
|
nkeynes@189 | 640 | * Parse the polygon context block and setup the internal state to receive
|
nkeynes@189 | 641 | * vertexes.
|
nkeynes@189 | 642 | * @param data 32 bytes of parameter data.
|
nkeynes@189 | 643 | */
|
nkeynes@189 | 644 | static void ta_parse_polygon_context( union ta_data *data ) {
|
nkeynes@189 | 645 | int colourfmt = TA_POLYCMD_COLOURFMT(data[0].i);
|
nkeynes@194 | 646 | if( TA_POLYCMD_USELENGTH(data[0].i) ) {
|
nkeynes@194 | 647 | ta_status.max_vertex = TA_POLYCMD_LENGTH(data[0].i);
|
nkeynes@194 | 648 | }
|
nkeynes@189 | 649 | ta_status.vertex_count = 0;
|
nkeynes@189 | 650 | ta_status.poly_context[0] =
|
nkeynes@189 | 651 | (data[1].i & 0xFC1FFFFF) | ((data[0].i & 0x0B) << 22);
|
nkeynes@189 | 652 | ta_status.poly_context[1] = data[2].i;
|
nkeynes@189 | 653 | ta_status.poly_context[3] = data[4].i;
|
nkeynes@189 | 654 | ta_status.poly_parity = 0;
|
nkeynes@189 | 655 | if( data[0].i & TA_POLYCMD_TEXTURED ) {
|
nkeynes@189 | 656 | ta_status.current_vertex_type = data[0].i & 0x0D;
|
nkeynes@189 | 657 | ta_status.poly_context[2] = data[3].i;
|
nkeynes@189 | 658 | ta_status.poly_context[4] = data[5].i;
|
nkeynes@189 | 659 | if( data[0].i & TA_POLYCMD_SPECULAR ) {
|
nkeynes@189 | 660 | ta_status.poly_context[0] |= 0x01000000;
|
nkeynes@189 | 661 | ta_status.poly_vertex_size = 4;
|
nkeynes@189 | 662 | } else {
|
nkeynes@189 | 663 | ta_status.poly_vertex_size = 3;
|
nkeynes@189 | 664 | }
|
nkeynes@189 | 665 | if( data[0].i & TA_POLYCMD_UV16 ) {
|
nkeynes@189 | 666 | ta_status.poly_vertex_size--;
|
nkeynes@189 | 667 | }
|
nkeynes@189 | 668 | } else {
|
nkeynes@189 | 669 | ta_status.current_vertex_type = 0;
|
nkeynes@189 | 670 | ta_status.poly_vertex_size = 1;
|
nkeynes@189 | 671 | ta_status.poly_context[2] = 0;
|
nkeynes@189 | 672 | ta_status.poly_context[4] = 0;
|
nkeynes@189 | 673 | }
|
nkeynes@189 | 674 |
|
nkeynes@189 | 675 | ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
|
nkeynes@189 | 676 | ta_status.poly_context_size = 3;
|
nkeynes@189 | 677 | if( data[0].i & TA_POLYCMD_MODIFIED ) {
|
nkeynes@189 | 678 | ta_status.poly_pointer |= 0x01000000;
|
nkeynes@189 | 679 | if( data[0].i & TA_POLYCMD_FULLMOD ) {
|
nkeynes@189 | 680 | ta_status.poly_context_size = 5;
|
nkeynes@189 | 681 | ta_status.poly_vertex_size <<= 1;
|
nkeynes@189 | 682 | ta_status.current_vertex_type |= 0x40;
|
nkeynes@189 | 683 | /* Modified/float not supported - behaves as per last intensity */
|
nkeynes@189 | 684 | if( colourfmt == TA_POLYCMD_COLOURFMT_FLOAT ) {
|
nkeynes@189 | 685 | colourfmt = TA_POLYCMD_COLOURFMT_LASTINT;
|
nkeynes@189 | 686 | }
|
nkeynes@189 | 687 | }
|
nkeynes@189 | 688 | }
|
nkeynes@189 | 689 |
|
nkeynes@189 | 690 | if( colourfmt == TA_POLYCMD_COLOURFMT_INTENSITY ) {
|
nkeynes@189 | 691 | if( TA_POLYCMD_IS_FULLMOD(data[0].i) ||
|
nkeynes@189 | 692 | TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
|
nkeynes@189 | 693 | ta_status.state = STATE_EXPECT_POLY_BLOCK2;
|
nkeynes@189 | 694 | } else {
|
nkeynes@189 | 695 | ta_status.intensity1 =
|
nkeynes@189 | 696 | parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
|
nkeynes@189 | 697 | }
|
nkeynes@189 | 698 | } else if( colourfmt == TA_POLYCMD_COLOURFMT_LASTINT ) {
|
nkeynes@189 | 699 | colourfmt = TA_POLYCMD_COLOURFMT_INTENSITY;
|
nkeynes@189 | 700 | }
|
nkeynes@189 | 701 |
|
nkeynes@189 | 702 | ta_status.current_vertex_type |= colourfmt;
|
nkeynes@189 | 703 | }
|
nkeynes@189 | 704 |
|
nkeynes@189 | 705 | /**
|
nkeynes@189 | 706 | * Parse the modifier volume context block and setup the internal state to
|
nkeynes@189 | 707 | * receive modifier vertexes.
|
nkeynes@189 | 708 | * @param data 32 bytes of parameter data.
|
nkeynes@189 | 709 | */
|
nkeynes@189 | 710 | static void ta_parse_modifier_context( union ta_data *data ) {
|
nkeynes@189 | 711 | ta_status.current_vertex_type = TA_VERTEX_MOD_VOLUME;
|
nkeynes@189 | 712 | ta_status.poly_vertex_size = 0;
|
nkeynes@189 | 713 | ta_status.poly_context_size = 3;
|
nkeynes@189 | 714 | ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
|
nkeynes@189 | 715 | ((data[0].i & 0x0B)<<22);
|
nkeynes@189 | 716 | if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
|
nkeynes@189 | 717 | ta_status.poly_context[0] |= 0x01000000;
|
nkeynes@189 | 718 | }
|
nkeynes@189 | 719 | ta_status.poly_context[1] = 0;
|
nkeynes@189 | 720 | ta_status.poly_context[2] = 0;
|
nkeynes@189 | 721 | ta_status.vertex_count = 0;
|
nkeynes@189 | 722 | ta_status.max_vertex = 3;
|
nkeynes@189 | 723 | ta_status.poly_pointer = 0;
|
nkeynes@189 | 724 | }
|
nkeynes@189 | 725 |
|
nkeynes@189 | 726 | /**
|
nkeynes@189 | 727 | * Parse the sprite context block and setup the internal state to receive
|
nkeynes@189 | 728 | * vertexes.
|
nkeynes@189 | 729 | * @param data 32 bytes of parameter data.
|
nkeynes@189 | 730 | */
|
nkeynes@189 | 731 | static void ta_parse_sprite_context( union ta_data *data ) {
|
nkeynes@189 | 732 | ta_status.poly_context_size = 3;
|
nkeynes@189 | 733 | ta_status.poly_context[0] = (data[1].i & 0xFC1FFFFF) |
|
nkeynes@189 | 734 | ((data[0].i & 0x0B)<<22) | 0x00400000;
|
nkeynes@189 | 735 | if( TA_POLYCMD_IS_SPECULAR(data[0].i) ) {
|
nkeynes@189 | 736 | ta_status.poly_context[0] |= 0x01000000;
|
nkeynes@189 | 737 | }
|
nkeynes@189 | 738 | ta_status.poly_context[1] = data[2].i;
|
nkeynes@189 | 739 | ta_status.poly_context[2] = data[3].i;
|
nkeynes@189 | 740 | if( data[0].i & TA_POLYCMD_TEXTURED ) {
|
nkeynes@189 | 741 | ta_status.poly_vertex_size = 2;
|
nkeynes@189 | 742 | ta_status.poly_vertex[2].detail[1] = data[4].i;
|
nkeynes@189 | 743 | ta_status.current_vertex_type = TA_VERTEX_TEX_SPRITE;
|
nkeynes@189 | 744 | } else {
|
nkeynes@189 | 745 | ta_status.poly_vertex_size = 1;
|
nkeynes@189 | 746 | ta_status.poly_vertex[2].detail[0] = data[4].i;
|
nkeynes@189 | 747 | ta_status.current_vertex_type = TA_VERTEX_SPRITE;
|
nkeynes@189 | 748 | }
|
nkeynes@189 | 749 | ta_status.vertex_count = 0;
|
nkeynes@189 | 750 | ta_status.max_vertex = 4;
|
nkeynes@189 | 751 | ta_status.poly_pointer = (ta_status.poly_vertex_size << 21);
|
nkeynes@189 | 752 | }
|
nkeynes@189 | 753 |
|
nkeynes@189 | 754 | /**
|
nkeynes@189 | 755 | * Copy the last read vertex into all vertexes up to max_vertex. Used for
|
nkeynes@189 | 756 | * Aborted polygons under some circumstances.
|
nkeynes@189 | 757 | */
|
nkeynes@189 | 758 | static void ta_fill_vertexes( ) {
|
nkeynes@189 | 759 | int i;
|
nkeynes@189 | 760 | for( i=ta_status.vertex_count; i<ta_status.max_vertex; i++ ) {
|
nkeynes@189 | 761 | memcpy( &ta_status.poly_vertex[i], &ta_status.poly_vertex[ta_status.vertex_count-1],
|
nkeynes@189 | 762 | sizeof( struct pvr2_ta_vertex ) );
|
nkeynes@189 | 763 | }
|
nkeynes@189 | 764 | }
|
nkeynes@189 | 765 |
|
nkeynes@189 | 766 | static void ta_parse_vertex( union ta_data *data ) {
|
nkeynes@189 | 767 | struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count];
|
nkeynes@189 | 768 | vertex->x = data[1].f;
|
nkeynes@189 | 769 | vertex->y = data[2].f;
|
nkeynes@189 | 770 | vertex->z = data[3].f;
|
nkeynes@189 | 771 |
|
nkeynes@189 | 772 | switch( ta_status.current_vertex_type ) {
|
nkeynes@189 | 773 | case TA_VERTEX_PACKED:
|
nkeynes@189 | 774 | vertex->detail[0] = data[6].i;
|
nkeynes@189 | 775 | break;
|
nkeynes@189 | 776 | case TA_VERTEX_FLOAT:
|
nkeynes@189 | 777 | vertex->detail[0] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
|
nkeynes@189 | 778 | break;
|
nkeynes@189 | 779 | case TA_VERTEX_INTENSITY:
|
nkeynes@189 | 780 | vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[6].f );
|
nkeynes@189 | 781 | break;
|
nkeynes@189 | 782 |
|
nkeynes@189 | 783 | case TA_VERTEX_TEX_SPEC_PACKED:
|
nkeynes@189 | 784 | vertex->detail[3] = data[7].i; /* ARGB */
|
nkeynes@189 | 785 | /* Fallthrough */
|
nkeynes@189 | 786 | case TA_VERTEX_TEX_PACKED:
|
nkeynes@189 | 787 | vertex->detail[0] = data[4].i; /* U */
|
nkeynes@189 | 788 | vertex->detail[1] = data[5].i; /* V */
|
nkeynes@189 | 789 | vertex->detail[2] = data[6].i; /* ARGB */
|
nkeynes@189 | 790 | break;
|
nkeynes@189 | 791 | case TA_VERTEX_TEX_UV16_SPEC_PACKED:
|
nkeynes@189 | 792 | vertex->detail[2] = data[7].i; /* ARGB */
|
nkeynes@189 | 793 | /* Fallthrough */
|
nkeynes@189 | 794 | case TA_VERTEX_TEX_UV16_PACKED:
|
nkeynes@189 | 795 | vertex->detail[0] = data[4].i; /* UV */
|
nkeynes@189 | 796 | vertex->detail[1] = data[6].i; /* ARGB */
|
nkeynes@189 | 797 | break;
|
nkeynes@189 | 798 |
|
nkeynes@189 | 799 | case TA_VERTEX_TEX_FLOAT:
|
nkeynes@189 | 800 | case TA_VERTEX_TEX_SPEC_FLOAT:
|
nkeynes@189 | 801 | vertex->detail[0] = data[4].i; /* U */
|
nkeynes@189 | 802 | vertex->detail[1] = data[5].i; /* UV */
|
nkeynes@189 | 803 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 804 | break;
|
nkeynes@189 | 805 | case TA_VERTEX_TEX_UV16_FLOAT:
|
nkeynes@189 | 806 | case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
|
nkeynes@189 | 807 | vertex->detail[0] = data[4].i; /* UV */
|
nkeynes@189 | 808 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 809 | break;
|
nkeynes@189 | 810 |
|
nkeynes@189 | 811 | case TA_VERTEX_TEX_SPEC_INTENSITY:
|
nkeynes@189 | 812 | vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[7].f );
|
nkeynes@189 | 813 | /* Fallthrough */
|
nkeynes@189 | 814 | case TA_VERTEX_TEX_INTENSITY:
|
nkeynes@189 | 815 | vertex->detail[0] = data[4].i; /* U */
|
nkeynes@189 | 816 | vertex->detail[1] = data[5].i; /* V */
|
nkeynes@189 | 817 | vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
|
nkeynes@189 | 818 | break;
|
nkeynes@189 | 819 | case TA_VERTEX_TEX_UV16_SPEC_INTENSITY:
|
nkeynes@189 | 820 | vertex->detail[2] = parse_intensity_colour( ta_status.intensity2, data[7].f );
|
nkeynes@189 | 821 | /* Fallthrough */
|
nkeynes@189 | 822 | case TA_VERTEX_TEX_UV16_INTENSITY:
|
nkeynes@189 | 823 | vertex->detail[0] = data[4].i; /* UV */
|
nkeynes@189 | 824 | vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
|
nkeynes@189 | 825 | break;
|
nkeynes@189 | 826 |
|
nkeynes@189 | 827 | case TA_VERTEX_PACKED_MOD:
|
nkeynes@189 | 828 | vertex->detail[0] = data[4].i; /* ARGB */
|
nkeynes@189 | 829 | vertex->detail[1] = data[5].i; /* ARGB */
|
nkeynes@189 | 830 | break;
|
nkeynes@189 | 831 | case TA_VERTEX_INTENSITY_MOD:
|
nkeynes@189 | 832 | vertex->detail[0] = parse_intensity_colour( ta_status.intensity1, data[4].f );
|
nkeynes@189 | 833 | vertex->detail[1] = parse_intensity_colour( ta_status.intensity2, data[5].f );
|
nkeynes@189 | 834 | break;
|
nkeynes@189 | 835 |
|
nkeynes@189 | 836 | case TA_VERTEX_TEX_SPEC_PACKED_MOD:
|
nkeynes@189 | 837 | vertex->detail[3] = data[7].i; /* ARGB0 */
|
nkeynes@189 | 838 | /* Fallthrough */
|
nkeynes@189 | 839 | case TA_VERTEX_TEX_PACKED_MOD:
|
nkeynes@189 | 840 | vertex->detail[0] = data[4].i; /* U0 */
|
nkeynes@189 | 841 | vertex->detail[1] = data[5].i; /* V0 */
|
nkeynes@189 | 842 | vertex->detail[2] = data[6].i; /* ARGB0 */
|
nkeynes@189 | 843 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 844 | break;
|
nkeynes@189 | 845 | case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
|
nkeynes@189 | 846 | vertex->detail[2] = data[7].i; /* ARGB0 */
|
nkeynes@189 | 847 | /* Fallthrough */
|
nkeynes@189 | 848 | case TA_VERTEX_TEX_UV16_PACKED_MOD:
|
nkeynes@189 | 849 | vertex->detail[0] = data[4].i; /* UV0 */
|
nkeynes@189 | 850 | vertex->detail[1] = data[6].i; /* ARGB0 */
|
nkeynes@189 | 851 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 852 | break;
|
nkeynes@189 | 853 |
|
nkeynes@189 | 854 | case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
|
nkeynes@189 | 855 | vertex->detail[3] = parse_intensity_colour( ta_status.intensity1, data[7].f );
|
nkeynes@189 | 856 | /* Fallthrough */
|
nkeynes@189 | 857 | case TA_VERTEX_TEX_INTENSITY_MOD:
|
nkeynes@189 | 858 | vertex->detail[0] = data[4].i; /* U0 */
|
nkeynes@189 | 859 | vertex->detail[1] = data[5].i; /* V0 */
|
nkeynes@189 | 860 | vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[6].f );
|
nkeynes@189 | 861 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 862 | break;
|
nkeynes@189 | 863 | case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
|
nkeynes@189 | 864 | vertex->detail[2] = parse_intensity_colour( ta_status.intensity1, data[7].f );
|
nkeynes@189 | 865 | /* Fallthrough */
|
nkeynes@189 | 866 | case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
|
nkeynes@189 | 867 | vertex->detail[0] = data[4].i; /* UV0 */
|
nkeynes@189 | 868 | vertex->detail[1] = parse_intensity_colour( ta_status.intensity1, data[6].f );
|
nkeynes@189 | 869 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 870 | break;
|
nkeynes@189 | 871 |
|
nkeynes@189 | 872 | case TA_VERTEX_SPRITE:
|
nkeynes@189 | 873 | case TA_VERTEX_TEX_SPRITE:
|
nkeynes@189 | 874 | case TA_VERTEX_MOD_VOLUME:
|
nkeynes@189 | 875 | vertex++;
|
nkeynes@189 | 876 | vertex->x = data[4].f;
|
nkeynes@189 | 877 | vertex->y = data[5].f;
|
nkeynes@189 | 878 | vertex->z = data[6].f;
|
nkeynes@189 | 879 | vertex++;
|
nkeynes@189 | 880 | vertex->x = data[7].f;
|
nkeynes@189 | 881 | ta_status.vertex_count += 2;
|
nkeynes@189 | 882 | ta_status.state = STATE_EXPECT_VERTEX_BLOCK2;
|
nkeynes@189 | 883 | break;
|
nkeynes@189 | 884 | }
|
nkeynes@189 | 885 | ta_status.vertex_count++;
|
nkeynes@189 | 886 | }
|
nkeynes@189 | 887 |
|
nkeynes@189 | 888 | static void ta_parse_vertex_block2( union ta_data *data ) {
|
nkeynes@189 | 889 | struct pvr2_ta_vertex *vertex = &ta_status.poly_vertex[ta_status.vertex_count-1];
|
nkeynes@189 | 890 |
|
nkeynes@189 | 891 | switch( ta_status.current_vertex_type ) {
|
nkeynes@189 | 892 | case TA_VERTEX_TEX_SPEC_FLOAT:
|
nkeynes@189 | 893 | vertex->detail[3] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
|
nkeynes@189 | 894 | /* Fallthrough */
|
nkeynes@189 | 895 | case TA_VERTEX_TEX_FLOAT:
|
nkeynes@189 | 896 | vertex->detail[2] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
|
nkeynes@189 | 897 | break;
|
nkeynes@189 | 898 | case TA_VERTEX_TEX_UV16_SPEC_FLOAT:
|
nkeynes@189 | 899 | vertex->detail[2] = parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
|
nkeynes@189 | 900 | /* Fallthrough */
|
nkeynes@189 | 901 | case TA_VERTEX_TEX_UV16_FLOAT:
|
nkeynes@189 | 902 | vertex->detail[1] = parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
|
nkeynes@189 | 903 | break;
|
nkeynes@189 | 904 | case TA_VERTEX_TEX_PACKED_MOD:
|
nkeynes@189 | 905 | vertex->detail[3] = data[0].i; /* U1 */
|
nkeynes@189 | 906 | vertex->detail[4] = data[1].i; /* V1 */
|
nkeynes@189 | 907 | vertex->detail[5] = data[2].i; /* ARGB1 */
|
nkeynes@189 | 908 | break;
|
nkeynes@189 | 909 | case TA_VERTEX_TEX_SPEC_PACKED_MOD:
|
nkeynes@189 | 910 | vertex->detail[4] = data[0].i; /* U1 */
|
nkeynes@189 | 911 | vertex->detail[5] = data[1].i; /* V1 */
|
nkeynes@189 | 912 | vertex->detail[6] = data[2].i; /* ARGB1 */
|
nkeynes@189 | 913 | vertex->detail[7] = data[3].i; /* ARGB1 */
|
nkeynes@189 | 914 | break;
|
nkeynes@189 | 915 | case TA_VERTEX_TEX_UV16_PACKED_MOD:
|
nkeynes@189 | 916 | vertex->detail[2] = data[0].i; /* UV1 */
|
nkeynes@189 | 917 | vertex->detail[3] = data[2].i; /* ARGB1 */
|
nkeynes@189 | 918 | break;
|
nkeynes@189 | 919 | case TA_VERTEX_TEX_UV16_SPEC_PACKED_MOD:
|
nkeynes@189 | 920 | vertex->detail[3] = data[0].i; /* UV1 */
|
nkeynes@189 | 921 | vertex->detail[4] = data[2].i; /* ARGB1 */
|
nkeynes@189 | 922 | vertex->detail[5] = data[3].i; /* ARGB1 */
|
nkeynes@189 | 923 | break;
|
nkeynes@189 | 924 |
|
nkeynes@189 | 925 | case TA_VERTEX_TEX_INTENSITY_MOD:
|
nkeynes@189 | 926 | vertex->detail[3] = data[0].i; /* U1 */
|
nkeynes@189 | 927 | vertex->detail[4] = data[1].i; /* V1 */
|
nkeynes@189 | 928 | vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
|
nkeynes@189 | 929 | break;
|
nkeynes@189 | 930 | case TA_VERTEX_TEX_SPEC_INTENSITY_MOD:
|
nkeynes@189 | 931 | vertex->detail[4] = data[0].i; /* U1 */
|
nkeynes@189 | 932 | vertex->detail[5] = data[1].i; /* V1 */
|
nkeynes@189 | 933 | vertex->detail[6] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
|
nkeynes@189 | 934 | vertex->detail[7] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
|
nkeynes@189 | 935 | break;
|
nkeynes@189 | 936 | case TA_VERTEX_TEX_UV16_INTENSITY_MOD:
|
nkeynes@189 | 937 | vertex->detail[2] = data[0].i; /* UV1 */
|
nkeynes@189 | 938 | vertex->detail[3] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
|
nkeynes@189 | 939 | break;
|
nkeynes@189 | 940 | case TA_VERTEX_TEX_UV16_SPEC_INTENSITY_MOD:
|
nkeynes@189 | 941 | vertex->detail[3] = data[0].i; /* UV1 */
|
nkeynes@189 | 942 | vertex->detail[4] = parse_intensity_colour( ta_status.intensity2, data[2].f ); /* ARGB1 */
|
nkeynes@189 | 943 | vertex->detail[5] = parse_intensity_colour( ta_status.intensity2, data[3].f ); /* ARGB1 */
|
nkeynes@189 | 944 | break;
|
nkeynes@189 | 945 |
|
nkeynes@189 | 946 | case TA_VERTEX_SPRITE:
|
nkeynes@189 | 947 | vertex->y = data[0].f;
|
nkeynes@189 | 948 | vertex->z = data[1].f;
|
nkeynes@189 | 949 | vertex++;
|
nkeynes@189 | 950 | ta_status.vertex_count++;
|
nkeynes@189 | 951 | vertex->x = data[2].f;
|
nkeynes@189 | 952 | vertex->y = data[3].f;
|
nkeynes@189 | 953 | vertex->z = 0;
|
nkeynes@189 | 954 | vertex->detail[0] = 0;
|
nkeynes@189 | 955 | ta_status.poly_vertex[0].detail[0] = 0;
|
nkeynes@189 | 956 | ta_status.poly_vertex[1].detail[0] = 0;
|
nkeynes@189 | 957 | break;
|
nkeynes@189 | 958 | case TA_VERTEX_TEX_SPRITE:
|
nkeynes@189 | 959 | vertex->y = data[0].f;
|
nkeynes@189 | 960 | vertex->z = data[1].f;
|
nkeynes@189 | 961 | vertex++;
|
nkeynes@189 | 962 | ta_status.vertex_count++;
|
nkeynes@189 | 963 | vertex->x = data[2].f;
|
nkeynes@189 | 964 | vertex->y = data[3].f;
|
nkeynes@189 | 965 | vertex->z = 0;
|
nkeynes@189 | 966 | vertex->detail[0] = 0;
|
nkeynes@189 | 967 | vertex->detail[1] = 0;
|
nkeynes@189 | 968 | ta_status.poly_vertex[0].detail[0] = data[5].i;
|
nkeynes@189 | 969 | ta_status.poly_vertex[0].detail[1] = 0;
|
nkeynes@189 | 970 | ta_status.poly_vertex[1].detail[0] = data[6].i;
|
nkeynes@189 | 971 | ta_status.poly_vertex[1].detail[1] = 0;
|
nkeynes@189 | 972 | ta_status.poly_vertex[2].detail[0] = data[7].i;
|
nkeynes@189 | 973 | break;
|
nkeynes@189 | 974 | case TA_VERTEX_MOD_VOLUME:
|
nkeynes@189 | 975 | vertex->y = data[0].f;
|
nkeynes@189 | 976 | vertex->z = data[1].f;
|
nkeynes@189 | 977 | break;
|
nkeynes@189 | 978 | }
|
nkeynes@194 | 979 | ta_status.state = STATE_IN_POLYGON;
|
nkeynes@189 | 980 | }
|
nkeynes@189 | 981 |
|
nkeynes@189 | 982 | /**
|
nkeynes@189 | 983 | * Process 1 32-byte block of ta data
|
nkeynes@189 | 984 | */
|
nkeynes@189 | 985 | void pvr2_ta_process_block( char *input ) {
|
nkeynes@189 | 986 | union ta_data *data = (union ta_data *)input;
|
nkeynes@189 | 987 |
|
nkeynes@189 | 988 | switch( ta_status.state ) {
|
nkeynes@189 | 989 | case STATE_ERROR:
|
nkeynes@189 | 990 | /* Error raised - stop processing until reset */
|
nkeynes@189 | 991 | return;
|
nkeynes@189 | 992 |
|
nkeynes@189 | 993 | case STATE_EXPECT_POLY_BLOCK2:
|
nkeynes@189 | 994 | /* This is always a pair of floating-point colours */
|
nkeynes@189 | 995 | ta_status.intensity1 =
|
nkeynes@189 | 996 | parse_float_colour( data[0].f, data[1].f, data[2].f, data[3].f );
|
nkeynes@189 | 997 | ta_status.intensity2 =
|
nkeynes@189 | 998 | parse_float_colour( data[4].f, data[5].f, data[6].f, data[7].f );
|
nkeynes@189 | 999 | ta_status.state = STATE_IN_LIST;
|
nkeynes@189 | 1000 | break;
|
nkeynes@189 | 1001 |
|
nkeynes@189 | 1002 | case STATE_EXPECT_VERTEX_BLOCK2:
|
nkeynes@189 | 1003 | ta_parse_vertex_block2( data );
|
nkeynes@189 | 1004 | if( ta_status.vertex_count == ta_status.max_vertex ) {
|
nkeynes@189 | 1005 | ta_split_polygon();
|
nkeynes@189 | 1006 | }
|
nkeynes@189 | 1007 | break;
|
nkeynes@189 | 1008 |
|
nkeynes@189 | 1009 | case STATE_EXPECT_END_VERTEX_BLOCK2:
|
nkeynes@189 | 1010 | ta_parse_vertex_block2( data );
|
nkeynes@189 | 1011 | ta_commit_polygon();
|
nkeynes@189 | 1012 | ta_status.vertex_count = 0;
|
nkeynes@189 | 1013 | ta_status.poly_parity = 0;
|
nkeynes@194 | 1014 | ta_status.state = STATE_IN_LIST;
|
nkeynes@194 | 1015 | break;
|
nkeynes@189 | 1016 | case STATE_IN_LIST:
|
nkeynes@194 | 1017 | case STATE_IN_POLYGON:
|
nkeynes@189 | 1018 | case STATE_IDLE:
|
nkeynes@189 | 1019 | switch( TA_CMD( data->i ) ) {
|
nkeynes@189 | 1020 | case TA_CMD_END_LIST:
|
nkeynes@189 | 1021 | ta_end_list();
|
nkeynes@189 | 1022 | break;
|
nkeynes@198 | 1023 | case TA_CMD_CLIP:
|
nkeynes@198 | 1024 | if( ta_status.state == STATE_IN_POLYGON ) {
|
nkeynes@198 | 1025 | asic_event( EVENT_PVR_BAD_INPUT );
|
nkeynes@198 | 1026 | asic_event( EVENT_TA_ERROR );
|
nkeynes@198 | 1027 | /* Enter stuffed up mode */
|
nkeynes@198 | 1028 | }
|
nkeynes@198 | 1029 | ta_status.clip.x1 = data[4].i & 0x3F;
|
nkeynes@198 | 1030 | ta_status.clip.y1 = data[5].i & 0x0F;
|
nkeynes@198 | 1031 | ta_status.clip.x2 = data[6].i & 0x3F;
|
nkeynes@198 | 1032 | ta_status.clip.y2 = data[7].i & 0x0F;
|
nkeynes@189 | 1033 | break;
|
nkeynes@189 | 1034 | case TA_CMD_POLYGON_CONTEXT:
|
nkeynes@189 | 1035 | if( ta_status.state == STATE_IDLE ) {
|
nkeynes@189 | 1036 | ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
|
nkeynes@189 | 1037 | }
|
nkeynes@189 | 1038 |
|
nkeynes@189 | 1039 | if( ta_status.vertex_count != 0 ) {
|
nkeynes@193 | 1040 | /* Error, and not a very well handled one either */
|
nkeynes@193 | 1041 | asic_event( EVENT_PVR_BAD_INPUT );
|
nkeynes@193 | 1042 | asic_event( EVENT_TA_ERROR );
|
nkeynes@193 | 1043 | ta_status.accept_vertexes = FALSE;
|
nkeynes@189 | 1044 | ta_fill_vertexes();
|
nkeynes@189 | 1045 | } else {
|
nkeynes@193 | 1046 | if( TA_IS_MODIFIER_LIST( ta_status.current_list_type ) ) {
|
nkeynes@193 | 1047 | ta_parse_modifier_context(data);
|
nkeynes@193 | 1048 | } else {
|
nkeynes@193 | 1049 | ta_parse_polygon_context(data);
|
nkeynes@193 | 1050 | }
|
nkeynes@189 | 1051 | }
|
nkeynes@189 | 1052 | break;
|
nkeynes@189 | 1053 | case TA_CMD_SPRITE_CONTEXT:
|
nkeynes@189 | 1054 | if( ta_status.state == STATE_IDLE ) {
|
nkeynes@189 | 1055 | ta_init_list( TA_POLYCMD_LISTTYPE( data->i ) );
|
nkeynes@189 | 1056 | }
|
nkeynes@189 | 1057 |
|
nkeynes@189 | 1058 | if( ta_status.vertex_count != 0 ) {
|
nkeynes@189 | 1059 | ta_fill_vertexes();
|
nkeynes@189 | 1060 | ta_commit_polygon();
|
nkeynes@189 | 1061 | }
|
nkeynes@189 | 1062 |
|
nkeynes@189 | 1063 | ta_parse_sprite_context(data);
|
nkeynes@189 | 1064 | break;
|
nkeynes@189 | 1065 | case TA_CMD_VERTEX:
|
nkeynes@194 | 1066 | ta_status.state = STATE_IN_POLYGON;
|
nkeynes@189 | 1067 | ta_parse_vertex(data);
|
nkeynes@189 | 1068 |
|
nkeynes@189 | 1069 | if( ta_status.state == STATE_EXPECT_VERTEX_BLOCK2 ) {
|
nkeynes@189 | 1070 | if( TA_IS_END_VERTEX(data[0].i) ) {
|
nkeynes@189 | 1071 | ta_status.state = STATE_EXPECT_END_VERTEX_BLOCK2;
|
nkeynes@189 | 1072 | }
|
nkeynes@189 | 1073 | } else if( TA_IS_END_VERTEX(data->i) ) {
|
nkeynes@189 | 1074 | ta_commit_polygon();
|
nkeynes@189 | 1075 | ta_status.vertex_count = 0;
|
nkeynes@189 | 1076 | ta_status.poly_parity = 0;
|
nkeynes@194 | 1077 | ta_status.state = STATE_IN_LIST;
|
nkeynes@189 | 1078 | } else if( ta_status.vertex_count == ta_status.max_vertex ) {
|
nkeynes@189 | 1079 | ta_split_polygon();
|
nkeynes@189 | 1080 | }
|
nkeynes@189 | 1081 | break;
|
nkeynes@189 | 1082 | }
|
nkeynes@189 | 1083 | break;
|
nkeynes@189 | 1084 | }
|
nkeynes@189 | 1085 |
|
nkeynes@189 | 1086 | }
|
nkeynes@189 | 1087 |
|
nkeynes@189 | 1088 |
|
nkeynes@189 | 1089 |
|
nkeynes@189 | 1090 | /**
|
nkeynes@189 | 1091 | * Write a block of data to the tile accelerator, adding the data to the
|
nkeynes@189 | 1092 | * current scene. We don't make any particular attempt to interpret the data
|
nkeynes@189 | 1093 | * at this stage, deferring that until render time.
|
nkeynes@189 | 1094 | *
|
nkeynes@189 | 1095 | * Currently copies the data verbatim to the vertex buffer, processing only
|
nkeynes@189 | 1096 | * far enough to generate the correct end-of-list events. Tile buffer is
|
nkeynes@189 | 1097 | * entirely ignored.
|
nkeynes@189 | 1098 | */
|
nkeynes@189 | 1099 | void pvr2_ta_write( char *buf, uint32_t length )
|
nkeynes@189 | 1100 | {
|
nkeynes@189 | 1101 | if( ta_status.debug_output ) {
|
nkeynes@189 | 1102 | fwrite_dump32( (uint32_t *)buf, length, stderr );
|
nkeynes@189 | 1103 | }
|
nkeynes@189 | 1104 |
|
nkeynes@189 | 1105 | for( ; length >=32; length -= 32 ) {
|
nkeynes@189 | 1106 | pvr2_ta_process_block( buf );
|
nkeynes@189 | 1107 | buf += 32;
|
nkeynes@189 | 1108 | }
|
nkeynes@189 | 1109 | }
|