mirror of https://github.com/aap/librw.git
worked on ps2 pipelines
This commit is contained in:
parent
99bdd4fd23
commit
4d461dbfbd
|
@ -26,6 +26,7 @@ main(int argc, char *argv[])
|
|||
gta::registerBreakableModelPlugin();
|
||||
gta::registerExtraVertColorPlugin();
|
||||
rw::ps2::registerADCPlugin();
|
||||
rw::ps2::registerPDSPlugin();
|
||||
rw::registerSkinPlugin();
|
||||
rw::registerNativeDataPlugin();
|
||||
// rw::ps2::registerNativeDataPlugin();
|
||||
|
|
|
@ -64,8 +64,8 @@ const char *toolkitchunks1[] = {
|
|||
|
||||
const char *RSchunks[] = { "Unused 1", "Unused 2", "Unused 3",
|
||||
"Pipeline Set", "Unused 5", "Unused 6", "Specular Material",
|
||||
"Unused 8", "2dfx", "Night Vertex Colors", "Collision Model",
|
||||
"Unused 12", "Reflection Material", "Mesh Extension", "Frame",
|
||||
"Unused 8", "2dfx", "Extra Colors", "Collision Model",
|
||||
"Unused 12", "Environment Material", "Breakable", "Node Name",
|
||||
"Unused 16"
|
||||
};
|
||||
|
||||
|
|
27
insttest.cpp
27
insttest.cpp
|
@ -23,16 +23,19 @@ main(int argc, char *argv[])
|
|||
gta::registerBreakableModelPlugin();
|
||||
gta::registerExtraVertColorPlugin();
|
||||
rw::ps2::registerADCPlugin();
|
||||
rw::ps2::registerPDSPlugin();
|
||||
rw::registerSkinPlugin();
|
||||
rw::registerNativeDataPlugin();
|
||||
rw::registerMeshPlugin();
|
||||
|
||||
rw::platform = rw::PLATFORM_PS2;
|
||||
|
||||
rw::Pipeline *defpipe = rw::ps2::makeDefaultPipeline();
|
||||
// rw::Pipeline *skinpipe = rw::ps2::makeSkinPipeline();
|
||||
// rw::ps2::dumpPipeline(defpipe);
|
||||
// rw::ps2::dumpPipeline(skinpipe);
|
||||
rw::ps2::ObjPipeline *defpipe = rw::ps2::makeDefaultPipeline();
|
||||
rw::ps2::ObjPipeline *skinpipe = rw::ps2::makeSkinPipeline();
|
||||
rw::ps2::ObjPipeline *matfxpipe = rw::ps2::makeMatFXPipeline();
|
||||
// rw::ps2::defaultMatPipe->dump();
|
||||
// skinpipe->groupPipeline->dump();
|
||||
// matfxpipe->groupPipeline->dump();
|
||||
|
||||
int uninstance = 0;
|
||||
int arg = 1;
|
||||
|
@ -62,7 +65,19 @@ main(int argc, char *argv[])
|
|||
c = Clump::streamRead(&in);
|
||||
assert(c != NULL);
|
||||
|
||||
printf("%s\n", argv[arg]);
|
||||
// printf("%s\n", argv[arg]);
|
||||
|
||||
for(int32 i = 0; i < c->numAtomics; i++){
|
||||
Atomic *a = c->atomicList[i];
|
||||
Pipeline *ap = a->pipeline;
|
||||
Geometry *g = a->geometry;
|
||||
for(int32 j = 0; j < g->numMaterials; j++){
|
||||
Pipeline *mp = g->materialList[j]->pipeline;
|
||||
if(ap && mp)
|
||||
printf("%s %x %x\n", argv[arg], ap->pluginData, mp->pluginData);
|
||||
}
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < c->numAtomics; i++){
|
||||
Atomic *a = c->atomicList[i];
|
||||
if(a->pipeline){
|
||||
|
@ -83,7 +98,6 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
data = new rw::uint8[256*1024];
|
||||
rw::StreamMemory out;
|
||||
out.open(data, 0, 256*1024);
|
||||
|
@ -95,7 +109,6 @@ main(int argc, char *argv[])
|
|||
fclose(cf);
|
||||
out.close();
|
||||
delete[] data;
|
||||
*/
|
||||
|
||||
delete c;
|
||||
|
||||
|
|
|
@ -398,7 +398,7 @@ static void
|
|||
readMaterialRights(Stream *stream, int32, void *, int32, int32)
|
||||
{
|
||||
stream->read(materialRights, 8);
|
||||
// printf("materialrights: %X %X\n", buffer[0], buffer[1]);
|
||||
// printf("materialrights: %X %X\n", materialRights[0], materialRights[1]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -20,8 +20,6 @@ Pipeline::Pipeline(uint32 platform)
|
|||
this->pluginID = 0;
|
||||
this->pluginData = 0;
|
||||
this->platform = platform;
|
||||
for(int i = 0; i < 10; i++)
|
||||
this->attribs[i] = NULL;
|
||||
}
|
||||
|
||||
Pipeline::Pipeline(Pipeline *)
|
||||
|
@ -33,6 +31,11 @@ Pipeline::~Pipeline(void)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Pipeline::dump(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Pipeline::instance(Atomic *atomic)
|
||||
{
|
||||
|
|
|
@ -592,6 +592,7 @@ readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
|||
{
|
||||
int32 flag;
|
||||
stream->read(&flag, 4);
|
||||
// printf("matfx: %d\n", flag);
|
||||
*PLUGINOFFSET(int32, object, offset) = flag;
|
||||
if(flag)
|
||||
((Atomic*)object)->pipeline =
|
||||
|
@ -609,9 +610,10 @@ writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
|||
static int32
|
||||
getSizeAtomicMatFX(void *object, int32 offset, int32)
|
||||
{
|
||||
int32 flag;
|
||||
/* int32 flag;
|
||||
flag = *PLUGINOFFSET(int32, object, offset);
|
||||
return flag ? 4 : -1;
|
||||
return flag ? 4 : -1; */
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Material
|
||||
|
|
197
src/ps2.cpp
197
src/ps2.cpp
|
@ -16,6 +16,9 @@ using namespace std;
|
|||
namespace rw {
|
||||
namespace ps2 {
|
||||
|
||||
ObjPipeline *defaultObjPipe;
|
||||
MatPipeline *defaultMatPipe;
|
||||
|
||||
void*
|
||||
destroyNativeData(void *object, int32, int32)
|
||||
{
|
||||
|
@ -237,8 +240,46 @@ PipeAttribute attribWeights = {
|
|||
AT_V4_32 | AT_RW
|
||||
};
|
||||
|
||||
Pipeline::Pipeline(uint32 platform)
|
||||
: rw::Pipeline(platform) { }
|
||||
MatPipeline::MatPipeline(uint32 platform)
|
||||
: rw::Pipeline(platform)
|
||||
{
|
||||
for(int i = 0; i < 10; i++)
|
||||
this->attribs[i] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
MatPipeline::dump(void)
|
||||
{
|
||||
if(this->platform != PLATFORM_PS2)
|
||||
return;
|
||||
PipeAttribute *a;
|
||||
for(uint i = 0; i < nelem(this->attribs); i++){
|
||||
a = this->attribs[i];
|
||||
if(a)
|
||||
printf("%d %s: %x\n", i, a->name, a->attrib);
|
||||
}
|
||||
printf("stride: %x\n", this->inputStride);
|
||||
printf("triSCount: %x\n", this->triStripCount);
|
||||
printf("triLCount: %x\n", this->triListCount);
|
||||
printf("vifOffset: %x\n", this->vifOffset);
|
||||
}
|
||||
|
||||
void
|
||||
MatPipeline::setTriBufferSizes(uint32 inputStride, uint32 stripCount)
|
||||
{
|
||||
this->inputStride = inputStride;
|
||||
this->triListCount = stripCount/12*12;
|
||||
PipeAttribute *a;
|
||||
for(uint i = 0; i < nelem(this->attribs); i++){
|
||||
a = this->attribs[i];
|
||||
if(a && a->attrib & AT_RW)
|
||||
goto brokenout;
|
||||
}
|
||||
this->triStripCount = stripCount/4*4;
|
||||
return;
|
||||
brokenout:
|
||||
this->triStripCount = (stripCount-2)/4*4+2;
|
||||
}
|
||||
|
||||
static uint32
|
||||
attribSize(uint32 unpack)
|
||||
|
@ -250,7 +291,7 @@ attribSize(uint32 unpack)
|
|||
#define QWC(x) (((x)+0xF)>>4)
|
||||
|
||||
static uint32
|
||||
getBatchSize(Pipeline *pipe, uint32 vertCount)
|
||||
getBatchSize(MatPipeline *pipe, uint32 vertCount)
|
||||
{
|
||||
PipeAttribute *a;
|
||||
uint32 size = 1;
|
||||
|
@ -345,7 +386,7 @@ instanceNormal(uint32 *wp, Geometry *g, Mesh *m, uint32 idx, uint32 n)
|
|||
uint32 markcnt = 0xf790;
|
||||
|
||||
static void
|
||||
instanceMat(Pipeline *pipe, Geometry *g, InstanceData *inst, Mesh *m)
|
||||
instanceMat(MatPipeline *pipe, Geometry *g, InstanceData *inst, Mesh *m)
|
||||
{
|
||||
PipeAttribute *a;
|
||||
uint32 numAttribs = 0;
|
||||
|
@ -367,7 +408,7 @@ instanceMat(Pipeline *pipe, Geometry *g, InstanceData *inst, Mesh *m)
|
|||
}
|
||||
batchVertCount = pipe->triStripCount;
|
||||
lastBatchVertCount = totalVerts%pipe->triStripCount;
|
||||
}else{ // trilist
|
||||
}else{ // trilist
|
||||
numBatches = (m->numIndices+pipe->triListCount-1) /
|
||||
pipe->triListCount;
|
||||
totalVerts = m->numIndices;
|
||||
|
@ -488,18 +529,17 @@ instanceMat(Pipeline *pipe, Geometry *g, InstanceData *inst, Mesh *m)
|
|||
*p++ = 0x06000000; // MSKPATH3; SA: FLUSH
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
FILE *f = fopen("out.bin", "w");
|
||||
fwrite(inst->data, inst->dataSize, 1, f);
|
||||
fclose(f);
|
||||
*/
|
||||
}
|
||||
|
||||
ObjPipeline::ObjPipeline(uint32 platform)
|
||||
: rw::Pipeline(platform), groupPipeline(NULL) { }
|
||||
|
||||
void
|
||||
Pipeline::instance(Atomic *atomic)
|
||||
ObjPipeline::instance(Atomic *atomic)
|
||||
{
|
||||
Geometry *geometry = atomic->geometry;
|
||||
if(geometry->geoflags & Geometry::NATIVE)
|
||||
return;
|
||||
InstanceDataHeader *header = new InstanceDataHeader;
|
||||
geometry->instData = header;
|
||||
header->platform = PLATFORM_PS2;
|
||||
|
@ -509,8 +549,14 @@ Pipeline::instance(Atomic *atomic)
|
|||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
Mesh *mesh = &geometry->meshHeader->mesh[i];
|
||||
InstanceData *instance = &header->instanceMeshes[i];
|
||||
// TODO: should depend on material pipeline
|
||||
instanceMat(this, geometry, instance, mesh);
|
||||
|
||||
MatPipeline *m;
|
||||
m = this->groupPipeline ?
|
||||
m = this->groupPipeline :
|
||||
(MatPipeline*)mesh->material->pipeline;
|
||||
if(m == NULL)
|
||||
m = defaultMatPipe;
|
||||
instanceMat(m, geometry, instance, mesh);
|
||||
//printf("\n");
|
||||
}
|
||||
geometry->geoflags |= Geometry::NATIVE;
|
||||
|
@ -543,7 +589,7 @@ printVertCounts(InstanceData *inst, int flag)
|
|||
|
||||
// Only a dummy right now
|
||||
void
|
||||
Pipeline::uninstance(Atomic *atomic)
|
||||
ObjPipeline::uninstance(Atomic *atomic)
|
||||
{
|
||||
Geometry *geometry = atomic->geometry;
|
||||
assert(geometry->instData->platform == PLATFORM_PS2);
|
||||
|
@ -560,41 +606,32 @@ Pipeline::uninstance(Atomic *atomic)
|
|||
|
||||
#undef QWC
|
||||
|
||||
void
|
||||
Pipeline::setTriBufferSizes(uint32 inputStride, uint32 stripCount)
|
||||
{
|
||||
this->inputStride = inputStride;
|
||||
this->triListCount = stripCount/12*12;
|
||||
PipeAttribute *a;
|
||||
for(uint i = 0; i < nelem(this->attribs); i++){
|
||||
a = this->attribs[i];
|
||||
if(a && a->attrib & AT_RW)
|
||||
goto brokenout;
|
||||
}
|
||||
this->triStripCount = stripCount/4*4;
|
||||
return;
|
||||
brokenout:
|
||||
this->triStripCount = (stripCount-2)/4*4+2;
|
||||
}
|
||||
|
||||
Pipeline*
|
||||
ObjPipeline*
|
||||
makeDefaultPipeline(void)
|
||||
{
|
||||
Pipeline *pipe = new Pipeline(PLATFORM_PS2);
|
||||
pipe->attribs[AT_XYZ] = &attribXYZ;
|
||||
pipe->attribs[AT_UV] = &attribUV;
|
||||
pipe->attribs[AT_RGBA] = &attribRGBA;
|
||||
pipe->attribs[AT_NORMAL] = &attribNormal;
|
||||
uint32 vertCount = Pipeline::getVertCount(VU_Lights, 4, 3, 2);
|
||||
pipe->setTriBufferSizes(4, vertCount);
|
||||
pipe->vifOffset = pipe->inputStride*vertCount;
|
||||
return pipe;
|
||||
if(defaultMatPipe == NULL){
|
||||
MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
|
||||
pipe->attribs[AT_XYZ] = &attribXYZ;
|
||||
pipe->attribs[AT_UV] = &attribUV;
|
||||
pipe->attribs[AT_RGBA] = &attribRGBA;
|
||||
pipe->attribs[AT_NORMAL] = &attribNormal;
|
||||
uint32 vertCount = MatPipeline::getVertCount(VU_Lights,4,3,2);
|
||||
pipe->setTriBufferSizes(4, vertCount);
|
||||
pipe->vifOffset = pipe->inputStride*vertCount;
|
||||
defaultMatPipe = pipe;
|
||||
}
|
||||
|
||||
if(defaultObjPipe == NULL){
|
||||
ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
|
||||
defaultObjPipe = opipe;
|
||||
}
|
||||
return defaultObjPipe;
|
||||
}
|
||||
|
||||
Pipeline*
|
||||
ObjPipeline*
|
||||
makeSkinPipeline(void)
|
||||
{
|
||||
Pipeline *pipe = new Pipeline(PLATFORM_PS2);
|
||||
MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
|
||||
pipe->pluginID = ID_SKIN;
|
||||
pipe->pluginData = 1;
|
||||
pipe->attribs[AT_XYZ] = &attribXYZ;
|
||||
|
@ -602,44 +639,36 @@ makeSkinPipeline(void)
|
|||
pipe->attribs[AT_RGBA] = &attribRGBA;
|
||||
pipe->attribs[AT_NORMAL] = &attribNormal;
|
||||
pipe->attribs[AT_NORMAL+1] = &attribWeights;
|
||||
uint32 vertCount = Pipeline::getVertCount(VU_Lights-0x100, 5, 3, 2);
|
||||
uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2);
|
||||
pipe->setTriBufferSizes(5, vertCount);
|
||||
pipe->vifOffset = pipe->inputStride*vertCount;
|
||||
return pipe;
|
||||
|
||||
ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
|
||||
opipe->pluginID = ID_SKIN;
|
||||
opipe->pluginData = 1;
|
||||
opipe->groupPipeline = pipe;
|
||||
return opipe;
|
||||
}
|
||||
|
||||
Pipeline*
|
||||
ObjPipeline*
|
||||
makeMatFXPipeline(void)
|
||||
{
|
||||
Pipeline *pipe = new Pipeline(PLATFORM_PS2);
|
||||
MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
|
||||
pipe->pluginID = ID_MATFX;
|
||||
pipe->pluginData = 0;
|
||||
pipe->attribs[AT_XYZ] = &attribXYZ;
|
||||
pipe->attribs[AT_UV] = &attribUV;
|
||||
pipe->attribs[AT_RGBA] = &attribRGBA;
|
||||
pipe->attribs[AT_NORMAL] = &attribNormal;
|
||||
uint32 vertCount = Pipeline::getVertCount(0x3C5, 4, 3, 3);
|
||||
uint32 vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
|
||||
pipe->setTriBufferSizes(4, vertCount);
|
||||
pipe->vifOffset = pipe->inputStride*vertCount;
|
||||
return pipe;
|
||||
}
|
||||
|
||||
void
|
||||
dumpPipeline(rw::Pipeline *rwpipe)
|
||||
{
|
||||
if(rwpipe->platform != PLATFORM_PS2)
|
||||
return;
|
||||
Pipeline *pipe = (Pipeline*)rwpipe;
|
||||
PipeAttribute *a;
|
||||
for(uint i = 0; i < nelem(pipe->attribs); i++){
|
||||
a = pipe->attribs[i];
|
||||
if(a)
|
||||
printf("%d %s: %x\n", i, a->name, a->attrib);
|
||||
}
|
||||
printf("stride: %x\n", pipe->inputStride);
|
||||
printf("triSCount: %x\n", pipe->triStripCount);
|
||||
printf("triLCount: %x\n", pipe->triListCount);
|
||||
printf("vifOffset: %x\n", pipe->vifOffset);
|
||||
ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
|
||||
opipe->pluginID = ID_MATFX;
|
||||
opipe->pluginData = 0;
|
||||
opipe->groupPipeline = pipe;
|
||||
return opipe;
|
||||
}
|
||||
|
||||
// Skin
|
||||
|
@ -731,6 +760,7 @@ getSizeNativeSkin(void *object, int32 offset)
|
|||
return size;
|
||||
}
|
||||
|
||||
|
||||
// ADC
|
||||
|
||||
static void*
|
||||
|
@ -788,6 +818,39 @@ registerADCPlugin(void)
|
|||
}
|
||||
|
||||
|
||||
// PDS plugin
|
||||
|
||||
static void
|
||||
atomicPDSRights(void *object, int32, int32, uint32 data)
|
||||
{
|
||||
Atomic *a = (Atomic*)object;
|
||||
// TODO: lookup pipeline by data
|
||||
a->pipeline = new Pipeline(PLATFORM_PS2);
|
||||
a->pipeline->pluginID = ID_PDS;
|
||||
a->pipeline->pluginData = data;
|
||||
}
|
||||
|
||||
static void
|
||||
materialPDSRights(void *object, int32, int32, uint32 data)
|
||||
{
|
||||
Material *m = (Material*)object;
|
||||
// TODO: lookup pipeline by data
|
||||
m->pipeline = new Pipeline(PLATFORM_PS2);
|
||||
m->pipeline->pluginID = ID_PDS;
|
||||
m->pipeline->pluginData = data;
|
||||
}
|
||||
|
||||
void
|
||||
registerPDSPlugin(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// misc stuff
|
||||
|
||||
void
|
||||
|
|
|
@ -8,17 +8,18 @@ struct PipeAttribute
|
|||
|
||||
struct Atomic;
|
||||
|
||||
struct Pipeline
|
||||
class Pipeline
|
||||
{
|
||||
public:
|
||||
uint32 pluginID;
|
||||
uint32 pluginData;
|
||||
|
||||
uint32 platform;
|
||||
PipeAttribute *attribs[10];
|
||||
|
||||
Pipeline(uint32 platform);
|
||||
Pipeline(Pipeline *p);
|
||||
~Pipeline(void);
|
||||
virtual void dump(void);
|
||||
// TODO: this is bad, maybe split obj and mat pipelines?
|
||||
virtual void instance(Atomic *atomic);
|
||||
virtual void uninstance(Atomic *atomic);
|
||||
virtual void render(Atomic *atomic);
|
||||
|
|
48
src/rwps2.h
48
src/rwps2.h
|
@ -38,27 +38,43 @@ void fixDmaOffsets(InstanceData *inst);
|
|||
void unfixDmaOffsets(InstanceData *inst);
|
||||
//
|
||||
|
||||
struct Pipeline : rw::Pipeline
|
||||
class MatPipeline : public rw::Pipeline
|
||||
{
|
||||
public:
|
||||
uint32 vifOffset;
|
||||
uint32 inputStride;
|
||||
uint32 triStripCount, triListCount;
|
||||
PipeAttribute *attribs[10];
|
||||
|
||||
static uint32 getVertCount(uint32 top, uint32 inAttribs,
|
||||
uint32 outAttribs, uint32 outBufs) {
|
||||
return (top-outBufs)/(inAttribs*2+outAttribs*outBufs);
|
||||
}
|
||||
|
||||
Pipeline(uint32 platform);
|
||||
virtual void instance(Atomic *atomic);
|
||||
virtual void uninstance(Atomic *atomic);
|
||||
// virtual void render(Atomic *atomic);
|
||||
MatPipeline(uint32 platform);
|
||||
virtual void dump(void);
|
||||
// virtual void instance(Atomic *atomic);
|
||||
// virtual void uninstance(Atomic *atomic);
|
||||
/// virtual void render(Atomic *atomic);
|
||||
void setTriBufferSizes(uint32 inputStride, uint32 stripCount);
|
||||
};
|
||||
|
||||
Pipeline *makeDefaultPipeline(void);
|
||||
Pipeline *makeSkinPipeline(void);
|
||||
Pipeline *makeMatFXPipeline(void);
|
||||
class ObjPipeline : public rw::Pipeline
|
||||
{
|
||||
public:
|
||||
MatPipeline *groupPipeline;
|
||||
|
||||
ObjPipeline(uint32 platform);
|
||||
virtual void instance(Atomic *atomic);
|
||||
virtual void uninstance(Atomic *atomic);
|
||||
};
|
||||
|
||||
extern ObjPipeline *defaultObjPipe;
|
||||
extern MatPipeline *defaultMatPipe;
|
||||
|
||||
ObjPipeline *makeDefaultPipeline(void);
|
||||
ObjPipeline *makeSkinPipeline(void);
|
||||
ObjPipeline *makeMatFXPipeline(void);
|
||||
void dumpPipeline(rw::Pipeline *pipe);
|
||||
|
||||
// Skin plugin
|
||||
|
@ -79,5 +95,21 @@ struct ADCData
|
|||
|
||||
void registerADCPlugin(void);
|
||||
|
||||
// PDS plugin
|
||||
|
||||
// IDs used by SA
|
||||
// n atomic material
|
||||
// 1892 53f20080 53f20081 // ?
|
||||
// 1 53f20080 53f2008d // triad_buddha01.dff
|
||||
// 56430 53f20082 53f20083 // world
|
||||
// 39 53f20082 53f2008f // reflective world
|
||||
// 6941 53f20084 53f20085 // vehicles
|
||||
// 3423 53f20084 53f20087 // vehicles
|
||||
// 4640 53f20084 53f2008b // vehicles
|
||||
// 418 53f20088 53f20089 // peds
|
||||
|
||||
|
||||
void registerPDSPlugin(void);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue