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