1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-04 10:03:36 +00:00
GLideN64/src/uCodes/ZSort.cpp
2022-01-29 17:22:09 -05:00

604 lines
16 KiB
C++

#include <assert.h>
#include <math.h>
#include "N64.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
#include "Log.h"
#include "F3D.h"
#include "ZSort.h"
#include "3DMath.h"
#include "DisplayWindow.h"
#define GZM_USER0 0
#define GZM_USER1 2
#define GZM_MMTX 4
#define GZM_PMTX 6
#define GZM_MPMTX 8
#define GZM_OTHERMODE 10
#define GZM_VIEWPORT 12
#define GZF_LOAD 0
#define GZF_SAVE 1
#define ZH_NULL 0
#define ZH_SHTRI 1
#define ZH_TXTRI 2
#define ZH_SHQUAD 3
#define ZH_TXQUAD 4
struct ZSORTRDP
{
f32 view_scale[2];
f32 view_trans[2];
} zSortRdp = {{0, 0}, {0, 0}};
void ZSort_RDPCMD( const Gwords words )
{
word addr = RSP_SegmentToPhysical(words.w1) >> 2;
if (addr) {
RSP.LLE = true;
while(true)
{
word w0 = ((word*)RDRAM)[addr++];
RSP.cmd = _SHIFTR( w0, 24, 8 );
if (RSP.cmd == 0xDF)
break;
word w1 = ((word*)RDRAM)[addr++];
if (RSP.cmd == G_TEXRECT || RSP.cmd == G_TEXRECTFLIP) {
addr++;
RDP.w2 = ((word*)RDRAM)[addr++];
addr++;
RDP.w3 = ((word*)RDRAM)[addr++];
}
GBI.cmd[RSP.cmd]( words );
};
RSP.LLE = false;
}
}
int Calc_invw (int _w) {
if (_w == 0)
return 0x7FFFFFFF;
return 0x7FFFFFFF / _w;
}
static
void ZSort_DrawObject (u8 * _addr, u32 _type)
{
u32 textured = 0, vnum = 0, vsize = 0;
switch (_type) {
case ZH_NULL:
textured = vnum = vsize = 0;
break;
case ZH_SHTRI:
textured = 0;
vnum = 3;
vsize = 8;
break;
case ZH_TXTRI:
textured = 1;
vnum = 3;
vsize = 16;
break;
case ZH_SHQUAD:
textured = 0;
vnum = 4;
vsize = 8;
break;
case ZH_TXQUAD:
textured = 1;
vnum = 4;
vsize = 16;
break;
}
GraphicsDrawer & drawer = dwnd().getDrawer();
drawer.setDMAVerticesSize(vnum);
SPVertex * pVtx = drawer.getDMAVerticesData();
for (u32 i = 0; i < vnum; ++i) {
SPVertex & vtx = pVtx[i];
vtx.x = _FIXED2FLOAT(((s16*)_addr)[0 ^ 1], 2);
vtx.y = _FIXED2FLOAT(((s16*)_addr)[1 ^ 1], 2);
vtx.z = 0.0f;
vtx.r = _addr[4^3] * 0.0039215689f;
vtx.g = _addr[5^3] * 0.0039215689f;
vtx.b = _addr[6^3] * 0.0039215689f;
vtx.a = _addr[7^3] * 0.0039215689f;
vtx.flag = 0;
vtx.HWLight = 0;
vtx.clip = 0;
if (textured != 0) {
if (gDP.otherMode.texturePersp != 0) {
vtx.s = _FIXED2FLOAT(((s16*)_addr)[4 ^ 1], 5);
vtx.t = _FIXED2FLOAT(((s16*)_addr)[5 ^ 1], 5);
} else {
vtx.s = _FIXED2FLOAT(((s16*)_addr)[4 ^ 1], 6);
vtx.t = _FIXED2FLOAT(((s16*)_addr)[5 ^ 1], 6);
}
vtx.w = Calc_invw(((int*)_addr)[3]) / 31.0f;
} else
vtx.w = 1.0f;
_addr += vsize;
}
drawer.drawScreenSpaceTriangle(vnum);
}
static
u32 ZSort_LoadObject (u32 _zHeader, u32 * _pRdpCmds)
{
const u32 type = _zHeader & 7;
u8 * addr = RDRAM + (_zHeader&0xFFFFFFF8);
u32 w1;
switch (type) {
case ZH_SHTRI:
case ZH_SHQUAD:
{
w1 = ((u32*)addr)[1];
if (w1 != _pRdpCmds[0]) {
_pRdpCmds[0] = w1;
ZSort_RDPCMD (Gwords(0, w1));
}
ZSort_DrawObject(addr + 8, type);
}
break;
case ZH_NULL:
case ZH_TXTRI:
case ZH_TXQUAD:
{
w1 = ((u32*)addr)[1];
if (w1 != _pRdpCmds[0]) {
_pRdpCmds[0] = w1;
ZSort_RDPCMD (Gwords(0, w1));
}
w1 = ((u32*)addr)[2];
if (w1 != _pRdpCmds[1]) {
ZSort_RDPCMD (Gwords(0, w1));
_pRdpCmds[1] = w1;
}
w1 = ((u32*)addr)[3];
if (w1 != _pRdpCmds[2]) {
ZSort_RDPCMD (Gwords(0, w1));
_pRdpCmds[2] = w1;
}
if (type != 0) {
ZSort_DrawObject(addr + 16, type);
}
}
break;
}
return RSP_SegmentToPhysical(((u32*)addr)[0]);
}
void ZSort_Obj( const Gwords words )
{
u32 rdpcmds[3] = {0, 0, 0};
u32 cmd1 = words.w1;
u32 zHeader = RSP_SegmentToPhysical(words.w0);
while (zHeader)
zHeader = ZSort_LoadObject(zHeader, rdpcmds);
zHeader = RSP_SegmentToPhysical(cmd1);
while (zHeader)
zHeader = ZSort_LoadObject(zHeader, rdpcmds);
}
void ZSort_Interpolate( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_Interpolate Ignored");
}
void ZSort_XFMLight( const Gwords words )
{
int mid = _SHIFTR(words.w0, 0, 8);
gSPNumLights(1 + _SHIFTR(words.w1, 12, 8));
word addr = -1024 + _SHIFTR(words.w1, 0, 12);
assert(mid == GZM_MMTX);
/*
M44 *m;
switch (mid) {
case 4:
m = (M44*)rdp.model;
break;
case 6:
m = (M44*)rdp.proj;
break;
case 8:
m = (M44*)gSP.matrix.combined;
break;
}
*/
gSP.lights.rgb[gSP.numLights][R] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+0)^3], 8 );
gSP.lights.rgb[gSP.numLights][G] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+1)^3], 8 );
gSP.lights.rgb[gSP.numLights][B] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+2)^3], 8 );
addr += 8;
u32 i;
for (i = 0; i < gSP.numLights; ++i)
{
gSP.lights.rgb[i][R] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+0)^3], 8 );
gSP.lights.rgb[i][G] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+1)^3], 8 );
gSP.lights.rgb[i][B] = _FIXED2FLOATCOLOR(((u8*)DMEM)[(addr+2)^3], 8 );
gSP.lights.xyz[i][X] = (f32)(((s8*)DMEM)[(addr+8)^3]);
gSP.lights.xyz[i][Y] = (f32)(((s8*)DMEM)[(addr+9)^3]);
gSP.lights.xyz[i][Z] = (f32)(((s8*)DMEM)[(addr+10)^3]);
addr += 24;
}
for (i = 0; i < 2; i++)
{
gSP.lookat.xyz[i][X] = (f32)(((s8*)DMEM)[(addr+8)^3]);
gSP.lookat.xyz[i][Y] = (f32)(((s8*)DMEM)[(addr+9)^3]);
gSP.lookat.xyz[i][Z] = (f32)(((s8*)DMEM)[(addr+10)^3]);
gSP.lookatEnable = (i == 0) || (gSP.lookat.xyz[i][X] != 0 && gSP.lookat.xyz[i][Y] != 0);
addr += 24;
}
}
void ZSort_LightingL( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_LightingL Ignored");
}
void ZSort_Lighting( const Gwords words )
{
u32 csrs = -1024 + _SHIFTR(words.w0, 12, 12);
u32 nsrs = -1024 + _SHIFTR(words.w0, 0, 12);
u32 num = 1 + _SHIFTR(words.w1, 24, 8);
u32 cdest = -1024 + _SHIFTR(words.w1, 12, 12);
u32 tdest = -1024 + _SHIFTR(words.w1, 0, 12);
int use_material = (csrs != 0x0ff0);
tdest >>= 1;
GraphicsDrawer & drawer = dwnd().getDrawer();
drawer.setDMAVerticesSize(num);
SPVertex * pVtx = drawer.getDMAVerticesData();
for (u32 i = 0; i < num; i++) {
SPVertex & vtx = pVtx[i];
vtx.nx = ((s8*)DMEM)[(nsrs++)^3];
vtx.ny = ((s8*)DMEM)[(nsrs++)^3];
vtx.nz = ((s8*)DMEM)[(nsrs++)^3];
TransformVectorNormalize( &vtx.nx, gSP.matrix.modelView[gSP.matrix.modelViewi] );
gSPLightVertex(vtx);
f32 fLightDir[3] = {vtx.nx, vtx.ny, vtx.nz};
TransformVectorNormalize(fLightDir, gSP.matrix.projection);
f32 x, y;
if (gSP.lookatEnable) {
x = DotProduct(gSP.lookat.xyz[0], fLightDir);
y = DotProduct(gSP.lookat.xyz[1], fLightDir);
} else {
x = fLightDir[0];
y = fLightDir[1];
}
vtx.s = (x + 1.0f) * 512.0f;
vtx.t = (y + 1.0f) * 512.0f;
vtx.a = 1.0f;
if (use_material)
{
vtx.r *= _FIXED2FLOATCOLOR(DMEM[(csrs++)^3], 8 );
vtx.g *= _FIXED2FLOATCOLOR(DMEM[(csrs++)^3], 8 );
vtx.b *= _FIXED2FLOATCOLOR(DMEM[(csrs++)^3], 8 );
vtx.a = _FIXED2FLOATCOLOR(DMEM[(csrs++)^3], 8 );
}
DMEM[(cdest++)^3] = (u8)(vtx.r * 255.0f);
DMEM[(cdest++)^3] = (u8)(vtx.g * 255.0f);
DMEM[(cdest++)^3] = (u8)(vtx.b * 255.0f);
DMEM[(cdest++)^3] = (u8)(vtx.a * 255.0f);
((s16*)DMEM)[(tdest++)^1] = (s16)(vtx.s * 32.0f);
((s16*)DMEM)[(tdest++)^1] = (s16)(vtx.t * 32.0f);
}
}
void ZSort_MTXRNSP( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_MTXRNSP Ignored");
}
void ZSort_MTXCAT( const Gwords words )
{
M44 *s = nullptr;
M44 *t = nullptr;
u32 S = _SHIFTR(words.w0, 0, 4);
u32 T = _SHIFTR(words.w1, 16, 4);
u32 D = _SHIFTR(words.w1, 0, 4);
switch (S) {
case GZM_MMTX:
s = (M44*)gSP.matrix.modelView[gSP.matrix.modelViewi];
break;
case GZM_PMTX:
s = (M44*)gSP.matrix.projection;
break;
case GZM_MPMTX:
s = (M44*)gSP.matrix.combined;
break;
}
switch (T) {
case GZM_MMTX:
t = (M44*)gSP.matrix.modelView[gSP.matrix.modelViewi];
break;
case GZM_PMTX:
t = (M44*)gSP.matrix.projection;
break;
case GZM_MPMTX:
t = (M44*)gSP.matrix.combined;
break;
}
assert(s != nullptr && t != nullptr);
f32 m[4][4];
MultMatrix(*s, *t, m);
switch (D) {
case GZM_MMTX:
memcpy (gSP.matrix.modelView[gSP.matrix.modelViewi], m, 64);;
break;
case GZM_PMTX:
memcpy (gSP.matrix.projection, m, 64);;
break;
case GZM_MPMTX:
memcpy (gSP.matrix.combined, m, 64);;
break;
}
}
void ZSort_MultMPMTX( const Gwords words )
{
int num = 1 + _SHIFTR(words.w1, 24, 8);
int src = -1024 + _SHIFTR(words.w1, 12, 12);
int dst = -1024 + _SHIFTR(words.w1, 0, 12);
s16 * saddr = (s16*)(DMEM+src);
zSortVDest * daddr = (zSortVDest*)(DMEM+dst);
int idx = 0;
zSortVDest v;
memset(&v, 0, sizeof(zSortVDest));
for (int i = 0; i < num; ++i) {
s16 sx = saddr[(idx++)^1];
s16 sy = saddr[(idx++)^1];
s16 sz = saddr[(idx++)^1];
f32 x = sx*gSP.matrix.combined[0][0] + sy*gSP.matrix.combined[1][0] + sz*gSP.matrix.combined[2][0] + gSP.matrix.combined[3][0];
f32 y = sx*gSP.matrix.combined[0][1] + sy*gSP.matrix.combined[1][1] + sz*gSP.matrix.combined[2][1] + gSP.matrix.combined[3][1];
f32 z = sx*gSP.matrix.combined[0][2] + sy*gSP.matrix.combined[1][2] + sz*gSP.matrix.combined[2][2] + gSP.matrix.combined[3][2];
f32 w = sx*gSP.matrix.combined[0][3] + sy*gSP.matrix.combined[1][3] + sz*gSP.matrix.combined[2][3] + gSP.matrix.combined[3][3];
v.sx = (s16)(zSortRdp.view_trans[0] + x / w * zSortRdp.view_scale[0]);
v.sy = (s16)(zSortRdp.view_trans[1] + y / w * zSortRdp.view_scale[1]);
v.xi = (s16)x;
v.yi = (s16)y;
v.wi = (s16)w;
v.invw = Calc_invw((int)(w * 31.0));
if (w < 0.0f)
v.fog = 0;
else {
int fog = (int)(z / w * gSP.fog.multiplier + gSP.fog.offset);
if (fog > 255)
fog = 255;
v.fog = (fog >= 0) ? (u8)fog : 0;
}
v.cc = 0;
if (x < -w) v.cc |= 0x10;
if (x > w) v.cc |= 0x01;
if (y < -w) v.cc |= 0x20;
if (y > w) v.cc |= 0x02;
if (w < 0.1f) v.cc |= 0x04;
daddr[i] = v;
}
}
void ZSort_LinkSubDL( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_LinkSubDL Ignored");
}
void ZSort_SetSubDL( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_SetSubDL Ignored");
}
void ZSort_WaitSignal( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_WaitSignal Ignored");
}
void ZSort_SendSignal( const Gwords words )
{
LOG(LOG_VERBOSE, "ZSort_SendSignal Ignored");
}
static
void ZSort_SetTexture()
{
gSP.texture.scales = 1.0f;
gSP.texture.scalet = 1.0f;
gSP.texture.level = 0;
gSP.texture.on = 1;
gSP.texture.tile = 0;
gSPSetGeometryMode(G_SHADING_SMOOTH | G_SHADE);
}
void ZSort_MoveMem( const Gwords words )
{
word idx = words.w0 & 0x0E;
word ofs = _SHIFTR(words.w0, 6, 9)<<3;
word len = 1 + (_SHIFTR(words.w0, 15, 9)<<3);
word flag = words.w0 & 0x01;
word addr = RSP_SegmentToPhysical(words.w1);
switch (idx)
{
case GZF_LOAD: //save/load
if (flag == 0) {
word dmem_addr = (idx<<3) + ofs;
memcpy(DMEM + dmem_addr, RDRAM + addr, len);
} else {
word dmem_addr = (idx<<3) + ofs;
memcpy(RDRAM + addr, DMEM + dmem_addr, len);
}
break;
case GZM_MMTX: // model matrix
RSP_LoadMatrix(gSP.matrix.modelView[gSP.matrix.modelViewi], addr);
gSP.changed |= CHANGED_MATRIX;
break;
case GZM_PMTX: // projection matrix
RSP_LoadMatrix(gSP.matrix.projection, addr);
gSP.changed |= CHANGED_MATRIX;
break;
case GZM_MPMTX: // combined matrix
RSP_LoadMatrix(gSP.matrix.combined, addr);
gSP.changed &= ~CHANGED_MATRIX;
break;
case GZM_OTHERMODE:
LOG(LOG_VERBOSE, "MoveMem Othermode Ignored");
break;
case GZM_VIEWPORT: // VIEWPORT
{
u32 a = addr >> 1;
const f32 scale_x = _FIXED2FLOAT( *(s16*)&RDRAM[(a+0)^1], 2 );
const f32 scale_y = _FIXED2FLOAT( *(s16*)&RDRAM[(a+1)^1], 2 );
const f32 scale_z = _FIXED2FLOAT( *(s16*)&RDRAM[(a+2)^1], 10 );
const s16 fm = ((s16*)RDRAM)[(a+3)^1];
const f32 trans_x = _FIXED2FLOAT( *(s16*)&RDRAM[(a+4)^1], 2 );
const f32 trans_y = _FIXED2FLOAT( *(s16*)&RDRAM[(a+5)^1], 2 );
const f32 trans_z = _FIXED2FLOAT( *(s16*)&RDRAM[(a+6)^1], 10 );
const s16 fo = ((s16*)RDRAM)[(a+7)^1];
gSPFogFactor(fm, fo);
gSP.viewport.vscale[0] = scale_x;
gSP.viewport.vscale[1] = scale_y;
gSP.viewport.vscale[2] = scale_z;
gSP.viewport.vtrans[0] = trans_x;
gSP.viewport.vtrans[1] = trans_y;
gSP.viewport.vtrans[2] = trans_z;
gSP.viewport.x = gSP.viewport.vtrans[0] - gSP.viewport.vscale[0];
gSP.viewport.y = gSP.viewport.vtrans[1] - gSP.viewport.vscale[1];
gSP.viewport.width = gSP.viewport.vscale[0] * 2;
gSP.viewport.height = gSP.viewport.vscale[1] * 2;
gSP.viewport.nearz = gSP.viewport.vtrans[2] - gSP.viewport.vscale[2];
gSP.viewport.farz = (gSP.viewport.vtrans[2] + gSP.viewport.vscale[2]) ;
zSortRdp.view_scale[0] = scale_x*4.0f;
zSortRdp.view_scale[1] = scale_y*4.0f;
zSortRdp.view_trans[0] = trans_x*4.0f;
zSortRdp.view_trans[1] = trans_y*4.0f;
gSP.changed |= CHANGED_VIEWPORT;
ZSort_SetTexture();
}
break;
default:
LOG(LOG_ERROR, "ZSort_MoveMem UNKNOWN %d", idx);
}
}
void SZort_SetScissor( const Gwords words )
{
RDP_SetScissor(words);
if ((gDP.scissor.lrx - gDP.scissor.ulx) > (zSortRdp.view_scale[0] - zSortRdp.view_trans[0]))
{
f32 w = (gDP.scissor.lrx - gDP.scissor.ulx) / 2.0f;
f32 h = (gDP.scissor.lry - gDP.scissor.uly) / 2.0f;
gSP.viewport.vscale[0] = w;
gSP.viewport.vscale[1] = h;
gSP.viewport.vtrans[0] = w;
gSP.viewport.vtrans[1] = h;
gSP.viewport.x = gSP.viewport.vtrans[0] - gSP.viewport.vscale[0];
gSP.viewport.y = gSP.viewport.vtrans[1] - gSP.viewport.vscale[1];
gSP.viewport.width = gSP.viewport.vscale[0] * 2;
gSP.viewport.height = gSP.viewport.vscale[1] * 2;
zSortRdp.view_scale[0] = w * 4.0f;
zSortRdp.view_scale[1] = h * 4.0f;
zSortRdp.view_trans[0] = w * 4.0f;
zSortRdp.view_trans[1] = h * 4.0f;
gSP.changed |= CHANGED_VIEWPORT;
ZSort_SetTexture();
}
}
#define G_ZS_ZOBJ 0x80
#define G_ZS_RDPCMD 0x81
#define G_ZS_SETOTHERMODE_H 0xE3
#define G_ZS_SETOTHERMODE_L 0xE2
#define G_ZS_ENDDL 0xDF
#define G_ZS_DL 0xDE
#define G_ZS_MOVEMEM 0xDC
#define G_ZS_MOVEWORD 0xDB
#define G_ZS_SENDSIGNAL 0xDA
#define G_ZS_WAITSIGNAL 0xD9
#define G_ZS_SETSUBDL 0xD8
#define G_ZS_LINKSUBDL 0xD7
#define G_ZS_MULT_MPMTX 0xD6
#define G_ZS_MTXCAT 0xD5
#define G_ZS_MTXTRNSP 0xD4
#define G_ZS_LIGHTING_L 0xD3
#define G_ZS_LIGHTING 0xD2
#define G_ZS_XFMLIGHT 0xD1
#define G_ZS_INTERPOLATE 0xD0
u32 G_ZSENDSIGNAL, G_ZSETSUBDL, G_ZLINKSUBDL, G_ZMTXTRNSP;
u32 G_ZLIGHTING_L, G_ZXFMLIGHT, G_ZINTERPOLATE, G_ZSETSCISSOR;
void ZSort_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );
GBI.PCStackSize = 10;
// GBI Command Command Value Command Function
GBI_SetGBI( G_SPNOOP, F3D_SPNOOP, F3D_SPNoOp );
GBI_SetGBI( G_RESERVED0, F3D_RESERVED0, F3D_Reserved0 );
GBI_SetGBI( G_RESERVED1, F3D_RESERVED1, F3D_Reserved1 );
GBI_SetGBI( G_DL, G_ZS_DL, F3D_DList );
GBI_SetGBI( G_RESERVED2, F3D_RESERVED2, F3D_Reserved2 );
GBI_SetGBI( G_RESERVED3, F3D_RESERVED3, F3D_Reserved3 );
GBI_SetGBI( G_CULLDL, F3D_CULLDL, F3D_CullDL );
GBI_SetGBI( G_MOVEWORD, G_ZS_MOVEWORD, F3D_MoveWord );
GBI_SetGBI( G_TEXTURE, F3D_TEXTURE, F3D_Texture );
GBI_SetGBI( G_ZSETSCISSOR, G_SETSCISSOR, SZort_SetScissor );
GBI_SetGBI( G_SETOTHERMODE_H, G_ZS_SETOTHERMODE_H, F3D_SetOtherMode_H );
GBI_SetGBI( G_SETOTHERMODE_L, G_ZS_SETOTHERMODE_L, F3D_SetOtherMode_L );
GBI_SetGBI( G_ENDDL, G_ZS_ENDDL, F3D_EndDL );
GBI_SetGBI( G_SETGEOMETRYMODE, F3D_SETGEOMETRYMODE, F3D_SetGeometryMode );
GBI_SetGBI( G_CLEARGEOMETRYMODE, F3D_CLEARGEOMETRYMODE, F3D_ClearGeometryMode );
GBI_SetGBI( G_RDPHALF_1, F3D_RDPHALF_1, F3D_RDPHalf_1 );
GBI_SetGBI( G_RDPHALF_2, F3D_RDPHALF_2, F3D_RDPHalf_2 );
GBI_SetGBI( G_RDPHALF_CONT, F3D_RDPHALF_CONT, F3D_RDPHalf_Cont );
GBI_SetGBI( G_ZOBJ, G_ZS_ZOBJ, ZSort_Obj );
GBI_SetGBI( G_ZRDPCMD, G_ZS_RDPCMD, ZSort_RDPCMD );
GBI_SetGBI( G_MOVEMEM, G_ZS_MOVEMEM, ZSort_MoveMem );
GBI_SetGBI( G_ZSENDSIGNAL, G_ZS_SENDSIGNAL, ZSort_SendSignal );
GBI_SetGBI( G_ZWAITSIGNAL, G_ZS_WAITSIGNAL, ZSort_WaitSignal );
GBI_SetGBI( G_ZSETSUBDL, G_ZS_SETSUBDL, ZSort_SetSubDL );
GBI_SetGBI( G_ZLINKSUBDL, G_ZS_LINKSUBDL, ZSort_LinkSubDL );
GBI_SetGBI( G_ZMULT_MPMTX, G_ZS_MULT_MPMTX, ZSort_MultMPMTX );
GBI_SetGBI( G_ZMTXCAT, G_ZS_MTXCAT, ZSort_MTXCAT );
GBI_SetGBI( G_ZMTXTRNSP, G_ZS_MTXTRNSP, ZSort_MTXRNSP );
GBI_SetGBI( G_ZLIGHTING_L, G_ZS_LIGHTING_L, ZSort_LightingL );
GBI_SetGBI( G_ZLIGHTING, G_ZS_LIGHTING, ZSort_Lighting );
GBI_SetGBI( G_ZXFMLIGHT, G_ZS_XFMLIGHT, ZSort_XFMLight );
GBI_SetGBI( G_ZINTERPOLATE, G_ZS_INTERPOLATE, ZSort_Interpolate );
}