nkeynes@1145 | 1 | /**
|
nkeynes@1145 | 2 | * $Id$
|
nkeynes@1145 | 3 | *
|
nkeynes@1145 | 4 | * Tile iterator ADT. Defines an iterator that can be used to iterate through
|
nkeynes@1145 | 5 | * a PVR2 tile list a polygon at a time.
|
nkeynes@1145 | 6 | *
|
nkeynes@1145 | 7 | * Note: The iterator functions are defined here to allow the compiler to
|
nkeynes@1145 | 8 | * inline them if it wants to, but it's not always beneficial to do so
|
nkeynes@1145 | 9 | * (hence we don't force them to be inlined)
|
nkeynes@1145 | 10 | *
|
nkeynes@1145 | 11 | * Copyright (c) 2010 Nathan Keynes.
|
nkeynes@1145 | 12 | *
|
nkeynes@1145 | 13 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@1145 | 14 | * it under the terms of the GNU General Public License as published by
|
nkeynes@1145 | 15 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@1145 | 16 | * (at your option) any later version.
|
nkeynes@1145 | 17 | *
|
nkeynes@1145 | 18 | * This program is distributed in the hope that it will be useful,
|
nkeynes@1145 | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@1145 | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@1145 | 21 | * GNU General Public License for more details.
|
nkeynes@1145 | 22 | */
|
nkeynes@1145 | 23 |
|
nkeynes@1145 | 24 | #ifndef lxdream_tileiter_H
|
nkeynes@1145 | 25 | #define lxdream_tileiter_H 1
|
nkeynes@1145 | 26 |
|
nkeynes@1145 | 27 | #include <assert.h>
|
nkeynes@1145 | 28 | #include "pvr2/pvr2.h"
|
nkeynes@1145 | 29 |
|
nkeynes@1145 | 30 | #ifdef __cplusplus
|
nkeynes@1145 | 31 | extern "C" {
|
nkeynes@1145 | 32 | #endif
|
nkeynes@1145 | 33 |
|
nkeynes@1145 | 34 |
|
nkeynes@1145 | 35 | /**
|
nkeynes@1145 | 36 | * tileiter: iterator over individual polygons in a tile list.
|
nkeynes@1145 | 37 | */
|
nkeynes@1145 | 38 | typedef struct tileiter {
|
nkeynes@1145 | 39 | uint32_t *ptr;
|
nkeynes@1145 | 40 | unsigned strip_count;
|
nkeynes@1145 | 41 | unsigned poly_size;
|
nkeynes@1145 | 42 | uint32_t poly_addr;
|
nkeynes@1145 | 43 | } tileiter;
|
nkeynes@1145 | 44 |
|
nkeynes@1145 | 45 |
|
nkeynes@1145 | 46 | #define TILEITER_IS_MODIFIED(it) ((*(it).ptr) & 0x01000000)
|
nkeynes@1145 | 47 | #define TILEITER_IS_TRIANGLE(it) (((*(it).ptr) >> 29) == 4)
|
nkeynes@1145 | 48 | #define TILEITER_IS_QUAD(it) (((*(it).ptr) >> 29) == 5)
|
nkeynes@1145 | 49 | #define TILEITER_IS_POLY(it) (((*(it).ptr) >> 31) == 0)
|
nkeynes@1145 | 50 |
|
nkeynes@1145 | 51 | #define TILEITER_POLYADDR(it) ((it).poly_addr)
|
nkeynes@1145 | 52 | #define TILEITER_STRIPCOUNT(it) ((it).strip_count)
|
nkeynes@1145 | 53 | #define TILEITER_DONE(it) ((it).ptr == 0)
|
nkeynes@1145 | 54 | #define TILEITER_BEGIN(it, tileent) (tileiter_init(&it, tileent))
|
nkeynes@1145 | 55 | #define TILEITER_NEXT(it) (tileiter_next(&it))
|
nkeynes@1145 | 56 | #define FOREACH_TILE(it, seg) for( TILEITER_BEGIN(it, seg); !TILEITER_DONE(it); TILEITER_NEXT(it) )
|
nkeynes@1145 | 57 |
|
nkeynes@1145 | 58 |
|
nkeynes@1145 | 59 | /**
|
nkeynes@1145 | 60 | * tileentryiter: iterator over entries in the tile list, where each entry is
|
nkeynes@1145 | 61 | * a polygon, triangle set, or quad set.
|
nkeynes@1145 | 62 | */
|
nkeynes@1145 | 63 | typedef struct tileentryiter {
|
nkeynes@1145 | 64 | uint32_t *ptr;
|
nkeynes@1145 | 65 | unsigned strip_count;
|
nkeynes@1145 | 66 | } tileentryiter;
|
nkeynes@1145 | 67 |
|
nkeynes@1145 | 68 | #define TILEENTRYITER_POLYADDR(it) ((*((it).ptr)) & 0x001FFFFF)
|
nkeynes@1145 | 69 | #define TILEENTRYITER_STRIPCOUNT(it) ((it).strip_count)
|
nkeynes@1145 | 70 | #define TILEENTRYITER_DONE(it) ((it).ptr == 0)
|
nkeynes@1145 | 71 | #define TILEENTRYITER_BEGIN(it, tileent) (tileentryiter_init(&(it),tileent))
|
nkeynes@1145 | 72 | #define TILEENTRYITER_NEXT(it) (tileentryiter_next(&(it)))
|
nkeynes@1145 | 73 | #define FOREACH_TILEENTRY(it,seg) for( TILEENTRYITER_BEGIN(it,seg); !TILEENTRYITER_DONE(it); TILEENTRYITER_NEXT(it) )
|
nkeynes@1145 | 74 |
|
nkeynes@1145 | 75 | /**************************** tileiter functions ****************************/
|
nkeynes@1145 | 76 |
|
nkeynes@1145 | 77 | /**
|
nkeynes@1145 | 78 | * Read the entry pointed to by it->ptr into the tileiter structure. If the
|
nkeynes@1145 | 79 | * entry if a list pointer or invalid entry, the pointer will first be
|
nkeynes@1145 | 80 | * updated to the next real entry. On end-of-list, sets ptr to NULL
|
nkeynes@1145 | 81 | */
|
nkeynes@1145 | 82 | static void tileiter_read( tileiter *it )
|
nkeynes@1145 | 83 | {
|
nkeynes@1145 | 84 | for(;;){
|
nkeynes@1145 | 85 | uint32_t entry = *it->ptr;
|
nkeynes@1145 | 86 | uint32_t tag = entry >> 29;
|
nkeynes@1153 | 87 | if( tag == 0x07 ) {
|
nkeynes@1153 | 88 | if( tag & 0x10000000 ) {
|
nkeynes@1153 | 89 | it->ptr = NULL;
|
nkeynes@1145 | 90 | return;
|
nkeynes@1145 | 91 | } else {
|
nkeynes@1153 | 92 | it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
|
nkeynes@1153 | 93 | it->poly_addr = -1;
|
nkeynes@1153 | 94 | entry = *it->ptr;
|
nkeynes@1145 | 95 | }
|
nkeynes@1153 | 96 | } else if( tag == 6 ) {
|
nkeynes@1153 | 97 | /* Illegal? Skip */
|
nkeynes@1153 | 98 | it->ptr++;
|
nkeynes@1153 | 99 | } else if( tag & 0x04 ) {
|
nkeynes@1153 | 100 | int vertex_count = tag-1; /* 4 == tri, 5 == quad */
|
nkeynes@1153 | 101 | int vertex_length = (entry >> 21) & 0x07;
|
nkeynes@1153 | 102 | if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) {
|
nkeynes@1153 | 103 | it->poly_size = 5 + (vertex_length<<1) * vertex_count;
|
nkeynes@1153 | 104 | } else {
|
nkeynes@1153 | 105 | it->poly_size = 3 + vertex_length * vertex_count;
|
nkeynes@1153 | 106 | }
|
nkeynes@1153 | 107 | it->strip_count = ((entry >> 25) & 0x0F);
|
nkeynes@1153 | 108 | it->poly_addr = entry & 0x001FFFFF;
|
nkeynes@1153 | 109 | return;
|
nkeynes@1151 | 110 | } else {
|
nkeynes@1153 | 111 | /* Other polygon */
|
nkeynes@1153 | 112 | it->strip_count = 0;
|
nkeynes@1153 | 113 | it->poly_addr = entry & 0x001FFFFF;
|
nkeynes@1153 | 114 | return;
|
nkeynes@1145 | 115 | }
|
nkeynes@1145 | 116 | }
|
nkeynes@1145 | 117 | }
|
nkeynes@1145 | 118 |
|
nkeynes@1145 | 119 | static void tileiter_init( tileiter *it, uint32_t segptr )
|
nkeynes@1145 | 120 | {
|
nkeynes@1145 | 121 | if( IS_TILE_PTR(segptr) ) {
|
nkeynes@1145 | 122 | it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
|
nkeynes@1145 | 123 | tileiter_read(it);
|
nkeynes@1145 | 124 | } else {
|
nkeynes@1145 | 125 | it->ptr = 0;
|
nkeynes@1145 | 126 | }
|
nkeynes@1145 | 127 | }
|
nkeynes@1145 | 128 |
|
nkeynes@1145 | 129 | static inline void tileiter_next( tileiter *it )
|
nkeynes@1145 | 130 | {
|
nkeynes@1145 | 131 | assert( it->ptr != NULL );
|
nkeynes@1145 | 132 | if( it->strip_count > 0 ) {
|
nkeynes@1145 | 133 | it->strip_count--;
|
nkeynes@1145 | 134 | it->poly_addr += it->poly_size;
|
nkeynes@1145 | 135 | } else {
|
nkeynes@1145 | 136 | it->ptr++;
|
nkeynes@1145 | 137 | tileiter_read(it);
|
nkeynes@1145 | 138 | }
|
nkeynes@1145 | 139 | }
|
nkeynes@1145 | 140 |
|
nkeynes@1145 | 141 |
|
nkeynes@1145 | 142 | /************************* tileentryiter functions **************************/
|
nkeynes@1145 | 143 |
|
nkeynes@1145 | 144 | /**
|
nkeynes@1145 | 145 | * Read the entry pointed to by it->ptr, updating the pointer to point
|
nkeynes@1145 | 146 | * to the next real element if the current value is not a polygon entry.
|
nkeynes@1145 | 147 | */
|
nkeynes@1145 | 148 | static void tileentryiter_read( tileentryiter *it )
|
nkeynes@1145 | 149 | {
|
nkeynes@1145 | 150 | for(;;){
|
nkeynes@1145 | 151 | uint32_t entry = *it->ptr;
|
nkeynes@1145 | 152 | uint32_t tag = entry >> 28;
|
nkeynes@1145 | 153 | if( tag < 0x0C ) {
|
nkeynes@1145 | 154 | if( tag & 0x08 ) {
|
nkeynes@1145 | 155 | it->strip_count = ((entry >> 25) & 0x0F);
|
nkeynes@1145 | 156 | } else {
|
nkeynes@1145 | 157 | it->strip_count = 0;
|
nkeynes@1145 | 158 | }
|
nkeynes@1145 | 159 | return;
|
nkeynes@1145 | 160 | } else {
|
nkeynes@1145 | 161 | if( tag == 0x0F ) {
|
nkeynes@1145 | 162 | it->ptr = NULL;
|
nkeynes@1145 | 163 | return;
|
nkeynes@1145 | 164 | } else if( tag == 0x0E ) {
|
nkeynes@1145 | 165 | it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
|
nkeynes@1145 | 166 | entry = *it->ptr;
|
nkeynes@1145 | 167 | } else {
|
nkeynes@1145 | 168 | /* Illegal? Skip */
|
nkeynes@1145 | 169 | it->ptr++;
|
nkeynes@1145 | 170 | }
|
nkeynes@1145 | 171 | }
|
nkeynes@1145 | 172 | }
|
nkeynes@1145 | 173 | }
|
nkeynes@1145 | 174 |
|
nkeynes@1145 | 175 |
|
nkeynes@1145 | 176 | static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
|
nkeynes@1145 | 177 | {
|
nkeynes@1145 | 178 | if( IS_TILE_PTR(segptr) ) {
|
nkeynes@1145 | 179 | it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
|
nkeynes@1145 | 180 | tileentryiter_read(it);
|
nkeynes@1145 | 181 | } else {
|
nkeynes@1145 | 182 | it->ptr = 0;
|
nkeynes@1145 | 183 | }
|
nkeynes@1145 | 184 | }
|
nkeynes@1145 | 185 |
|
nkeynes@1145 | 186 | static void inline tileentryiter_next( tileentryiter *it )
|
nkeynes@1145 | 187 | {
|
nkeynes@1145 | 188 | it->ptr++;
|
nkeynes@1145 | 189 | tileentryiter_read(it);
|
nkeynes@1145 | 190 | }
|
nkeynes@1145 | 191 |
|
nkeynes@1145 | 192 |
|
nkeynes@1145 | 193 | #ifdef __cplusplus
|
nkeynes@1145 | 194 | }
|
nkeynes@1145 | 195 | #endif
|
nkeynes@1145 | 196 |
|
nkeynes@1145 | 197 | #endif /* !lxdream_tileiter_H */
|