diff --git a/librw.vcxproj b/librw.vcxproj
index b92783a..c90ddde 100644
--- a/librw.vcxproj
+++ b/librw.vcxproj
@@ -198,6 +198,7 @@
+
diff --git a/src/d3d.cpp b/src/d3d.cpp
index 3538010..c4a0da2 100644
--- a/src/d3d.cpp
+++ b/src/d3d.cpp
@@ -420,18 +420,25 @@ void
D3dRaster::fromImage(Raster *raster, Image *image)
{
int32 format;
- if(image->depth == 32)
- format = Raster::C8888;
- else if(image->depth == 24)
+ switch(image->depth){
+ case 32:
+ format = image->hasAlpha() ? Raster::C8888 : Raster::C888;
+ break;
+ case 24:
format = Raster::C888;
- else if(image->depth == 16)
+ break;
+ case 16:
format = Raster::C1555;
- else if(image->depth == 8)
+ break;
+ case 8:
format = Raster::PAL8 | Raster::C8888;
- else if(image->depth == 4)
+ break;
+ case 4:
format = Raster::PAL4 | Raster::C8888;
- else
+ break;
+ default:
return;
+ }
format |= 4;
raster->type = format & 0x7;
@@ -458,11 +465,13 @@ D3dRaster::fromImage(Raster *raster, Image *image)
}
}
+ int32 inc = image->depth/8;
in = image->pixels;
out = raster->lock(0);
if(pallength)
memcpy(out, in, raster->width*raster->height);
else
+ // TODO: stride
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
switch(raster->format & 0xF00){
@@ -471,7 +480,7 @@ D3dRaster::fromImage(Raster *raster, Image *image)
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
- in += 4;
+ in += inc;
out += 4;
break;
case Raster::C888:
@@ -479,7 +488,7 @@ D3dRaster::fromImage(Raster *raster, Image *image)
out[1] = in[1];
out[2] = in[0];
out[3] = 0xFF;
- in += 3;
+ in += inc;
out += 4;
break;
case Raster::C1555:
diff --git a/src/geometry.cpp b/src/geometry.cpp
index bd4edc9..25c3b1e 100644
--- a/src/geometry.cpp
+++ b/src/geometry.cpp
@@ -447,6 +447,65 @@ Geometry::buildMeshes(void)
}
}
+// HAS to be called with an existing mesh
+void
+Geometry::removeUnusedMaterials(void)
+{
+ if(this->meshHeader == NULL)
+ return;
+ MeshHeader *mh = this->meshHeader;
+ int32 *map = new int32[this->numMaterials];
+ Material **matlist = new Material*[this->numMaterials];
+ int32 numMaterials = 0;
+ /* Build new material list and map */
+ for(uint32 i = 0; i < mh->numMeshes; i++){
+ Mesh *m = &mh->mesh[i];
+ if(m->numIndices <= 0)
+ continue;
+ matlist[numMaterials] = m->material;
+ int32 oldid = findPointer((void*)m->material,
+ (void**)this->materialList,
+ this->numMaterials);
+ map[oldid] = numMaterials;
+ numMaterials++;
+ }
+ delete[] this->materialList;
+ this->materialList = matlist;
+ this->numMaterials = numMaterials;
+ /* Build new meshes */
+ MeshHeader *newmh = new MeshHeader;
+ newmh->flags = mh->flags;
+ newmh->numMeshes = numMaterials;
+ newmh->mesh = new Mesh[newmh->numMeshes];
+ newmh->totalIndices = mh->totalIndices;
+ Mesh *newm = newmh->mesh;
+ for(uint32 i = 0; i < mh->numMeshes; i++){
+ Mesh *oldm = &mh->mesh[i];
+ if(oldm->numIndices <= 0)
+ continue;
+ newm->numIndices = oldm->numIndices;
+ newm->material = oldm->material;
+ newm++;
+ }
+ newmh->allocateIndices();
+ /* Copy indices */
+ newm = newmh->mesh;
+ for(uint32 i = 0; i < mh->numMeshes; i++){
+ Mesh *oldm = &mh->mesh[i];
+ if(oldm->numIndices <= 0)
+ continue;
+ memcpy(newm->indices, oldm->indices,
+ oldm->numIndices*sizeof(*oldm->indices));
+ newm++;
+ }
+ delete this->meshHeader;
+ this->meshHeader = newmh;
+ /* Remap triangle material IDs */
+ for(int32 i = 0; i < this->numTriangles; i++)
+ this->triangles[i].matId = map[this->triangles[i].matId];
+ delete[] map;
+}
+
//
// Material
//
diff --git a/src/image.cpp b/src/image.cpp
index ef028cc..516a269 100755
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -379,6 +379,27 @@ Image::setPalette(uint8 *palette)
this->flags |= 2;
}
+bool32
+Image::hasAlpha(void)
+{
+ uint8 ret = 0xFF;
+ uint8 *pixels = this->pixels;
+ if(this->depth == 24)
+ return 0;
+ // TODO: palettized textures
+ if(this->depth == 32){
+ for(int y = 0; y < this->height; y++){
+ uint8 *line = pixels;
+ for(int x = 0; x < this->width; x++){
+ ret &= line[3];
+ line += 4;
+ }
+ pixels += this->stride;
+ }
+ }
+ return ret != 0xFF;
+}
+
static char *searchPaths = NULL;
int numSearchPaths = 0;
diff --git a/src/pds.cpp b/src/pds.cpp
new file mode 100644
index 0000000..1dd2395
--- /dev/null
+++ b/src/pds.cpp
@@ -0,0 +1,185 @@
+#include
+#include
+#include
+#include
+
+#include "rwbase.h"
+#include "rwplugin.h"
+#include "rwpipeline.h"
+#include "rwobjects.h"
+#include "rwps2.h"
+
+namespace rw {
+namespace ps2 {
+
+struct PdsGlobals
+{
+ Pipeline **pipes;
+ int32 maxPipes;
+ int32 numPipes;
+};
+static PdsGlobals pdsGlobals;
+
+Pipeline*
+getPDSPipe(uint32 data)
+{
+ for(int32 i = 0; i < pdsGlobals.numPipes; i++)
+ if(pdsGlobals.pipes[i]->pluginData == data)
+ return pdsGlobals.pipes[i];
+ return NULL;
+}
+
+void
+registerPDSPipe(Pipeline *pipe)
+{
+ assert(pdsGlobals.numPipes < pdsGlobals.maxPipes);
+ pdsGlobals.pipes[pdsGlobals.numPipes++] = pipe;
+}
+
+static void
+atomicPDSRights(void *object, int32, int32, uint32 data)
+{
+ Atomic *a = (Atomic*)object;
+ //printf("atm pds: %x\n", data);
+ a->pipeline = (ObjPipeline*)getPDSPipe(data);
+}
+
+static void
+materialPDSRights(void *object, int32, int32, uint32 data)
+{
+ Material *m = (Material*)object;
+ //printf("mat pds: %x\n", data);
+ m->pipeline = (ObjPipeline*)getPDSPipe(data);
+}
+
+void
+registerPDSPlugin(int32 n)
+{
+ pdsGlobals.maxPipes = n;
+ pdsGlobals.numPipes = 0;
+ pdsGlobals.pipes = new Pipeline*[n];
+ Atomic::registerPlugin(0, ID_PDS, NULL, NULL, NULL);
+ Atomic::setStreamRightsCallback(ID_PDS, atomicPDSRights);
+
+ Material::registerPlugin(0, ID_PDS, NULL, NULL, NULL);
+ Material::setStreamRightsCallback(ID_PDS, materialPDSRights);
+}
+
+void
+registerPluginPDSPipes(void)
+{
+ // rwPDS_G3_Skin_GrpMatPipeID
+ MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
+ pipe->pluginID = ID_PDS;
+ pipe->pluginData = 0x11001;
+ pipe->attribs[AT_XYZ] = &attribXYZ;
+ pipe->attribs[AT_UV] = &attribUV;
+ pipe->attribs[AT_RGBA] = &attribRGBA;
+ pipe->attribs[AT_NORMAL] = &attribNormal;
+ pipe->attribs[AT_NORMAL+1] = &attribWeights;
+ uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2);
+ pipe->setTriBufferSizes(5, vertCount);
+ pipe->vifOffset = pipe->inputStride*vertCount;
+ pipe->instanceCB = skinInstanceCB;
+ pipe->uninstanceCB = skinUninstanceCB;
+ pipe->preUninstCB = skinPreCB;
+ pipe->postUninstCB = skinPostCB;
+ registerPDSPipe(pipe);
+
+ // rwPDS_G3_Skin_GrpAtmPipeID
+ ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
+ opipe->pluginID = ID_PDS;
+ opipe->pluginData = 0x11002;
+ opipe->groupPipeline = pipe;
+ registerPDSPipe(opipe);
+
+ // rwPDS_G3_MatfxUV1_GrpMatPipeID
+ pipe = new MatPipeline(PLATFORM_PS2);
+ pipe->pluginID = ID_PDS;
+ pipe->pluginData = 0x1100b;
+ pipe->attribs[AT_XYZ] = &attribXYZ;
+ pipe->attribs[AT_UV] = &attribUV;
+ pipe->attribs[AT_RGBA] = &attribRGBA;
+ pipe->attribs[AT_NORMAL] = &attribNormal;
+ vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
+ pipe->setTriBufferSizes(4, vertCount);
+ pipe->vifOffset = pipe->inputStride*vertCount;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ registerPDSPipe(pipe);
+
+ // rwPDS_G3_MatfxUV1_GrpAtmPipeID
+ opipe = new ObjPipeline(PLATFORM_PS2);
+ opipe->pluginID = ID_PDS;
+ opipe->pluginData = 0x1100d;
+ opipe->groupPipeline = pipe;
+ registerPDSPipe(opipe);
+
+ // rwPDS_G3_MatfxUV2_GrpMatPipeID
+ pipe = new MatPipeline(PLATFORM_PS2);
+ pipe->pluginID = ID_PDS;
+ pipe->pluginData = 0x1100c;
+ pipe->attribs[AT_XYZ] = &attribXYZ;
+ pipe->attribs[AT_UV] = &attribUV2;
+ pipe->attribs[AT_RGBA] = &attribRGBA;
+ pipe->attribs[AT_NORMAL] = &attribNormal;
+ vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
+ pipe->setTriBufferSizes(4, vertCount);
+ pipe->vifOffset = pipe->inputStride*vertCount;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ registerPDSPipe(pipe);
+
+ // rwPDS_G3_MatfxUV2_GrpAtmPipeID
+ opipe = new ObjPipeline(PLATFORM_PS2);
+ opipe->pluginID = ID_PDS;
+ opipe->pluginData = 0x1100e;
+ opipe->groupPipeline = pipe;
+ registerPDSPipe(opipe);
+
+ // RW World plugin
+
+ // rwPDS_G3x_Generic_AtmPipeID
+ opipe = new ObjPipeline(PLATFORM_PS2);
+ opipe->pluginID = ID_PDS;
+ opipe->pluginData = 0x50001;
+ opipe->groupPipeline = pipe;
+ registerPDSPipe(opipe);
+
+ // rwPDS_G3x_Skin_AtmPipeID
+ opipe = new ObjPipeline(PLATFORM_PS2);
+ opipe->pluginID = ID_PDS;
+ opipe->pluginData = 0x5000b;
+ opipe->groupPipeline = pipe;
+ registerPDSPipe(opipe);
+
+ // rwPDS_G3xd_A4D_MatPipeID
+ pipe = new MatPipeline(PLATFORM_PS2);
+ pipe->pluginID = ID_PDS;
+ pipe->pluginData = 0x5002f;
+ pipe->attribs[0] = &attribXYZW;
+ pipe->attribs[1] = &attribUV;
+ pipe->attribs[2] = &attribNormal;
+ vertCount = 0x50;
+ pipe->setTriBufferSizes(3, vertCount);
+ pipe->vifOffset = pipe->inputStride*vertCount;
+ // TODO:
+ //pipe->uninstanceCB = defaultUninstanceCB;
+ registerPDSPipe(pipe);
+
+ // rwPDS_G3xd_A4DSkin_MatPipeID
+ pipe = new MatPipeline(PLATFORM_PS2);
+ pipe->pluginID = ID_PDS;
+ pipe->pluginData = 0x5003e;
+ pipe->attribs[0] = &attribXYZW;
+ pipe->attribs[1] = &attribUV;
+ pipe->attribs[2] = &attribNormal;
+ pipe->attribs[3] = &attribWeights;
+ vertCount = 0x30;
+ pipe->setTriBufferSizes(4, vertCount);
+ pipe->vifOffset = pipe->inputStride*vertCount;
+ // TODO:
+ //pipe->uninstanceCB = skinUninstanceCB;
+ registerPDSPipe(pipe);
+}
+
+}
+}
\ No newline at end of file
diff --git a/src/ps2.cpp b/src/ps2.cpp
index b2af046..288f2a3 100644
--- a/src/ps2.cpp
+++ b/src/ps2.cpp
@@ -191,6 +191,11 @@ PipeAttribute attribXYZ = {
AT_V3_32
};
+PipeAttribute attribXYZW = {
+ "XYZW",
+ AT_V4_32
+};
+
PipeAttribute attribUV = {
"UV",
AT_V2_32
@@ -256,6 +261,23 @@ instanceXYZ(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
return p;
}
+uint32*
+instanceXYZW(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
+{
+ uint16 j;
+ uint32 *d = (uint32*)g->morphTargets[0].vertices;
+ int8 *adcbits = getADCbitsForMesh(g, m);
+ for(uint32 i = idx; i < idx+n; i++){
+ j = m->indices[i];
+ *p++ = d[j*3+0];
+ *p++ = d[j*3+1];
+ *p++ = d[j*3+2];
+ *p++ = adcbits && adcbits[i] ? 0x8000 : 0;
+ }
+ // don't need to pad
+ return p;
+}
+
uint32*
instanceUV(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
@@ -393,7 +415,55 @@ brokenout:
this->triStripCount = (stripCount-2)/4*4+2;
}
-uint32 markcnt = 0xf790;
+// Instance format:
+// no broken out clusters
+// ======================
+// DMAret [FLUSH; MSKPATH3 || FLUSH; FLUSH] {
+// foreach batch {
+// foreach cluster {
+// MARK/0; STMOD; STCYCL; UNPACK
+// unpack-data
+// }
+// ITOP; MSCALF/MSCNT; // if first/not-first
+// 0/FLUSH; 0/MSKPATH3 || 0/FLUSH; 0/FLUSH // if not-last/last
+// }
+// }
+//
+// broken out clusters
+// ===================
+// foreach batch {
+// foreach broken out cluster {
+// DMAref [STCYCL; UNPACK] -> pointer into unpack-data
+// DMAcnt (empty)
+// }
+// DMAcnt/ret {
+// foreach cluster {
+// MARK/0; STMOD; STCYCL; UNPACK
+// unpack-data
+// }
+// ITOP; MSCALF/MSCNT; // if first/not-first
+// 0/FLUSH; 0/MSKPATH3 || 0/FLUSH; 0/FLUSH // if not-last/last
+// }
+// }
+// unpack-data for broken out clusters
+
+uint32 markcnt = 0;
+
+enum {
+ DMAcnt = 0x10000000,
+ DMAref = 0x30000000,
+ DMAret = 0x60000000,
+
+ VIF_NOP = 0,
+ VIF_STCYCL = 0x01000100, // WL = 1
+ VIF_ITOP = 0x04000000,
+ VIF_STMOD = 0x05000000,
+ VIF_MSKPATH3 = 0x06000000,
+ VIF_MARK = 0x07000000,
+ VIF_FLUSH = 0x11000000,
+ VIF_MSCALF = 0x15000000,
+ VIF_MSCNT = 0x17000000,
+};
struct InstMeshInfo
{
@@ -401,7 +471,9 @@ struct InstMeshInfo
uint32 batchVertCount, lastBatchVertCount;
uint32 numBatches;
uint32 batchSize, lastBatchSize;
- uint32 size, size2, stride;
+ uint32 size; // size of DMA chain without broken out data
+ uint32 size2; // size of broken out data
+ uint32 vertexSize;
uint32 attribPos[10];
};
@@ -412,16 +484,15 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m)
InstMeshInfo im;
im.numAttribs = 0;
im.numBrokenAttribs = 0;
- im.stride = 0;
+ im.vertexSize = 0;
for(uint i = 0; i < nelem(pipe->attribs); i++)
if(a = pipe->attribs[i])
if(a->attrib & AT_RW)
im.numBrokenAttribs++;
else{
- im.stride += attribSize(a->attrib);
+ im.vertexSize += attribSize(a->attrib);
im.numAttribs++;
}
- uint32 totalVerts = 0;
if(g->meshHeader->flags == MeshHeader::TRISTRIP){
im.numBatches = (m->numIndices-2) / (pipe->triStripCount-2);
im.batchVertCount = pipe->triStripCount;
@@ -430,7 +501,7 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m)
im.numBatches++;
im.lastBatchVertCount += 2;
}
- }else{
+ }else{ // TRILIST; nothing else supported yet
im.numBatches = (m->numIndices+pipe->triListCount-1) /
pipe->triListCount;
im.batchVertCount = pipe->triListCount;
@@ -441,7 +512,6 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m)
im.batchSize = getBatchSize(pipe, im.batchVertCount);
im.lastBatchSize = getBatchSize(pipe, im.lastBatchVertCount);
- im.size = 0;
if(im.numBrokenAttribs == 0)
im.size = 1 + im.batchSize*(im.numBatches-1) + im.lastBatchSize;
else
@@ -477,13 +547,16 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m)
if((a = this->attribs[i]) && a->attrib & AT_RW)
dp[i] = inst->data + im.attribPos[i]*0x10;
+ // TODO: not sure if this is correct
+ uint32 msk_flush = rw::version >= 0x35000 ? VIF_FLUSH : VIF_MSKPATH3;
+
uint32 idx = 0;
uint32 *p = (uint32*)inst->data;
if(im.numBrokenAttribs == 0){
- *p++ = 0x60000000 | im.size-1;
+ *p++ = DMAret | im.size-1;
*p++ = 0;
- *p++ = 0x11000000; // FLUSH
- *p++ = 0x06000000; // MSKPATH3; SA: FLUSH
+ *p++ = VIF_FLUSH;
+ *p++ = msk_flush;
}
for(uint32 j = 0; j < im.numBatches; j++){
uint32 nverts, bsize;
@@ -497,44 +570,46 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m)
for(uint i = 0; i < nelem(this->attribs); i++)
if((a = this->attribs[i]) && a->attrib & AT_RW){
uint32 atsz = attribSize(a->attrib);
- *p++ = 0x30000000 | QWC(nverts*atsz);
+ *p++ = DMAref | QWC(nverts*atsz);
*p++ = im.attribPos[i];
- *p++ = 0x01000100 |
- this->inputStride; // STCYCL
+ *p++ = VIF_STCYCL | this->inputStride;
// Round up nverts so UNPACK will fit exactly into the DMA packet
// (can't pad with zeroes in broken out sections).
// TODO: check for clash with vifOffset somewhere
*p++ = (a->attrib&0xFF004000)
| 0x8000 | (QWC(nverts*atsz)<<4)/atsz << 16 | i; // UNPACK
- *p++ = 0x10000000;
- *p++ = 0x0;
- *p++ = 0x0;
+ *p++ = DMAcnt;
*p++ = 0x0;
+ *p++ = VIF_NOP;
+ *p++ = VIF_NOP;
im.attribPos[i] += g->meshHeader->flags == 1 ?
QWC((im.batchVertCount-2)*atsz) :
QWC(im.batchVertCount*atsz);
}
if(im.numBrokenAttribs){
- *p++ = (j < im.numBatches-1 ? 0x10000000 : 0x60000000) |
- bsize;
- *p++ = 0x0;
- *p++ = 0x0;
+ *p++ = (j < im.numBatches-1 ? DMAcnt : DMAret) | bsize;
*p++ = 0x0;
+ *p++ = VIF_NOP;
+ *p++ = VIF_NOP;
}
for(uint i = 0; i < nelem(this->attribs); i++)
if((a = this->attribs[i]) && (a->attrib & AT_RW) == 0){
- *p++ = 0x07000000 | markcnt++; // MARK (SA: NOP)
- *p++ = 0x05000000; // STMOD
- *p++ = 0x01000100 |
- this->inputStride; // STCYCL
+ if(rw::version >= 0x35000)
+ *p++ = VIF_NOP;
+ else
+ *p++ = VIF_MARK | markcnt++;
+ *p++ = VIF_STMOD;
+ *p++ = VIF_STCYCL | this->inputStride;
*p++ = (a->attrib&0xFF004000)
| 0x8000 | nverts << 16 | i; // UNPACK
if(a == &attribXYZ)
p = instanceXYZ(p, g, m, idx, nverts);
+ else if(a == &attribXYZW)
+ p = instanceXYZW(p, g, m, idx, nverts);
else if(a == &attribUV)
p = instanceUV(p, g, m, idx, nverts);
else if(a == &attribUV2)
@@ -547,14 +622,14 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m)
idx += g->meshHeader->flags == 1
? im.batchVertCount-2 : im.batchVertCount;
- *p++ = 0x04000000 | nverts; // ITOP
- *p++ = j == 0 ? 0x15000000 : 0x17000000;
+ *p++ = VIF_ITOP | nverts;
+ *p++ = j == 0 ? VIF_MSCALF : VIF_MSCNT;
if(j < im.numBatches-1){
- *p++ = 0x0;
- *p++ = 0x0;
+ *p++ = VIF_NOP;
+ *p++ = VIF_NOP;
}else{
- *p++ = 0x11000000; // FLUSH
- *p++ = 0x06000000; // MSKPATH3; SA: FLUSH
+ *p++ = VIF_FLUSH;
+ *p++ = msk_flush;
}
}
@@ -568,7 +643,8 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[]
PipeAttribute *a;
InstMeshInfo im = getInstMeshInfo(this, g, m);
- uint8 *raw = im.stride*m->numIndices ? new uint8[im.stride*m->numIndices] : NULL;
+ uint8 *raw = im.vertexSize*m->numIndices ?
+ new uint8[im.vertexSize*m->numIndices] : NULL;
uint8 *dp = raw;
for(uint i = 0; i < nelem(this->attribs); i++)
if(a = this->attribs[i])
@@ -722,12 +798,7 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
if(m->postUninstCB) m->postUninstCB(m, geo);
}
- int8 *bits = NULL;
- if(adcOffset){
- ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset);
- if(adc->adcFormatted)
- bits = adc->adcBits;
- }
+ int8 *bits = getADCbits(geo);
geo->generateTriangles(bits);
delete[] flags;
destroyNativeData(geo, 0, 0);
@@ -802,6 +873,18 @@ insertVertex(Geometry *geo, int32 i, uint32 mask, Vertex *v)
memcpy(&geo->texCoords[1][i*2], v->t1, 8);
}
+void
+genericUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
+{
+//extern PipeAttribute attribXYZ;
+//extern PipeAttribute attribXYZW;
+//extern PipeAttribute attribUV;
+//extern PipeAttribute attribUV2;
+//extern PipeAttribute attribRGBA;
+//extern PipeAttribute attribNormal;
+//extern PipeAttribute attribWeights;
+}
+
void
defaultUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
{
@@ -872,9 +955,6 @@ makeDefaultPipeline(void)
return defaultObjPipe;
}
-static void skinInstanceCB(MatPipeline*, Geometry*, Mesh*, uint8**);
-static void skinUninstanceCB(MatPipeline*, Geometry*, uint32*, Mesh*, uint8**);
-
ObjPipeline*
makeSkinPipeline(void)
{
@@ -1026,7 +1106,7 @@ instanceSkinData(Geometry*, Mesh *m, Skin *skin, uint32 *data)
}
}
-static void
+void
skinInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data)
{
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
@@ -1095,7 +1175,7 @@ insertVertexSkin(Geometry *geo, int32 i, uint32 mask, SkinVertex *v)
}
}
-static void
+void
skinUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
{
float32 *verts = (float32*)data[AT_XYZ];
@@ -1171,6 +1251,30 @@ skinPostCB(MatPipeline*, Geometry *geo)
int32 adcOffset;
+int8*
+getADCbits(Geometry *geo)
+{
+ int8 *bits = NULL;
+ if(adcOffset){
+ ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset);
+ if(adc->adcFormatted)
+ bits = adc->adcBits;
+ }
+ return bits;
+}
+
+int8*
+getADCbitsForMesh(Geometry *geo, Mesh *mesh)
+{
+ int8 *bits = getADCbits(geo);
+ if(bits == NULL)
+ return NULL;
+ int32 n = mesh - geo->meshHeader->mesh;
+ for(int32 i = 0; i < n; i++)
+ bits += geo->meshHeader->mesh[i].numIndices;
+ return bits;
+}
+
// TODO
void
convertADC(Geometry*)
@@ -1324,130 +1428,6 @@ registerADCPlugin(void)
getSizeADC);
}
-
-// PDS plugin
-
-struct PdsGlobals
-{
- Pipeline **pipes;
- int32 maxPipes;
- int32 numPipes;
-};
-PdsGlobals pdsGlobals;
-
-Pipeline*
-getPDSPipe(uint32 data)
-{
- for(int32 i = 0; i < pdsGlobals.numPipes; i++)
- if(pdsGlobals.pipes[i]->pluginData == data)
- return pdsGlobals.pipes[i];
- return NULL;
-}
-
-void
-registerPDSPipe(Pipeline *pipe)
-{
- assert(pdsGlobals.numPipes < pdsGlobals.maxPipes);
- pdsGlobals.pipes[pdsGlobals.numPipes++] = pipe;
-}
-
-static void
-atomicPDSRights(void *object, int32, int32, uint32 data)
-{
- Atomic *a = (Atomic*)object;
- //printf("atm pds: %x\n", data);
- a->pipeline = (ObjPipeline*)getPDSPipe(data);
-}
-
-static void
-materialPDSRights(void *object, int32, int32, uint32 data)
-{
- Material *m = (Material*)object;
- //printf("mat pds: %x\n", data);
- m->pipeline = (ObjPipeline*)getPDSPipe(data);
-}
-
-void
-registerPDSPlugin(int32 n)
-{
- pdsGlobals.maxPipes = n;
- pdsGlobals.numPipes = 0;
- pdsGlobals.pipes = new Pipeline*[n];
- Atomic::registerPlugin(0, ID_PDS, NULL, NULL, NULL);
- Atomic::setStreamRightsCallback(ID_PDS, atomicPDSRights);
-
- Material::registerPlugin(0, ID_PDS, NULL, NULL, NULL);
- Material::setStreamRightsCallback(ID_PDS, materialPDSRights);
-}
-
-void
-registerPluginPDSPipes(void)
-{
- // Skin
- MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
- pipe->pluginID = ID_PDS;
- pipe->pluginData = 0x11001; // rwPDS_G3_Generic_GrpMatPipeID
- pipe->attribs[AT_XYZ] = &attribXYZ;
- pipe->attribs[AT_UV] = &attribUV;
- pipe->attribs[AT_RGBA] = &attribRGBA;
- pipe->attribs[AT_NORMAL] = &attribNormal;
- pipe->attribs[AT_NORMAL+1] = &attribWeights;
- uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2);
- pipe->setTriBufferSizes(5, vertCount);
- pipe->vifOffset = pipe->inputStride*vertCount;
- pipe->instanceCB = skinInstanceCB;
- pipe->uninstanceCB = skinUninstanceCB;
- pipe->preUninstCB = skinPreCB;
- pipe->postUninstCB = skinPostCB;
- registerPDSPipe(pipe);
-
- ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
- opipe->pluginID = ID_PDS;
- opipe->pluginData = 0x11002; // rwPDS_G3_Skin_GrpAtmPipeID
- opipe->groupPipeline = pipe;
- registerPDSPipe(opipe);
-
- // MatFX UV1
- pipe = new MatPipeline(PLATFORM_PS2);
- pipe->pluginID = ID_PDS;
- pipe->pluginData = 0x1100b; // rwPDS_G3_MatfxUV1_GrpMatPipeID
- pipe->attribs[AT_XYZ] = &attribXYZ;
- pipe->attribs[AT_UV] = &attribUV;
- pipe->attribs[AT_RGBA] = &attribRGBA;
- pipe->attribs[AT_NORMAL] = &attribNormal;
- vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
- pipe->setTriBufferSizes(4, vertCount);
- pipe->vifOffset = pipe->inputStride*vertCount;
- pipe->uninstanceCB = defaultUninstanceCB;
- registerPDSPipe(pipe);
-
- opipe = new ObjPipeline(PLATFORM_PS2);
- opipe->pluginID = ID_PDS;
- opipe->pluginData = 0x1100d; // rwPDS_G3_MatfxUV1_GrpAtmPipeID
- opipe->groupPipeline = pipe;
- registerPDSPipe(opipe);
-
- // MatFX UV2
- pipe = new MatPipeline(PLATFORM_PS2);
- pipe->pluginID = ID_PDS;
- pipe->pluginData = 0x1100c; // rwPDS_G3_MatfxUV2_GrpMatPipeID
- pipe->attribs[AT_XYZ] = &attribXYZ;
- pipe->attribs[AT_UV] = &attribUV2;
- pipe->attribs[AT_RGBA] = &attribRGBA;
- pipe->attribs[AT_NORMAL] = &attribNormal;
- vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
- pipe->setTriBufferSizes(4, vertCount);
- pipe->vifOffset = pipe->inputStride*vertCount;
- pipe->uninstanceCB = defaultUninstanceCB;
- registerPDSPipe(pipe);
-
- opipe = new ObjPipeline(PLATFORM_PS2);
- opipe->pluginID = ID_PDS;
- opipe->pluginData = 0x1100e; // rwPDS_G3_MatfxUV2_GrpAtmPipeID
- opipe->groupPipeline = pipe;
- registerPDSPipe(opipe);
-}
-
// misc stuff
void
@@ -1456,20 +1436,17 @@ printDMA(InstanceData *inst)
uint32 *tag = (uint32*)inst->data;
for(;;){
switch(tag[0]&0x70000000){
- // DMAcnt
- case 0x10000000:
+ case DMAcnt:
printf("%08x %08x\n", tag[0], tag[1]);
tag += (1+(tag[0]&0xFFFF))*4;
break;
- // DMAref
- case 0x30000000:
+ case DMAref:
printf("%08x %08x\n", tag[0], tag[1]);
tag += 4;
break;
- // DMAret
- case 0x60000000:
+ case DMAret:
printf("%08x %08x\n", tag[0], tag[1]);
return;
}
@@ -1486,19 +1463,16 @@ sizedebug(InstanceData *inst)
uint32 *last = NULL;
for(;;){
switch(tag[0]&0x70000000){
- // DMAcnt
- case 0x10000000:
+ case DMAcnt:
tag += (1+(tag[0]&0xFFFF))*4;
break;
- // DMAref
- case 0x30000000:
+ case DMAref:
last = base + tag[1]*4 + (tag[0]&0xFFFF)*4;
tag += 4;
break;
- // DMAret
- case 0x60000000:
+ case DMAret:
tag += (1+(tag[0]&0xFFFF))*4;
uint32 diff;
if(!last)
diff --git a/src/rwbase.cpp b/src/rwbase.cpp
index e2c9b57..bc95121 100644
--- a/src/rwbase.cpp
+++ b/src/rwbase.cpp
@@ -168,7 +168,7 @@ Matrix3::makeRotation(const Quat &q)
res.at.z = q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z;
return res;
}
-
+
void
Matrix3::setIdentity(void)
{
diff --git a/src/rwobjects.h b/src/rwobjects.h
index 362e25f..8b35900 100644
--- a/src/rwobjects.h
+++ b/src/rwobjects.h
@@ -218,6 +218,7 @@ struct Image
void free(void);
void setPixels(uint8 *pixels);
void setPalette(uint8 *palette);
+ bool32 hasAlpha(void);
static void setSearchPath(const char*);
static void printSearchPath(void);
@@ -507,6 +508,7 @@ struct Geometry : PluginBase
void allocateData(void);
void generateTriangles(int8 *adc = NULL);
void buildMeshes(void);
+ void removeUnusedMaterials(void);
enum Flags
{
diff --git a/src/rwps2.h b/src/rwps2.h
index 11b968d..ad182b7 100644
--- a/src/rwps2.h
+++ b/src/rwps2.h
@@ -38,6 +38,7 @@ enum PS2Attribs {
AT_RW = 0x6
};
+// Not really types as in RW but offsets
enum PS2AttibTypes {
AT_XYZ = 0,
AT_UV = 1,
@@ -65,6 +66,14 @@ struct PipeAttribute
uint32 attrib;
};
+extern PipeAttribute attribXYZ;
+extern PipeAttribute attribXYZW;
+extern PipeAttribute attribUV;
+extern PipeAttribute attribUV2;
+extern PipeAttribute attribRGBA;
+extern PipeAttribute attribNormal;
+extern PipeAttribute attribWeights;
+
class MatPipeline : public rw::Pipeline
{
public:
@@ -122,6 +131,10 @@ void insertVertex(Geometry *geo, int32 i, uint32 mask, Vertex *v);
extern ObjPipeline *defaultObjPipe;
extern MatPipeline *defaultMatPipe;
+void defaultUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[]);
+void skinInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data);
+void skinUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[]);
+
ObjPipeline *makeDefaultPipeline(void);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
@@ -164,6 +177,8 @@ struct ADCData
extern int32 adcOffset;
void registerADCPlugin(void);
+int8 *getADCbits(Geometry *geo);
+int8 *getADCbitsForMesh(Geometry *geo, Mesh *mesh);
void convertADC(Geometry *g);
void unconvertADC(Geometry *geo);
void allocateADC(Geometry *geo);