Search
lxdream.org :: lxdream :: r1145:45674791c6ad
lxdream 0.9.1
released Jun 29
Download Now
changeset1145:45674791c6ad
parent1144:00dd49743974
child1146:76c5d1064262
authornkeynes
dateMon Nov 08 14:33:38 2010 +1000 (9 years ago)
Introduce tile iterators to simplify processing of the tile lists
src/Makefile.am
src/Makefile.in
src/pvr2/glrender.c
src/pvr2/pvr2.h
src/pvr2/tacore.c
src/pvr2/tileiter.h
1.1 --- a/src/Makefile.am Mon Nov 08 14:12:10 2010 +1000
1.2 +++ b/src/Makefile.am Mon Nov 08 14:33:38 2010 +1000
1.3 @@ -56,10 +56,9 @@
1.4 aica/armcore.c aica/armcore.h aica/armdasm.c aica/armdasm.h aica/armmem.c \
1.5 aica/aica.c aica/aica.h aica/audio.c aica/audio.h \
1.6 pvr2/pvr2.c pvr2/pvr2.h pvr2/pvr2mem.c pvr2/pvr2mmio.h \
1.7 - pvr2/tacore.c pvr2/rendsort.c \
1.8 + pvr2/tacore.c pvr2/rendsort.c pvr2/tileiter.h pvr2/shaders.glsl \
1.9 pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c pvr2/scene.c pvr2/scene.h \
1.10 pvr2/gl_sl.c pvr2/shaders.h pvr2/shaders.def pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c \
1.11 - pvr2/vertex.glsl pvr2/fragment.glsl \
1.12 maple/maple.c maple/maple.h \
1.13 maple/controller.c maple/kbd.c maple/mouse.c maple/lightgun.c maple/vmu.c \
1.14 loader.c loader.h elf.h bootstrap.c bootstrap.h util.c gdlist.c gdlist.h \
2.1 --- a/src/Makefile.in Mon Nov 08 14:12:10 2010 +1000
2.2 +++ b/src/Makefile.in Mon Nov 08 14:33:38 2010 +1000
2.3 @@ -156,10 +156,10 @@
2.4 aica/armcore.h aica/armdasm.c aica/armdasm.h aica/armmem.c \
2.5 aica/aica.c aica/aica.h aica/audio.c aica/audio.h pvr2/pvr2.c \
2.6 pvr2/pvr2.h pvr2/pvr2mem.c pvr2/pvr2mmio.h pvr2/tacore.c \
2.7 - pvr2/rendsort.c pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c \
2.8 - pvr2/scene.c pvr2/scene.h pvr2/gl_sl.c pvr2/shaders.h \
2.9 - pvr2/shaders.def pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c \
2.10 - pvr2/vertex.glsl pvr2/fragment.glsl maple/maple.c \
2.11 + pvr2/rendsort.c pvr2/tileiter.h pvr2/shaders.glsl \
2.12 + pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c pvr2/scene.c \
2.13 + pvr2/scene.h pvr2/gl_sl.c pvr2/shaders.h pvr2/shaders.def \
2.14 + pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c maple/maple.c \
2.15 maple/maple.h maple/controller.c maple/kbd.c maple/mouse.c \
2.16 maple/lightgun.c maple/vmu.c loader.c loader.h elf.h \
2.17 bootstrap.c bootstrap.h util.c gdlist.c gdlist.h vmu/vmuvol.c \
2.18 @@ -576,14 +576,14 @@
2.19 aica/armdasm.h aica/armmem.c aica/aica.c aica/aica.h \
2.20 aica/audio.c aica/audio.h pvr2/pvr2.c pvr2/pvr2.h \
2.21 pvr2/pvr2mem.c pvr2/pvr2mmio.h pvr2/tacore.c pvr2/rendsort.c \
2.22 - pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c pvr2/scene.c \
2.23 - pvr2/scene.h pvr2/gl_sl.c pvr2/shaders.h pvr2/shaders.def \
2.24 - pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c pvr2/vertex.glsl \
2.25 - pvr2/fragment.glsl maple/maple.c maple/maple.h \
2.26 - maple/controller.c maple/kbd.c maple/mouse.c maple/lightgun.c \
2.27 - maple/vmu.c loader.c loader.h elf.h bootstrap.c bootstrap.h \
2.28 - util.c gdlist.c gdlist.h vmu/vmuvol.c vmu/vmuvol.h \
2.29 - vmu/vmulist.c vmu/vmulist.h display.c display.h dckeysyms.h \
2.30 + pvr2/tileiter.h pvr2/shaders.glsl pvr2/texcache.c pvr2/yuv.c \
2.31 + pvr2/rendsave.c pvr2/scene.c pvr2/scene.h pvr2/gl_sl.c \
2.32 + pvr2/shaders.h pvr2/shaders.def pvr2/glutil.c pvr2/glutil.h \
2.33 + pvr2/glrender.c maple/maple.c maple/maple.h maple/controller.c \
2.34 + maple/kbd.c maple/mouse.c maple/lightgun.c maple/vmu.c \
2.35 + loader.c loader.h elf.h bootstrap.c bootstrap.h util.c \
2.36 + gdlist.c gdlist.h vmu/vmuvol.c vmu/vmuvol.h vmu/vmulist.c \
2.37 + vmu/vmulist.h display.c display.h dckeysyms.h \
2.38 drivers/audio_null.c drivers/video_null.c drivers/video_gl.c \
2.39 drivers/video_gl.h drivers/gl_fbo.c drivers/serial_unix.c \
2.40 drivers/cdrom/cdrom.h drivers/cdrom/cdrom.c \
3.1 --- a/src/pvr2/glrender.c Mon Nov 08 14:12:10 2010 +1000
3.2 +++ b/src/pvr2/glrender.c Mon Nov 08 14:33:38 2010 +1000
3.3 @@ -21,8 +21,9 @@
3.4 #include "display.h"
3.5 #include "pvr2/pvr2.h"
3.6 #include "pvr2/pvr2mmio.h"
3.7 +#include "pvr2/glutil.h"
3.8 #include "pvr2/scene.h"
3.9 -#include "pvr2/glutil.h"
3.10 +#include "pvr2/tileiter.h"
3.11
3.12 #define IS_EMPTY_TILE_LIST(p) ((*((uint32_t *)(pvr2_main_ram+(p))) >> 28) == 0x0F)
3.13
3.14 @@ -59,6 +60,16 @@
3.15 return tile[0] < tile[1] && tile[2] < tile[3];
3.16 }
3.17
3.18 +static void drawrect2d( uint32_t tile_bounds[], float z )
3.19 +{
3.20 + glBegin( GL_QUADS );
3.21 + glVertex3f( tile_bounds[0], tile_bounds[2], z );
3.22 + glVertex3f( tile_bounds[1], tile_bounds[2], z );
3.23 + glVertex3f( tile_bounds[1], tile_bounds[3], z );
3.24 + glVertex3f( tile_bounds[0], tile_bounds[3], z );
3.25 + glEnd();
3.26 +}
3.27 +
3.28 void pvr2_scene_load_textures()
3.29 {
3.30 int i;
3.31 @@ -239,107 +250,8 @@
3.32 }
3.33 }
3.34
3.35 -static void gl_render_bkgnd( struct polygon_struct *poly )
3.36 -{
3.37 - glBindTexture(GL_TEXTURE_2D, poly->tex_id);
3.38 - render_set_tsp_context( poly->context[0], poly->context[1] );
3.39 - glDisable( GL_DEPTH_TEST );
3.40 - glBlendFunc( GL_ONE, GL_ZERO );
3.41 - gl_draw_vertexes(poly);
3.42 - glEnable( GL_DEPTH_TEST );
3.43 -}
3.44
3.45 -void gl_render_tilelist( pvraddr_t tile_entry, gboolean set_depth )
3.46 -{
3.47 - uint32_t *tile_list = (uint32_t *)(pvr2_main_ram+tile_entry);
3.48 - int strip_count;
3.49 - struct polygon_struct *poly;
3.50 -
3.51 - if( !IS_TILE_PTR(tile_entry) )
3.52 - return;
3.53 -
3.54 - while(1) {
3.55 - uint32_t entry = *tile_list++;
3.56 - switch( entry >> 28 ) {
3.57 - case 0x0F:
3.58 - return; // End-of-list
3.59 - case 0x0E:
3.60 - tile_list = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
3.61 - break;
3.62 - case 0x08: case 0x09: case 0x0A: case 0x0B:
3.63 - strip_count = ((entry >> 25) & 0x0F)+1;
3.64 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.65 - while( strip_count > 0 ) {
3.66 - assert( poly != NULL );
3.67 - gl_render_poly( poly, set_depth );
3.68 - poly = poly->next;
3.69 - strip_count--;
3.70 - }
3.71 - break;
3.72 - default:
3.73 - if( entry & 0x7E000000 ) {
3.74 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.75 - gl_render_poly( poly, set_depth );
3.76 - }
3.77 - }
3.78 - }
3.79 -}
3.80 -
3.81 -/**
3.82 - * Render the tilelist with depthbuffer updates only.
3.83 - */
3.84 -void gl_render_tilelist_depthonly( pvraddr_t tile_entry )
3.85 -{
3.86 - uint32_t *tile_list = (uint32_t *)(pvr2_main_ram+tile_entry);
3.87 - int strip_count;
3.88 - struct polygon_struct *poly;
3.89 -
3.90 - if( !IS_TILE_PTR(tile_entry) )
3.91 - return;
3.92 -
3.93 - while(1) {
3.94 - uint32_t entry = *tile_list++;
3.95 - switch( entry >> 28 ) {
3.96 - case 0x0F:
3.97 - return; // End-of-list
3.98 - case 0x0E:
3.99 - tile_list = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
3.100 - break;
3.101 - case 0x08: case 0x09: case 0x0A: case 0x0B:
3.102 - strip_count = ((entry >> 25) & 0x0F)+1;
3.103 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.104 - while( strip_count > 0 ) {
3.105 - if( poly->vertex_count != 0 ) {
3.106 - render_set_base_context(poly->context[0],TRUE);
3.107 - gl_draw_vertexes(poly);
3.108 - }
3.109 - poly = poly->next;
3.110 - strip_count--;
3.111 - }
3.112 - break;
3.113 - default:
3.114 - if( entry & 0x7E000000 ) {
3.115 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.116 - if( poly->vertex_count != 0 ) {
3.117 - render_set_base_context(poly->context[0],TRUE);
3.118 - gl_draw_vertexes(poly);
3.119 - }
3.120 - }
3.121 - }
3.122 - }
3.123 -}
3.124 -
3.125 -static void drawrect2d( uint32_t tile_bounds[], float z )
3.126 -{
3.127 - glBegin( GL_QUADS );
3.128 - glVertex3f( tile_bounds[0], tile_bounds[2], z );
3.129 - glVertex3f( tile_bounds[1], tile_bounds[2], z );
3.130 - glVertex3f( tile_bounds[1], tile_bounds[3], z );
3.131 - glVertex3f( tile_bounds[0], tile_bounds[3], z );
3.132 - glEnd();
3.133 -}
3.134 -
3.135 -void gl_render_modifier_polygon( struct polygon_struct *poly, uint32_t tile_bounds[] )
3.136 +static void gl_render_modifier_polygon( struct polygon_struct *poly, uint32_t tile_bounds[] )
3.137 {
3.138 /* A bit of explanation:
3.139 * In theory it works like this: generate a 1-bit stencil for each polygon
3.140 @@ -405,55 +317,79 @@
3.141 }
3.142 }
3.143
3.144 -void gl_render_modifier_tilelist( pvraddr_t tile_entry, uint32_t tile_bounds[] )
3.145 +static void gl_render_bkgnd( struct polygon_struct *poly )
3.146 {
3.147 - uint32_t *tile_list = (uint32_t *)(pvr2_main_ram+tile_entry);
3.148 - int strip_count;
3.149 - struct polygon_struct *poly;
3.150 + glBindTexture(GL_TEXTURE_2D, poly->tex_id);
3.151 + render_set_tsp_context( poly->context[0], poly->context[1] );
3.152 + glDisable( GL_DEPTH_TEST );
3.153 + glBlendFunc( GL_ONE, GL_ZERO );
3.154 + gl_draw_vertexes(poly);
3.155 + glEnable( GL_DEPTH_TEST );
3.156 +}
3.157 +
3.158 +void gl_render_tilelist( pvraddr_t tile_entry, gboolean set_depth )
3.159 +{
3.160 + tileentryiter list;
3.161 +
3.162 + FOREACH_TILEENTRY(list, tile_entry) {
3.163 + struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEENTRYITER_POLYADDR(list)];
3.164 + if( poly != NULL ) {
3.165 + do {
3.166 + gl_render_poly(poly, set_depth);
3.167 + poly = poly->next;
3.168 + } while( list.strip_count-- > 0 );
3.169 + }
3.170 + }
3.171 +}
3.172 +
3.173 +/**
3.174 + * Render the tilelist with depthbuffer updates only.
3.175 + */
3.176 +static void gl_render_tilelist_depthonly( pvraddr_t tile_entry )
3.177 +{
3.178 + tileentryiter list;
3.179 +
3.180 + FOREACH_TILEENTRY(list, tile_entry) {
3.181 + struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEENTRYITER_POLYADDR(list)];
3.182 + if( poly != NULL ) {
3.183 + do {
3.184 + render_set_base_context(poly->context[0],TRUE);
3.185 + gl_draw_vertexes(poly);
3.186 + poly = poly->next;
3.187 + } while( list.strip_count-- > 0 );
3.188 + }
3.189 + }
3.190 +}
3.191 +
3.192 +static void gl_render_modifier_tilelist( pvraddr_t tile_entry, uint32_t tile_bounds[] )
3.193 +{
3.194 + tileentryiter list;
3.195
3.196 if( !IS_TILE_PTR(tile_entry) )
3.197 return;
3.198
3.199 glEnable( GL_STENCIL_TEST );
3.200 glEnable( GL_DEPTH_TEST );
3.201 - glDepthFunc( GL_LEQUAL );
3.202 -
3.203 glStencilFunc( GL_ALWAYS, 0, 1 );
3.204 glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP );
3.205 glStencilMask( 0x01 );
3.206 + glDepthFunc( GL_LEQUAL );
3.207 glDepthMask( GL_FALSE );
3.208
3.209 - while(1) {
3.210 - uint32_t entry = *tile_list++;
3.211 - switch( entry >> 28 ) {
3.212 - case 0x0F:
3.213 - glDepthMask( GL_TRUE );
3.214 - glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
3.215 - glDisable( GL_STENCIL_TEST );
3.216 - return; // End-of-list
3.217 - case 0x0E:
3.218 - tile_list = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
3.219 - break;
3.220 - case 0x08: case 0x09: case 0x0A: case 0x0B:
3.221 - strip_count = ((entry >> 25) & 0x0F)+1;
3.222 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.223 - while( strip_count > 0 ) {
3.224 + FOREACH_TILEENTRY(list, tile_entry ) {
3.225 + struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEENTRYITER_POLYADDR(list)];
3.226 + if( poly != NULL ) {
3.227 + do {
3.228 gl_render_modifier_polygon( poly, tile_bounds );
3.229 poly = poly->next;
3.230 - strip_count--;
3.231 - }
3.232 - break;
3.233 - default:
3.234 - if( entry & 0x7E000000 ) {
3.235 - poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
3.236 - gl_render_modifier_polygon( poly, tile_bounds );
3.237 - }
3.238 + } while( list.strip_count-- > 0 );
3.239 }
3.240 }
3.241 -
3.242 + glDepthMask( GL_TRUE );
3.243 + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
3.244 + glDisable( GL_STENCIL_TEST );
3.245 }
3.246
3.247 -
3.248 /**
3.249 * Render the currently defined scene in pvr2_scene
3.250 */
4.1 --- a/src/pvr2/pvr2.h Mon Nov 08 14:12:10 2010 +1000
4.2 +++ b/src/pvr2/pvr2.h Mon Nov 08 14:33:38 2010 +1000
4.3 @@ -21,7 +21,6 @@
4.4
4.5 #include <stdio.h>
4.6 #include "lxdream.h"
4.7 -#include "mem.h"
4.8 #include "display.h"
4.9
4.10 #ifdef __cplusplus
4.11 @@ -431,6 +430,11 @@
4.12 pvraddr_t punchout_ptr;
4.13 };
4.14
4.15 +
4.16 +struct tile_bounds {
4.17 + int32_t x1, y1, x2, y2;
4.18 +};
4.19 +
4.20 #ifdef __cplusplus
4.21 }
4.22 #endif
5.1 --- a/src/pvr2/tacore.c Mon Nov 08 14:12:10 2010 +1000
5.2 +++ b/src/pvr2/tacore.c Mon Nov 08 14:33:38 2010 +1000
5.3 @@ -126,10 +126,6 @@
5.4 uint32_t detail[8]; /* 0-8 detail words */
5.5 };
5.6
5.7 -struct tile_bounds {
5.8 - int32_t x1, y1, x2, y2;
5.9 -};
5.10 -
5.11 struct pvr2_ta_status {
5.12 int32_t state;
5.13 int32_t width, height; /* Tile resolution, ie 20x15 */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/src/pvr2/tileiter.h Mon Nov 08 14:33:38 2010 +1000
6.3 @@ -0,0 +1,197 @@
6.4 +/**
6.5 + * $Id$
6.6 + *
6.7 + * Tile iterator ADT. Defines an iterator that can be used to iterate through
6.8 + * a PVR2 tile list a polygon at a time.
6.9 + *
6.10 + * Note: The iterator functions are defined here to allow the compiler to
6.11 + * inline them if it wants to, but it's not always beneficial to do so
6.12 + * (hence we don't force them to be inlined)
6.13 + *
6.14 + * Copyright (c) 2010 Nathan Keynes.
6.15 + *
6.16 + * This program is free software; you can redistribute it and/or modify
6.17 + * it under the terms of the GNU General Public License as published by
6.18 + * the Free Software Foundation; either version 2 of the License, or
6.19 + * (at your option) any later version.
6.20 + *
6.21 + * This program is distributed in the hope that it will be useful,
6.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.24 + * GNU General Public License for more details.
6.25 + */
6.26 +
6.27 +#ifndef lxdream_tileiter_H
6.28 +#define lxdream_tileiter_H 1
6.29 +
6.30 +#include <assert.h>
6.31 +#include "pvr2/pvr2.h"
6.32 +
6.33 +#ifdef __cplusplus
6.34 +extern "C" {
6.35 +#endif
6.36 +
6.37 +
6.38 +/**
6.39 + * tileiter: iterator over individual polygons in a tile list.
6.40 + */
6.41 +typedef struct tileiter {
6.42 + uint32_t *ptr;
6.43 + unsigned strip_count;
6.44 + unsigned poly_size;
6.45 + uint32_t poly_addr;
6.46 +} tileiter;
6.47 +
6.48 +
6.49 +#define TILEITER_IS_MODIFIED(it) ((*(it).ptr) & 0x01000000)
6.50 +#define TILEITER_IS_TRIANGLE(it) (((*(it).ptr) >> 29) == 4)
6.51 +#define TILEITER_IS_QUAD(it) (((*(it).ptr) >> 29) == 5)
6.52 +#define TILEITER_IS_POLY(it) (((*(it).ptr) >> 31) == 0)
6.53 +
6.54 +#define TILEITER_POLYADDR(it) ((it).poly_addr)
6.55 +#define TILEITER_STRIPCOUNT(it) ((it).strip_count)
6.56 +#define TILEITER_DONE(it) ((it).ptr == 0)
6.57 +#define TILEITER_BEGIN(it, tileent) (tileiter_init(&it, tileent))
6.58 +#define TILEITER_NEXT(it) (tileiter_next(&it))
6.59 +#define FOREACH_TILE(it, seg) for( TILEITER_BEGIN(it, seg); !TILEITER_DONE(it); TILEITER_NEXT(it) )
6.60 +
6.61 +
6.62 +/**
6.63 + * tileentryiter: iterator over entries in the tile list, where each entry is
6.64 + * a polygon, triangle set, or quad set.
6.65 + */
6.66 +typedef struct tileentryiter {
6.67 + uint32_t *ptr;
6.68 + unsigned strip_count;
6.69 +} tileentryiter;
6.70 +
6.71 +#define TILEENTRYITER_POLYADDR(it) ((*((it).ptr)) & 0x001FFFFF)
6.72 +#define TILEENTRYITER_STRIPCOUNT(it) ((it).strip_count)
6.73 +#define TILEENTRYITER_DONE(it) ((it).ptr == 0)
6.74 +#define TILEENTRYITER_BEGIN(it, tileent) (tileentryiter_init(&(it),tileent))
6.75 +#define TILEENTRYITER_NEXT(it) (tileentryiter_next(&(it)))
6.76 +#define FOREACH_TILEENTRY(it,seg) for( TILEENTRYITER_BEGIN(it,seg); !TILEENTRYITER_DONE(it); TILEENTRYITER_NEXT(it) )
6.77 +
6.78 +/**************************** tileiter functions ****************************/
6.79 +
6.80 +/**
6.81 + * Read the entry pointed to by it->ptr into the tileiter structure. If the
6.82 + * entry if a list pointer or invalid entry, the pointer will first be
6.83 + * updated to the next real entry. On end-of-list, sets ptr to NULL
6.84 + */
6.85 +static void tileiter_read( tileiter *it )
6.86 +{
6.87 + for(;;){
6.88 + uint32_t entry = *it->ptr;
6.89 + uint32_t tag = entry >> 29;
6.90 + if( tag == 0x07 ) {
6.91 + if( tag & 0x10000000 ) {
6.92 + it->ptr = NULL;
6.93 + return;
6.94 + } else {
6.95 + it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
6.96 + it->poly_addr = -1;
6.97 + entry = *it->ptr;
6.98 + }
6.99 + } else if( tag == 6 ) {
6.100 + /* Illegal? Skip */
6.101 + it->ptr++;
6.102 + } else if( tag & 0x04 ) {
6.103 + int vertex_count = tag-1; /* 4 == tri, 5 == quad */
6.104 + int vertex_length = (entry >> 21) & 0x07;
6.105 + if( (entry & 0x01000000) && (pvr2_scene.shadow_mode == SHADOW_FULL) ) {
6.106 + it->poly_size = 5 + (vertex_length<<1) * vertex_count;
6.107 + } else {
6.108 + it->poly_size = 3 + vertex_length * vertex_count;
6.109 + }
6.110 + it->strip_count = ((entry >> 25) & 0x0F);
6.111 + it->poly_addr = entry & 0x001FFFFF;
6.112 + return;
6.113 + } else {
6.114 + /* Other polygon */
6.115 + it->strip_count = 0;
6.116 + it->poly_addr = entry & 0x001FFFFF;
6.117 + return;
6.118 + }
6.119 + }
6.120 +}
6.121 +
6.122 +static void tileiter_init( tileiter *it, uint32_t segptr )
6.123 +{
6.124 + if( IS_TILE_PTR(segptr) ) {
6.125 + it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
6.126 + tileiter_read(it);
6.127 + } else {
6.128 + it->ptr = 0;
6.129 + }
6.130 +}
6.131 +
6.132 +static inline void tileiter_next( tileiter *it )
6.133 +{
6.134 + assert( it->ptr != NULL );
6.135 + if( it->strip_count > 0 ) {
6.136 + it->strip_count--;
6.137 + it->poly_addr += it->poly_size;
6.138 + } else {
6.139 + it->ptr++;
6.140 + tileiter_read(it);
6.141 + }
6.142 +}
6.143 +
6.144 +
6.145 +/************************* tileentryiter functions **************************/
6.146 +
6.147 +/**
6.148 + * Read the entry pointed to by it->ptr, updating the pointer to point
6.149 + * to the next real element if the current value is not a polygon entry.
6.150 + */
6.151 +static void tileentryiter_read( tileentryiter *it )
6.152 +{
6.153 + for(;;){
6.154 + uint32_t entry = *it->ptr;
6.155 + uint32_t tag = entry >> 28;
6.156 + if( tag < 0x0C ) {
6.157 + if( tag & 0x08 ) {
6.158 + it->strip_count = ((entry >> 25) & 0x0F);
6.159 + } else {
6.160 + it->strip_count = 0;
6.161 + }
6.162 + return;
6.163 + } else {
6.164 + if( tag == 0x0F ) {
6.165 + it->ptr = NULL;
6.166 + return;
6.167 + } else if( tag == 0x0E ) {
6.168 + it->ptr = (uint32_t *)(pvr2_main_ram + (entry&0x007FFFFF));
6.169 + entry = *it->ptr;
6.170 + } else {
6.171 + /* Illegal? Skip */
6.172 + it->ptr++;
6.173 + }
6.174 + }
6.175 + }
6.176 +}
6.177 +
6.178 +
6.179 +static void tileentryiter_init( tileentryiter *it, uint32_t segptr )
6.180 +{
6.181 + if( IS_TILE_PTR(segptr) ) {
6.182 + it->ptr = (uint32_t *)(pvr2_main_ram + (segptr & 0x007FFFFF));
6.183 + tileentryiter_read(it);
6.184 + } else {
6.185 + it->ptr = 0;
6.186 + }
6.187 +}
6.188 +
6.189 +static void inline tileentryiter_next( tileentryiter *it )
6.190 +{
6.191 + it->ptr++;
6.192 + tileentryiter_read(it);
6.193 +}
6.194 +
6.195 +
6.196 +#ifdef __cplusplus
6.197 +}
6.198 +#endif
6.199 +
6.200 +#endif /* !lxdream_tileiter_H */
.