merge initial ps2 rendering support from other project

This commit is contained in:
aap
2026-08-09 00:05:03 +02:00
parent 4c8cab66bb
commit bb063f4ac5
25 changed files with 3904 additions and 34 deletions
+28 -23
View File
@@ -63,8 +63,8 @@ workspace "librw"
filter "configurations:Release*"
defines { "NDEBUG" }
optimize "On"
filter "configurations:ReleaseStatic"
staticruntime("On")
-- filter "configurations:ReleaseStatic"
-- staticruntime("On")
filter { "platforms:*null" }
defines { "RW_NULL" }
@@ -119,6 +119,16 @@ workspace "librw"
Libdir = "lib/%{cfg.platform}/%{cfg.buildcfg}"
Bindir = "bin/%{cfg.platform}/%{cfg.buildcfg}"
function vucode()
filter "files:**.dsm"
buildmessage 'dvp-as %{file.name}'
buildcommands {
'cpp -x assembler-with-cpp "%{file.abspath}" | ee-dvp-as -I "%{file.directory}" -o "%{cfg.objdir}/%{file.basename}.o"'
}
buildoutputs { '%{cfg.objdir}/%{file.basename}.o' }
filter {}
end
project "librw"
kind "StaticLib"
targetname "rw"
@@ -128,6 +138,10 @@ project "librw"
files { "src/*/*.*" }
filter { "platforms:*gl3" }
files { "src/gl/glad/*.*" }
filter { "platforms:*ps2" }
vucode()
files { "src/ps2/vu1/*.dsm" }
includedirs { "src/ps2/vu1" }
project "dumprwtree"
kind "ConsoleApp"
@@ -194,15 +208,6 @@ function skeltool(dir)
findlibs()
end
function vucode()
filter "files:**.dsm"
buildcommands {
'cpp "%{file.relpath}" | dvp-as -o "%{cfg.objdir}/%{file.basename}.o"'
}
buildoutputs { '%{cfg.objdir}/%{file.basename}.o' }
filter {}
end
project "playground"
kind "WindowedApp"
characterset ("MBCS")
@@ -272,18 +277,18 @@ project "ska2anm"
findlibs()
removeplatforms { "*gl3", "*d3d9", "*ps2" }
project "ps2test"
kind "ConsoleApp"
targetdir (Bindir)
vucode()
removeplatforms { "*gl3", "*d3d9", "*null" }
targetextension '.elf'
includedirs { "." }
files { "tools/ps2test/*.cpp",
"tools/ps2test/vu/*.dsm",
"tools/ps2test/*.h" }
libdirs { "$(PS2SDK)/ee/lib" }
links { "librw" }
--project "ps2test"
-- kind "ConsoleApp"
-- targetdir (Bindir)
-- vucode()
-- removeplatforms { "*gl3", "*d3d9", "*null" }
-- targetextension '.elf'
-- includedirs { "." }
-- files { "tools/ps2test/*.cpp",
-- "tools/ps2test/vu/*.dsm",
-- "tools/ps2test/*.h" }
-- libdirs { "$(PS2SDK)/ee/lib" }
-- links { "librw" }
--project "ps2rastertest"
-- kind "ConsoleApp"
+3
View File
@@ -948,6 +948,9 @@ ObjPipeline::init(void)
this->groupPipeline = nil;
this->impl.instance = objInstance;
this->impl.uninstance = objUninstance;
#ifdef RW_PS2
this->impl.render = defaultAtomicRender;
#endif
}
ObjPipeline*
+1172 -11
View File
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
#ifdef RW_PS2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include <sifdev.h>
struct FILE_PS2
{
int used;
int fd;
int pos;
int size;
};
FILE_PS2 ps2files[64];
/* file functions */
void*
ps2fopen(const char *path, const char *mode)
{
int flags = 0;
int fd;
int i;
char *r, *w, *plus;
// printf("trying to open <%s> mode <%s>\n", path, mode);
for(i = 0; i < nelem(ps2files); i++){
if(!ps2files[i].used)
goto found;
}
// no file pointer available
return nil;
found:
r = strchr(mode, 'r');
w = strchr(mode, 'w');
plus = strchr(mode, '+');
if(plus)
flags = SCE_RDWR;
else if(r)
flags = SCE_RDONLY;
else if(w)
flags = SCE_WRONLY;
if(w)
flags |= SCE_CREAT | SCE_TRUNC;
fd = sceOpen(path, flags);
if(fd < 0)
return nil;
ps2files[i].used = 1;
ps2files[i].fd = fd;
ps2files[i].pos = 0;
if(w){
ps2files[i].size = 0;
}else{
ps2files[i].size = sceLseek(fd, 0, SCE_SEEK_END);
sceLseek(fd, 0, SCE_SEEK_SET);
}
return &ps2files[i];
}
int
ps2fclose(void *fp)
{
FILE_PS2 *f = (FILE_PS2*)fp;
if(!f->used)
return EOF;
sceClose(f->fd);
f->used = 0;
f->fd = -1;
return 0;
}
int
ps2fseek(void *fp, long offset, int whence)
{
FILE_PS2 *f = (FILE_PS2*)fp;
f->pos = sceLseek(f->fd, offset, whence);
return f->pos;
}
long
ps2ftell(void *fp)
{
FILE_PS2 *f = (FILE_PS2*)fp;
return f->pos;
}
size_t
ps2fread(void *ptr, size_t size, size_t nmemb, void *fp)
{
FILE_PS2 *f = (FILE_PS2*)fp;
int n = sceRead(f->fd, ptr, size*nmemb);
f->pos += n;
return n/size;
}
size_t
ps2fwrite(const void *ptr, size_t size, size_t nmemb, void *fp)
{
FILE_PS2 *f = (FILE_PS2*)fp;
int n = sceWrite(f->fd, ptr, size*nmemb);
f->pos += n;
if(f->pos > f->size)
f->size = f->pos;
return n/size;
}
int
ps2feof(void *fp)
{
FILE_PS2 *f = (FILE_PS2*)fp;
return f->pos >= f->size;
}
#endif
+7
View File
@@ -0,0 +1,7 @@
void *ps2fopen(const char *path, const char *mode);
int ps2fclose(void *fp);
int ps2fseek(void *fp, long offset, int whence);
long ps2ftell(void *fp);
size_t ps2fread(void *ptr, size_t size, size_t nmemb, void *fp);
size_t ps2fwrite(const void *ptr, size_t size, size_t nmemb, void *fp);
int ps2feof(void *fp);
+345
View File
@@ -0,0 +1,345 @@
#ifdef RW_PS2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "../rwanim.h"
#include "../rwplugins.h"
#include "rwps2.h"
#include "rwps2plg.h"
#include "rwps2impl.h"
#include <eestruct.h>
#define PLUGIN_ID 2
extern rw::ps2::VUdesc vu1_im3d_desc[7];
extern rw::ps2::VUdesc vu1_im2d_desc[2];
extern rw::uint32 vu1_im2d[];
extern rw::uint32 vu1_im3d[];
namespace rw {
namespace ps2 {
struct BatchInfo
{
uint32 numBatches;
uint32 batchSize;
int32 repeat;
};
int
prologue(BatchInfo *bi, PrimitiveType type, int32 numVerts)
{
// 2 words for GIF tags, 2 input and output buffers, 3 qw per vertex
bi->batchSize = (vuMatrix - 2)/(2*3 + 2*3);
int primsz = primSize[type];
bi->repeat = primRepeat[type];
int numPrims = 0;
int numPrimsBatch = 0;
switch(type){
case PRIMTYPEPOINTLIST:
case PRIMTYPELINELIST:
case PRIMTYPETRILIST:
numPrims = numVerts/primsz;
numPrimsBatch = bi->batchSize/primsz;
numPrimsBatch &= ~3;
bi->batchSize = numPrimsBatch*primsz;
break;
case PRIMTYPEPOLYLINE:
case PRIMTYPETRISTRIP:
case PRIMTYPETRIFAN:
numPrims = numVerts - bi->repeat;
bi->batchSize &= ~3;
numPrimsBatch = bi->batchSize - bi->repeat;
break;
}
// nothing to draw
if(bi->batchSize < primSize[type])
return 1;
bi->numBatches = (numPrims + numPrimsBatch-1) / numPrimsBatch;
uploadRaster(rwStateCache.raster);
setTexture(rwStateCache.raster, rwStateCache.addressU, rwStateCache.addressV, rwStateCache.filterMode);
flushGSRegs();
return 0;
}
int
prologue2d(BatchInfo *bi, PrimitiveType type, int32 numVerts)
{
uint128 tmp;
prologue(bi, type, numVerts);
uploadVUCode(vu1_im2d);
// DMAcnt for everything
int dmasz = 8 // general VIF unpacks
+ 3*(numVerts + (bi->numBatches-1)*bi->repeat) // vertices
+ bi->numBatches*2; // batch prolog and epilog
assert(dmasz <= 0xFFFF);
MAKEQ(tmp, VIFflush, VIFflush, 0, DMAcnt + dmasz);
vifPacket[vifPacksz++].q_u128 = tmp;
// some uploads and double buffer
uint32 offset = bi->batchSize*3;
MAKEQ(tmp, UNPACK(V4_32, 2, vuXyzwScale), STCYCL(4,4), VIFoffset + offset, VIFbase + 0);
vifPacket[vifPacksz++].q_u128 = tmp;
vifPacket[vifPacksz++] = vuConst.xyzwScale_2D;
vifPacket[vifPacksz++] = vuConst.xyzwOffset_2D;
MAKEQ(tmp, UNPACK(V4_32, 2, vuGifTag), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
MAKE128(tmp, 0x412, SCE_GIF_SET_TAG(0, 1, 1,rw2gsPrim[type], SCE_GIF_PACKED, 3));
vifPacket[vifPacksz++].q_u128 = tmp;
vifPacket[vifPacksz++] = (rwStateCache.raster == nil || doModulate2) ? colorNoScale : colorTexScale;
MAKEQ(tmp, UNPACK(V4_32, 1, vuVuSwitch), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
VUdesc *desc = rwStateCache.fogEnable ? &vu1_im2d_desc[1] : &vu1_im2d_desc[0];
MAKEQ(tmp, 0, 0, 0, desc->process>>3);
vifPacket[vifPacksz++].q_u128 = tmp;
return 0;
}
int
prologue3d(BatchInfo *bi, PrimitiveType type, int32 numVerts)
{
uint128 tmp;
prologue(bi, type, numVerts);
uploadVUCode(vu1_im3d);
// DMAcnt for everything
int dmasz = 13 // general VIF unpacks
+ 3*(numVerts + (bi->numBatches-1)*bi->repeat) // vertices
+ bi->numBatches*2; // batch prolog and epilog
assert(dmasz <= 0xFFFF);
MAKEQ(tmp, VIFflush, VIFflush, 0, DMAcnt + dmasz);
vifPacket[vifPacksz++].q_u128 = tmp;
// some uploads and double buffer
uint32 offset = bi->batchSize*3;
MAKEQ(tmp, UNPACK(V4_32, 7, vuMatrix), STCYCL(4,4), VIFoffset + offset, VIFbase + 0);
vifPacket[vifPacksz++].q_u128 = tmp;
vifPacket[vifPacksz++] = vuConst.mat0;
vifPacket[vifPacksz++] = vuConst.mat1;
vifPacket[vifPacksz++] = vuConst.mat2;
vifPacket[vifPacksz++] = vuConst.mat3;
vifPacket[vifPacksz++] = vuConst.xyzwScale_3D;
vifPacket[vifPacksz++] = vuConst.xyzwOffset_3D;
vifPacket[vifPacksz++] = vuConst.clipConsts;
MAKEQ(tmp, UNPACK(V4_32, 2, vuGifTag), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
MAKE128(tmp, 0x412, SCE_GIF_SET_TAG(0, 1, 1,rw2gsPrim[type], SCE_GIF_PACKED, 3));
vifPacket[vifPacksz++].q_u128 = tmp;
vifPacket[vifPacksz++] = (rwStateCache.raster == nil || doModulate2) ? colorNoScale : colorTexScale;
MAKEQ(tmp, UNPACK(V4_32, 1, vuVuSwitch), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
VUdesc *desc;
if(!doClipping)
desc = &vu1_im3d_desc[0];
else if(type != PRIMTYPETRIFAN && type <= PRIMTYPEPOINTLIST)
desc = &vu1_im3d_desc[type];
else
printf("invalid primitive type\n");
MAKEQ(tmp, 0, desc->buf2, desc->buf1, desc->process>>3);
vifPacket[vifPacksz++].q_u128 = tmp;
return 0;
}
void
renderPrim_VU(PrimitiveType type, void *verts, int32 numVerts)
{
uint128 tmp;
BatchInfo bi;
if(prologue2d(&bi, type, numVerts))
return;
int i, j, vx;
Im2DVertex *v;
vx = 0;
for(i = 0; i < bi.numBatches; i++){
int32 vertCount = numVerts;
if(vertCount > bi.batchSize)
vertCount = bi.batchSize;
MAKEQ(tmp, UNPACK(V4_32, vertCount*3, 0x8000 + 0), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
for(j = 0; j < vertCount; j++){
if(j == 0 && type == PRIMTYPETRIFAN)
v = &((Im2DVertex*)verts)[0];
else
v = &((Im2DVertex*)verts)[vx];
memcpy(&vifPacket[vifPacksz], v, 3*16);
vifPacksz += 3;
vx++;
}
uint64 call, flush;
if(i == 0)
call = UINT64(VIFmscalf + 0, VIFitop + vertCount);
else
call = UINT64(VIFmscnt, VIFitop + vertCount);
if(i == bi.numBatches-1)
flush = UINT64(VIFflush, VIFflush);
else
flush = UINT64(VIFnop, VIFnop);
MAKE128(tmp, flush, call);
vifPacket[vifPacksz++].q_u128 = tmp;
numVerts -= vertCount;
numVerts += bi.repeat;
vx -= bi.repeat;
}
}
void
renderIndexedPrim_VU(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices)
{
uint128 tmp;
BatchInfo bi;
if(prologue2d(&bi, type, numIndices))
return;
int i, j, ix, vx;
Im2DVertex *v;
ix = 0;
for(i = 0; i < bi.numBatches; i++){
int32 vertCount = numIndices;
if(vertCount > bi.batchSize)
vertCount = bi.batchSize;
MAKEQ(tmp, UNPACK(V4_32, vertCount*3, 0x8000 + 0), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
for(j = 0; j < vertCount; j++){
if(j == 0 && type == PRIMTYPETRIFAN)
vx = ((uint16*)indices)[0];
else
vx = ((uint16*)indices)[ix];
v = &((Im2DVertex*)verts)[vx];
memcpy(&vifPacket[vifPacksz], v, 3*16);
vifPacksz += 3;
ix++;
}
uint64 call, flush;
if(i == 0)
call = UINT64(VIFmscalf + 0, VIFitop + vertCount);
else
call = UINT64(VIFmscnt, VIFitop + vertCount);
if(i == bi.numBatches-1)
flush = UINT64(VIFflush, VIFflush);
else
flush = UINT64(VIFnop, VIFnop);
MAKE128(tmp, flush, call);
vifPacket[vifPacksz++].q_u128 = tmp;
numIndices -= vertCount;
numIndices += bi.repeat;
ix -= bi.repeat;
}
}
/*********
* VU Im3D
*********/
static Im3DVertex *im3dVerts;
void
vuIm3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags)
{
im3dVerts = (Im3DVertex*)vertices;
setMatrix((RawMatrix*)&vuConst.mat0, world);
}
void
vuIm3DEnd(void)
{
}
void
vuIm3DRenderIndexed(PrimitiveType type, void *indices, int32 numIndices)
{
uint128 tmp;
BatchInfo bi;
QWord q;
if(prologue3d(&bi, type, numIndices))
return;
int i, j, ix, vx;
Im3DVertex *v;
ix = 0;
int first = 1;
for(i = 0; i < bi.numBatches; i++){
int32 vertCount = numIndices;
if(vertCount > bi.batchSize)
vertCount = bi.batchSize;
MAKEQ(tmp, UNPACK(V4_32, vertCount*3, 0x8000 + 0), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
for(j = 0; j < vertCount; j++){
if(j == 0 && type == PRIMTYPETRIFAN)
vx = ((uint16*)indices)[0];
else
vx = ((uint16*)indices)[ix];
v = &im3dVerts[vx];
q.q_f[0] = v->position.x;
q.q_f[1] = v->position.y;
q.q_f[2] = v->position.z;
q.q_f[3] = 0.0f; // ADC flag
vifPacket[vifPacksz++] = q;
q.q_f[0] = v->u;
q.q_f[1] = v->v;
q.q_f[2] = 0.0f;
q.q_f[3] = 0.0f;
vifPacket[vifPacksz++] = q;
ix++;
q.q_u32[0] = v->r;
q.q_u32[1] = v->g;
q.q_u32[2] = v->b;
q.q_u32[3] = v->a;
vifPacket[vifPacksz++] = q;
}
uint64 call, flush;
if(i == 0)
call = UINT64(VIFmscalf + 0, VIFitop + vertCount);
else
call = UINT64(VIFmscnt, VIFitop + vertCount);
if(i == bi.numBatches-1)
flush = UINT64(VIFflush, VIFflush);
else
flush = UINT64(VIFnop, VIFnop);
MAKE128(tmp, flush, call);
vifPacket[vifPacksz++].q_u128 = tmp;
numIndices -= vertCount;
numIndices += bi.repeat;
ix -= bi.repeat;
}
}
}
}
#endif
+248
View File
@@ -0,0 +1,248 @@
#ifdef RW_PS2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "../rwanim.h"
#include "../rwplugins.h"
#include "rwps2.h"
#include "rwps2plg.h"
#include "rwps2impl.h"
#define PLUGIN_ID 2
#include <libgraph.h>
extern rw::ps2::VUdesc vu1_default_desc[3];
extern rw::uint32 vu1_default[];
namespace rw {
namespace ps2 {
void
uploadLights(WorldLights *lightData, Matrix *worldMat)
{
int i;
uint128 tmp;
QWord q;
RGBAf *col;
V3d localDir;
int dmasz = 1;
if(lightData->numAmbients)
dmasz++;
dmasz += lightData->numDirectionals*2;
Matrix lightmat;
if(lightData->numDirectionals || lightData->numLocals)
Matrix::invert(&lightmat, worldMat);
assert(dmasz <= 0x3F0-0x3D0);
MAKEQ(tmp, UNPACK(V4_32, dmasz, vuLight), STCYCL(4,4), 0, DMAcnt + dmasz);
vifPacket[vifPacksz++].q_u128 = tmp;
if(lightData->numAmbients){
q.q_f[0] = lightData->ambient.red*255.0f;
q.q_f[1] = lightData->ambient.green*255.0f;
q.q_f[2] = lightData->ambient.blue*255.0f;
q.q_u32[3] = 1; // ambient
vifPacket[vifPacksz++] = q;
}
for(i = 0; i < lightData->numDirectionals; i++){
Light *l = lightData->directionals[i];
col = &l->color;
q.q_f[0] = col->red*255.0f;
q.q_f[1] = col->green*255.0f;
q.q_f[2] = col->blue*255.0f;
q.q_u32[3] = 3; // direct
vifPacket[vifPacksz++] = q;
V3d *dir = &l->getFrame()->getLTM()->at;
V3d::transformVectors(&localDir, dir, 1, &lightmat);
q.q_f[0] = localDir.x;
q.q_f[1] = localDir.y;
q.q_f[2] = localDir.z;
q.q_f[3] = 0.0f;
vifPacket[vifPacksz++] = q;
}
// TODO: local lights
MAKEQ(tmp, 0, 0, 0, 0);
vifPacket[vifPacksz++].q_u128 = tmp; // end
}
void
lightingCB(Atomic *atomic)
{
WorldLights lightData;
Light *directionals[8];
Light *locals[8];
lightData.directionals = directionals;
lightData.numDirectionals = 8;
lightData.locals = locals;
lightData.numLocals = 8;
if(atomic->geometry->flags & rw::Geometry::LIGHT){
engine->currentWorld->enumerateLights(atomic, &lightData);
if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){
// Get rid of lights that need normals when we don't have any
lightData.numDirectionals = 0;
lightData.numLocals = 0;
}
return uploadLights(&lightData, atomic->getFrame()->getLTM());
}else{
memset(&lightData, 0, sizeof(lightData));
return uploadLights(&lightData, nil);
}
}
int
setupAtomic(Atomic *atomic)
{
uint128 tmp;
setMatrix((RawMatrix*)&vuConst.mat0, atomic->getFrame()->getLTM());
lightingCB(atomic);
MeshHeader *header = atomic->geometry->meshHeader;
PrimitiveType type = header->flags == rw::MeshHeader::TRISTRIP ?
rw::PRIMTYPETRISTRIP : rw::PRIMTYPETRILIST;
uploadVUCode(vu1_default);
// DMAcnt
int dmasz = 12; // general VIF unpacks
MAKEQ(tmp, VIFflush, VIFflush, 0, DMAcnt + dmasz);
vifPacket[vifPacksz++].q_u128 = tmp;
// some uploads
MAKEQ(tmp, UNPACK(V4_32, 7, vuMatrix), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
vifPacket[vifPacksz++] = vuConst.mat0;
vifPacket[vifPacksz++] = vuConst.mat1;
vifPacket[vifPacksz++] = vuConst.mat2;
vifPacket[vifPacksz++] = vuConst.mat3;
vifPacket[vifPacksz++] = vuConst.xyzwScale_3D;
vifPacket[vifPacksz++] = vuConst.xyzwOffset_3D;
vifPacket[vifPacksz++] = vuConst.clipConsts;
MAKEQ(tmp, UNPACK(V4_32, 1, vuGifTag), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
MAKE128(tmp, 0x412, SCE_GIF_SET_TAG(0, 1, 1,rw2gsPrim[type], SCE_GIF_PACKED, 3));
vifPacket[vifPacksz++].q_u128 = tmp;
MAKEQ(tmp, UNPACK(V4_32, 1, vuVuSwitch), STCYCL(4,4), VIFnop, VIFnop);
vifPacket[vifPacksz++].q_u128 = tmp;
VUdesc *desc;
if(doClipping){
if(type == PRIMTYPETRILIST)
desc = &vu1_default_desc[1];
else if(type == PRIMTYPETRISTRIP)
desc = &vu1_default_desc[2];
else
printf("invalid primitive type\n");
}else
desc = &vu1_default_desc[0];
MAKEQ(tmp, 0, desc->buf2, desc->buf1, desc->process>>3);
vifPacket[vifPacksz++].q_u128 = tmp;
return 0;
}
void
setupMaterial(Material *mat)
{
uint128 tmp;
QWord q;
RGBAf matcol;
Texture *tex = mat->texture;
// TODO: set texture alpha state
if(tex)
uploadRaster(tex->raster);
// TODO: no vertex alpha, sad
rw::SetRenderState(VERTEXALPHA, mat->color.alpha != 0xFF);
QWord scale = (tex == nil || doModulate2) ? colorNoScale : colorTexScale;
MAKEQ(tmp, UNPACK(V4_32, 2, vuColScale), STCYCL(4,4), 0, DMAcnt + 2);
vifPacket[vifPacksz++].q_u128 = tmp;
// material color
convColor(&matcol, &mat->color);
if(tex){
setTexture(tex->raster, tex->getAddressU(), tex->getAddressV(), tex->getFilter());
q.q_f[0] = matcol.red*scale.q_f[0];
q.q_f[1] = matcol.green*scale.q_f[1];
q.q_f[2] = matcol.blue*scale.q_f[2];
q.q_f[3] = matcol.alpha*scale.q_f[3];
}else{
setTexture(nil, 0, 0, 0);
q.q_f[0] = matcol.red*scale.q_f[0];
q.q_f[1] = matcol.green*scale.q_f[1];
q.q_f[2] = matcol.blue*scale.q_f[2];
q.q_f[3] = matcol.alpha*scale.q_f[3];
}
vifPacket[vifPacksz++] = q;
// surface props
q.q_f[0] = mat->surfaceProps.ambient;
q.q_f[1] = mat->surfaceProps.specular;
q.q_f[2] = mat->surfaceProps.diffuse;
q.q_f[3] = 0.0f;
vifPacket[vifPacksz++] = q;
flushGSRegs();
}
void
defaultAtomicRender(rw::ObjPipeline *pipe, Atomic *atomic)
{
int i;
uint128 tmp;
ObjPipeline *op = (ObjPipeline*)pipe;
Geometry *geo = atomic->geometry;
op->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_PS2);
InstanceDataHeader *instData = (InstanceDataHeader*)geo->instData;
MeshHeader *header = geo->meshHeader;
setupAtomic(atomic);
for(i = 0; i < instData->numMeshes; i++){
Material *mat = instData->instanceMeshes[i].material;
MatPipeline *mp = op->groupPipeline;
if(mp == nil)
mp = (MatPipeline*)mat->pipeline;
if(mp == nil)
mp = defaultMatPipe;
// TODO: this should be a method of the pipeline
setupMaterial(mat);
// call geometry
MAKEQ(tmp, VIFoffset+mp->vifOffset, VIFbase + 0, (uint32)instData->instanceMeshes[i].data, DMAcall);
vifPacket[vifPacksz++].q_u128 = tmp;
}
}
}
}
#endif
+63
View File
@@ -0,0 +1,63 @@
#ifdef RW_PS2
#include <eetypes.h>
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef unsigned int uintptr_t;
typedef u_long128 uint128_t;
typedef union QWord QWord;
union QWord {
u_long128 q_u128;
u_long q_u64[2];
u_int q_u32[4];
float q_f[4];
};
#define MAKE128(RES,MSB,LSB) \
__asm__ ( "pcpyld %0, %1, %2" : "=r" (RES) : "r" ((uint64)MSB), "r" ((uint64)LSB))
#define UINT64(HIGH,LOW) (((uint64)(uint32)HIGH)<<32 | ((uint64)(uint32)LOW))
#define MAKEQ(RES,W3,W2,W1,W0) MAKE128(RES,UINT64(W3,W2),UINT64(W1,W0))
enum {
IntFlg = 0x80000000,
DMAcnt = 0x10000000,
DMAref = 0x30000000,
DMAcall = 0x50000000,
DMAret = 0x60000000,
DMAend = 0x70000000,
VIFnop = 0,
VIFoffset = 0x02000000,
VIFbase = 0x03000000,
VIFitop = 0x04000000,
VIFstmod = 0x05000000,
VIFmskpath3 = 0x06008000,
VIFunmskpath3 = 0x06000000,
VIFmark = 0x07000000,
VIFflushe = 0x10000000,
VIFflush = 0x11000000,
VIFflusha = 0x13000000,
VIFmscal = 0x14000000,
VIFmscalf = 0x15000000,
VIFmscnt = 0x17000000,
VIFstmask = 0x20000000,
VIFstrow = 0x30000000,
VIFstcol = 0x31000000,
VIFdirect = 0x50000000,
V4_32 = 0x6C
};
#define UNPACK(type, nq, offset) ((type)<<24 | (nq)<<16 | (offset))
#define STCYCL(WL,CL) (0x01000000 | (WL)<<8 | (CL))
#endif
+53
View File
@@ -0,0 +1,53 @@
typedef struct GsDispCtx GsDispCtx;
struct GsDispCtx
{
// two circuits
uint64_t pmode;
uint64_t dispfb1;
uint64_t dispfb2;
uint64_t display1;
uint64_t display2;
uint64_t bgcolor;
};
typedef struct GsDrawCtx GsDrawCtx;
struct GsDrawCtx
{
//two contexts
uint128_t gifTag;
uint64_t frame1;
uint64_t ad_frame1;
uint64_t frame2;
uint64_t ad_frame2;
uint64_t zbuf1;
uint64_t ad_zbuf1;
uint64_t zbuf2;
uint64_t ad_zbuf2;
uint64_t xyoffset1;
uint64_t ad_xyoffset1;
uint64_t xyoffset2;
uint64_t ad_xyoffset2;
uint64_t scissor1;
uint64_t ad_scissor1;
uint64_t scissor2;
uint64_t ad_scissor2;
};
typedef struct GsCtx GsCtx;
struct GsCtx
{
// display context; two buffers
GsDispCtx disp[2];
// draw context; two buffers
GsDrawCtx draw[2];
};
typedef struct GsCrtState GsCrtState;
struct GsCrtState
{
int16_t inter, mode, ff;
};
void GsSetDisp(GsDispCtx *disp);
void GsSetDraw(GsDrawCtx *draw);
+44
View File
@@ -1,3 +1,8 @@
#ifdef RW_PS2
#include "ps2types.h"
#include "ps2file.h"
#endif
namespace rw {
#ifdef RW_PS2
@@ -277,5 +282,44 @@ Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
#ifdef RW_PS2
// Real hardware
// very messy atm
void dmaFlip(int i);
void dmaKick(void);
extern rw::uint32 gifPacksz, gifBufSize;
extern rw::uint32 vifPacksz, vifBufSize;
extern QWord *gifPacket, *vifPacket;
extern int path2Textures;
extern int synchTextures;
extern int gateTextures;
extern int finishCycle;
extern int32 doClipping;
extern int32 doModulate2;
extern QWord colorNoScale;
extern QWord colorTexScale;
void beginFrame(int frame);
void endFrame(float *t1, float *t2);
void uploadRaster(Raster *raster);
void setTexture(Raster *raster, uint32 addressU, uint32 addressV, uint32 filterMode);
void flushGSRegs(void);
void uploadVUCode(uint32 *code);
void setMatrix(RawMatrix *combined, Matrix *world);
void defaultAtomicRender(rw::ObjPipeline *pipe, Atomic *atomic);
#endif
}
}
+98
View File
@@ -1,6 +1,104 @@
// lower level stuff
// this should go elsewhere
//#define PAL
#define SCREEN_WIDTH 640
#ifdef PAL
#define SCREEN_HEIGHT 512
#define VIDEOMODE SCE_GS_PAL
#else
#define SCREEN_HEIGHT 448
#define VIDEOMODE SCE_GS_NTSC
#endif
// RW proper
namespace rw {
#ifdef RW_PS2
typedef uint128_t uint128;
#endif
namespace ps2 {
#ifdef RW_PS2
struct VUdesc
{
uint32 process, buf1, buf2, buf3;
};
extern int rw2gsPrim[];
extern int primSize[];
extern int primRepeat[];
struct RwStateCache {
Raster *raster;
uint32 addressU;
uint32 addressV;
uint32 filterMode;
bool32 vertexAlpha;
uint32 alphaTestEnable;
uint32 alphaFunc;
bool32 textureAlpha;
bool32 blendEnable;
uint32 srcblend, destblend;
uint32 zwrite;
uint32 ztest;
uint32 cullmode;
uint32 fogEnable;
float32 fogStart;
float32 fogEnd;
};
extern RwStateCache rwStateCache;
enum {
vuLight = 0x3D0,
vuMatrix = 0x3F0,
vuXyzwScale = 0x3F4,
vuXyzwOffset = 0x3F5,
vuClipConsts = 0x3F6,
vuGifTag = 0x3FA,
vuColScale = 0x3FB,
vuSurfProps = 0x3FC,
vuVuSwitch = 0x3FF
};
struct VuConst {
QWord mat0, mat1, mat2, mat3;
QWord xyzwScale_2D;
QWord xyzwOffset_2D;
QWord xyzwScale_3D;
QWord xyzwOffset_3D;
QWord clipConsts;
QWord gifTag;
QWord surfProps;
QWord vuSwitch;
};
extern VuConst vuConst;
// The reset should be private
void renderPrim_VU(PrimitiveType type, void *verts, int32 numVerts);
void renderIndexedPrim_VU(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices);
void vuIm3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags);
void vuIm3DRenderIndexed(PrimitiveType type, void *indices, int32 numIndices);
void vuIm3DEnd(void);
void clearCamera(Camera *cam, RGBA *col, uint32 mode);
void beginUpdate(Camera *cam);
void endUpdate(Camera *cam);
void setRenderState(int32 state, void *pvalue);
void *getRenderState(int32 state);
int deviceSystem(DeviceReq req, void *arg, int32 n);
#endif
Raster *rasterCreate(Raster *raster);
uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32 level);
+79
View File
@@ -0,0 +1,79 @@
nop xtop vi02 ; input pointer
nop xitop vi04 ; vertex count
LLClipLoop:
nop iaddiu vi03,vi00,0 ; clipped vertex count
nop iadd vi09,vi00,vi02 ; clipPtr, can do this in-place
nop lq vf24,clipConsts(vi00) ; [fogNear, fogFar, near, far]
LLClipPrimLoop:
nop lq vf01,0+0*numInAttribs(vi02) ; - load pos[0]
nop lq vf03,0+1*numInAttribs(vi02) ; - load pos[1]
addw.x vf02,vf00,vf00 nop ; make bary1
addw.y vf04,vf00,vf00 move.yz vf02,vf00 ; make bary2 - make bary1
mulax acc,vf28,vf01 move.xz vf04,vf00 ; xform pos[0] - make bary2
madday acc,vf29,vf01 nop
maddaz acc,vf30,vf01 iaddiu vi02,vi02,2*numInAttribs ; - next input segment
maddw vf01,vf31,vf00 isubiu vi04,vi04,2
mulax acc,vf28,vf03 nop ; xform pos[1]
madday acc,vf29,vf03 nop
maddaz acc,vf30,vf03 nop
maddw vf03,vf31,vf00 nop
nop nop
nop nop
clipw.xyz vf01,vf01 nop
clipw.xyz vf03,vf03 nop
nop nop
nop nop
nop nop
nop fcand vi01,0xFFF ; test if any vert is out of the frustum
nop ibeq vi01,vi00,LLClipAllInside ; no, all inside
;; Call Clipper
nop nop ; ClipLine tests clip flags in first instruction!
nop bal vi15,ClipLine ; skips return if there is a segment
nop nop
nop b LLClipNext
nop nop
LLClipNewSeg:
;; insert new segment here
addx.z vf01,vf00,vf00 lq vf05,1-2*numInAttribs(vi02) ; clear ADC - load st[0]
addx.z vf03,vf00,vf00 lq vf06,1-1*numInAttribs(vi02) ; clear ADC - load st[1]
nop lq vf07,2-2*numInAttribs(vi02) ; - load rgba[0]
nop lq vf08,2-1*numInAttribs(vi02) ; - load rgba[1]
mulax acc,vf05,vf02 nop ; interpolate st[0]
maddy vf09,vf06,vf02 sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
mulax acc,vf07,vf02 nop ; interpolate rgba[0]
maddy vf10,vf08,vf02 sq vf03,0+1*numInAttribs(vi09) ; - store clip[1]
mulax acc,vf05,vf04 nop ; interpolate st[1]
maddy vf11,vf06,vf04 sq vf09,1+0*numInAttribs(vi09) ; - store st[0]
mulax acc,vf07,vf04 iaddiu vi03,vi03,2 ; interpolate rgba[1] - inc nClipped
maddy vf12,vf08,vf04 sq vf10,2+0*numInAttribs(vi09) ; - store rgba[0]
nop iaddiu vi09,vi09,2*numInAttribs
nop sq vf11,1-1*numInAttribs(vi09) ; - store st[1]
nop b LLClipNext
nop sq vf12,2-1*numInAttribs(vi09) ; - store rgba[1]
LLClipAllInside:
;; segment completely inside
addx.z vf01,vf00,vf00 lq vf05,1-2*numInAttribs(vi02) ; clear ADC - load st[0]
addx.z vf03,vf00,vf00 lq vf06,1-1*numInAttribs(vi02) ; clear ADC - load st[1]
nop lq vf07,2-2*numInAttribs(vi02) ; - load rgba[0]
nop lq vf08,2-1*numInAttribs(vi02) ; - load rgba[1]
nop sq vf05,1+0*numInAttribs(vi09) ; - store st[0]
nop sq vf06,1+1*numInAttribs(vi09) ; - store st[1]
nop sq vf07,2+0*numInAttribs(vi09) ; - store rgba[0]
nop sq vf08,2+1*numInAttribs(vi09) ; - store rgba[1]
nop sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
nop sq vf03,0+1*numInAttribs(vi09) ; - store clip[1]
nop iaddiu vi03,vi03,2 ; - inc nClipped
nop iaddiu vi09,vi09,2*numInAttribs
LLClipNext:
nop ibgtz vi04,LLClipPrimLoop ; more input
nop nop
nop ibeq vi03,vi00,End ; nothing to render
nop nop
;; Process Clip buffer to output buffer and render
nop bal vi15,ProcessClip
nop xtop vi09
nop b End
nop nop
+100
View File
@@ -0,0 +1,100 @@
nop xtop vi02 ; input pointer
nop xitop vi04 ; vertex count
nop isubiu vi04,vi04,1 ; for linestrip
LSClipLoop:
nop iaddiu vi03,vi00,0 ; clipped vertex count
nop iaddiu vi09,vi00,clipBuf ; clipPtr
nop lq vf24,clipConsts(vi00) ; [fogNear, fogFar, near, far]
nop iaddiu vi08,vi00,1 ; restartStrip flag
LSClipPrimLoop:
nop lq vf01,0+0*numInAttribs(vi02) ; - load pos[0]
nop lq vf03,0+1*numInAttribs(vi02) ; - load pos[1]
addw.x vf02,vf00,vf00 ilw.w vi15,0+1*numInAttribs(vi02) ; make bary1 - load pos[1].w, ADC flag
addw.y vf04,vf00,vf00 isubiu vi04,vi04,1 ; make bary2
mulax acc,vf28,vf01 nop ; xform pos[0]
madday acc,vf29,vf01 ibltz vi04,LSClipRender ; - this could only really happen the first time
maddaz acc,vf30,vf01 iaddiu vi02,vi02,numInAttribs ; - next input segment
maddw vf01,vf31,vf00 ibne vi15,vi00,LSClipSkip ; - this segment is marked, skip it
mulax acc,vf28,vf03 ior vi08,vi08,vi15 ; xform pos[1] - also set restart flag
madday acc,vf29,vf03 nop
maddaz acc,vf30,vf03 nop
maddw vf03,vf31,vf00 nop
nop nop
nop nop
clipw.xyz vf01,vf01 move.yz vf02,vf00 ; - make bary1
clipw.xyz vf03,vf03 move.xz vf04,vf00 ; - mark bary2
nop nop
nop nop
nop nop
nop fcand vi01,0xFFF ; test if any vert is out of the frustum
nop ibeq vi01,vi00,LSClipAllInside ; no, all inside
;; Call Clipper
nop nop ; ClipLine tests clip flags in first instruction!
nop bal vi15,ClipLine ; skips return if there is a segment
nop nop
nop b LSClipSkip
nop iaddiu vi08,vi00,1 ; have to restart strip
LSClipNewSeg:
;; insert new segment here
nop loi 2048.0
addi.z vf01,vf00,i lq vf05,1-1*numInAttribs(vi02) ; set ADC - load st[0
addx.z vf03,vf00,vf00 lq vf06,1-0*numInAttribs(vi02) ; clear ADC - load st[1]
nop lq vf07,2-1*numInAttribs(vi02) ; - load rgba[0]
nop lq vf08,2-0*numInAttribs(vi02) ; - load rgba[1]
mulax acc,vf05,vf02 iaddiu vi08,vi00,1 ; interpolate st[0] - have to restart strip
maddy vf09,vf06,vf02 sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
mulax acc,vf07,vf02 nop ; interpolate rgba[0]
maddy vf10,vf08,vf02 sq vf03,0+1*numInAttribs(vi09) ; - store clip[1]
mulax acc,vf05,vf04 nop ; interpolate st[1]
maddy vf11,vf06,vf04 sq vf09,1+0*numInAttribs(vi09) ; - store st[0]
mulax acc,vf07,vf04 iaddiu vi03,vi03,2 ; interpolate rgba[1] - inc nClipped
maddy vf12,vf08,vf04 sq vf10,2+0*numInAttribs(vi09) ; - store rgba[0]
nop iaddiu vi09,vi09,2*numInAttribs
nop sq vf11,1-1*numInAttribs(vi09) ; - store st[1]
nop b LSClipPrimEnd
nop sq vf12,2-1*numInAttribs(vi09) ; - store rgba[1]
LSClipAllInside:
nop ibeq vi08,vi00,LSClipContStrip
nop loi 2048.0
addi.z vf01,vf00,i lq vf05,1-1*numInAttribs(vi02) ; clear ADC - load st[0]
nop lq vf07,2-1*numInAttribs(vi02) ; - load rgba[0]
nop iaddiu vi03,vi03,1 ; - inc nClipped
nop iaddiu vi09,vi09,numInAttribs
nop sq vf05,1-1*numInAttribs(vi09) ; - store st[0]
nop sq vf07,2-1*numInAttribs(vi09) ; - store rgba[0]
nop sq vf01,0-1*numInAttribs(vi09) ; - store clip[0]
LSClipContStrip:
addx.z vf03,vf00,vf00 lq vf06,1-0*numInAttribs(vi02) ; clear ADC - load st[1]
nop lq vf08,2-0*numInAttribs(vi02) ; - load rgba[1]
nop iaddiu vi03,vi03,1 ; - inc nClipped
nop iaddiu vi09,vi09,numInAttribs
nop sq vf06,1-1*numInAttribs(vi09) ; - store st[1]
nop sq vf08,2-1*numInAttribs(vi09) ; - store rgba[1]
nop sq vf03,0-1*numInAttribs(vi09) ; - store clip[1]
nop iaddiu vi08,vi00,0 ; we'll be in a strip after this
LSClipPrimEnd:
;; TODO: don't use clipVertLimitTS
nop isubiu vi15,vi03,clipVertLimitTS ; can we overflow next time?
nop nop
nop ibgtz vi15,LSClipRender ; yes, have to render
LSClipSkip:
nop nop
nop ibgtz vi04,LSClipPrimLoop ; next segment
nop nop
LSClipRender:
nop ibeq vi03,vi00,End ; nothing to render
nop nop
;; Process Clip buffer to output buffer and render
nop bal vi15,ProcessClip
nop iaddiu vi09,vi00,clipBuf
nop iblez vi04,End ; no more verts to process
nop nop
nop b LSClipLoop ; next batch
nop nop
+35
View File
@@ -0,0 +1,35 @@
nop xtop vi02 ; input pointer
nop xitop vi04 ; vertex count
nop lq vf10,0(vi02) ; load pos
nop iadd vi03,vi00,vi00 ; nClipped
nop iadd vi09,vi00,vi02 ; we're culling in-place
mulaw acc,vf31,vf00 nop
PCullLoop:
maddax acc,vf28,vf10 lq vf02,1(vi02) ; xform pos - load st
madday acc,vf29,vf10 lq vf03,2(vi02) ; - load rgba
maddz vf01,vf30,vf10 nop
nop iaddiu vi02,vi02,numInAttribs
nop isubiu vi04,vi04,1
nop lq vf10,0(vi02) ; load next pos
clipw.xyz vf01,vf01 nop ; check if clipped
addx.z vf01,vf00,vf00 nop ; clear ADC
nop nop
mulaw acc,vf31,vf00 nop
nop fcand vi01,0x3F ; test if vert is out of the frustum
nop ibne vi01,vi00,PCullSkip ; yup, skip it
nop sq vf01,0(vi09) ; - store clip
nop sq vf02,1(vi09) ; - store st
nop sq vf03,2(vi09) ; - store rgba
nop iaddiu vi03,vi03,1 ; - inc nClipped
nop iaddiu vi09,vi09,numInAttribs
PCullSkip:
nop ibne vi04,vi00,PCullLoop ; more input
nop nop
nop ibeq vi03,vi00,End ; nothing to render
nop nop
;; Process Clip buffer to output buffer and render
nop bal vi15,ProcessClip
nop xtop vi09
nop b End
nop nop
+182
View File
@@ -0,0 +1,182 @@
;;; Triangle List clipping
;;; Process input buffer to Clipping buffer
;;; flush Clipping buffer whenever it gets full
; vi01
; vi02 input buffer have to save this
; vi03 nClipped
; vi04 nVerts have to save this
; vi05 polyInPtr
; vi06 polyInEnd
; vi07 polyOutPtr
; vi08
; vi09 clipPtr
; vi10 polyBuf1
; vi11 polyBuf2
; vi12
; vi15
nop xtop vi02 ; input pointer
nop xitop vi04 ; vertex count
TLClipLoop:
nop iaddiu vi03,vi00,0 ; clipped vertex count
nop iaddiu vi09,vi00,clipBuf ; clipPtr
nop iadd vi10,vi00,vi12 ; polyBuf1
nop iaddiu vi11,vi10,2*10 ; polyBuf2, need some space for trailing junk
nop lq vf24,clipConsts(vi00) ; [fogNear, fogFar, near, far]
TLClipPrimLoop:
;; We have two polygon buffers (at vi10 and vi11).
;; For every clipping plane, clip polygon in one and generate new poly in the other
nop iadd vi05,vi00,vi10 ; polyInPtr
nop iaddiu vi06,vi05,6 ; polyInEnd
nop iadd vi07,vi00,vi11 ; polyOutPtr
;; init polygon buffer
nop lq vf01,0+0*numInAttribs(vi02) ; - load pos[0]
nop ilw.w vi15,0+2*numInAttribs(vi02) ; - load pos[2].w, ADC flag
nop lq vf02,0+1*numInAttribs(vi02) ; - load pos[1]
nop lq vf03,0+2*numInAttribs(vi02) ; - load pos[2]
mulax acc,vf28,vf01 nop ; xform pos[0]
madday acc,vf29,vf01 nop
maddaz acc,vf30,vf01 iaddiu vi02,vi02,3*numInAttribs ; - next input triangle
maddw vf01,vf31,vf00 isubiu vi04,vi04,3
mulax acc,vf28,vf02 nop ; xform pos[1]
madday acc,vf29,vf02 ibltz vi04,TLClipRender
maddaz acc,vf30,vf02 mr32 vf06,vf00 ; - make bary[2]
maddw vf02,vf31,vf00 sq vf01,0(vi05) ; - store pos[0] in polybuf
mulax acc,vf28,vf03 ibne vi15,vi00,TLClipSkip ; xform pos[2] - this tri is marked, skip it
madday acc,vf29,vf03 nop
maddaz acc,vf30,vf03 mr32 vf05,vf06 ; - make bary[1]
maddw vf03,vf31,vf00 sq vf02,2(vi05) ; - store pos[1] in polybuf
; do first clipping test (note we test the first one twice)
; note only z-test is valid at this point because w can still be negative
clipw.xyz vf01,vf01 nop
clipw.xyz vf01,vf01 nop
clipw.xyz vf02,vf02 mr32 vf04,vf05 ; - make bary[0]
clipw.xyz vf03,vf03 sq vf03,4(vi05) ; - store pos[2] in polybuf
nop sq vf06,5(vi05) ; - store bary[2]
nop sq vf05,3(vi05) ; - store bary[1]
nop sq vf04,1(vi05) ; - store bary[0]
nop fcand vi01,0xFFFFFF ; test if any vert is out of the frustum
nop ibeq vi01,vi00,TLClipAllInside ; no, all inside
;; Call Clipper
nop nop
nop bal vi15,ClipTriangle ; skips return if there is a poly
nop nop
nop b TLClipSkip
nop nop
TLClipTriangulate:
;; interpolate vertices and create new primitives from polygon buffer here
;; this depends on the INPUTFORMAT
/*
v0 = interp(c0);
v1 = interp(c1);
clipPtr[1] = v1;
i = 2;
do {
vi = interp(ci);
i++;
clipPtr[0] = v0;
clipPtr[2] = vi;
clipPtr += 3;
if(polyPtr == polyEnd)
break;
clipPtr[1] = vi;
}
*/
; vf01 - clip[0]
; vf02 - bary[0]
; vf03 - clip[i]
; vf04 - bary[i]
; input verts
; vf10 - rgba[0]
; vf11 - rgba[1]
; vf12 - rgba[2]
; vf13 - st[0]
; vf14 - st[1]
; vf15 - st[2]
; vf16 - clip rgba[0]
; vf17 - clip st[0]
; vf18 - clip rgba[n]
; vf19 - clip st[n]
nop lq vf04,3(vi05) ; - load bary[1]
nop ibeq vi05,vi06,TLClipSkip ; - no vertices at all
addx.z vf01,vf00,vf00 lq vf10,1-3*numInAttribs(vi02) ; clear ADC - load st[0]
addx.z vf03,vf00,vf00 lq vf11,1-2*numInAttribs(vi02) ; clear ADC - load st[1]
nop lq vf12,1-1*numInAttribs(vi02) ; - load st[2]
nop lq vf13,2-3*numInAttribs(vi02) ; - load rgba[0]
mulax acc,vf10,vf04 lq vf14,2-2*numInAttribs(vi02) ; interpolate st[1] - load rgba[1]
madday acc,vf11,vf04 lq vf15,2-1*numInAttribs(vi02) ; interpolate st[1] - load rgba[2]
maddz vf18,vf12,vf04 lq vf02,1(vi05) ; interpolate st[1] - load bary[0]
mulax acc,vf13,vf04 lq.xyw vf03,2(vi05) ; interpolate rgba[1] - load clip[1]
madday acc,vf14,vf04 lq.xyw vf01,0(vi05) ; interpolate rgba[1] - load clip[0]
maddz vf19,vf15,vf04 iaddiu vi05,vi05,4 ; interpolate rgba[1]
mulax acc,vf10,vf02 nop ; interpolate st[0]
madday acc,vf11,vf02 sq vf03,0+1*numInAttribs(vi09) ; interpolate st[0] - store clip[1]
maddz vf16,vf12,vf02 sq vf18,1+1*numInAttribs(vi09) ; interpolate st[0] - store st[1]
mulax acc,vf13,vf02 sq vf19,2+1*numInAttribs(vi09) ; interpolate rgba[0] - store rgba[1]
madday acc,vf14,vf02 nop ; interpolate rgba[0]
maddz vf17,vf15,vf02 nop ; interpolate rgba[0]
TLClipTriLoop:
;; write one triangle here
nop lq vf04,1(vi05) ; - load bary[i]
nop lq.xyw vf03,0(vi05) ; - load clip[i]
nop sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
nop sq vf16,1+0*numInAttribs(vi09) ; - store st[0]
mulax acc,vf10,vf04 sq vf17,2+0*numInAttribs(vi09) ; interpolate st[i] - store rgba[0]
madday acc,vf11,vf04 iaddiu vi05,vi05,2 ; interpolate st[i] - inc polyPtr
maddz vf18,vf12,vf04 iaddiu vi03,vi03,3 ; interpolate st[i] - inc nClipped
mulax acc,vf13,vf04 nop ; interpolate rgba[i]
madday acc,vf14,vf04 nop ; interpolate rgba[i]
maddz vf19,vf15,vf04 sq vf03,0+2*numInAttribs(vi09) ; interpolate rgba[i] - store clip[i]
nop sq vf18,1+2*numInAttribs(vi09) ; - store st[i]
nop iaddiu vi09,vi09,3*numInAttribs ; - inc clipPtr
nop ibeq vi05,vi06,TLClipPrimEnd ; - reached the end
nop sq vf19,2-1*numInAttribs(vi09) ; - store rgba[i]
nop sq vf03,0+1*numInAttribs(vi09) ; - store clip[i]
nop sq vf18,1+1*numInAttribs(vi09) ; - store st[i]
nop b TLClipTriLoop
nop sq vf19,2+1*numInAttribs(vi09) ; - store rgba[i]
TLClipAllInside:
;; copy full triangle
;; this depends on the INPUTFORMAT
nop lq vf04,1-3*numInAttribs(vi02) ; - load st[0]
nop lq vf05,1-2*numInAttribs(vi02) ; - load st[1]
nop lq vf06,1-1*numInAttribs(vi02) ; - load st[2]
nop lq vf07,2-3*numInAttribs(vi02) ; - load rgba[0]
nop lq vf08,2-2*numInAttribs(vi02) ; - load rgba[1]
nop lq vf09,2-1*numInAttribs(vi02) ; - load rgba[2]
nop sq vf04,1+0*numInAttribs(vi09) ; - store st[0]
nop sq vf05,1+1*numInAttribs(vi09) ; - store st[1]
addx.z vf01,vf00,vf00 sq vf06,1+2*numInAttribs(vi09) ; clear ADC - store st[2]
addx.z vf02,vf00,vf00 sq vf07,2+0*numInAttribs(vi09) ; clear ADC - store rgba[0]
addx.z vf03,vf00,vf00 sq vf08,2+1*numInAttribs(vi09) ; clear ADC - store rgba[1]
nop sq vf09,2+2*numInAttribs(vi09) ; - store rgba[2]
nop sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
nop sq vf02,0+1*numInAttribs(vi09) ; - store clip[1]
nop sq vf03,0+2*numInAttribs(vi09) ; - store clip[2]
nop iaddiu vi03,vi03,3 ; - inc nClipped
nop iaddiu vi09,vi09,3*numInAttribs
TLClipPrimEnd:
nop isubiu vi15,vi03,clipVertLimitTL ; can we overflow next time?
nop nop
nop ibgtz vi15,TLClipRender ; yes, have to render
TLClipSkip:
nop nop
nop ibgtz vi04,TLClipPrimLoop ; next Triangle
nop nop
TLClipRender:
nop ibeq vi03,vi00,End
nop nop
;; Process Clip buffer to output buffer and render
nop bal vi15,ProcessClip
nop iaddiu vi09,vi00,clipBuf
nop iblez vi04,End ; no more verts to process
nop nop
nop b TLClipLoop ; next batch
nop nop
+187
View File
@@ -0,0 +1,187 @@
;;; Triangle List clipping
;;; Process input buffer to Clipping buffer
;;; flush Clipping buffer whenever it gets full
; vi01
; vi02 input buffer have to save this
; vi03 nClipped
; vi04 nVerts have to save this
; vi05 polyInPtr
; vi06 polyInEnd
; vi07 polyOutPtr
; vi08
; vi09 clipPtr
; vi10 polyBuf1
; vi11 polyBuf2
; vi12
; vi15
nop xtop vi02 ; input pointer
nop xitop vi04 ; vertex count
nop isubiu vi04,vi04,2 ; for tristrip
TSClipLoop:
nop iaddiu vi03,vi00,0 ; clipped vertex count
nop iaddiu vi09,vi00,clipBuf ; clipPtr
nop iadd vi10,vi00,vi12 ; polyBuf1
nop iaddiu vi11,vi10,2*10 ; polyBuf2, need some space for trailing junk
nop lq vf24,clipConsts(vi00) ; [fogNear, fogFar, near, far]
nop iaddiu vi08,vi00,1 ; restartStrip flag
TSClipPrimLoop:
;; We have two polygon buffers (at vi10 and vi11).
;; For every clipping plane, clip polygon in one and generate new poly in the other
nop iadd vi05,vi00,vi10 ; polyInPtr
nop iaddiu vi06,vi05,6 ; polyInEnd
nop iadd vi07,vi00,vi11 ; polyOutPtr
;; init polygon buffer
nop lq vf10,0+0*numInAttribs(vi02) ; - load pos[0]
nop ilw.w vi15,0+2*numInAttribs(vi02) ; - load pos[2].w, ADC flag
nop lq vf11,0+1*numInAttribs(vi02) ; - load pos[1]
nop lq vf12,0+2*numInAttribs(vi02) ; - load pos[2]
mulax acc,vf28,vf10 isubiu vi04,vi04,1 ; xform pos[0]
madday acc,vf29,vf10 iaddiu vi02,vi02,numInAttribs ; - next input triangle
maddaz acc,vf30,vf10 ibltz vi04,TSClipRender ; - this could only really happen the first time
maddw vf01,vf31,vf00 nop
mulax acc,vf28,vf11 ibne vi15,vi00,TSClipSkip ; xform pos[1] - this tri is marked, skip it
madday acc,vf29,vf11 ior vi08,vi08,vi15 ; - also set restart flag
maddaz acc,vf30,vf11 mr32 vf06,vf00 ; - make bary[2]
maddw vf02,vf31,vf00 sq vf01,0(vi05) ; - store pos[0] in polybuf
mulax acc,vf28,vf12 nop ; xform pos[2]
madday acc,vf29,vf12 nop
maddaz acc,vf30,vf12 mr32 vf05,vf06 ; - make bary[1]
maddw vf03,vf31,vf00 sq vf02,2(vi05) ; - store pos[1] in polybuf
; do first clipping test (note we test the first one twice)
; note only z-test is valid at this point because w can still be negative
clipw.xyz vf01,vf01 nop
clipw.xyz vf01,vf01 nop
clipw.xyz vf02,vf02 mr32 vf04,vf05 ; - make bary[0]
clipw.xyz vf03,vf03 sq vf03,4(vi05) ; - store pos[2] in polybuf
sub.xyz vf13,vf11,vf10 sq vf06,5(vi05) ; get vectors for zero-area test - store bary[2]
sub.xyz vf14,vf12,vf10 sq vf05,3(vi05) ; - store bary[1]
nop sq vf04,1(vi05) ; - store bary[0]
nop fcand vi01,0xFFFFFF ; test if any vert is out of the frustum
nop ibeq vi01,vi00,TSClipAllInside ; no, all inside
;;; TEMP? cull degenerate tris that can become visible from clipping
.if 1
.if 1
opmula.xyz acc,vf13,vf14 iaddiu vi15,vi00,0xE
opmsub.xyz vf00,vf14,vf13 nop
nop nop
nop nop
nop nop
nop fmand vi01,vi15
nop ibeq vi01,vi15,TSClipZeroArea
.else ;; less efficient unless maybe it can be inserted above somewhere
sub.xyz vf00,vf11,vf10 nop
nop nop
sub.xyz vf00,vf12,vf10 nop
nop iaddiu vi15,vi00,0xE
sub.xyz vf00,vf11,vf12 fmand vi01,vi15
nop ibeq vi01,vi15,TSClipZeroArea
nop fmand vi01,vi15
nop ibeq vi01,vi15,TSClipZeroArea
nop fmand vi01,vi15
nop ibeq vi01,vi15,TSClipZeroArea
.endif
.endif
;; Call Clipper
nop nop
nop bal vi15,ClipTriangle ; skips return if there is a poly
nop nop
nop b TSClipSkip
nop iaddiu vi08,vi00,1 ; have to restart strip
TSClipTriangulate:
;; interpolate vertices and create new primitives from polygon buffer here
;; this depends on the INPUTFORMAT
nop ibeq vi05,vi06,TSClipSkip ; - no vertices at all
nop iaddiu vi08,vi00,1 ; - have to restart strip
nop loi 2048.0
addi.z vf01,vf00,i lq vf10,1-1*numInAttribs(vi02) ; insert first two with ADC - load st[0]
addi.z vf02,vf00,i lq vf11,1-0*numInAttribs(vi02) ; - load st[1]
nop lq vf12,1+1*numInAttribs(vi02) ; - load st[2]
nop lq vf13,2-1*numInAttribs(vi02) ; - load rgba[0]
nop lq vf14,2-0*numInAttribs(vi02) ; - load rgba[1]
nop lq vf15,2+1*numInAttribs(vi02) ; - load rgba[2]
nop lq vf03,1(vi05) ; - bary1
nop lq vf04,-1(vi06) ; - bary2
nop lq.xyw vf01,0(vi05) ; - clip1
nop lq.xyw vf02,-2(vi06) ; - clip2
TSClipTriLoop:
nop iaddiu vi08,vi00,1 ; - have to restart strip
mulax acc,vf10,vf03 iaddiu vi05,vi05,2 ; interpolate st1
madday acc,vf11,vf03 isubiu vi07,vi06,2
maddz vf16,vf12,vf03 iaddiu vi03,vi03,1 ; inc nClipped
mulax acc,vf13,vf03 sq vf01,0+0*numInAttribs(vi09) ; interpolate rgba1 - store clip1
madday acc,vf14,vf03 lq.xyw vf01,0(vi05) ; - next clip1
maddz vf17,vf15,vf03 lq vf03,1(vi05) ; - next bary1
mulax acc,vf10,vf04 lq vf05,-3(vi06) ; interpolate st2 - next bary2
madday acc,vf11,vf04 lq.xyw vf06,-4(vi06)
maddz vf18,vf12,vf04 sq vf16,1+0*numInAttribs(vi09) ; - store rgba1
mulax acc,vf13,vf04 sq vf17,2+0*numInAttribs(vi09) ; interpolate rgba2 - store st1
madday acc,vf14,vf04 ibeq vi05,vi06,TSClipPrimEnd
maddz vf19,vf15,vf04 iaddiu vi09,vi09,numInAttribs
addx vf04,vf05,vf00 iaddiu vi03,vi03,1 ; advance bary2
addx.xyw vf02,vf06,vf00 sq vf02,0+0*numInAttribs(vi09) ; advance clip2 - store clip2
nop sq vf18,1+0*numInAttribs(vi09) ; - store st2
nop sq vf19,2+0*numInAttribs(vi09) ; - store rgba2
addx.z vf01,vf00,vf00 ibeq vi05,vi06,TSClipPrimEnd ; insert all others without ADC
addx.z vf02,vf00,vf00 iaddiu vi09,vi09,numInAttribs
nop b TSClipTriLoop
nop nop
TSClipZeroArea:
nop b TSClipSkip
nop iaddiu vi08,vi00,1 ; - have to restart strip
nop nop ; make assembler happy
TSClipAllInside:
;; copy full triangle
;; this depends on the INPUTFORMAT
nop ibeq vi08,vi00,TSClipContStrip
nop loi 2048.0
;; Have to restart the strip here
nop lq vf04,1-1*numInAttribs(vi02) ; - load st[0]
nop lq vf05,1-0*numInAttribs(vi02) ; - load st[1]
addi.z vf01,vf00,i lq vf07,2-1*numInAttribs(vi02) ; set ADC - load rgba[0]
addi.z vf02,vf00,i lq vf08,2-0*numInAttribs(vi02) ; set ADC - load rgba[1]
nop sq vf04,1+0*numInAttribs(vi09) ; - store st[0]
nop sq vf05,1+1*numInAttribs(vi09) ; - store st[1]
nop sq vf07,2+0*numInAttribs(vi09) ; - store rgba[0]
nop sq vf08,2+1*numInAttribs(vi09) ; - store rgba[1]
nop sq vf01,0+0*numInAttribs(vi09) ; - store clip[0]
nop sq vf02,0+1*numInAttribs(vi09) ; - store clip[1]
nop iaddiu vi03,vi03,2 ; - inc nClipped
nop iaddiu vi09,vi09,2*numInAttribs
nop iaddiu vi08,vi00,0 ; we ll be in a strip after this
TSClipContStrip:
addx.z vf03,vf00,vf00 lq vf06,1+1*numInAttribs(vi02) ; clear ADC - load st[2]
nop lq vf09,2+1*numInAttribs(vi02) ; - load rgab[2]
nop iaddiu vi03,vi03,1 ; - inc nClipped
nop iaddiu vi09,vi09,numInAttribs
nop sq vf06,1-1*numInAttribs(vi09) ; - store st[2]
nop sq vf09,2-1*numInAttribs(vi09) ; - store rgba[2]
nop sq vf03,0-1*numInAttribs(vi09) ; - store clip[2]
TSClipPrimEnd:
nop isubiu vi15,vi03,clipVertLimitTS ; can we overflow next time?
nop nop
nop ibgtz vi15,TSClipRender ; yes, have to render
TSClipSkip:
nop nop
nop ibgtz vi04,TSClipPrimLoop ; next Triangle
nop nop
TSClipRender:
nop ibeq vi03,vi00,End ; nothing to render
nop nop
;; Process Clip buffer to output buffer and render
nop bal vi15,ProcessClip
nop iaddiu vi09,vi00,clipBuf
nop iblez vi04,End ; no more verts to process
nop nop
nop b TSClipLoop ; next batch
nop nop
+230
View File
@@ -0,0 +1,230 @@
;;;;;;;;;;;;
;;;;;;; Perspective Line Segment Clipper
;;;;;;;;;;;
;; TODO? start interpolating earlier and test the clipping flags later
;;;; Uses the following registers
;;
;; vi01 tmp
;; vi15 tmp (return address)
;;
;; vf01 p1 pos input
;; vf02 p1 bary input
;; vf03 p2 pos input
;; vf04 p2 bary input
;; vf05 interp pos
;; vf06 interp bary
;; vf07.w d2
;; vf08.w d1
;; vf09.w d1-d2
ClipLine:
.if 1
;;; ====== w = near plane ======
nop fcor vi01,negZo2 ; test if both out
sub.w vf09,vf01,vf03 ibne vi01,vi00,CullLine ; d1-d2 - yes, skip this segment completely
subz.w vf07,vf01,vf24 fcand vi01,negZn2 ; d1 - test if both in
subz.w vf08,vf03,vf24 ibeq vi01,vi00,LClipNegZ_End ; d2 - yes, no need to clip against this plane
;; So we need to interpolate
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,negZn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipNegZ_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipNegZ_Done
clipw.xyz vf05,vf05 move vf04,vf06
LClipNegZ_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipNegZ_Done:
nop nop ; wait for clipping flags
nop nop
nop nop
LClipNegZ_End:
.endif
.if 1
;;; ====== w = far plane ======
nop fcor vi01,posZo2 ; test if both out
sub.w vf09,vf03,vf01 ibne vi01,vi00,CullLine ; d1-d2 - yes, skip this segment completely
sub.w vf07,vf24,vf01 fcand vi01,posZn2 ; d1 - test if both in
sub.w vf08,vf24,vf03 ibeq vi01,vi00,LClipPosZ_End ; d2 - yes, no need to clip against this plane
;; So we need to interpolate
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,posZn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipPosZ_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipPosZ_Done
clipw.xyz vf05,vf05 move vf04,vf06
LClipPosZ_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipPosZ_Done:
nop nop ; wait for clipping flags
nop nop
nop nop
LClipPosZ_End:
.endif
.if 1
;;; ====== w = -x ======
addax.w acc,vf01,vf01 fcor vi01,negXo2 ; test if both out
msubax.w acc,vf00,vf03 ibne vi01,vi00,CullLine ; yes, skip this segment completely
msub.w vf09,vf00,vf03 fcand vi01,negXn2 ; d1-d2 test if both in
addx.w vf07,vf01,vf01 ibeq vi01,vi00,LClipNegX_End ; d1 yes, no need to clip against this plane
;; So we need to interpolate
addx.w vf08,vf03,vf03 nop ; d2
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,negXn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipNegX_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipNegX_Done
clipw.xyz vf05,vf05 move vf04,vf06
LClipNegX_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipNegX_Done:
nop nop ; wait for clipping flags
nop nop
nop nop
LClipNegX_End:
.endif
.if 1
;;; ====== w = x ======
subax.w acc,vf01,vf01 fcor vi01,posXo2 ; test if both out
maddax.w acc,vf00,vf03 ibne vi01,vi00,CullLine ; yes, skip this segment completely
msub.w vf09,vf00,vf03 fcand vi01,posXn2 ; d1-d2 - test if both in
subx.w vf07,vf01,vf01 ibeq vi01,vi00,LClipPosX_End ; d1 - yes, no need to clip against this plane
;; So we need to interpolate
subx.w vf08,vf03,vf03 nop ; d2
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,posXn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipPosX_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipPosX_Done
clipw.xyz vf05,vf05 move vf04,vf06
LClipPosX_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipPosX_Done:
nop nop ; wait for clipping flags
nop nop
nop nop
LClipPosX_End:
.endif
.if 1
;;; ====== w = -y ======
adday.w acc,vf01,vf01 fcor vi01,negYo2 ; test if both out
msubay.w acc,vf00,vf03 ibne vi01,vi00,CullLine ; yes, skip this segment completely
msub.w vf09,vf00,vf03 fcand vi01,negYn2 ; d1-d2 - test if both in
addy.w vf07,vf01,vf01 ibeq vi01,vi00,LClipNegY_End ; d1 - yes, no need to clip against this plane
;; So we need to interpolate
addy.w vf08,vf03,vf03 nop ; d2
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,negYn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipNegY_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipNegY_Done
clipw.xyz vf05,vf05 move vf04,vf06
LClipNegY_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipNegY_Done:
nop nop ; wait for clipping flags
nop nop
nop nop
LClipNegY_End:
.endif
.if 1
;;; ====== w = y ======
subay.w acc,vf01,vf01 fcor vi01,posYo2 ; test if both out
madday.w acc,vf00,vf03 ibne vi01,vi00,CullLine ; yes, skip this segment completely
msub.w vf09,vf00,vf03 fcand vi01,posYn2 ; d1-d2 - test if both in
suby.w vf07,vf01,vf01 ibeq vi01,vi00,LClipPosY_End ; d2 - yes, no need to clip against this plane
;; So we need to interpolate
suby.w vf08,vf03,vf03 nop ; d2
nop nop
nop div q,vf00w,vf09w
mulaw acc,vf03,vf07 nop ; interp pos (acc = p2*d1)
msubw vf05,vf01,vf08 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf07 nop ; interp bary (acc = p2*d1)
msubw vf06,vf02,vf08 nop ; interp bary (acc - p1*d2)
nop nop
nop nop
mulq vf05,vf05,q nop ; interp pos
mulq vf06,vf06,q nop ; interp bary
nop fcand vi01,posYn1 ; test p2's cliping
nop ibeq vi01,vi00,LClipPosY_p1 ; it's in, so p1 is out
;; p2 is out, so replace it
nop nop
clipw.xyz vf01,vf01 move vf03,vf05
nop b LClipPosY_End
clipw.xyz vf05,vf05 move vf04,vf06
LClipPosY_p1: ;; p1 is out, so replace it
clipw.xyz vf05,vf05 move vf01,vf05
clipw.xyz vf03,vf03 move vf02,vf06
LClipPosY_End:
.endif
nop iaddiu vi15,vi15,2
CullLine:
nop jr vi15
nop nop
+272
View File
@@ -0,0 +1,272 @@
;;;;;;;;;;;;
;;;;;;; Perspective Triangle Clipper
;;;;;;;;;;;
;;;; Uses the following registers
;;
;; vi01 tmp
;; vi05 polyInPtr input
;; vi06 polyInEnd input
;; vi07 polyOutPtr input
;; vi10 polyBuf1 input
;; vi11 polyBuf2 input
;; vi15 tmp (return address)
;;
;; vf01 p2 pos input
;; vf02 interp pos
;; vf03 p1 pos input
;; vf04 p2 bary
;; vf05 interp bary
;; vf06 p1 bary input
;; vf07.w d2
;; vf08.w d1
;; vf09.w d1-d2
;; vf22 tmp
;; vf23 tmp
ClipTriangle:
nop isw.w vi08,codeSwitch(vi00) ; save return
nop nop ;; TODO: assembler complains about hazard here. why?
nop iadd vi08,vi00,vi15 ;
.if 1
;;; ====== w = near plane ======
nop fcor vi01,negZo ; test if all out
nop ibne vi01,vi00,CullTri ; yes, skip this triangle completely
nop fcand vi01,negZn ; test if all in
nop ibeq vi01,vi00,ClipNegZ_Skip ; yes, no need to clip against this plane
ClipNegZ_Loop:
sub.w vf09,vf03,vf01 lq vf04,1(vi05) ; d1-d2 - load bary2
subz.w vf08,vf03,vf24 move vf22,vf03 ; d1 - save pos1
subz.w vf07,vf01,vf24 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipNegZ_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; advance bary1 - sign of d1*d2
clipw.xyz vf22,vf22 sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipNegZ_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipNegZ_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
clipw.xyz vf02,vf02 sq vf02,-2(vi07) ; - store interp pos
ClipNegZ_Next:
nop ibne vi05,vi06,ClipNegZ_Loop
nop sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipNegZ_Skip:
.endif
.if 1
;; Early out if all verts outside of any one plane
nop fcor vi01,posZo
nop ibne vi01,vi00,CullTri
nop fcor vi01,negXo
nop ibne vi01,vi00,CullTri
nop fcor vi01,posXo
nop ibne vi01,vi00,CullTri
nop fcor vi01,negYo
nop ibne vi01,vi00,CullTri
nop fcor vi01,posYo
nop ibne vi01,vi00,CullTri
.endif
.if 1
;;; ====== w = far plane ======
nop lq vf01,0(vi05) ; load p2 pos
nop ibeq vi05,vi06,CullTri
nop fcand vi01,posZn ; test if all in
nop ibeq vi01,vi00,ClipPosZ_Skip ; yes, no need to clip against this plane
nop nop
ClipPosZ_Loop:
sub.w vf09,vf01,vf03 lq vf04,1(vi05) ; d1-d2 - load bary2
sub.w vf08,vf24,vf03 move vf22,vf03 ; d1 - save pos1
sub.w vf07,vf24,vf01 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipPosZ_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; sign of d1*d2
nop sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipPosZ_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipPosZ_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
nop sq vf02,-2(vi07) ; - store interp pos
ClipPosZ_Next:
nop ibne vi05,vi06,ClipPosZ_Loop
nop sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipPosZ_Skip:
.endif
.if 1
;;; ====== w = -x plane ======
nop lq vf01,0(vi05) ; load p2 pos
nop ibeq vi05,vi06,CullTri
nop fcand vi01,negXn ; test if all in
addax.w acc,vf03,vf03 ibeq vi01,vi00,ClipNegX_Skip ; yes, no need to clip against this plane
msubax.w acc,vf00,vf01 nop
ClipNegX_Loop:
msub.w vf09,vf00,vf01 lq vf04,1(vi05) ; d1-d2 - load bary2
addx.w vf08,vf03,vf03 move vf22,vf03 ; d1 - save pos1
addx.w vf07,vf01,vf01 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipNegX_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; sign of d1*d2
nop sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipNegX_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipNegX_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
nop sq vf02,-2(vi07) ; - store interp pos
ClipNegX_Next:
addax.w acc,vf03,vf03 ibne vi05,vi06,ClipNegX_Loop
msubax.w acc,vf00,vf01 sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipNegX_Skip:
.endif
.if 1
;;; ====== w = +x plane ======
nop lq vf01,0(vi05) ; load p2 pos
nop ibeq vi05,vi06,CullTri
nop fcand vi01,posXn ; test if all in
subax.w acc,vf03,vf03 ibeq vi01,vi00,ClipPosX_Skip ; yes, no need to clip against this plane
maddax.w acc,vf00,vf01 nop
ClipPosX_Loop:
msub.w vf09,vf00,vf01 lq vf04,1(vi05) ; d1-d2 - load bary2
subx.w vf08,vf03,vf03 move vf22,vf03 ; d1 - save pos1
subx.w vf07,vf01,vf01 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipPosX_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; sign of d1*d2
nop sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipPosX_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipPosX_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
nop sq vf02,-2(vi07) ; - store interp pos
ClipPosX_Next:
subax.w acc,vf03,vf03 ibne vi05,vi06,ClipPosX_Loop
maddax.w acc,vf00,vf01 sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipPosX_Skip:
.endif
.if 1
;;; ====== w = -y plane ======
nop lq vf01,0(vi05) ; load p2 pos
nop ibeq vi05,vi06,CullTri
nop fcand vi01,negYn ; test if all in
adday.w acc,vf03,vf03 ibeq vi01,vi00,ClipNegY_Skip ; yes, no need to clip against this plane
msubay.w acc,vf00,vf01 nop
ClipNegY_Loop:
msub.w vf09,vf00,vf01 lq vf04,1(vi05) ; d1-d2 - load bary2
addy.w vf08,vf03,vf03 move vf22,vf03 ; d1 - save pos1
addy.w vf07,vf01,vf01 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipNegY_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; sign of d1*d2
nop sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipNegY_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipNegY_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
nop sq vf02,-2(vi07) ; - store interp pos
ClipNegY_Next:
adday.w acc,vf03,vf03 ibne vi05,vi06,ClipNegY_Loop
msubay.w acc,vf00,vf01 sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipNegY_Skip:
.endif
.if 1
;;; ====== w = +y plane ======
nop lq vf01,0(vi05) ; load p2 pos
nop ibeq vi05,vi06,CullTri
nop fcand vi01,posYn ; test if all in
subay.w acc,vf03,vf03 ibeq vi01,vi00,ClipPosY_Skip ; yes, no need to clip against this plane
madday.w acc,vf00,vf01 nop
ClipPosY_Loop:
msub.w vf09,vf00,vf01 lq vf04,1(vi05) ; d1-d2 - load bary2
suby.w vf08,vf03,vf03 move vf22,vf03 ; d1 - save pos1
suby.w vf07,vf01,vf01 move vf23,vf06 ; d2 - save pos2
addx vf03,vf01,vf00 iaddiu vi05,vi05,2 ; advance pos1
nop div q,vf00w,vf09w ; - 1/(d1-d2)
mulaw acc,vf01,vf08 fsand vi01,2 ; interp pos (acc = p2*d1) get d1 sign
mul.w vf00,vf07,vf08 lq vf01,0(vi05) ; d1*d2
msubw vf02,vf22,vf07 nop ; interp pos (acc - p1*d2)
mulaw acc,vf04,vf08 nop ; interp bary (acc = p2*d1)
msubw vf05,vf06,vf07 ibne vi01,vi00,ClipPosY_Clipped ; interp bary (acc - p1*d2)
addx vf06,vf04,vf00 fsand vi15,2 ; sign of d1*d2
nop sqi vf22,(vi07++) ; store p1
nop sqi vf23,(vi07++)
ClipPosY_Clipped: ; p1 is clipped
mulq vf02,vf02,q ibeq vi15,vi00,ClipPosY_Next ; interp pos
nop iadd vi01,vi00,vi07 ; always store interp bary here
mulq vf05,vf05,q iaddiu vi07,vi07,2 ; interp bary - advance out ptr
nop nop
nop sq vf02,-2(vi07) ; - store interp pos
ClipPosY_Next:
subay.w acc,vf03,vf03 ibne vi05,vi06,ClipPosY_Loop
madday.w acc,vf00,vf01 sq vf05,1(vi01) ; - store interp bary (or junk if no interpolation)
nop bal vi15,SwapClipBuffers
nop nop
ClipPosY_Skip:
.endif
nop iaddiu vi08,vi08,2
CullTri:
nop jr vi08
nop ilw.w vi08,codeSwitch(vi00)
;;;;;;;;;;;;
;;;;;;; End of Perspective Triangle Clipper
;;;;;;;;;;;
SwapClipBuffers:
nop iadd vi05,vi00,vi11 ; polyInPtr
nop iadd vi06,vi00,vi07 ; polyInEnd
nop iadd vi07,vi00,vi10 ; polyOutPtr
nop iadd vi11,vi00,vi10
nop iadd vi10,vi00,vi05
nop lq vf03,-2(vi06) ; load last vertex as p1
nop jr vi15
nop lq vf06,-1(vi06)
+131
View File
@@ -0,0 +1,131 @@
.equ vertexTop, 0x3d0
.equ numInAttribs, 4
.equ numOutAttribs, 3
.equ numOutBuf, 2
.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf))
.equ offset, (vertCount*numInAttribs)
.equ outBuf1, (2*offset)
;.equ outSize, ((vertexTop-outBuf1-numOutBuf)/numOutBuf)
.equ outSize, (1 + vertCount*numOutAttribs)
.equ outBuf2, (outBuf1+outSize)
.equ clipVertCount, ((vertexTop-outBuf1-numOutBuf)/(numInAttribs+numOutAttribs*numOutBuf))
.equ clipOutSize, (1 + clipVertCount*numOutAttribs)
.equ clipOutBuf2, (outBuf1+clipOutSize)
.equ clipBuf, (clipOutBuf2+clipOutSize)
; up to 9 verts => 7 tris per poly in worst case, a lot for lists unfortunately
.equ clipVertLimitTL, (clipVertCount-21)
.equ clipVertLimitTS, (clipVertCount-15) ;;; TODO: this crashes when i set it to -9 as it should be
.include "defines.inc"
#define IN_VERTEX(n,r) 0 + (n)*numInAttribs(r)
#define IN_UV(n,r) 1 + (n)*numInAttribs(r)
#define IN_RGBA(n,r) 2 + (n)*numInAttribs(r)
#define IN_NORMAL(n,r) 3 + (n)*numInAttribs(r)
#define OUT_STQ(n,r) 0 + (n)*numOutAttribs(r)
#define OUT_RGBA(n,r) 1 + (n)*numOutAttribs(r)
#define OUT_XYZ(n,r) 2 + (n)*numOutAttribs(r)
.balign 16,0
.global vu1_default
vu1_default:
DMAret *
MPG 0, *
.vu
start:
nop ilw.y vi12,codeSwitch(vi00)
nop ilw.z vi13,codeSwitch(vi00)
nop lq vf28,matrix0(vi00)
nop lq vf29,matrix1(vi00)
nop lq vf30,matrix2(vi00)
nop lq vf31,matrix3(vi00)
nop lq vf27,xyzwScale(vi00)
nop lq vf26,xyzwOffset(vi00)
nop lq vf25,colorScale(vi00)
nop lq vf24,clipConsts(vi00)
restart:
nop ilw.x vi09,codeSwitch(vi00) ; process switch
;; Calculate end of input buffer with vertex count rounded up to multiple of 4
;; Note that the maximum vertex count is always a multiple of 4 so this is always legal
nop xtop vi02 ; input pointer
nop xitop vi01 ; vertex count
nop iaddiu vi03,vi01,3
nop iaddiu vi04,vi00,~3
nop iand vi04,vi03,vi04 ; round up vertex count
nop iadd vi03,vi02,vi04
.rept numInAttribs-1
nop iadd vi03,vi03,vi04
.endr
;; Convert normals and colors to float. this is also where we d do skinning probably
;; TODO: could simplify this if we have no lighting
nop iaddiu vi02,vi02,4*numInAttribs
nop loi 0.007874015748031496 ; normal scale
nop lq vf01,IN_RGBA(0-4,vi02)
sub vf09,vf00,vf00 lq vf02,IN_RGBA(1-4,vi02)
nop lq vf03,IN_RGBA(2-4,vi02)
nop lq vf04,IN_RGBA(3-4,vi02)
PreprocLoop:
itof0 vf01,vf01 lq vf05,IN_NORMAL(0-4,vi02)
itof0 vf02,vf02 lq vf06,IN_NORMAL(1-4,vi02)
itof0 vf03,vf03 lq vf07,IN_NORMAL(2-4,vi02)
itof0 vf04,vf04 lq vf08,IN_NORMAL(3-4,vi02)
itof0.xyz vf05,vf05 sq vf01,IN_RGBA(0-4,vi02)
itof0.xyz vf06,vf06 sq vf02,IN_RGBA(1-4,vi02)
itof0.xyz vf07,vf07 sq vf03,IN_RGBA(2-4,vi02)
itof0.xyz vf08,vf08 sq vf04,IN_RGBA(3-4,vi02)
muli.xyz vf05,vf05,i lq vf01,IN_RGBA(0,vi02)
muli.xyz vf06,vf06,i lq vf02,IN_RGBA(1,vi02)
muli.xyz vf07,vf07,i lq vf03,IN_RGBA(2,vi02)
muli.xyz vf08,vf08,i lq vf04,IN_RGBA(3,vi02)
nop sq vf05,IN_NORMAL(0-4,vi02)
nop sq vf06,IN_NORMAL(1-4,vi02)
nop sq vf07,IN_NORMAL(2-4,vi02)
nop sq vf08,IN_NORMAL(3-4,vi02)
.if 0
;; clear ADC flag here if geometry doesn t write it
nop sq.w vf09,IN_VERTEX(0-4,vi02)
nop sq.w vf09,IN_VERTEX(1-4,vi02)
nop sq.w vf09,IN_VERTEX(2-4,vi02)
nop sq.w vf09,IN_VERTEX(3-4,vi02)
.endif
nop ibne vi02,vi03,PreprocLoop
nop iaddiu vi02,vi02,4*numInAttribs
#include "lighting.vu"
nop jr vi09
nop nop
Process:
#include "default_proc.vu"
TLClip:
#include "TLclip.vu"
TSClip:
#include "TSclip.vu"
End:
nop[e] nop
nop nop
nop b restart
nop nop
#include "cliptri.vu"
#include "default_clipproc.vu"
.EndMPG
.EndDmaData
.global vu1_default_desc
vu1_default_desc:
.word Process, outBuf1, outBuf2, 0
.word TLClip, outBuf1, clipOutBuf2, 0
.word TSClip, outBuf1, clipOutBuf2, 0
+46
View File
@@ -0,0 +1,46 @@
;; Process clipping buffer to output
;; vertices are already in clip space
;; vi09: input buffer
;; vi03: vertex Count
;; CANNOT use: vi02, vi04 (clipping), vi15 (return)
;; TMP: vi06
ProcessClip:
nop lq vf01,gifTag(vi00) ; GIF tag
nop iaddiu vi06,vi00,0x4000
nop iadd vi06,vi06,vi06 ; EOP bit
nop ior vi06,vi06,vi03 ; enter vertex count
nop sq vf01,0(vi12) ; store GIF tag
nop isw.x vi06,0(vi12)
addw.z vf12,vf00,vf00 lq.xyw vf10,0(vi09) ; xyw
addw.z vf10,vf00,vf00 lq vf11,2(vi09) ; rgba
nop lq.xy vf12,1(vi09) ; st
nop iaddiu vi05,vi12,1 ; output pointer
ProcessClipLoop:
miniy.w vf01,vf10,vf24 div q,vf00w,vf10w ; clamp to fog far - start perspective division
nop nop
mul.xyz vf22,vf10,vf27 lq.z vf13,0(vi09) ; pos.xyz*scale.xyz - load ADC flag
addax acc,vf26,vf00 nop ; init acc
maxx.w vf01,vf01,vf24 nop ; clamp to fog near
ftoi0 vf02,vf11 isubiu vi03,vi03,1 ; convert rgba
maddaz.w acc,vf00,vf13 iaddiu vi09,vi09,numInAttribs ; add ADC flag
maddq.xyz vf01,vf22,q nop ; calc pos (can use q now)
madd.w vf01,vf01,vf27 nop ; calc fog
mulq.xyz vf03,vf12,q lq.xyw vf10,0(vi09) ; scale stq - next xyw
addw.z vf12,vf00,vf00 lq vf11,2(vi09) ; - next rgba
addw.z vf10,vf00,vf00 lq.xy vf12,1(vi09) ; - next st
ftoi4 vf01,vf01 iaddiu vi05,vi05,numOutAttribs ; convert xyzf
nop sq vf02,1-numOutAttribs(vi05) ; rgba
nop sq vf03,0-numOutAttribs(vi05) ; stq
nop ibne vi03,vi00,ProcessClipLoop
nop sq vf01,2-numOutAttribs(vi05) ; xyzf
;; Render it
nop xgkick vi12
nop iadd vi05,vi00,vi12
nop iadd vi12,vi00,vi13
nop iadd vi13,vi00,vi05
nop jr vi15
nop nop
+38
View File
@@ -0,0 +1,38 @@
mul.xyw vf23,vf31,vf27 xtop vi02 ; scale matrix - input pointer
mul.xyw vf20,vf28,vf27 lq vf10,IN_VERTEX(0,vi02) ; scale matrix - load vert-1
mul.xyw vf21,vf29,vf27 lq vf01,gifTag(vi00) ; scale matrix
mul.xyw vf22,vf30,vf27 xitop vi01 ; scale matrix - vertex count
mulaw acc,vf23,vf00 iaddiu vi05,vi00,0x4000 ; xform vert-1
maddax acc,vf20,vf10 iadd vi05,vi05,vi05 ; xform vert-1 - EOP bit
madday acc,vf21,vf10 ior vi05,vi05,vi01 ; xform vert-1 - enter vertex count
maddz.xyw vf01,vf22,vf10 sq vf01,0(vi12) ; xform vert-1 - store GIF tag
mulw.xy vf06,vf24,vf27 move.z vf01,vf27 ; scale fog clamp - init z-1
add.w vf05,vf26,vf10 isw.x vi05,0(vi12) ; add adc-1 to w-offset - store vertex count
nop lq vf10,IN_VERTEX(1,vi02) ; - load vert-2
nop div q,vf27w,vf01w ; - divide vert-1
miniy.w vf01,vf01,vf06 nop ; clamp fog-1
nop lq.xy vf12,IN_UV(0,vi02) ; - load uv-1
mulaw acc,vf23,vf00 lq vf11,IN_RGBA(0,vi02) ; xform vert-2 - load rgba-1
maddax acc,vf20,vf10 mr32.z vf12,vf00 ; xform vert-2
maxx.w vf04,vf01,vf06 move.xyz vf05,vf26 ; clamp fog-1
madday acc,vf21,vf10 iaddiu vi04,vi12,1 ; xform vert-2 - output pointer
ProcessLoop:
mulq.xyz vf04,vf01,q move.z vf01,vf27
maddz.xyw vf01,vf22,vf10 nop
ftoi0 vf02,vf11 lq vf11,IN_RGBA(1,vi02)
mulq.xyz vf03,vf12,q lq.xy vf12,IN_UV(1,vi02)
add vf04,vf04,vf05 iaddiu vi02,vi02,numInAttribs
add.w vf05,vf26,vf10 div q,vf27w,vf01w
miniy.w vf01,vf01,vf06 lq vf10,IN_VERTEX(1,vi02)
mulaw acc,vf23,vf00 sqi vf03,(vi04++)
ftoi4 vf07,vf04 sqi vf02,(vi04++)
nop nop
maxx.w vf04,vf01,vf06 mr32.z vf12,vf00
maddax acc,vf20,vf10 ibne vi02,vi03,ProcessLoop
madday acc,vf21,vf10 sqi vf07,(vi04++)
nop xgkick vi12 ; draw kick
nop iadd vi15,vi00,vi12 ; swap output buffers
nop iadd vi12,vi00,vi13
nop b End
nop iadd vi13,vi00,vi15
+65
View File
@@ -0,0 +1,65 @@
.equ light, 0x3d0
.equ matrix0, 0x3f0
.equ matrix1, 0x3f1
.equ matrix2, 0x3f2
.equ matrix3, 0x3f3
.equ xyzwScale, 0x3f4
.equ xyzwOffset, 0x3f5
.equ clipConsts, 0x3f6
.equ gifTag, 0x3fa
.equ colorScale, 0x3fb
.equ surfaceProps, 0x3fc
.equ codeSwitch, 0x3ff
;; FCAND masks -- if register is 0, the whole poly is out
.equ posXn, (0x041041)
.equ negXn, (0x082082)
.equ posYn, (0x104104)
.equ negYn, (0x208208)
.equ posZn, (0x410410)
.equ negZn, (0x820820)
.equ posXn3, (posXn&0x3FFFF)
.equ negXn3, (negXn&0x3FFFF)
.equ posYn3, (posYn&0x3FFFF)
.equ negYn3, (negYn&0x3FFFF)
.equ posZn3, (posZn&0x3FFFF)
.equ negZn3, (negZn&0x3FFFF)
.equ posXn2, (posXn&0xFFF)
.equ negXn2, (negXn&0xFFF)
.equ posYn2, (posYn&0xFFF)
.equ negYn2, (negYn&0xFFF)
.equ posZn2, (posZn&0xFFF)
.equ negZn2, (negZn&0xFFF)
.equ posXn1, (posXn&0x3F)
.equ negXn1, (negXn&0x3F)
.equ posYn1, (posYn&0x3F)
.equ negYn1, (negYn&0x3F)
.equ posZn1, (posZn&0x3F)
.equ negZn1, (negZn&0x3F)
;; FCOR masks -- if register is 1, the whole poly is in
.equ posXo, (0xFBEFBE)
.equ negXo, (0xF7DF7D)
.equ posYo, (0xEFBEFB)
.equ negYo, (0xDF7DF7)
.equ posZo, (0xBEFBEF)
.equ negZo, (0x7DF7DF)
.equ posXo3, (posXo|0xFC0000)
.equ negXo3, (negXo|0xFC0000)
.equ posYo3, (posYo|0xFC0000)
.equ negYo3, (negYo|0xFC0000)
.equ posZo3, (posZo|0xFC0000)
.equ negZo3, (negZo|0xFC0000)
.equ posXo2, (posXo|0xFFF000)
.equ negXo2, (negXo|0xFFF000)
.equ posYo2, (posYo|0xFFF000)
.equ negYo2, (negYo|0xFFF000)
.equ posZo2, (posZo|0xFFF000)
.equ negZo2, (negZo|0xFFF000)
.equ posXo1, (posXo|0xFFFFC0)
.equ negXo1, (negXo|0xFFFFC0)
.equ posYo1, (posYo|0xFFFFC0)
.equ negYo1, (negYo|0xFFFFC0)
.equ posZo1, (posZo|0xFFFFC0)
.equ negZo1, (negZo|0xFFFFC0)
+123
View File
@@ -0,0 +1,123 @@
.equ vertexTop, 0x3f0
.equ numInAttribs, 3
.equ numOutAttribs, 3
.equ numOutBuf, 2
.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf))
.equ offset, (vertCount*numInAttribs)
.equ outBuf1, (2*offset)
;.equ outSize, ((vertexTop-outBuf1-numOutBuf)/numOutBuf)
.equ outSize, (1 + vertCount*numOutAttribs)
.equ outBuf2, (outBuf1+outSize)
.include "defines.inc"
#define IN_VERTEX(n,r) 0 + (n)*numInAttribs(r)
#define IN_UV(n,r) 1 + (n)*numInAttribs(r)
#define IN_RGBA(n,r) 2 + (n)*numInAttribs(r)
#define OUT_STQ(n,r) 0 + (n)*numOutAttribs(r)
#define OUT_RGBA(n,r) 1 + (n)*numOutAttribs(r)
#define OUT_XYZ(n,r) 2 + (n)*numOutAttribs(r)
.balign 16,0
.global vu1_im2d
vu1_im2d:
DMAret *
MPG 0, *
.vu
start:
nop iaddiu vi12,vi00,outBuf1
nop iaddiu vi13,vi00,outBuf2
nop lq vf04,xyzwOffset(vi00)
nop lq vf05,colorScale(vi00)
nop lq vf06,colorScale(vi00)
restart:
nop ilw.x vi09,codeSwitch(vi00) ; process switch
nop xtop vi02 ; input pointer
nop jr vi09
nop xtop vi01 ; vertex count
NoFog:
nop xtop vi02 ; input pointer
mulz.w vf01,vf00,vf00 lq vf13,IN_RGBA(0,vi02) ; clear ADC flag - load rgba
nop lq.xyz vf11,IN_VERTEX(0,vi02) ; - load xyz
nop lq.xyz vf02,IN_UV(0,vi02) ; - load uvq
nop lq vf03,gifTag(vi00) ; - GIF tag
itof0 vf13,vf13 xitop vi01 ; rgba to float - vertex count
add.xy vf11,vf11,vf04 iaddiu vi05,vi00,0x4000 ; add xy offset
mulz.xy vf02,vf02,vf02 iadd vi05,vi05,vi05 ; - EOP bit
nop ior vi05,vi05,vi01 ; - enter vertex count
nop sq vf03,0(vi12) ; - store GIF tag
nop isw.x vi05,0(vi12)
nop iaddiu vi03,vi12,1 ; - output pointer
nop iadd vi05,vi03,vi01
.rept numOutAttribs-1
nop iadd vi05,vi05,vi01
.endr
NoFogLoop:
mul vf03,vf13,vf05 lq.xyz vf12,IN_UV(1,vi02)
nop lq vf13,IN_RGBA(1,vi02)
ftoi4.xyz vf01,vf11 lq.xyz vf11,IN_VERTEX(1,vi02)
nop iaddiu vi02,vi02,numInAttribs
ftoi0 vf03,vf03 iaddiu vi03,vi03,numOutAttribs
itof0 vf13,vf13 sq vf02,OUT_STQ(-1,vi03)
add.xy vf11,vf11,vf04 sq vf01,OUT_XYZ(-1,vi03)
mulz.xy vf02,vf12,vf12 ibne vi03,vi05,NoFogLoop
addx.z vf02,vf12,vf00 sq vf03,OUT_RGBA(-1,vi03)
nop b End
nop nop
Fog:
nop loi 255.0
nop xtop vi02 ; input pointer
nop lq vf21,IN_VERTEX(0,vi02) ; - load xyzw
nop lq vf13,IN_RGBA(0,vi02) ; - load rgba
nop lq.xyz vf02,IN_UV(0,vi02) ; - load uvq
addax acc,vf04,vf00 lq vf03,gifTag(vi00) ; - GIF tag
madd vf21,vf05,vf21 xitop vi01 ; - vertex count
itof0 vf13,vf13 iaddiu vi05,vi00,0x4000 ;
nop iadd vi05,vi05,vi05 ; - EOP bit
nop ior vi05,vi05,vi01 ; - enter vertex count
minii.w vf11,vf21,i sq vf03,0(vi12) ; - store GIF tag
addx.xyz vf01,vf21,vf00 isw.x vi05,0(vi12)
nop iaddiu vi03,vi12,1 ; - output pointer
nop iadd vi05,vi03,vi01
.rept numInAttribs-1
nop iadd vi05,vi05,vi01
.endr
FogLoop:
mul vf03,vf13,vf06 nop
addax acc,vf04,vf00 lq vf21,IN_VERTEX(1,vi02)
maxw.w vf01,vf11,vf00 nop
mulz.xy vf02,vf02,vf02 lq vf13,IN_RGBA(1,vi02)
ftoi0 vf03,vf03 lq.xyz vf12,IN_UV(1,vi02)
madd vf21,vf05,vf21 iaddiu vi02,vi02,numInAttribs
ftoi4 vf01,vf01 iaddiu vi03,vi03,numOutAttribs
itof0 vf13,vf13 sq vf02,OUT_STQ(-1,vi03)
addx vf02,vf12,vf00 sq vf03,OUT_RGBA(-1,vi03)
minii.w vf11,vf21,i ibne vi03,vi05,FogLoop
addx.xyz vf01,vf21,vf00 sq vf01,OUT_XYZ(-1,vi03)
nop b End
nop nop
End:
nop xgkick vi12
nop iadd vi15,vi00,vi12
nop[e] iadd vi12,vi00,vi13
nop iadd vi13,vi00,vi15
nop b restart
nop nop
.EndMPG
.EndDmaData
.global vu1_im2d_desc
vu1_im2d_desc:
.word NoFog, 0, 0, 0
.word Fog, 0, 0, 0
+125
View File
@@ -0,0 +1,125 @@
.equ vertexTop, 0x3f0
.equ numInAttribs, 3
.equ numOutAttribs, 3
.equ numOutBuf, 2
.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf))
.equ offset, (vertCount*numInAttribs)
.equ outBuf1, (2*offset)
;.equ outSize, ((vertexTop-outBuf1-numOutBuf)/numOutBuf)
.equ outSize, (1 + vertCount*numOutAttribs)
.equ outBuf2, (outBuf1+outSize)
.equ clipVertCount, ((vertexTop-outBuf1-numOutBuf)/(numInAttribs+numOutAttribs*numOutBuf))
.equ clipOutSize, (1 + clipVertCount*numOutAttribs)
.equ clipOutBuf2, (outBuf1+clipOutSize)
.equ clipBuf, (clipOutBuf2+clipOutSize)
; up to 9 verts => 7 tris per poly in worst case
.equ clipVertLimitTL, (clipVertCount-21)
.equ clipVertLimitTS, (clipVertCount-15) ;;; TODO: this crashes when i set it to -9 as it should be
.include "defines.inc"
#define IN_VERTEX(n,r) 0 + (n)*numInAttribs(r)
#define IN_UV(n,r) 1 + (n)*numInAttribs(r)
#define IN_RGBA(n,r) 2 + (n)*numInAttribs(r)
#define OUT_STQ(n,r) 0 + (n)*numOutAttribs(r)
#define OUT_RGBA(n,r) 1 + (n)*numOutAttribs(r)
#define OUT_XYZ(n,r) 2 + (n)*numOutAttribs(r)
.balign 16,0
.global vu1_im3d
vu1_im3d:
DMAret *
MPG 0, *
.vu
start:
nop ilw.y vi12,codeSwitch(vi00)
nop ilw.z vi13,codeSwitch(vi00)
nop lq vf28,matrix0(vi00)
nop lq vf29,matrix1(vi00)
nop lq vf30,matrix2(vi00)
nop lq vf31,matrix3(vi00)
nop lq vf27,xyzwScale(vi00)
nop lq vf26,xyzwOffset(vi00)
nop lq vf25,colorScale(vi00)
nop lq vf24,clipConsts(vi00)
restart:
nop ilw.x vi09,codeSwitch(vi00) ; process switch
;; Calculate end of input buffer with vertex count rounded up to multiple of 4
;; Note that the maximum vertex count is always a multiple of 4 so this is always legal
nop xtop vi02 ; input pointer
nop xitop vi01 ; vertex count
nop iaddiu vi03,vi01,3
nop iaddiu vi04,vi00,~3
nop iand vi04,vi03,vi04 ; round up vertex count
nop iadd vi03,vi02,vi04
.rept numInAttribs-1
nop iadd vi03,vi03,vi04
.endr
;; Convert colors to float
nop iaddiu vi02,vi02,4*numInAttribs
nop lq vf01,IN_RGBA(0-4,vi02)
nop lq vf02,IN_RGBA(1-4,vi02)
nop lq vf03,IN_RGBA(2-4,vi02)
nop lq vf04,IN_RGBA(3-4,vi02)
itof0 vf01,vf01 nop
itof0 vf02,vf02 nop
itof0 vf03,vf03 nop
itof0 vf04,vf04 nop
PreprocLoop:
mul vf05,vf01,vf25 lq vf01,IN_RGBA(0,vi02)
mul vf06,vf02,vf25 lq vf02,IN_RGBA(1,vi02)
mul vf07,vf03,vf25 lq vf03,IN_RGBA(2,vi02)
mul vf08,vf04,vf25 lq vf04,IN_RGBA(3,vi02)
itof0 vf01,vf01 sq vf05,IN_RGBA(0-4,vi02)
itof0 vf02,vf02 sq vf06,IN_RGBA(1-4,vi02)
itof0 vf03,vf03 sq vf07,IN_RGBA(2-4,vi02)
itof0 vf04,vf04 sq vf08,IN_RGBA(3-4,vi02)
nop ibne vi02,vi03,PreprocLoop
nop iaddiu vi02,vi02,4*numInAttribs
nop jr vi09
nop nop
Process:
#include "default_proc.vu"
TLClip:
.include "TLclip.vu"
TSClip:
.include "TSclip.vu"
LLClip:
.include "LLclip.vu"
LSClip:
.include "LSclip.vu"
PointCull:
.include "PointCull.vu"
End:
nop[e] nop
nop nop
nop b restart
nop nop
.include "cliptri.vu"
.include "clipline.vu"
#include "default_clipproc.vu"
.EndMPG
.EndDmaData
;; indexed by PrimitiveType
.global vu1_im3d_desc
vu1_im3d_desc:
.word Process, outBuf1, outBuf2, 0 ; PRIMTYPENONE
.word LLClip, outBuf1, outBuf2, 0 ; PRIMTYPELINELIST
.word LSClip, outBuf1, clipOutBuf2, 0 ; PRIMTYPEPOLYLINE
.word TLClip, outBuf1, clipOutBuf2, 0 ; PRIMTYPETRILIST
.word TSClip, outBuf1, clipOutBuf2, 0 ; PRIMTYPETRISTRIP
.word 0, 0, 0, 0 ; PRIMTYPETRIFAN TODO
.word PointCull, outBuf1, outBuf2, 0 ; PRIMTYPEPOINTLIST
+106
View File
@@ -0,0 +1,106 @@
;;; Register usage:
;; vf20 light color
;; vf21 light direction
;; vf23 surfaceProps
Lighting:
nop iaddiu vi08,vi00,light
nop lq vf23,surfaceProps(vi00)
LightLoop:
nop ilw.w vi15,0(vi08) ; load light type
nop lqi.xyz vf20,(vi08++) ; light color
nop ibeq vi15,vi00,PostLighting
nop xtop vi02 ; input pointer
nop iaddiu vi15,vi15,LightSwitch
nop jr vi15
LightSwitch:
;; Light type dispatch table
nop nop
nop b AmbientLight
nop nop
nop b DirectLight
nop lqi.xyz vf21,(vi08++) ; light direction
;; Apply Ambient light
AmbientLight:
mulx.xyz vf20,vf20,vf23 iaddiu vi02,vi02,4*numInAttribs
nop lq vf01,IN_RGBA(0-4,vi02)
nop lq vf02,IN_RGBA(1-4,vi02)
nop lq vf03,IN_RGBA(2-4,vi02)
nop lq vf04,IN_RGBA(3-4,vi02)
AmbientLoop:
add vf05,vf01,vf20 lq vf01,IN_RGBA(0,vi02)
add vf06,vf02,vf20 lq vf02,IN_RGBA(1,vi02)
add vf07,vf03,vf20 lq vf03,IN_RGBA(2,vi02)
add vf08,vf04,vf20 lq vf04,IN_RGBA(3,vi02)
nop sq vf05,IN_RGBA(0-4,vi02)
nop sq vf06,IN_RGBA(1-4,vi02)
nop sq vf07,IN_RGBA(2-4,vi02)
nop sq vf08,IN_RGBA(3-4,vi02)
nop ibne vi02,vi03,AmbientLoop
nop iaddiu vi02,vi02,4*numInAttribs
nop b LightLoop
nop nop
;; Apply Directional light
DirectLight:
sub.xyz vf21,vf00,vf21 lq vf01,IN_NORMAL(0,vi02) ; flip light directio
mulz.xyz vf20,vf20,vf23 lq vf02,IN_NORMAL(1,vi02) ; multiply color by surfProps
nop lq vf03,IN_NORMAL(2,vi02)
nop lq vf04,IN_NORMAL(3,vi02)
mul.xyz vf01,vf01,vf21 nop
mul.xyz vf02,vf02,vf21 nop
mul.xyz vf03,vf03,vf21 nop
mul.xyz vf04,vf04,vf21 nop
addy.x vf11,vf01,vf01 nop
addx.y vf11,vf02,vf02 nop
addx.z vf11,vf03,vf03 nop
addy.z vf04,vf04,vf04 mr32 vf09,vf04
DirectLoop:
addz.x vf10,vf11,vf01 lq vf01,IN_NORMAL(0+4,vi02)
addz.y vf10,vf11,vf02 lq vf02,IN_NORMAL(1+4,vi02)
addy.z vf10,vf11,vf03 lq vf03,IN_NORMAL(2+4,vi02)
addz.w vf10,vf09,vf04 lq vf04,IN_NORMAL(3+4,vi02)
mul.xyz vf01,vf01,vf21 lq vf05,IN_RGBA(0,vi02)
mul.xyz vf02,vf02,vf21 lq vf06,IN_RGBA(1,vi02)
mul.xyz vf03,vf03,vf21 lq vf07,IN_RGBA(2,vi02)
maxx vf10,vf10,vf00 lq vf08,IN_RGBA(3,vi02)
mul.xyz vf04,vf04,vf21 nop
addy.x vf11,vf01,vf01 nop
addax acc,vf05,vf00 nop
maddx.xyz vf05,vf20,vf10 nop
addax acc,vf06,vf00 mr32 vf09,vf04
maddy.xyz vf06,vf20,vf10 nop
addax acc,vf07,vf00 iaddiu vi02,vi02,4*numInAttribs
maddz.xyz vf07,vf20,vf10 sq vf05,IN_RGBA(0-4,vi02)
addax acc,vf08,vf00 nop
maddw.xyz vf08,vf20,vf10 sq vf06,IN_RGBA(1-4,vi02)
addx.y vf11,vf02,vf02 nop
addx.z vf11,vf03,vf03 sq vf07,IN_RGBA(2-4,vi02)
addy.z vf04,vf04,vf04 ibne vi02,vi03,DirectLoop
nop sq vf08,IN_RGBA(3-4,vi02)
nop b LightLoop
nop nop
;;; Clamp lighting and multiply by material color
PostLighting:
nop loi 255.0
nop lq vf01,IN_RGBA(0,vi02)
nop lq vf02,IN_RGBA(1,vi02)
nop lq vf03,IN_RGBA(2,vi02)
nop lq vf04,IN_RGBA(3,vi02)
minii vf05,vf01,i iaddiu vi02,vi02,4*numInAttribs
minii vf06,vf02,i nop
minii vf07,vf03,i nop
minii vf08,vf04,i nop
PostLightLoop:
mul vf05,vf05,vf25 lq vf01,IN_RGBA(0,vi02)
mul vf06,vf06,vf25 lq vf02,IN_RGBA(1,vi02)
mul vf07,vf07,vf25 lq vf03,IN_RGBA(2,vi02)
mul vf08,vf08,vf25 lq vf04,IN_RGBA(3,vi02)
minii vf05,vf01,i sq vf05,IN_RGBA(0-4,vi02)
minii vf06,vf02,i sq vf06,IN_RGBA(1-4,vi02)
minii vf07,vf03,i sq vf07,IN_RGBA(2-4,vi02)
minii vf08,vf04,i sq vf08,IN_RGBA(3-4,vi02)
nop ibne vi02,vi03,PostLightLoop
nop iaddiu vi02,vi02,4*numInAttribs