Search
lxdream.org :: lxdream/src/pvr2/tacore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/tacore.c
changeset 200:c3bdcd373b6d
prev199:4433d9c1638c
next203:c86a40546fc0
author nkeynes
date Sun Aug 06 04:01:37 2006 +0000 (16 years ago)
permissions -rw-r--r--
last change Fix parse_float_colour for values <= 0 and qNaN
file annotate diff log raw
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
}
.