2014-12-20 18:24:08 +01:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
|
2014-12-27 23:18:10 +01:00
|
|
|
#include <new>
|
2014-12-20 18:24:08 +01:00
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwplugin.h"
|
2014-12-23 15:59:14 +01:00
|
|
|
#include "rwobjects.h"
|
2014-12-20 18:24:08 +01:00
|
|
|
#include "rwps2.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace Rw {
|
2014-12-30 17:39:39 +01:00
|
|
|
namespace Ps2 {
|
2014-12-20 18:24:08 +01:00
|
|
|
|
2014-12-20 20:18:41 +01:00
|
|
|
void*
|
2014-12-30 17:39:39 +01:00
|
|
|
DestroyNativeData(void *object, int32, int32)
|
2014-12-20 20:18:41 +01:00
|
|
|
{
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
assert(geometry->instData->platform == PLATFORM_PS2);
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
|
2014-12-20 20:18:41 +01:00
|
|
|
for(uint32 i = 0; i < header->numMeshes; i++)
|
|
|
|
delete[] header->instanceMeshes[i].data;
|
|
|
|
delete[] header->instanceMeshes;
|
|
|
|
delete header;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2014-12-20 18:24:08 +01:00
|
|
|
void
|
2014-12-30 17:39:39 +01:00
|
|
|
ReadNativeData(Stream *stream, int32, void *object, int32, int32)
|
2014-12-20 18:24:08 +01:00
|
|
|
{
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
|
2014-12-27 23:18:10 +01:00
|
|
|
assert(stream->readU32() == PLATFORM_PS2);
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceDataHeader *header = new InstanceDataHeader;
|
2014-12-20 18:24:08 +01:00
|
|
|
geometry->instData = header;
|
2014-12-23 11:29:37 +01:00
|
|
|
header->platform = PLATFORM_PS2;
|
2014-12-20 18:24:08 +01:00
|
|
|
assert(geometry->meshHeader != NULL);
|
|
|
|
header->numMeshes = geometry->meshHeader->numMeshes;
|
2014-12-30 17:39:39 +01:00
|
|
|
header->instanceMeshes = new InstanceData[header->numMeshes];
|
2014-12-20 18:24:08 +01:00
|
|
|
for(uint32 i = 0; i < header->numMeshes; i++){
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceData *instance = &header->instanceMeshes[i];
|
2014-12-20 18:24:08 +01:00
|
|
|
uint32 buf[2];
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->read(buf, 8);
|
2014-12-20 18:24:08 +01:00
|
|
|
instance->dataSize = buf[0];
|
2014-12-30 19:30:13 +01:00
|
|
|
instance->arePointersFixed = buf[1];
|
2014-12-30 17:39:39 +01:00
|
|
|
// TODO: force alignment
|
2014-12-20 18:24:08 +01:00
|
|
|
instance->data = new uint8[instance->dataSize];
|
2014-12-30 19:30:13 +01:00
|
|
|
#ifdef RW_PS2
|
|
|
|
uint32 a = (uint32)instance->data;
|
2014-12-30 17:39:39 +01:00
|
|
|
assert(a % 0x10 == 0);
|
2014-12-30 19:30:13 +01:00
|
|
|
#endif
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->read(instance->data, instance->dataSize);
|
2014-12-20 18:24:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-12-30 17:39:39 +01:00
|
|
|
WriteNativeData(Stream *stream, int32 len, void *object, int32, int32)
|
2014-12-20 18:24:08 +01:00
|
|
|
{
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
WriteChunkHeader(stream, ID_STRUCT, len-12);
|
2014-12-20 20:18:41 +01:00
|
|
|
assert(geometry->instData->platform == PLATFORM_PS2);
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->writeU32(PLATFORM_PS2);
|
2014-12-20 18:24:08 +01:00
|
|
|
assert(geometry->instData != NULL);
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
|
2014-12-20 18:24:08 +01:00
|
|
|
for(uint32 i = 0; i < header->numMeshes; i++){
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceData *instance = &header->instanceMeshes[i];
|
2014-12-30 19:30:13 +01:00
|
|
|
if(instance->arePointersFixed == 2)
|
|
|
|
unfixDmaOffsets(instance);
|
2014-12-20 18:24:08 +01:00
|
|
|
uint32 buf[2];
|
|
|
|
buf[0] = instance->dataSize;
|
2014-12-30 19:30:13 +01:00
|
|
|
buf[1] = instance->arePointersFixed;
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->write(buf, 8);
|
|
|
|
stream->write(instance->data, instance->dataSize);
|
2014-12-20 18:24:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32
|
2014-12-30 17:39:39 +01:00
|
|
|
GetSizeNativeData(void *object, int32, int32)
|
2014-12-20 18:24:08 +01:00
|
|
|
{
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
int32 size = 16;
|
2014-12-20 20:18:41 +01:00
|
|
|
assert(geometry->instData->platform == PLATFORM_PS2);
|
2014-12-20 18:24:08 +01:00
|
|
|
assert(geometry->instData != NULL);
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
|
2014-12-20 18:24:08 +01:00
|
|
|
for(uint32 i = 0; i < header->numMeshes; i++){
|
2014-12-30 17:39:39 +01:00
|
|
|
InstanceData *instance = &header->instanceMeshes[i];
|
2014-12-20 18:24:08 +01:00
|
|
|
size += 8;
|
|
|
|
size += instance->dataSize;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2014-12-30 17:39:39 +01:00
|
|
|
void
|
|
|
|
registerNativeDataPlugin(void)
|
|
|
|
{
|
|
|
|
Geometry::registerPlugin(0, ID_NATIVEDATA,
|
|
|
|
NULL, DestroyNativeData, NULL);
|
|
|
|
Geometry::registerPluginStream(ID_NATIVEDATA,
|
|
|
|
(StreamRead)ReadNativeData,
|
|
|
|
(StreamWrite)WriteNativeData,
|
|
|
|
(StreamGetSize)GetSizeNativeData);
|
|
|
|
}
|
|
|
|
|
2014-12-30 19:30:13 +01:00
|
|
|
#ifdef RW_PS2
|
|
|
|
void
|
|
|
|
fixDmaOffsets(InstanceData *inst)
|
|
|
|
{
|
|
|
|
if(inst->arePointersFixed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint32 base = (uint32)inst->data;
|
|
|
|
uint32 *tag = (uint32*)inst->data;
|
|
|
|
for(;;){
|
|
|
|
switch(tag[0]&0x70000000){
|
|
|
|
// DMAcnt
|
|
|
|
case 0x10000000:
|
|
|
|
// no need to fix
|
|
|
|
tag += (1+(tag[0]&0xFFFF))*4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// DMAref
|
|
|
|
case 0x30000000:
|
|
|
|
// fix address and jump to next
|
|
|
|
tag[1] = base + tag[1]*0x10;
|
|
|
|
tag += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// DMAret
|
|
|
|
case 0x60000000:
|
|
|
|
// we're done
|
|
|
|
inst->arePointersFixed = 2;
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "error: unknown DMAtag %X\n", tag[0]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
unfixDmaOffsets(InstanceData *inst)
|
|
|
|
{
|
|
|
|
#ifdef RW_PS2
|
|
|
|
if(inst->arePointersFixed != 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint32 base = (uint32)inst->data;
|
|
|
|
uint32 *tag = (uint32*)inst->data;
|
|
|
|
for(;;){
|
|
|
|
switch(tag[0]&0x70000000){
|
|
|
|
// DMAcnt
|
|
|
|
case 0x10000000:
|
|
|
|
// no need to unfix
|
|
|
|
tag += (1+(tag[0]&0xFFFF))*4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// DMAref
|
|
|
|
case 0x30000000:
|
|
|
|
// unfix address and jump to next
|
|
|
|
tag[1] = (tag[1] - base)/0x10;
|
|
|
|
tag += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// DMAret
|
|
|
|
case 0x60000000:
|
|
|
|
// we're done
|
|
|
|
inst->arePointersFixed = 0;
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "error: unknown DMAtag %X\n", tag[0]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-12-30 17:39:39 +01:00
|
|
|
}
|
2014-12-20 18:24:08 +01:00
|
|
|
}
|