Added functions for fixing/unfixing DMA pointers in PS2 data.

This commit is contained in:
Angelo Papenhoff 2014-12-30 19:30:13 +01:00
parent cbc31bdb25
commit cec7963a9d
2 changed files with 92 additions and 4 deletions

View File

@ -45,11 +45,13 @@ ReadNativeData(Stream *stream, int32, void *object, int32, int32)
uint32 buf[2]; uint32 buf[2];
stream->read(buf, 8); stream->read(buf, 8);
instance->dataSize = buf[0]; instance->dataSize = buf[0];
instance->noRefChain = buf[1]; instance->arePointersFixed = buf[1];
// TODO: force alignment // TODO: force alignment
instance->data = new uint8[instance->dataSize]; instance->data = new uint8[instance->dataSize];
uint64 a = (uint64)instance->data ; #ifdef RW_PS2
uint32 a = (uint32)instance->data;
assert(a % 0x10 == 0); assert(a % 0x10 == 0);
#endif
stream->read(instance->data, instance->dataSize); stream->read(instance->data, instance->dataSize);
} }
} }
@ -65,9 +67,11 @@ WriteNativeData(Stream *stream, int32 len, void *object, int32, int32)
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){ for(uint32 i = 0; i < header->numMeshes; i++){
InstanceData *instance = &header->instanceMeshes[i]; InstanceData *instance = &header->instanceMeshes[i];
if(instance->arePointersFixed == 2)
unfixDmaOffsets(instance);
uint32 buf[2]; uint32 buf[2];
buf[0] = instance->dataSize; buf[0] = instance->dataSize;
buf[1] = instance->noRefChain; buf[1] = instance->arePointersFixed;
stream->write(buf, 8); stream->write(buf, 8);
stream->write(instance->data, instance->dataSize); stream->write(instance->data, instance->dataSize);
} }
@ -100,5 +104,81 @@ registerNativeDataPlugin(void)
(StreamGetSize)GetSizeNativeData); (StreamGetSize)GetSizeNativeData);
} }
#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
}
} }
} }

View File

@ -3,7 +3,11 @@ namespace Ps2 {
struct InstanceData struct InstanceData
{ {
uint32 noRefChain; // 0 - addresses in ref tags need fixing
// 1 - no ref tags, so no fixing
// set by the program:
// 2 - ref tags are fixed, need to unfix before stream write
uint32 arePointersFixed;
uint32 dataSize; uint32 dataSize;
uint8 *data; uint8 *data;
Material *material; Material *material;
@ -21,5 +25,9 @@ void WriteNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeData(void *object, int32, int32); int32 GetSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void); void registerNativeDataPlugin(void);
// only RW_PS2
void fixDmaOffsets(InstanceData *inst);
void unfixDmaOffsets(InstanceData *inst);
} }
} }