Implemented rudimentary StreamMemory.

This commit is contained in:
Angelo Papenhoff 2014-12-30 17:39:39 +01:00
parent e9819e9f8a
commit cbc31bdb25
7 changed files with 181 additions and 46 deletions

View File

@ -3,9 +3,6 @@
#include <cstring>
#include <cassert>
//#include <iostream>
//#include <fstream>
//#include <list>
#include <new>
#include "rw.h"
@ -21,17 +18,32 @@ main(int argc, char *argv[])
registerNodeNamePlugin();
registerBreakableModelPlugin();
registerNativeDataPlugin();
// registerNativeDataPS2Plugin();
// Ps2::registerNativeDataPlugin();
registerMeshPlugin();
Rw::Clump *c;
// ifstream in(argv[1], ios::binary);
Rw::StreamFile in;
in.open(argv[1], "rb");
// Rw::StreamFile in;
// in.open(argv[1], "rb");
FILE *cf = fopen(argv[1], "rb");
assert(cf != NULL);
fseek(cf, 0, SEEK_END);
Rw::uint32 len = ftell(cf);
fseek(cf, 0, SEEK_SET);
Rw::uint8 *data = new Rw::uint8[len];
fread(data, len, 1, cf);
fclose(cf);
Rw::StreamMemory in;
in.open(data, len);
Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL);
c = Rw::Clump::streamRead(&in);
assert(c != NULL);
in.close();
delete[] data;
// Rw::Image *tga = Rw::readTGA("b.tga");
// assert(tga != NULL);
@ -41,10 +53,19 @@ main(int argc, char *argv[])
// Rw::Gl::Instance(c->atomicList[i]);
// ofstream out(argv[2], ios::binary);
Rw::StreamFile out;
out.open(argv[2], "wb");
// Rw::StreamFile out;
// out.open(argv[2], "wb");
data = new Rw::uint8[256*1024];
Rw::StreamMemory out;
out.open(data, 0, 256*1024);
c->streamWrite(&out);
cf = fopen(argv[2], "wb");
assert(cf != NULL);
fwrite(data, out.getLength(), 1, cf);
fclose(cf);
out.close();
delete[] data;
delete c;

View File

@ -201,7 +201,7 @@ destroyNativeData(void *object, int32 offset, int32 size)
if(geometry->instData == NULL)
return object;
if(geometry->instData->platform == PLATFORM_PS2)
return DestroyNativeDataPS2(object, offset, size);
return Ps2::DestroyNativeData(object, offset, size);
if(geometry->instData->platform == PLATFORM_OGL)
return Gl::DestroyNativeData(object, offset, size);
return object;
@ -223,7 +223,7 @@ readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
platform = stream->readU32();
stream->seek(-16);
if(platform == PLATFORM_PS2)
ReadNativeDataPS2(stream, len, object, o, s);
Ps2::ReadNativeData(stream, len, object, o, s);
else if(platform == PLATFORM_XBOX)
stream->seek(len);
}else{
@ -239,7 +239,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
if(geometry->instData == NULL)
return;
if(geometry->instData->platform == PLATFORM_PS2)
WriteNativeDataPS2(stream, len, object, o, s);
Ps2::WriteNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_OGL)
Gl::WriteNativeData(stream, len, object, o, s);
}
@ -251,7 +251,7 @@ getSizeNativeData(void *object, int32 offset, int32 size)
if(geometry->instData == NULL)
return -1;
if(geometry->instData->platform == PLATFORM_PS2)
return GetSizeNativeDataPS2(object, offset, size);
return Ps2::GetSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_XBOX)
return -1;
else if(geometry->instData->platform == PLATFORM_OGL)
@ -270,17 +270,6 @@ registerNativeDataPlugin(void)
(StreamGetSize)getSizeNativeData);
}
void
registerNativeDataPS2Plugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
NULL, DestroyNativeDataPS2, NULL);
Geometry::registerPluginStream(ID_NATIVEDATA,
(StreamRead)ReadNativeDataPS2,
(StreamWrite)WriteNativeDataPS2,
(StreamGetSize)GetSizeNativeDataPS2);
}
// Breakable Model
// TODO: put this in a header

View File

