Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
285 lines
6.9 KiB
C++
285 lines
6.9 KiB
C++
/*{{{ all about pxpl5 card*/
|
|
/*
|
|
|
|
The texture manager associated with the pxpl5 card is all in here.
|
|
This is not based on the TEXHSP card texture format, since pxpl5 is
|
|
much easier to deal with.
|
|
|
|
Textures are addressed as 64x64x1 word units, and 64x64 is the only
|
|
alignment demanded by the card. A free list of 64x64 chunks is maintained,
|
|
SORTED, in memory. To acquire a 128x128 we just look for a free 64x64, then
|
|
check the next 3 items in the list. If all 4 are consecutive, we remove
|
|
all 4 from the list and hand them back to the application.
|
|
|
|
*/
|
|
|
|
/*}}} */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "dpltypes.h"
|
|
#include "culltypes.h"
|
|
#include "vpxtypes.h"
|
|
|
|
/*
|
|
#define dbgtex 1
|
|
*/
|
|
|
|
#define total_texture_space (512*512)
|
|
|
|
|
|
/*{{{ structs, statics*/
|
|
|
|
static texcell *freeCell, *list_head;
|
|
static int texturesInited=0;
|
|
/*}}} */
|
|
|
|
/*{{{ static texcell *newCell( int size, int id )*/
|
|
static texcell *newCell( int size, int id )
|
|
{
|
|
texcell *p;
|
|
|
|
p=(texcell *) malloc (sizeof(texcell));
|
|
|
|
if (p!=NULL) {
|
|
p->edge=size;
|
|
p->id=id;
|
|
p->hwareOffs=id; /* same number now */
|
|
p->next=NULL;
|
|
}
|
|
return p;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static int cell_hwareSize ( int edge )*/
|
|
static int cell_hwareSize ( int edge )
|
|
{
|
|
/* **************************************************
|
|
0 = 64x64
|
|
1 = 128x128
|
|
2 = 256x256
|
|
*************************************************** */
|
|
|
|
if (edge == 64) return 0;
|
|
if (edge == 128) return 1;
|
|
if (edge == 256) return 2;
|
|
|
|
return 1;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void texInit ()*/
|
|
void texInit ()
|
|
{
|
|
int i;
|
|
texcell *a, *b, *c, *d;
|
|
|
|
if (texturesInited) return;
|
|
|
|
texturesInited=1;
|
|
freeCell=NULL;
|
|
|
|
/* pre-malloc texcells */
|
|
|
|
for (i=0; i<(total_texture_space>>12); i++ ) {
|
|
a=newCell (64, 0);
|
|
a->next=freeCell;
|
|
freeCell=a;
|
|
}
|
|
|
|
list_head=a;
|
|
|
|
for (i=0, a=freeCell; a; i++, a=a->next ) {
|
|
a->id=i;
|
|
a->hwareOffs=i;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ texcell *allocateHSPtexture( int u_size, int v_size )*/
|
|
texcell *allocateHSPtexture( int u_size, int v_size )
|
|
{
|
|
texcell *cell;
|
|
int i, cells, u, v;
|
|
|
|
#if dbgtex
|
|
printf ("allocateHSPtex, u_size=%d v_size=%d\n", u_size, v_size );
|
|
#endif
|
|
|
|
if (u_size != v_size)
|
|
return NULL;
|
|
else if ((u_size != 256) && (u_size != 128) && (u_size != 64))
|
|
return NULL;
|
|
else {
|
|
texcell *p=list_head, *prev=NULL;
|
|
|
|
if (u_size==256) cells=16;
|
|
else if (u_size==128) cells=4;
|
|
else if (u_size== 64) cells=1;
|
|
|
|
if (cells == 1) {
|
|
/*{{{ pull just 1 off head of list*/
|
|
if (p) {
|
|
texcell *cell=p;
|
|
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture requires just 1 cell\n" );
|
|
#endif
|
|
/*}}} */
|
|
|
|
cell->hwareSize=cell_hwareSize(u_size);
|
|
|
|
list_head=cell->next;
|
|
cell->next=NULL;
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture returned id 0x%x hwareID 0x%x hwareSize %d\n",
|
|
cell->id, cell->hwareOffs, cell->hwareSize );
|
|
#endif
|
|
/*}}} */
|
|
return cell;
|
|
}
|
|
else {
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture, list empty\n" );
|
|
#endif
|
|
/*}}} */
|
|
return NULL;
|
|
}
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture needs %d consecutive cells\n", cells );
|
|
#endif
|
|
/*}}} */
|
|
while (p) {
|
|
texcell *cell=p->next, *firstcell=p;
|
|
int looking = 1,
|
|
found_cells=1,
|
|
found_id=p->id+1;
|
|
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture search head now 0x%x\n", p );
|
|
#endif
|
|
/*}}} */
|
|
|
|
while (looking) {
|
|
/*{{{ check for consecutive numbers*/
|
|
if (cell == NULL) {
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture ran off end of list\n" );
|
|
#endif
|
|
/*}}} */
|
|
return NULL;
|
|
}
|
|
if (cell->id == found_id) {
|
|
/*{{{ doing fine, keep looking*/
|
|
found_cells++;
|
|
found_id++;
|
|
/*{{{ */
|
|
#if dbgtex
|
|
printf ("allocateTexture found consecutive id, now found %d\n", found_cells );
|
|
#endif
|
|
/*}}} */
|
|
if (found_cells == cells) {
|
|
/*{{{ done it, patch list + return*/
|
|
texcell *nextcell=cell->next;
|
|
cell->next=NULL;
|
|
cell=firstcell;
|
|
|
|
/* found it, remove cells from p upwards, chain prev */
|
|
|
|
if (prev==NULL)
|
|
list_head=nextcell;
|
|
else
|
|
prev->next=nextcell;
|
|
|
|
cell->hwareSize=cell_hwareSize(u_size);
|
|
|
|
#if dbgtex
|
|
while (cell) {
|
|
printf ("allocateTexture returned id 0x%x hwareID 0x%x hwareSize %d\n",
|
|
cell->id, cell->hwareOffs, cell->hwareSize );
|
|
cell=cell->next;
|
|
}
|
|
#endif
|
|
|
|
return firstcell;
|
|
/*}}} */
|
|
}
|
|
cell=cell->next;
|
|
/*}}} */
|
|
}
|
|
else {
|
|
printf ( "no contiguous, restarting search\n" );
|
|
looking=0;
|
|
}
|
|
/*}}} */
|
|
}
|
|
prev=p;
|
|
p=p->next;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static int paletfix ( int r )*/
|
|
static int paletfix ( int r )
|
|
{
|
|
if (r < 0) r=0;
|
|
if (r > 255) r=255;
|
|
|
|
return r>>4;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int codeWordFromRamp ( cull_RAMP *ramp, int entry )*/
|
|
void codeWordFromRamp ( cull_RAMP *ramp, int entry )
|
|
{
|
|
int ir0, ir1, ig0,
|
|
ig1, ib0, ib1;
|
|
float texscale=255.9f;
|
|
|
|
if ((entry < 0) || (entry >= 4)) return;
|
|
|
|
ir0=paletfix ((int) (ramp->color0[0]*texscale));
|
|
ig0=paletfix ((int) (ramp->color0[1]*texscale));
|
|
ib0=paletfix ((int) (ramp->color0[2]*texscale));
|
|
|
|
ir1=paletfix ((int) (ramp->color1[0]*texscale));
|
|
ig1=paletfix ((int) (ramp->color1[1]*texscale));
|
|
ib1=paletfix ((int) (ramp->color1[2]*texscale));
|
|
|
|
ramp->codeWord=entry | ((ir0 |(ir1<<4)|
|
|
(ig0<<8) |(ig1<<12)|
|
|
(ib0<<16)|(ib1<<20)) << 3);
|
|
}
|
|
/*}}} */
|
|
/*{{{ void setRampEntry ( cull_RAMP *ramp, int entry,*/
|
|
void setRampEntry ( cull_RAMP *ramp, int entry,
|
|
float r0, float g0, float b0,
|
|
float r1, float g1, float b1 )
|
|
{
|
|
if ((entry < 0) || (entry >= 4)) return;
|
|
|
|
ramp->color0[0]=r0;
|
|
ramp->color0[1]=g0;
|
|
ramp->color0[2]=b0;
|
|
|
|
ramp->color1[0]=r1;
|
|
ramp->color1[1]=g1;
|
|
ramp->color1[2]=b1;
|
|
|
|
codeWordFromRamp ( ramp, entry );
|
|
|
|
/*
|
|
printf ("setRampEntry %f %f %f %f %f %f ramp %d\n",
|
|
r0,g0,b0,
|
|
r1,g1,b1, entry );
|
|
*/
|
|
}
|
|
/*}}} */
|