diff --git a/src/d3d.cpp b/src/d3d.cpp index 38a155d..3538010 100644 --- a/src/d3d.cpp +++ b/src/d3d.cpp @@ -550,6 +550,7 @@ createNativeRaster(void *object, int32 offset, int32) raster->palette = NULL; raster->format = 0; raster->hasAlpha = 0; + raster->customFormat = 0; return object; } @@ -569,6 +570,7 @@ copyNativeRaster(void *dst, void *, int32 offset, int32) raster->palette = NULL; raster->format = 0; raster->hasAlpha = 0; + raster->customFormat = 0; return dst; } diff --git a/src/d3d8.cpp b/src/d3d8.cpp index d6d14f0..370ad0d 100644 --- a/src/d3d8.cpp +++ b/src/d3d8.cpp @@ -393,7 +393,7 @@ readNativeTexture(Stream *stream) stream->read(tex->mask, 32); // Raster - int32 format = stream->readI32(); + uint32 format = stream->readU32(); bool32 hasAlpha = stream->readI32(); int32 width = stream->readU16(); int32 height = stream->readU16(); @@ -406,11 +406,13 @@ readNativeTexture(Stream *stream) D3dRaster *ras; if(compression){ raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D8); + ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); allocateDXT(raster, compression, numLevels, hasAlpha); - }else + ras->customFormat = 1; + }else{ raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D8); - - ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + } tex->raster = raster; // TODO: check if format supported and convert if necessary diff --git a/src/d3d9.cpp b/src/d3d9.cpp index 8040f59..e30a306 100644 --- a/src/d3d9.cpp +++ b/src/d3d9.cpp @@ -512,5 +512,137 @@ makeMatFXPipeline(void) return pipe; } +// Native Texture and Raster + +Texture* +readNativeTexture(Stream *stream) +{ + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + assert(stream->readU32() == PLATFORM_D3D9); + Texture *tex = Texture::create(NULL); + + // Texture + tex->filterAddressing = stream->readU32(); + stream->read(tex->name, 32); + stream->read(tex->mask, 32); + + // Raster + int32 format = stream->readI32(); + int32 d3dformat = stream->readI32(); + int32 width = stream->readU16(); + int32 height = stream->readU16(); + int32 depth = stream->readU8(); + int32 numLevels = stream->readU8(); + int32 type = stream->readU8(); + int32 flags = stream->readU8(); + + Raster *raster; + D3dRaster *ras; + + assert((flags & 2) == 0); + if(flags & 8){ + raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D9); + ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ras->format = d3dformat; + ras->hasAlpha = flags & 1; + ras->texture = createTexture(raster->width, raster->height, + raster->format & Raster::MIPMAP ? numLevels : 1, + ras->format); + raster->flags &= ~0x80; + ras->customFormat = 1; + }else{ + raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D9); + ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + } + tex->raster = raster; + + // TODO: check if format supported and convert if necessary + + if(raster->format & Raster::PAL4) + stream->read(ras->palette, 4*32); + else if(raster->format & Raster::PAL8) + stream->read(ras->palette, 4*256); + + uint32 size; + uint8 *data; + for(int32 i = 0; i < numLevels; i++){ + size = stream->readU32(); + if(i < raster->getNumLevels()){ + data = raster->lock(i); + stream->read(data, size); + raster->unlock(i); + }else + stream->seek(size); + } + tex->streamReadPlugins(stream); + return tex; +} + +void +writeNativeTexture(Texture *tex, Stream *stream) +{ + int32 chunksize = getSizeNativeTexture(tex); + int32 plgsize = tex->streamGetPluginSize(); + writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize); + writeChunkHeader(stream, ID_STRUCT, chunksize-24-plgsize); + stream->writeU32(PLATFORM_D3D9); + + // Texture + stream->writeU32(tex->filterAddressing); + stream->write(tex->name, 32); + stream->write(tex->mask, 32); + + // Raster + Raster *raster = tex->raster; + D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + int32 numLevels = raster->getNumLevels(); + stream->writeI32(raster->format); + stream->writeU32(ras->format); + stream->writeU16(raster->width); + stream->writeU16(raster->height); + stream->writeU8(raster->depth); + stream->writeU8(numLevels); + stream->writeU8(raster->type); + uint8 flags = 0; + if(ras->hasAlpha) + flags |= 1; + // 2 - cube map + // 4 - something about mipmaps... + if(ras->customFormat) + flags |= 8; + stream->writeU8(flags); + + if(raster->format & Raster::PAL4) + stream->write(ras->palette, 4*32); + else if(raster->format & Raster::PAL8) + stream->write(ras->palette, 4*256); + + uint32 size; + uint8 *data; + for(int32 i = 0; i < numLevels; i++){ + size = getLevelSize(raster, i); + stream->writeU32(size); + data = raster->lock(i); + stream->write(data, size); + raster->unlock(i); + } + tex->streamWritePlugins(stream); +} + +uint32 +getSizeNativeTexture(Texture *tex) +{ + uint32 size = 12 + 72 + 16; + int32 levels = tex->raster->getNumLevels(); + if(tex->raster->format & Raster::PAL4) + size += 4*32; + else if(tex->raster->format & Raster::PAL8) + size += 4*256; + for(int32 i = 0; i < levels; i++) + size += 4 + getLevelSize(tex->raster, i); + size += 12 + tex->streamGetPluginSize(); + return size; +} + } } diff --git a/src/image.cpp b/src/image.cpp index 94a8788..752c261 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -11,6 +11,7 @@ #include "rwd3d.h" #include "rwxbox.h" #include "rwd3d8.h" +#include "rwd3d9.h" #ifdef _WIN32 /* srsly? */ @@ -243,14 +244,10 @@ Texture::streamReadNative(Stream *stream) return ps2::readNativeTexture(stream); if(platform == PLATFORM_D3D8) return d3d8::readNativeTexture(stream); + if(platform == PLATFORM_D3D9) + return d3d9::readNativeTexture(stream); if(platform == PLATFORM_XBOX) return xbox::readNativeTexture(stream); - -// if(rw::platform == PLATFORM_D3D8) -// return d3d8::readNativeTexture(stream); -// if(rw::platform == PLATFORM_XBOX) -// return xbox::readNativeTexture(stream); - assert(0 && "unsupported platform"); return NULL; } @@ -262,6 +259,8 @@ Texture::streamWriteNative(Stream *stream) ps2::writeNativeTexture(this, stream); else if(this->raster->platform == PLATFORM_D3D8) d3d8::writeNativeTexture(this, stream); + else if(this->raster->platform == PLATFORM_D3D9) + d3d9::writeNativeTexture(this, stream); else if(this->raster->platform == PLATFORM_XBOX) xbox::writeNativeTexture(this, stream); else @@ -275,6 +274,8 @@ Texture::streamGetSizeNative(void) return ps2::getSizeNativeTexture(this); if(this->raster->platform == PLATFORM_D3D8) return d3d8::getSizeNativeTexture(this); + if(this->raster->platform == PLATFORM_D3D9) + return d3d9::getSizeNativeTexture(this); if(this->raster->platform == PLATFORM_XBOX) return xbox::getSizeNativeTexture(this); assert(0 && "unsupported platform"); diff --git a/src/rwd3d.h b/src/rwd3d.h index 11458f0..2977292 100644 --- a/src/rwd3d.h +++ b/src/rwd3d.h @@ -78,6 +78,7 @@ struct D3dRaster : NativeRaster void *palette; uint32 format; bool32 hasAlpha; + bool32 customFormat; virtual void create(Raster *raster); virtual uint8 *lock(Raster *raster, int32 level); diff --git a/src/rwd3d9.h b/src/rwd3d9.h index 65fad26..7810746 100644 --- a/src/rwd3d9.h +++ b/src/rwd3d9.h @@ -75,5 +75,11 @@ ObjPipeline *makeSkinPipeline(void); ObjPipeline *makeMatFXPipeline(void); +// Native Texture and Raster + +Texture *readNativeTexture(Stream *stream); +void writeNativeTexture(Texture *tex, Stream *stream); +uint32 getSizeNativeTexture(Texture *tex); + } }