@ -13,14 +13,14 @@
using namespace std;
namespace Rw {
namespace Ps2 {
void*
DestroyNativeDataPS2(void *object, int32, int32)
DestroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_PS2);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++)
delete[] header->instanceMeshes[i].data;
delete[] header->instanceMeshes;
@ -29,40 +29,42 @@ DestroyNativeDataPS2(void *object, int32, int32)
}
void
ReadNativeDataPS2(Stream *stream, int32, void *object, int32, int32)
ReadNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
assert(stream->readU32() == PLATFORM_PS2);
PS2InstanceDataHeader *header = new PS2InstanceDataHeader;
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_PS2;
assert(geometry->meshHeader != NULL);
header->numMeshes = geometry->meshHeader->numMeshes;
header->instanceMeshes = new PS2InstanceData[header->numMeshes];
header->instanceMeshes = new InstanceData[header->numMeshes];
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
InstanceData *instance = &header->instanceMeshes[i];
uint32 buf[2];
stream->read(buf, 8);
instance->dataSize = buf[0];
instance->noRefChain = buf[1];
// TODO: force alignment
instance->data = new uint8[instance->dataSize];
uint64 a = (uint64)instance->data ;
assert(a % 0x10 == 0);
stream->read(instance->data, instance->dataSize);
}
}
void
WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32)
WriteNativeData(Stream *stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
WriteChunkHeader(stream, ID_STRUCT, len-12);
assert(geometry->instData->platform == PLATFORM_PS2);
stream->writeU32(PLATFORM_PS2);
assert(geometry->instData != NULL);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
InstanceData *instance = &header->instanceMeshes[i];
uint32 buf[2];
buf[0] = instance->dataSize;
buf[1] = instance->noRefChain;
@ -72,20 +74,31 @@ WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32)
}
int32
GetSizeNativeDataPS2(void *object, int32, int32)
GetSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
int32 size = 16;
assert(geometry->instData->platform == PLATFORM_PS2);
assert(geometry->instData != NULL);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
InstanceData *instance = &header->instanceMeshes[i];
size += 8;
size += instance->dataSize;
}
return size;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
NULL, DestroyNativeData, NULL);
Geometry::registerPluginStream(ID_NATIVEDATA,
(StreamRead)ReadNativeData,
(StreamWrite)WriteNativeData,
(StreamGetSize)GetSizeNativeData);
}
}
}

View File

@ -1,5 +1,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
@ -113,6 +114,94 @@ Stream::readF32(void)
}
void
StreamMemory::close(void)
{
}
uint32
StreamMemory::write(const void *data, uint32 len)
{
if(this->eof())
return 0;
uint32 l = len;
if(this->position+l > this->length){
if(this->position+l > this->capacity)
l = this->capacity-this->position;
this->length = this->position+l;
}
memcpy(&this->data[this->position], data, l);
this->position += l;
if(len != l)
this->position = S_EOF;
return l;
}
uint32
StreamMemory::read(void *data, uint32 len)
{
if(this->eof())
return 0;
uint32 l = len;
if(this->position+l > this->length)
l = this->length-this->position;
memcpy(data, &this->data[this->position], l);
this->position += l;
if(len != l)
this->position = S_EOF;
return l;
}
void
StreamMemory::seek(int32 offset, int32 whence)
{
if(whence == 0)
this->position = offset;
else if(whence == 1)
this->position += offset;
else
this->position = this->length-offset;
if(this->position > this->length){
// TODO: ideally this would depend on the mode
if(this->position > this->capacity)
this->position = S_EOF;
else
this->length = this->position;
}
}
uint32
StreamMemory::tell(void)
{
return this->position;
}
bool
StreamMemory::eof(void)
{
return this->position == S_EOF;
}
StreamMemory*
StreamMemory::open(uint8 *data, uint32 length, uint32 capacity)
{
this->data = data;
this->capacity = capacity;
this->length = length;
if(this->capacity < this->length)
this->capacity = this->length;
this->position = 0;
return this;
}
uint32
StreamMemory::getLength(void)
{
return this->length;
}
StreamFile*
StreamFile::open(const char *path, const char *mode)
{

View File

@ -38,6 +38,27 @@ public:
float32 readF32(void);
};
class StreamMemory : public Stream
{
uint8 *data;
uint32 length;
uint32 capacity;
uint32 position;
public:
void close(void);
uint32 write(const void *data, uint32 length);
uint32 read(void *data, uint32 length);
void seek(int32 offset, int32 whence);
uint32 tell(void);
bool eof(void);
StreamMemory *open(uint8 *data, uint32 length, uint32 capacity = 0);
uint32 getLength(void);
enum {
S_EOF = 0xFFFFFFFF
};
};
class StreamFile : public Stream
{
FILE *file;

View File

@ -230,5 +230,4 @@ private:
void registerNodeNamePlugin(void);
void registerMeshPlugin(void);
void registerNativeDataPlugin(void);
void registerNativeDataPS2Plugin(void);
void registerBreakableModelPlugin(void);

View File

@ -1,6 +1,7 @@
namespace Rw {
namespace Ps2 {
struct PS2InstanceData
struct InstanceData
{
uint32 noRefChain;
uint32 dataSize;
@ -8,15 +9,17 @@ struct PS2InstanceData
Material *material;
};
struct PS2InstanceDataHeader : InstanceDataHeader
struct InstanceDataHeader : Rw::InstanceDataHeader
{
uint32 numMeshes;
PS2InstanceData *instanceMeshes;
InstanceData *instanceMeshes;
};
void *DestroyNativeDataPS2(void *object, int32, int32);
void ReadNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32);
void WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeDataPS2(void *object, int32, int32);
void *DestroyNativeData(void *object, int32, int32);
void ReadNativeData(Stream *stream, int32 len, void *object, int32, int32);
void WriteNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
}
}