mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-24 00:02:43 +02:00
1180 lines
28 KiB
C
1180 lines
28 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/dyntex.h"
|
|
#include "game/tex.h"
|
|
#include "game/texdecompress.h"
|
|
#include "bss.h"
|
|
#include "data.h"
|
|
#include "gbiex.h"
|
|
#include "textures.h"
|
|
#include "types.h"
|
|
#include "platform.h"
|
|
|
|
#define TXMODE_WRAP 0
|
|
#define TXMODE_CLAMP 1
|
|
#define TXMODE_MIRROR 2
|
|
|
|
struct tilestate {
|
|
bool inuse;
|
|
s32 format;
|
|
s32 depth;
|
|
s32 line;
|
|
s32 tmem;
|
|
s32 smode;
|
|
s32 tmode;
|
|
s32 masks;
|
|
s32 maskt;
|
|
s32 shifts;
|
|
s32 shiftt;
|
|
};
|
|
|
|
struct tilesize {
|
|
bool inuse;
|
|
s32 uls;
|
|
s32 ult;
|
|
s32 lrs;
|
|
s32 lrt;
|
|
};
|
|
|
|
s32 g_TexLutMode;
|
|
u32 var800ab5b4;
|
|
struct tilestate g_TexTileStates[8];
|
|
struct tilesize g_TexTileSizes[8];
|
|
#ifndef PLATFORM_N64
|
|
u32 g_TexFilter2D = G_TF_BILERP;
|
|
#endif
|
|
|
|
// Default
|
|
u16 g_SurfaceTypeDefaultSounds[] = { SFX_HIT_STONE_8087, SFX_HIT_STONE_8088 };
|
|
u8 g_SurfaceTypeDefaultTexes[] = { WALLHITTEX_BULLET2 };
|
|
|
|
struct surfacetype g_SurfaceTypeDefault = {
|
|
g_SurfaceTypeDefaultSounds, g_SurfaceTypeDefaultTexes, 2, 1,
|
|
};
|
|
|
|
// Stone
|
|
u16 g_SurfaceTypeStoneSounds[] = { SFX_HIT_STONE_8087, SFX_HIT_STONE_8088 };
|
|
u8 g_SurfaceTypeStoneTexes[] = { WALLHITTEX_BULLET1 };
|
|
|
|
struct surfacetype g_SurfaceTypeStone = {
|
|
g_SurfaceTypeStoneSounds, g_SurfaceTypeStoneTexes, 2, 1,
|
|
};
|
|
|
|
// Wood
|
|
u16 g_SurfaceTypeWoodSounds[] = { SFX_HIT_WOOD_807E, SFX_HIT_WOOD_807F };
|
|
u8 g_SurfaceTypeWoodTexes[] = { WALLHITTEX_WOOD };
|
|
|
|
struct surfacetype g_SurfaceTypeWood = {
|
|
g_SurfaceTypeWoodSounds, g_SurfaceTypeWoodTexes, 2, 1,
|
|
};
|
|
|
|
// Metal
|
|
u16 g_SurfaceTypeMetalSounds[] = { SFX_HIT_METAL_8079, SFX_HIT_METAL_807B };
|
|
u8 g_SurfaceTypeMetalTexes[] = { WALLHITTEX_METAL };
|
|
|
|
struct surfacetype g_SurfaceTypeMetal = {
|
|
g_SurfaceTypeMetalSounds, g_SurfaceTypeMetalTexes, 2, 1,
|
|
};
|
|
|
|
// Glass
|
|
u16 g_SurfaceTypeGlassSounds[] = { SFX_HIT_GLASS };
|
|
u8 g_SurfaceTypeGlassTexes[] = { WALLHITTEX_GLASS1, WALLHITTEX_GLASS2, WALLHITTEX_GLASS3 };
|
|
|
|
struct surfacetype g_SurfaceTypeGlass = {
|
|
g_SurfaceTypeGlassSounds, g_SurfaceTypeGlassTexes, 1, 3,
|
|
};
|
|
|
|
// Snow
|
|
u16 g_SurfaceTypeSnowSounds[] = { SFX_HIT_SNOW };
|
|
u8 g_SurfaceTypeSnowTexes[] = { WALLHITTEX_BULLET1 };
|
|
|
|
struct surfacetype g_SurfaceTypeSnow = {
|
|
g_SurfaceTypeSnowSounds, g_SurfaceTypeSnowTexes, 1, 1,
|
|
};
|
|
|
|
// Dirt
|
|
u16 g_SurfaceTypeDirtSounds[] = { SFX_HIT_DIRT_8084, SFX_HIT_DIRT_8085 };
|
|
u8 g_SurfaceTypeDirtTexes[] = { WALLHITTEX_SOFT };
|
|
|
|
struct surfacetype g_SurfaceTypeDirt = {
|
|
g_SurfaceTypeDirtSounds, g_SurfaceTypeDirtTexes, 2, 1,
|
|
};
|
|
|
|
// Mud
|
|
u16 g_SurfaceTypeMudSounds[] = { SFX_HIT_MUD_8081, SFX_HIT_MUD_8082, SFX_HIT_MUD_8083 };
|
|
u8 g_SurfaceTypeMudTexes[] = { WALLHITTEX_SOFT };
|
|
|
|
struct surfacetype g_SurfaceTypeMud = {
|
|
g_SurfaceTypeMudSounds, g_SurfaceTypeMudTexes, 3, 1,
|
|
};
|
|
|
|
// Tile
|
|
u16 g_SurfaceTypeTileSounds[] = { SFX_HIT_TILE };
|
|
u8 g_SurfaceTypeTileTexes[] = { WALLHITTEX_BULLET1 };
|
|
|
|
struct surfacetype g_SurfaceTypeTile = {
|
|
g_SurfaceTypeTileSounds, g_SurfaceTypeTileTexes, 1, 1,
|
|
};
|
|
|
|
// Metal obj
|
|
u16 g_SurfaceTypeMetalObjSounds[] = { SFX_HIT_METALOBJ_8089, SFX_HIT_METALOBJ_808A };
|
|
u8 g_SurfaceTypeMetalObjTexes[] = { WALLHITTEX_BULLET1, WALLHITTEX_BULLET2 };
|
|
|
|
struct surfacetype g_SurfaceTypeMetalObj = {
|
|
g_SurfaceTypeMetalObjSounds, g_SurfaceTypeMetalObjTexes, 2, 2,
|
|
};
|
|
|
|
// Chr
|
|
u16 g_SurfaceTypeChrSounds[] = { SFX_HIT_CHR };
|
|
u8 g_SurfaceTypeChrTexes[] = { WALLHITTEX_SOFT };
|
|
|
|
struct surfacetype g_SurfaceTypeChr = {
|
|
g_SurfaceTypeChrSounds, g_SurfaceTypeChrTexes, 1, 1,
|
|
};
|
|
|
|
// Glass XLU
|
|
u16 g_SurfaceTypeGlassXluSounds[] = { SFX_HIT_GLASS };
|
|
u8 g_SurfaceTypeGlassXluTexes[] = { WALLHITTEX_GLASS1, WALLHITTEX_GLASS2, WALLHITTEX_GLASS3 };
|
|
|
|
struct surfacetype g_SurfaceTypeGlassXlu = {
|
|
g_SurfaceTypeGlassXluSounds, g_SurfaceTypeGlassXluTexes, 1, 3,
|
|
};
|
|
|
|
// None
|
|
struct surfacetype g_SurfaceTypeNone = {
|
|
NULL, NULL, 0, 0,
|
|
};
|
|
|
|
// Shallow water
|
|
u16 g_SurfaceTypeShallowWaterSounds[] = { SFX_HIT_WATER };
|
|
u8 g_SurfaceTypeShallowWaterTexes[] = { WALLHITTEX_WATER };
|
|
|
|
struct surfacetype g_SurfaceTypeShallowWater = {
|
|
g_SurfaceTypeShallowWaterSounds, g_SurfaceTypeShallowWaterTexes, 1, 1,
|
|
};
|
|
|
|
// Deep water
|
|
u16 g_SurfaceTypeDeepWaterSounds[] = { SFX_HIT_WATER };
|
|
u8 g_SurfaceTypeDeepWaterTexes[] = { WALLHITTEX_WATER };
|
|
|
|
struct surfacetype g_SurfaceTypeDeepWater = {
|
|
g_SurfaceTypeDeepWaterSounds, g_SurfaceTypeDeepWaterTexes, 1, 1,
|
|
};
|
|
|
|
struct surfacetype *g_SurfaceTypes[] = {
|
|
/* 0*/ &g_SurfaceTypeDefault,
|
|
/* 1*/ &g_SurfaceTypeStone,
|
|
/* 2*/ &g_SurfaceTypeWood,
|
|
/* 3*/ &g_SurfaceTypeMetal,
|
|
/* 4*/ &g_SurfaceTypeGlass,
|
|
/* 5*/ &g_SurfaceTypeShallowWater,
|
|
/* 6*/ &g_SurfaceTypeSnow,
|
|
/* 7*/ &g_SurfaceTypeDirt,
|
|
/* 8*/ &g_SurfaceTypeMud,
|
|
/* 9*/ &g_SurfaceTypeTile,
|
|
/*10*/ &g_SurfaceTypeMetalObj,
|
|
/*11*/ &g_SurfaceTypeChr,
|
|
/*12*/ &g_SurfaceTypeGlassXlu,
|
|
/*13*/ &g_SurfaceTypeNone,
|
|
/*14*/ &g_SurfaceTypeDeepWater,
|
|
};
|
|
|
|
char *var80084494[] = {
|
|
"default",
|
|
"stone",
|
|
"wood",
|
|
"metal",
|
|
"glass",
|
|
"shallow water",
|
|
"snow",
|
|
"dirt",
|
|
"mud",
|
|
"tile",
|
|
"metalobj",
|
|
"chr",
|
|
"glass xlu",
|
|
"no hit",
|
|
"deep water",
|
|
};
|
|
|
|
const char var7f1b7c24[] = "";
|
|
const char var7f1b7c28[] = "";
|
|
const char var7f1b7c2c[] = "";
|
|
|
|
bool g_TexPipeSynced = false;
|
|
u32 var800844d4 = 0x00000000;
|
|
u32 var800844d8 = 0x00000000;
|
|
u32 var800844dc = 0x00000000;
|
|
u32 var800844e0 = 0x00000103;
|
|
u32 var800844e4 = 0x00000000;
|
|
u32 var800844e8 = 0x00000000;
|
|
u32 var800844ec = 0x00000000;
|
|
|
|
void tex0f173a00(void)
|
|
{
|
|
// empty
|
|
}
|
|
|
|
void texResetTiles(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAYCOUNT(g_TexTileStates); i++) {
|
|
g_TexTileStates[i].inuse = false;
|
|
g_TexTileSizes[i].inuse = false;
|
|
}
|
|
|
|
g_TexLutMode = -1;
|
|
}
|
|
|
|
bool texTrySetLutMode(u32 lutmode)
|
|
{
|
|
if (g_TexLutMode == lutmode) {
|
|
return false;
|
|
}
|
|
|
|
g_TexLutMode = lutmode;
|
|
return true;
|
|
}
|
|
|
|
bool texTrySetTileState(s32 tile, s32 format, s32 depth, s32 line, s32 tmem, s32 smode, s32 tmode, s32 masks, s32 maskt, s32 shifts, s32 shiftt)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (g_TexTileStates[tile].inuse == false
|
|
|| format != g_TexTileStates[tile].format
|
|
|| depth != g_TexTileStates[tile].depth
|
|
|| line != g_TexTileStates[tile].line
|
|
|| tmem != g_TexTileStates[tile].tmem
|
|
|| smode != g_TexTileStates[tile].smode
|
|
|| tmode != g_TexTileStates[tile].tmode
|
|
|| masks != g_TexTileStates[tile].masks
|
|
|| maskt != g_TexTileStates[tile].maskt
|
|
|| shifts != g_TexTileStates[tile].shifts
|
|
|| shiftt != g_TexTileStates[tile].shiftt) {
|
|
changed = true;
|
|
g_TexTileStates[tile].inuse = true;
|
|
g_TexTileStates[tile].format = format;
|
|
g_TexTileStates[tile].depth = depth;
|
|
g_TexTileStates[tile].line = line;
|
|
g_TexTileStates[tile].tmem = tmem;
|
|
g_TexTileStates[tile].smode = smode;
|
|
g_TexTileStates[tile].tmode = tmode;
|
|
g_TexTileStates[tile].masks = masks;
|
|
g_TexTileStates[tile].maskt = maskt;
|
|
g_TexTileStates[tile].shifts = shifts;
|
|
g_TexTileStates[tile].shiftt = shiftt;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool texTrySetTileSize(s32 tile, s32 uls, s32 ult, s32 lrs, s32 lrt)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (g_TexTileSizes[tile].inuse == false
|
|
|| uls != g_TexTileSizes[tile].uls
|
|
|| ult != g_TexTileSizes[tile].ult
|
|
|| lrs != g_TexTileSizes[tile].lrs
|
|
|| lrt != g_TexTileSizes[tile].lrt) {
|
|
changed = true;
|
|
g_TexTileSizes[tile].inuse = true;
|
|
g_TexTileSizes[tile].uls = uls;
|
|
g_TexTileSizes[tile].ult = ult;
|
|
g_TexTileSizes[tile].lrs = lrs;
|
|
g_TexTileSizes[tile].lrt = lrt;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
s32 texGetWidthAtLod(struct tex *tex, s32 lod)
|
|
{
|
|
s32 i;
|
|
s32 width = tex->width;
|
|
|
|
if (lod == 0) {
|
|
return width;
|
|
}
|
|
|
|
if (tex->hasloddata) {
|
|
for (i = 0; i < g_TexCacheCount; i++) {
|
|
if (tex->texturenum == g_TexCacheItems[i].texturenum) {
|
|
return g_TexCacheItems[i].widths[lod - 1];
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
for (i = 0; i < lod; i++) {
|
|
width = (width + 1) >> 1;
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
s32 texGetHeightAtLod(struct tex *tex, s32 lod)
|
|
{
|
|
s32 i;
|
|
s32 height = tex->height;
|
|
|
|
if (lod == 0) {
|
|
return height;
|
|
}
|
|
|
|
if (tex->hasloddata) {
|
|
for (i = 0; i < g_TexCacheCount; i++) {
|
|
if (tex->texturenum == g_TexCacheItems[i].texturenum) {
|
|
return g_TexCacheItems[i].heights[lod - 1];
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
for (i = 0; i < lod; i++) {
|
|
height = (height + 1) >> 1;
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
s32 texGetLineSizeInBytes(struct tex *tex, s32 lod)
|
|
{
|
|
s32 depth = tex->depth;
|
|
s32 width = texGetWidthAtLod(tex, lod);
|
|
|
|
if (depth == G_IM_SIZ_32b) {
|
|
return (width + 3) / 4;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_16b) {
|
|
return (width + 3) / 4;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_8b) {
|
|
return (width + 7) / 8;
|
|
}
|
|
|
|
return (width + 15) / 16;
|
|
}
|
|
|
|
s32 texGetSizeInBytes(struct tex *tex, s32 lod)
|
|
{
|
|
return texGetHeightAtLod(tex, lod) * texGetLineSizeInBytes(tex, lod);
|
|
}
|
|
|
|
void texGetDepthAndSize(struct tex *tex, s32 *deptharg, s32 *lenarg)
|
|
{
|
|
s32 depth = tex->depth;
|
|
s32 numlods = tex->numlods ? tex->numlods : 1;
|
|
s32 lod;
|
|
|
|
*lenarg = 0;
|
|
|
|
if (depth == G_IM_SIZ_32b) {
|
|
*deptharg = G_IM_SIZ_32b;
|
|
} else if (depth == G_IM_SIZ_16b) {
|
|
*deptharg = G_IM_SIZ_16b;
|
|
} else if (depth == G_IM_SIZ_8b) {
|
|
*deptharg = G_IM_SIZ_16b;
|
|
} else {
|
|
*deptharg = G_IM_SIZ_16b;
|
|
}
|
|
|
|
for (lod = 0; lod < numlods; lod++) {
|
|
*lenarg += texGetSizeInBytes(tex, lod) * 4;
|
|
}
|
|
}
|
|
|
|
s32 texDimensionToMask(s32 dimension)
|
|
{
|
|
s32 i = 0;
|
|
|
|
dimension--;
|
|
|
|
while (dimension > 0 && i < 8) {
|
|
dimension >>= 1;
|
|
i++;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
s32 texModeToGbiMode(s32 txmode)
|
|
{
|
|
if (txmode == TXMODE_CLAMP) {
|
|
return G_TX_CLAMP;
|
|
}
|
|
|
|
if (txmode == TXMODE_MIRROR) {
|
|
return G_TX_MIRROR;
|
|
}
|
|
|
|
return G_TX_WRAP;
|
|
}
|
|
|
|
Gfx *texWriteTileFromDefinition(Gfx *gdl, struct tex *tex, s32 offset, s32 shifts, s32 shiftt, s32 min)
|
|
{
|
|
struct texture *s0 = &g_Textures[tex->texturenum];
|
|
s32 masks;
|
|
s32 maskt;
|
|
s32 line;
|
|
u32 stack[4];
|
|
s32 uls;
|
|
s32 ult;
|
|
s32 lrs;
|
|
s32 lrt;
|
|
|
|
masks = texDimensionToMask(tex->width);
|
|
maskt = texDimensionToMask(tex->height);
|
|
|
|
line = texGetLineSizeInBytes(tex, 0);
|
|
|
|
gDPSetPrimColorViaWord(gdl++, min, 0, 0xffffffff);
|
|
|
|
if (texTrySetLutMode(tex->lutmodeindex << G_MDSFT_TEXTLUT)) {
|
|
gDPSetTextureLUT(gdl++, tex->lutmodeindex << G_MDSFT_TEXTLUT);
|
|
}
|
|
|
|
if (texTrySetTileState(0, tex->gbiformat, tex->depth, line, s0->unk04_00 + line * s0->unk04_04, 0, 0, masks - s0->unk04_08, maskt - s0->unk04_0c, shifts, shiftt)) {
|
|
gDPSetTile(gdl++, tex->gbiformat, tex->depth, line, s0->unk04_00 + line * s0->unk04_04, 0, 0,
|
|
texModeToGbiMode(TXMODE_WRAP), maskt - s0->unk04_0c, shiftt,
|
|
texModeToGbiMode(TXMODE_WRAP), masks - s0->unk04_08, shifts);
|
|
}
|
|
|
|
uls = (offset == 2 && !tex->hasloddata ? 2 : 0) + 0;
|
|
ult = (offset == 2 && !tex->hasloddata ? 2 : 0) + 0;
|
|
lrs = (offset == 2 && !tex->hasloddata ? 2 : 0) + ((tex->width - 1) << 2);
|
|
lrt = (offset == 2 && !tex->hasloddata ? 2 : 0) + ((tex->height - 1) << 2);
|
|
|
|
if (texTrySetTileSize(0, uls, ult, lrs, lrt)) {
|
|
gDPSetTileSize(gdl++, 0, uls, ult, lrs, lrt);
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
/**
|
|
* Write a gSPTexture command with the lowest detail LOD number.
|
|
*
|
|
* If texcmd is provided then it will be used as a reference, otherwise a new
|
|
* command is written with some assumed arguments.
|
|
*
|
|
* If append is true then the command will be appended to the given gdl,
|
|
* otherwise the existing texcmd will be patched in place.
|
|
*/
|
|
Gfx *texWriteTextureCmd(Gfx *gdl, Gfx *texcmd, struct tex *tex, bool append)
|
|
{
|
|
s32 lod = tex->numlods ? tex->numlods - 1 : 0;
|
|
|
|
if (append) {
|
|
if (texcmd != NULL) {
|
|
// Copy the gSPTexture command, but with the new lod
|
|
u32 w0 = (texcmd->words.w0 & ~0x3800) | (lod << 11);
|
|
|
|
if (w0 != texcmd->words.w0) {
|
|
gdl->words.w0 = w0;
|
|
gdl->words.w1 = texcmd->words.w1;
|
|
gdl++;
|
|
}
|
|
} else {
|
|
gSPTexture(gdl++, 0xffff, 0xffff, lod, G_TX_RENDERTILE, G_ON);
|
|
}
|
|
} else {
|
|
texcmd->words.w0 &= ~0x3800;
|
|
texcmd->words.w0 |= lod << 11;
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texWriteLoadToTmemAddr(Gfx *gdl, struct tex *tex, s32 tmemoffset)
|
|
{
|
|
s32 depth;
|
|
s32 len;
|
|
|
|
texGetDepthAndSize(tex, &depth, &len);
|
|
|
|
if (tex->lutmodeindex == 0) {
|
|
gDPSetTextureImage(gdl++, tex->gbiformat, depth, 1, tex->data);
|
|
|
|
if (!g_TexPipeSynced) {
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_16b && tmemoffset == 0) {
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, G_TX_LOADTILE, 0, 0, len - 1, 0);
|
|
} else {
|
|
if (texTrySetTileState(5, 0, depth, 0, tmemoffset, 0, 0, 0, 0, 0, 0)) {
|
|
gDPSetTile(gdl++, G_IM_FMT_RGBA, depth, 0, tmemoffset, 5, 0,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
|
}
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, 5, 0, 0, len - 1, 0);
|
|
}
|
|
} else {
|
|
gDPSetTextureImage(gdl++, tex->gbiformat, depth, 1, tex->data);
|
|
|
|
if (!g_TexPipeSynced) {
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_16b && tmemoffset == 0) {
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, G_TX_LOADTILE, 0, 0, len - 1, 0);
|
|
} else {
|
|
if (texTrySetTileState(5, 0, depth, 0, tmemoffset, 0, 0, 0, 0, 0, 0)) {
|
|
gDPSetTile(gdl++, G_IM_FMT_RGBA, depth, 0, tmemoffset, 5, 0,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
|
}
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, 5, 0, 0, len - 1, 0);
|
|
}
|
|
|
|
{
|
|
s32 tmp = len;
|
|
s32 a2 = (u32)(0x3ff - tex->unk0a) < len ? (u32)(0x3ff - tex->unk0a) : 0;
|
|
|
|
tmp -= a2;
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadTLUT06(gdl++, tmp, a2, tex->unk0a + tmp, a2);
|
|
}
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texWriteTileLods(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset, s32 starttile, s32 numlodsarg, u32 tmemoffsetarg)
|
|
{
|
|
u32 tmemoffset;
|
|
s32 numlods;
|
|
s32 tile;
|
|
|
|
tmemoffset = tmemoffsetarg;
|
|
numlods = tex->numlods;
|
|
|
|
if (numlodsarg >= 0 && numlodsarg < numlods) {
|
|
numlods = numlodsarg;
|
|
}
|
|
|
|
for (tile = starttile; tile < numlods + starttile && tile < 6; tile++) {
|
|
s32 stack[2];
|
|
s32 lod = tile - starttile;
|
|
s32 masks = texDimensionToMask(texGetWidthAtLod(tex, lod));
|
|
s32 maskt = texDimensionToMask(texGetHeightAtLod(tex, lod));
|
|
s32 line = texGetLineSizeInBytes(tex, lod);
|
|
s32 uls;
|
|
s32 ult;
|
|
s32 lrs;
|
|
s32 lrt;
|
|
s32 bytes = texGetSizeInBytes(tex, lod);
|
|
bool hasloddata = tex->hasloddata;
|
|
|
|
if (texTrySetLutMode(tex->lutmodeindex << G_MDSFT_TEXTLUT)) {
|
|
gDPSetTextureLUT(gdl++, tex->lutmodeindex << G_MDSFT_TEXTLUT);
|
|
}
|
|
|
|
if (texTrySetTileState(tile, tex->gbiformat, tex->depth, line, tmemoffset, smode, tmode, masks, maskt, lod, lod)) {
|
|
gDPSetTile(gdl++, tex->gbiformat, tex->depth, line, tmemoffset, tile, 0,
|
|
texModeToGbiMode(tmode), maskt, lod,
|
|
texModeToGbiMode(smode), masks, tile - starttile);
|
|
}
|
|
|
|
uls = (offset == 2 && hasloddata == false ? 2 : 0) + 0;
|
|
ult = (offset == 2 && hasloddata == false ? 2 : 0) + 0;
|
|
lrs = ((texGetWidthAtLod(tex, lod) - 1) << 2) + (offset == 2 && hasloddata == false ? 2 : 0);
|
|
lrt = ((texGetHeightAtLod(tex, lod) - 1) << 2) + (offset == 2 && hasloddata == false ? 2 : 0);
|
|
|
|
if (texTrySetTileSize(tile, uls, ult, lrs, lrt)) {
|
|
gDPSetTileSize(gdl++, tile, uls, ult, lrs, lrt);
|
|
}
|
|
|
|
tmemoffset += bytes;
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texWriteLoadToTmemZero(Gfx *gdl, struct tex *tex)
|
|
{
|
|
s32 depth;
|
|
s32 len;
|
|
|
|
texGetDepthAndSize(tex, &depth, &len);
|
|
|
|
if (tex->lutmodeindex == 0) {
|
|
gDPSetTextureImage(gdl++, tex->gbiformat, depth, 1, tex->data);
|
|
|
|
if (!g_TexPipeSynced) {
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_16b) {
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, G_TX_LOADTILE, 0, 0, len - 1, 0);
|
|
} else {
|
|
if (texTrySetTileState(5, 0, depth, 0, 0, 0, 0, 0, 0, 0, 0)) {
|
|
gDPSetTile(gdl++, G_IM_FMT_RGBA, depth, 0, 0x0000, 5, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
|
}
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, 5, 0, 0, len - 1, 0);
|
|
}
|
|
} else {
|
|
gDPSetTextureImage(gdl++, tex->gbiformat, depth, 1, tex->data);
|
|
|
|
if (!g_TexPipeSynced) {
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
}
|
|
|
|
if (depth == G_IM_SIZ_16b) {
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, G_TX_LOADTILE, 0, 0, len - 1, 0);
|
|
} else {
|
|
if (texTrySetTileState(5, 0, depth, 0, 0, 0, 0, 0, 0, 0, 0)) {
|
|
gDPSetTile(gdl++, G_IM_FMT_RGBA, depth, 0, 0x0000, 5, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
|
}
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadBlock(gdl++, 5, 0, 0, len - 1, 0);
|
|
}
|
|
|
|
{
|
|
s32 tmp = len;
|
|
s32 a2 = (u32)(0x3ff - tex->unk0a) < len ? (u32)(0x3ff - tex->unk0a) : 0;
|
|
|
|
tmp -= a2;
|
|
|
|
gDPLoadSync(gdl++);
|
|
gDPLoadTLUT06(gdl++, tmp, a2, tex->unk0a + tmp, a2);
|
|
}
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texWriteTile(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset, s32 tile)
|
|
{
|
|
s32 masks;
|
|
s32 maskt;
|
|
s32 line;
|
|
s32 uls;
|
|
s32 ult;
|
|
s32 lrs;
|
|
s32 lrt;
|
|
bool hasloddata;
|
|
|
|
masks = texDimensionToMask(tex->width);
|
|
maskt = texDimensionToMask(tex->height);
|
|
line = texGetLineSizeInBytes(tex, 0);
|
|
hasloddata = tex->hasloddata;
|
|
|
|
if (texTrySetLutMode(tex->lutmodeindex << G_MDSFT_TEXTLUT)) {
|
|
gDPSetTextureLUT(gdl++, tex->lutmodeindex << G_MDSFT_TEXTLUT);
|
|
}
|
|
|
|
if (texTrySetTileState(tile, tex->gbiformat, tex->depth, line, 0, smode, tmode, masks, maskt, 0, 0)) {
|
|
gDPSetTile(gdl++, tex->gbiformat, tex->depth, line, 0x0000, tile, 0,
|
|
texModeToGbiMode(tmode), maskt, G_TX_NOLOD,
|
|
texModeToGbiMode(smode), masks, G_TX_NOLOD);
|
|
}
|
|
|
|
uls = (offset == 2 && hasloddata == false ? 2 : 0) + 0;
|
|
ult = (offset == 2 && hasloddata == false ? 2 : 0) + 0;
|
|
lrs = (offset == 2 && hasloddata == false ? 2 : 0) + ((tex->width - 1) << 2);
|
|
lrt = (offset == 2 && hasloddata == false ? 2 : 0) + ((tex->height - 1) << 2);
|
|
|
|
if (texTrySetTileSize(tile, uls, ult, lrs, lrt)) {
|
|
gDPSetTileSize(gdl++, tile, uls, ult, lrs, lrt);
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texHandleType2(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset, bool flag)
|
|
{
|
|
s32 tile = 0;
|
|
|
|
gdl = texWriteLoadToTmemAddr(gdl, tex, 0);
|
|
|
|
if (flag) {
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, 1, 0);
|
|
tile++;
|
|
}
|
|
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, -1, 0);
|
|
tile += tex->numlods;
|
|
|
|
if (!flag && tex->numlods == 1) {
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, -1, 0);
|
|
tile += tex->numlods;
|
|
}
|
|
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texHandleType1(Gfx *gdl, struct tex *tex1, s32 smode, s32 tmode, s32 offset, struct tex *tex2, s32 shifts, s32 shiftt, s32 min, bool flag)
|
|
{
|
|
s32 size = texGetSizeInBytes(tex2, 0);
|
|
s32 tile = 0;
|
|
|
|
gdl = texWriteLoadToTmemZero(gdl, tex2);
|
|
gDPTileSync(gdl++);
|
|
gdl = texWriteLoadToTmemAddr(gdl, tex1, size);
|
|
|
|
gdl = texWriteTileFromDefinition(gdl, tex2, offset, shifts, shiftt, min);
|
|
tile++;
|
|
|
|
if (flag) {
|
|
gdl = texWriteTileLods(gdl, tex1, smode, tmode, offset, tile, 1, size);
|
|
tile++;
|
|
}
|
|
|
|
gdl = texWriteTileLods(gdl, tex1, smode, tmode, offset, tile, -1, size);
|
|
tile += tex1->numlods;
|
|
|
|
if (!flag && tex1->numlods == 1) {
|
|
gdl = texWriteTileLods(gdl, tex1, smode, tmode, offset, tile, -1, size);
|
|
tile += tex1->numlods;
|
|
}
|
|
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texHandleType0(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset, s32 shifts, s32 shiftt, s32 min, bool flag)
|
|
{
|
|
s32 tile = 0;
|
|
|
|
gdl = texWriteLoadToTmemAddr(gdl, tex, 0);
|
|
|
|
gdl = texWriteTileFromDefinition(gdl, tex, offset, shifts, shiftt, min);
|
|
tile++;
|
|
|
|
if (flag) {
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, 1, 0);
|
|
tile++;
|
|
}
|
|
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, -1, 0);
|
|
tile += tex->numlods;
|
|
|
|
if (!flag && tex->numlods == 1) {
|
|
gdl = texWriteTileLods(gdl, tex, smode, tmode, offset, tile, -1, 0);
|
|
tile += tex->numlods;
|
|
}
|
|
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texHandleType4(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset)
|
|
{
|
|
gdl = texWriteLoadToTmemZero(gdl, tex);
|
|
gdl = texWriteTile(gdl, tex, smode, tmode, offset, 0);
|
|
|
|
gDPPipeSync(gdl++);
|
|
g_TexPipeSynced = true;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *texHandleType3(Gfx *gdl, struct tex *tex, s32 smode, s32 tmode, s32 offset)
|
|
{
|
|
gdl = texWriteLoadToTmemZero(gdl, tex);
|
|
gdl = texWriteTile(gdl, tex, smode, tmode, offset, 0);
|
|
gdl = texWriteTile(gdl, tex, smode, tmode, offset, 1);
|
|
|
|
gDPPipeSync(gdl++);
|
|
|
|
g_TexPipeSynced = true;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
/**
|
|
* Read the instart displaylist and write the same displaylist to outstart,
|
|
* but substitute the special C0 commands with ones that the RSP will understand,
|
|
* and load textures from the ROM as they are found in the displaylist.
|
|
*
|
|
* The C0 command only exists in asset files. It has no implementation in the RSP.
|
|
* The command packs together several texture-related commands. It's likely done
|
|
* for ease of development, as it allows asset designers to spam its use everywhere
|
|
* in the displaylist rather than have to keep track of the RSP state.
|
|
* The code that expands the C0 commands keeps track of RSP state and avoids
|
|
* emitting duplicate or redundant commands.
|
|
*/
|
|
s32 texLoadFromGdl(Gfx *instart, s32 gdlsizeinbytes, Gfx *outstart, struct texpool *pool, u8 *vtxstart)
|
|
{
|
|
struct tex *tex1;
|
|
struct tex *tex2;
|
|
Gfx *texcmd;
|
|
s32 numcmdsremaining;
|
|
s32 smode;
|
|
s32 tmode;
|
|
s32 offset;
|
|
s32 shifts;
|
|
s32 shiftt;
|
|
s32 min;
|
|
bool flag;
|
|
s32 j;
|
|
bool appendtex;
|
|
u8 animated;
|
|
Gfx *ingdl;
|
|
Gfx *outgdl;
|
|
u32 spf4;
|
|
s32 texturenum;
|
|
s32 texturenum2;
|
|
bool spe8;
|
|
s32 spe4;
|
|
s32 spe0;
|
|
Vtx *spa0[16];
|
|
u8 sp90[16];
|
|
s32 i;
|
|
|
|
texcmd = NULL;
|
|
appendtex = true;
|
|
animated = false;
|
|
spe8 = false;
|
|
spe4 = false;
|
|
g_TexPipeSynced = false;
|
|
spf4 = 0;
|
|
ingdl = instart;
|
|
outgdl = outstart;
|
|
|
|
#ifdef PLATFORM_64BIT
|
|
numcmdsremaining = gdlsizeinbytes >> 4;
|
|
#else
|
|
numcmdsremaining = gdlsizeinbytes >> 3;
|
|
#endif
|
|
|
|
texResetTiles();
|
|
|
|
spe0 = dyntexHasRoom();
|
|
|
|
if (spe0) {
|
|
for (j = 0; j < ARRAYCOUNT(sp90); j++) {
|
|
sp90[j] = 0;
|
|
}
|
|
}
|
|
|
|
if (pool == NULL) {
|
|
pool = &g_TexSharedPool;
|
|
}
|
|
|
|
while (numcmdsremaining > 0) {
|
|
switch (ingdl->texture.cmd) {
|
|
case G_NOOP: // 0xc0, repurposed
|
|
spe4 = true;
|
|
|
|
if (animated) {
|
|
spe8 = true;
|
|
}
|
|
|
|
texturenum = ingdl->words.w1 & 0xfff;
|
|
flag = ingdl->words.w0 & 0x200;
|
|
|
|
texLoadFromTextureNum(texturenum, pool);
|
|
|
|
tex1 = texFindInPool(texturenum, pool);
|
|
|
|
if (tex1 != NULL) {
|
|
spf4 = tex1->unk0c_03;
|
|
} else {
|
|
spf4 = 0;
|
|
}
|
|
|
|
if (tex1 != NULL) {
|
|
outgdl = texWriteTextureCmd(outgdl, texcmd, tex1, appendtex);
|
|
appendtex = false;
|
|
animated = false;
|
|
|
|
switch (ingdl->unkc0.subcmd) {
|
|
case 0:
|
|
min = (ingdl->words.w1 >> 24) & 0xff;
|
|
smode = (ingdl->words.w0 >> 22) & 3;
|
|
tmode = (ingdl->words.w0 >> 20) & 3;
|
|
offset = (ingdl->words.w0 >> 18) & 3;
|
|
shifts = (ingdl->words.w0 >> 14) & 0xf;
|
|
shiftt = (ingdl->words.w0 >> 10) & 0xf;
|
|
|
|
outgdl = texHandleType0(outgdl, tex1, smode, tmode, offset, shifts, shiftt, min, flag);
|
|
break;
|
|
case 1:
|
|
texturenum2 = (ingdl->words.w1 >> 12) & 0xfff;
|
|
texLoadFromTextureNum(texturenum2, pool);
|
|
tex2 = texFindInPool(texturenum2, pool);
|
|
|
|
if (tex2 != NULL) {
|
|
min = (ingdl->words.w1 >> 24) & 0xff;
|
|
smode = (ingdl->words.w0 >> 22) & 3;
|
|
tmode = (ingdl->words.w0 >> 20) & 3;
|
|
offset = (ingdl->words.w0 >> 18) & 3;
|
|
shifts = (ingdl->words.w0 >> 14) & 0xf;
|
|
shiftt = (ingdl->words.w0 >> 10) & 0xf;
|
|
|
|
outgdl = texHandleType1(outgdl, tex1, smode, tmode, offset, tex2, shifts, shiftt, min, flag);
|
|
}
|
|
break;
|
|
case 2:
|
|
smode = (ingdl->words.w0 >> 22) & 3;
|
|
tmode = (ingdl->words.w0 >> 20) & 3;
|
|
offset = (ingdl->words.w0 >> 18) & 3;
|
|
|
|
outgdl = texHandleType2(outgdl, tex1, smode, tmode, offset, flag);
|
|
break;
|
|
case 3:
|
|
smode = (ingdl->words.w0 >> 22) & 3;
|
|
tmode = (ingdl->words.w0 >> 20) & 3;
|
|
offset = (ingdl->words.w0 >> 18) & 3;
|
|
|
|
outgdl = texHandleType3(outgdl, tex1, smode, tmode, offset);
|
|
break;
|
|
case 4:
|
|
smode = (ingdl->words.w0 >> 22) & 3;
|
|
tmode = (ingdl->words.w0 >> 20) & 3;
|
|
offset = (ingdl->words.w0 >> 18) & 3;
|
|
|
|
outgdl = texHandleType4(outgdl, tex1, smode, tmode, offset);
|
|
break;
|
|
}
|
|
|
|
if (spe0 != 0) {
|
|
// Deep Sea - green river under floor
|
|
if (texturenum == TEXTURE_06CB) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_RIVER);
|
|
animated = true;
|
|
}
|
|
|
|
// Deep Sea - juice that flows inside SA megaweapon
|
|
// Attack Ship - juice that flows inside engine power node
|
|
if (texturenum == TEXTURE_0A6A) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_POWERJUICE);
|
|
animated = true;
|
|
}
|
|
|
|
// Deep Sea - white rings around SA megaweapon node
|
|
// Attack Ship - white rings around engine power node
|
|
if (texturenum == TEXTURE_0A69) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_POWERRING);
|
|
animated = true;
|
|
}
|
|
|
|
// Deep Sea - teleport
|
|
if (texturenum == TEXTURE_06E2) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_TELEPORTAL);
|
|
animated = true;
|
|
}
|
|
|
|
// 01c7 - Air Base - distant water
|
|
// 01c7 - Investigation - puddle behind glass near shield
|
|
// 0dae - Chicago - canal
|
|
// 0dae - Villa - shallow water
|
|
// 0dae - Sewers (MP)
|
|
if (texturenum == TEXTURE_01C7 || texturenum == TEXTURE_0DAE) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_RIVER);
|
|
animated = true;
|
|
}
|
|
|
|
// Air Force One - Monitor
|
|
if (texturenum == TEXTURE_029B) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_MONITOR);
|
|
animated = true;
|
|
}
|
|
|
|
// Villa - deep water
|
|
// Complex - water
|
|
if (texturenum == TEXTURE_090F) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_OCEAN);
|
|
animated = true;
|
|
}
|
|
|
|
// Attack Ship - triangular arrows
|
|
if (texturenum == TEXTURE_0A42) {
|
|
dyntexSetCurrentType(DYNTEXTYPE_ARROWS);
|
|
animated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
ingdl++;
|
|
break;
|
|
case G_VTX:
|
|
{
|
|
s32 start;
|
|
s32 count;
|
|
u32 offset;
|
|
Vtx *vtx;
|
|
|
|
if (spe0) {
|
|
start = ingdl->bytes[GFX_W0_BYTE(1)] & 0xf;
|
|
count = ingdl->vtx.unk08 + 1;
|
|
vtx = (Vtx *)(UNSEGADDR(ingdl->dma.addr) & 0x00ffffff);
|
|
|
|
for (i = start; i < start + count; i++) {
|
|
if (animated && sp90[i]) {
|
|
dyntexAddVertex(spa0[i]);
|
|
sp90[i] = 0;
|
|
}
|
|
|
|
spa0[i] = vtx;
|
|
vtx++;
|
|
}
|
|
}
|
|
|
|
if (spf4 && vtxstart) {
|
|
s32 count = ingdl->vtx.unk08 + 1;
|
|
Vtx *vtx;
|
|
s32 i;
|
|
|
|
offset = UNSEGADDR(ingdl->dma.addr) & 0x00ffffff;
|
|
vtx = (Vtx *) (vtxstart + offset);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
vtx[i].s >>= 1;
|
|
vtx[i].t >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
case G_RDPPIPESYNC:
|
|
g_TexPipeSynced = true;
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
case (u8) G_TRI4:
|
|
case (u8) G_TRI1:
|
|
if (animated) {
|
|
if (ingdl->texture.cmd == (u8) G_TRI1) {
|
|
sp90[ingdl->tri.tri.v[GFX_TRI_VTX(0)] / 10] = 1;
|
|
sp90[ingdl->tri.tri.v[GFX_TRI_VTX(1)] / 10] = 1;
|
|
sp90[ingdl->tri.tri.v[GFX_TRI_VTX(2)] / 10] = 1;
|
|
} else {
|
|
Gfx *tmp = ingdl;
|
|
|
|
if (tmp->tri4.x1 != tmp->tri4.y1 || tmp->tri4.z1 != tmp->tri4.y1) {
|
|
sp90[tmp->tri4.x1] = 1;
|
|
sp90[tmp->tri4.y1] = 1;
|
|
sp90[tmp->tri4.z1] = 1;
|
|
}
|
|
|
|
if (tmp->tri4.x2 != tmp->tri4.y2 || tmp->tri4.z2 != tmp->tri4.y2) {
|
|
sp90[tmp->tri4.x2] = 1;
|
|
sp90[tmp->tri4.y2] = 1;
|
|
sp90[tmp->tri4.z2] = 1;
|
|
}
|
|
|
|
if (tmp->tri4.x3 != tmp->tri4.y3 || tmp->tri4.z3 != tmp->tri4.y3) {
|
|
sp90[tmp->tri4.x3] = 1;
|
|
sp90[tmp->tri4.y3] = 1;
|
|
sp90[tmp->tri4.z3] = 1;
|
|
}
|
|
|
|
if (tmp->tri4.x4 != tmp->tri4.y4 || tmp->tri4.z4 != tmp->tri4.y4) {
|
|
sp90[tmp->tri4.x4] = 1;
|
|
sp90[tmp->tri4.y4] = 1;
|
|
sp90[tmp->tri4.z4] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
appendtex = true;
|
|
g_TexPipeSynced = false;
|
|
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
case (u8) G_TEXTURE:
|
|
spe4 = true;
|
|
|
|
if (animated) {
|
|
spe8 = true;
|
|
}
|
|
|
|
animated = false;
|
|
appendtex = false;
|
|
|
|
texcmd = outgdl;
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
case (u8) G_SETOTHERMODE_H:
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
default:
|
|
*outgdl = *ingdl;
|
|
outgdl++;
|
|
ingdl++;
|
|
break;
|
|
}
|
|
|
|
numcmdsremaining--;
|
|
|
|
if (spe4 || numcmdsremaining <= 0) {
|
|
spe4 = false;
|
|
|
|
if (spe8 || animated) {
|
|
s32 i;
|
|
|
|
spe8 = false;
|
|
|
|
for (i = 0; i < ARRAYCOUNT(sp90); i++) {
|
|
if (sp90[i]) {
|
|
dyntexAddVertex(spa0[i]);
|
|
sp90[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (uintptr_t) outgdl - (uintptr_t) outstart;
|
|
}
|
|
|
|
void texCopyGdls(Gfx *src, Gfx *dst, s32 count)
|
|
{
|
|
#ifdef PLATFORM_64BIT
|
|
count = (count >> 4);
|
|
#else
|
|
count = (count >> 3);
|
|
#endif
|
|
|
|
src = src + (count - 1);
|
|
dst = dst + (count - 1);
|
|
|
|
while (count--) {
|
|
*dst = *src;
|
|
dst--;
|
|
src--;
|
|
}
|
|
}
|