diff --git a/librw.sln b/librw.sln index 527e630..b44ee8b 100644 --- a/librw.sln +++ b/librw.sln @@ -67,7 +67,6 @@ Global {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.ActiveCfg = Release|x64 {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.Build.0 = Release|x64 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 - {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.Build.0 = Debug - null|Win32 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|x64.ActiveCfg = Debug - null|x64 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|x64.ActiveCfg = Debug|x64 @@ -97,6 +96,7 @@ Global {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.ActiveCfg = Release|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.Build.0 = Release|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 + {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.Build.0 = Debug - null|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|x64.ActiveCfg = Debug - null|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug|Win32.ActiveCfg = Debug|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug|x64.ActiveCfg = Debug|x64 @@ -106,7 +106,6 @@ Global {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.ActiveCfg = Release|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.Build.0 = Release|x64 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 - {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.Build.0 = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|x64.ActiveCfg = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.ActiveCfg = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.Build.0 = Debug - null|Win32 diff --git a/src/gtaplg.cpp b/src/gtaplg.cpp index 5a0bdd8..1e98f1b 100644 --- a/src/gtaplg.cpp +++ b/src/gtaplg.cpp @@ -291,6 +291,7 @@ readExtraNormals(Stream *stream, int32, void *object, int32 offset, int32) delete[] *plgp; float *extranormals = *plgp = new float[geo->numVertices*3]; stream->read(extranormals, geo->numVertices*3*4); +// printf("extra normals\n"); // for(int i = 0; i < geo->numVertices; i++){ // float *nx = extranormals+i*3; @@ -618,7 +619,7 @@ static void readPipeline(Stream *stream, int32, void *object, int32 offset, int32) { *PLUGINOFFSET(uint32, object, offset) = stream->readU32(); - printf("%x\n", *PLUGINOFFSET(uint32, object, offset)); +// printf("%x\n", *PLUGINOFFSET(uint32, object, offset)); } static void diff --git a/src/image.cpp b/src/image.cpp index a47ea0a..fb4f2d0 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -9,6 +9,7 @@ #include "rwplugin.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwps2.h" #include "rwd3d.h" #include "rwxbox.h" #include "rwd3d8.h" @@ -211,6 +212,8 @@ Texture::streamReadNative(Stream *stream) assert(findChunk(stream, ID_STRUCT, NULL, NULL)); uint32 platform = stream->readU32(); stream->seek(-16); + if(platform == FOURCC_PS2) + return ps2::readNativeTexture(stream); if(platform == PLATFORM_D3D8) return d3d8::readNativeTexture(stream); if(platform == PLATFORM_XBOX) @@ -228,7 +231,9 @@ Texture::streamReadNative(Stream *stream) void Texture::streamWriteNative(Stream *stream) { - if(this->raster->platform == PLATFORM_D3D8) + if(this->raster->platform == PLATFORM_PS2) + ps2::writeNativeTexture(this, stream); + else if(this->raster->platform == PLATFORM_D3D8) d3d8::writeNativeTexture(this, stream); else if(this->raster->platform == PLATFORM_XBOX) xbox::writeNativeTexture(this, stream); @@ -239,6 +244,8 @@ Texture::streamWriteNative(Stream *stream) uint32 Texture::streamGetSizeNative(void) { + if(this->raster->platform == PLATFORM_PS2) + return ps2::getSizeNativeTexture(this); if(this->raster->platform == PLATFORM_D3D8) return d3d8::getSizeNativeTexture(this); if(this->raster->platform == PLATFORM_XBOX) diff --git a/src/ps2.cpp b/src/ps2.cpp index bb96ccf..3edef74 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -1068,9 +1068,6 @@ skinUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, u mask |= 0x1000; mask |= 0x10000; - float32 n[3]; - float32 w[4]; - uint8 ix[4]; SkinVertex v; for(uint32 i = 0; i < mesh->numIndices; i++){ if(mask & 0x1) @@ -1507,12 +1504,341 @@ sizedebug(InstanceData *inst) int32 nativeRasterOffset; +#define MAXLEVEL(r) ((r)->tex1[1]>>18 & 0x3F) +#define SETMAXLEVEL(r, l) ((r)->tex1[1] = (r)->tex1[1]&~0xFF0000 | l<<18) +#define SETKL(r, val) ((r)->tex1[1] = (r)->tex1[1]&~0xFFFF | (uint16)(val)) +static bool32 noNewStyleRasters; + +// i don't really understand this, stolen from RW +static void +ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) +{ + *minh = 1; + switch(psm){ + case 0x00: + case 0x30: + *minw = 2; // 32 bit + break; + case 0x02: + case 0x0A: + case 0x32: + case 0x3A: + *minw = 4; // 16 bit + break; + case 0x01: + case 0x13: + case 0x14: + case 0x1B: + case 0x24: + case 0x2C: + case 0x31: + *minw = 8; // everything else + break; + } + if(flags & 0x2 && psm == 0x13){ // PSMT8 + *minw = 16; + *minh = 4; + } + if(flags & 0x4 && psm == 0x14){ // PSMT4 + *minw = 32; + *minh = 4; + } +} + +void +Ps2Raster::create(Raster *raster) +{ + int32 pageWidth, pageHeight; + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + //printf("%x %x %x %x\n", raster->format, raster->flags, raster->type, noNewStyleRasters); + assert(raster->type == 4); // Texture + switch(raster->depth){ + case 4: + pageWidth = 128; + pageHeight = 128; + break; + case 8: + pageWidth = 128; + pageHeight = 64; + break; + case 16: + pageWidth = 64; + pageHeight = 64; + break; + case 32: + pageWidth = 64; + pageHeight = 32; + break; + default: + assert(0 && "unsupported depth"); + } + int32 logw = 0, logh = 0; + int32 s; + for(s = 1; s < raster->width; s *= 2) + logw++; + for(s = 1; s < raster->height; s *= 2) + logh++; + SETKL(ras, 0xFC0); + //printf("%d %d %d %d\n", raster->width, logw, raster->height, logh); + ras->tex0[0] |= (raster->width < pageWidth ? pageWidth : raster->width)/64 << 14; + ras->tex0[0] |= logw << 26; + ras->tex0[0] |= logh << 30; + ras->tex0[1] |= logh >> 2; + + int32 paletteWidth, paletteHeight, paletteDepth; + int32 palettePagewidth, palettePageheight; + if(raster->format & (Raster::PAL4 | Raster::PAL8)) + switch(raster->format & 0xF00){ + case Raster::C1555: + ras->tex0[1] |= 0xA << 19; // PSMCT16S + paletteDepth = 2; + palettePagewidth = palettePageheight = 64; + break; + case Raster::C8888: + // PSMCT32 + paletteDepth = 4; + palettePagewidth = 64; + palettePageheight = 32; + break; + default: + assert(0 && "unsupported palette format\n"); + } + if(raster->format & Raster::PAL4){ + ras->tex0[0] |= 0x14 << 20; // PSMT4 + ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA + paletteWidth = 8; + paletteHeight = 2; + }else if(raster->format & Raster::PAL8){ + ras->tex0[0] |= 0x13 << 20; // PSMT8 + ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA + paletteWidth = paletteHeight = 16; + }else{ + paletteWidth = 0; + paletteHeight = 0; + paletteDepth = 0; + palettePagewidth = 0; + palettePageheight = 0; + switch(raster->format & 0xF00){ + case Raster::C1555: + ras->tex0[0] |= 0xA << 20; // PSMCT16S + ras->tex0[1] |= 1 << 2; // TCC RGBA + break; + case Raster::C8888: + // PSMCT32 + ras->tex0[1] |= 1 << 2; // TCC RGBA + break; + case Raster::C888: + ras->tex0[0] |= 1 << 20; // PSMCT24 + break; + default: + assert(0 && "unsupported raster format\n"); + } + } + + raster->stride = raster->width*raster->depth/8; + if(raster->format & Raster::MIPMAP){ + assert(0); + }else{ + ras->texelSize = raster->stride*raster->depth+0xF & ~0xF; + ras->paletteSize = paletteWidth*paletteHeight*paletteDepth; + ras->miptbp1[0] |= 1<<14; // TBW1 + ras->miptbp1[1] |= 1<<2 | 1<<22; // TBW2,3 + ras->miptbp2[0] |= 1<<14; // TBW4 + ras->miptbp2[1] |= 1<<2 | 1<<22; // TBW5,6 + SETMAXLEVEL(ras, 0); + int32 nPagW = (raster->width + pageWidth-1)/pageWidth; + int32 nPagH = (raster->height + pageHeight-1)/pageHeight; + ras->gsSize = (nPagW*nPagH*0x800)&~0x7FF; + if(ras->paletteSize){ + // BITBLTBUF DBP + if(pageWidth*nPagW > raster->width || + pageHeight*nPagH > raster->height) + ras->tex1[0] = (ras->gsSize >> 6) - 4; + else{ + ras->tex1[0] = ras->gsSize >> 6; + } + nPagW = (paletteWidth + palettePagewidth-1)/palettePagewidth; + nPagH = (paletteHeight + palettePageheight-1)/palettePageheight; + ras->gsSize += (nPagW*nPagH*0x800)&~0x7FF; + }else + ras->tex1[0] = 0; + } + + // allocate data and fill with GIF packets + ras->texelSize = ras->texelSize+0xF & ~0xF; + int32 numLevels = MAXLEVEL(ras)+1; + if(noNewStyleRasters || + (raster->width*raster->height*raster->depth & ~0x7F) >= 0x3FFF80){ + assert(0); + }else{ + ras->flags |= 1; // include GIF packets + int32 psm = ras->tex0[0]>>20 & 0x3F; + int32 cpsm = ras->tex0[1]>>19 & 0x3F; + if(psm == 0x13){ // PSMT8 + ras->flags |= 2; + // TODO: stuff + } + if(psm == 0x14){ // PSMT4 + // swizzle flag probably depends on version :/ + if(rw::version > 0x31000) + ras->flags |= 4; + // TODO: stuff + } + ras->texelSize = 0x50*numLevels; // GIF packets + int32 minW, minH; + ps2MinSize(psm, ras->flags, &minW, &minH); + int32 w = raster->width; + int32 h = raster->height; + int32 mipw, miph; + int32 n = numLevels; + while(n--){ + mipw = w < minW ? minW : w; + miph = h < minH ? minH : h; + ras->texelSize += mipw*miph*raster->depth/8+0xF & ~0xF; + w /= 2; + h /= 2; + } + if(ras->paletteSize){ + if(rw::version > 0x31000 && paletteHeight == 2) + paletteHeight = 3; + ras->paletteSize = 0x50 + + paletteDepth*paletteWidth*paletteHeight; + } + // TODO: allocate space for more DMA packets + ras->dataSize = ras->paletteSize+ras->texelSize; + uint8 *data = new uint8[ras->dataSize]; + assert(data); + ras->data = data; + raster->texels = data + 0x50; + if(ras->paletteSize) + raster->palette = data + ras->texelSize + 0x50; + uint32 *p = (uint32*)data; + w = raster->width; + h = raster->height; + for(n = 0; n < numLevels; n++){ + mipw = w < minW ? minW : w; + miph = h < minH ? minH : h; + + // GIF tag + *p++ = 3; // NLOOP = 3 + *p++ = 0x10000000; // NREG = 1 + *p++ = 0xE; // A+D + *p++ = 0; + + // TRXPOS + *p++ = 0; // TODO + *p++ = 0; // TODO + *p++ = 0x51; + *p++ = 0; + + // TRXREG + if(ras->flags & 2 && psm == 0x13 || + ras->flags & 4 && psm == 0x14){ + *p++ = mipw/2; + *p++ = miph/2; + }else{ + *p++ = mipw; + *p++ = miph; + } + *p++ = 0x52; + *p++ = 0; + + // TRXDIR + *p++ = 0; // host -> local + *p++ = 0; + *p++ = 0x53; + *p++ = 0; + + // GIF tag + uint32 sz = mipw*miph*raster->depth/8 + 0xF >> 4; + *p++ = sz; + *p++ = 0x08000000; // IMAGE + *p++ = 0; + *p++ = 0; + + p += sz*4; + w /= 2; + h /= 2; + } + if(ras->paletteSize){ + p = (uint32*)(raster->palette - 0x50); + // GIF tag + *p++ = 3; // NLOOP = 3 + *p++ = 0x10000000; // NREG = 1 + *p++ = 0xE; // A+D + *p++ = 0; + + // TRXPOS + *p++ = 0; // TODO + *p++ = 0; // TODO + *p++ = 0x51; + *p++ = 0; + + // TRXREG + *p++ = paletteWidth; + *p++ = paletteHeight; + *p++ = 0x52; + *p++ = 0; + + // TRXDIR + *p++ = 0; // host -> local + *p++ = 0; + *p++ = 0x53; + *p++ = 0; + + // GIF tag + uint32 sz = paletteSize - 0x50 + 0xF >> 4; + *p++ = sz; + *p++ = 0x08000000; // IMAGE + *p++ = 0; + *p++ = 0; + + } + } +} + +uint8* +Ps2Raster::lock(Raster *raster, int32 level) +{ + return NULL; +} + +void +Ps2Raster::unlock(Raster *raster, int32 level) +{ +} + +int32 +Ps2Raster::getNumLevels(Raster *raster) +{ + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + if(raster->texels == NULL) return 0; + if(raster->format & Raster::MIPMAP) + return MAXLEVEL(ras)+1; + return 1; +} + static void* createNativeRaster(void *object, int32 offset, int32) { Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset); new (raster) Ps2Raster; - raster->mipmap = 0xFC0; + raster->tex0[0] = 0; + raster->tex0[1] = 0; + raster->tex1[0] = 0; + raster->tex1[1] = 0; + raster->miptbp1[0] = 0; + raster->miptbp1[1] = 0; + raster->miptbp2[0] = 0; + raster->miptbp2[1] = 0; + raster->texelSize = 0; + raster->paletteSize = 0; + raster->gsSize = 0; + raster->flags = 0; + SETKL(raster, 0xFC0); + + raster->dataSize = 0; + raster->data = NULL; return object; } @@ -1527,19 +1853,19 @@ copyNativeRaster(void *dst, void *src, int32 offset, int32) { Ps2Raster *dstraster = PLUGINOFFSET(Ps2Raster, dst, offset); Ps2Raster *srcraster = PLUGINOFFSET(Ps2Raster, src, offset); - dstraster->mipmap = srcraster->mipmap; + *dstraster = *srcraster; return dst; } static void readMipmap(Stream *stream, int32 len, void *object, int32 offset, int32) { - int32 val = stream->readI32(); + uint16 val = stream->readI32(); Texture *tex = (Texture*)object; if(tex->raster == NULL) return; Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset); - raster->mipmap = val; + SETKL(raster, val); } static void @@ -1548,7 +1874,7 @@ writeMipmap(Stream *stream, int32 len, void *object, int32 offset, int32) Texture *tex = (Texture*)object; assert(tex->raster); Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset); - stream->writeI32(raster->mipmap); + stream->writeI32(raster->tex1[1]&0xFFFF); } static int32 @@ -1570,5 +1896,151 @@ registerNativeRaster(void) Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap); } +struct StreamRasterExt +{ + int32 width; + int32 height; + int32 depth; + uint16 rasterFormat; + int16 type; + uint32 tex0[2]; + uint32 tex1[2]; + uint32 miptbp1[2]; + uint32 miptbp2[2]; + uint32 texelSize; + uint32 paletteSize; + uint32 gsSize; + uint32 mipmapVal; +}; + +Texture* +readNativeTexture(Stream *stream) +{ + uint32 length, oldversion, version; + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + assert(stream->readU32() == 0x00325350); // 'PS2\0' + Texture *tex = new Texture; + + // Texture + tex->filterAddressing = stream->readU32(); + assert(findChunk(stream, ID_STRING, &length, NULL)); + stream->read(tex->name, length); + assert(findChunk(stream, ID_STRING, &length, NULL)); + stream->read(tex->mask, length); + + // Raster + StreamRasterExt streamExt; + oldversion = rw::version; + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, NULL, &version)); + stream->read(&streamExt, 0x40); + Raster *raster; + noNewStyleRasters = streamExt.type < 2; + rw::version = version; + raster = new Raster(streamExt.width, streamExt.height, + streamExt.depth, streamExt.rasterFormat, + PLATFORM_PS2); + noNewStyleRasters = 0; + rw::version = oldversion; + tex->raster = raster; + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + //printf("%08X%08X %08X%08X %08X%08X %08X%08X\n", + // ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0], + // ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]); + ras->tex0[0] = streamExt.tex0[0]; + ras->tex0[1] = streamExt.tex0[1]; + ras->tex1[0] = streamExt.tex1[0]; + ras->tex1[1] = ras->tex1[1]&~0xFF0000 | streamExt.tex1[1]<<16 & 0xFF0000; + ras->miptbp1[0] = streamExt.miptbp1[0]; + ras->miptbp1[1] = streamExt.miptbp1[1]; + ras->miptbp2[0] = streamExt.miptbp2[0]; + ras->miptbp2[1] = streamExt.miptbp2[1]; + ras->texelSize = streamExt.texelSize; + ras->paletteSize = streamExt.paletteSize; + ras->gsSize = streamExt.gsSize; + SETKL(ras, streamExt.mipmapVal); + //printf("%08X%08X %08X%08X %08X%08X %08X%08X\n", + // ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0], + // ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]); + + assert(findChunk(stream, ID_STRUCT, &length, NULL)); + if(streamExt.type < 2){ + stream->read(raster->texels, length); + }else{ + stream->read(raster->texels-0x50, ras->texelSize); + stream->read(raster->palette-0x50, ras->paletteSize); + } + + tex->streamReadPlugins(stream); + return tex; +} + +void +writeNativeTexture(Texture *tex, Stream *stream) +{ + Raster *raster = tex->raster; + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + int32 chunksize = getSizeNativeTexture(tex); + writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize); + writeChunkHeader(stream, ID_STRUCT, 8); + stream->writeU32(FOURCC_PS2); + stream->writeU32(tex->filterAddressing); + int32 len = strlen(tex->name)+4 & ~3; + writeChunkHeader(stream, ID_STRING, len); + stream->write(tex->name, len); + len = strlen(tex->mask)+4 & ~3; + writeChunkHeader(stream, ID_STRING, len); + stream->write(tex->mask, len); + + int32 sz = ras->texelSize + ras->paletteSize; + writeChunkHeader(stream, ID_STRUCT, 12 + 64 + 12 + sz); + writeChunkHeader(stream, ID_STRUCT, 64); + StreamRasterExt streamExt; + streamExt.width = raster->width; + streamExt.height = raster->height; + streamExt.depth = raster->depth; + streamExt.rasterFormat = raster->format | raster->type; + streamExt.type = 0; + if(ras->flags == 2 && raster->depth == 8) + streamExt.type = 1; + if(ras->flags & 1) + streamExt.type = 2; + streamExt.tex0[0] = ras->tex0[0]; + streamExt.tex0[1] = ras->tex0[1]; + streamExt.tex1[0] = ras->tex1[0]; + streamExt.tex1[1] = ras->tex1[1]>>16 & 0xFF; + streamExt.miptbp1[0] = ras->miptbp1[0]; + streamExt.miptbp1[1] = ras->miptbp1[1]; + streamExt.miptbp2[0] = ras->miptbp2[0]; + streamExt.miptbp2[1] = ras->miptbp2[1]; + streamExt.texelSize = ras->texelSize; + streamExt.paletteSize = ras->paletteSize; + streamExt.gsSize = ras->gsSize; + streamExt.mipmapVal = ras->tex1[1]&0xFFFF; + stream->write(&streamExt, 64); + + writeChunkHeader(stream, ID_STRUCT, sz); + if(streamExt.type < 2){ + stream->write(raster->texels, sz); + }else{ + stream->write(raster->texels-0x50, ras->texelSize); + stream->write(raster->palette-0x50, ras->paletteSize); + } + tex->streamWritePlugins(stream); +} + +uint32 +getSizeNativeTexture(Texture *tex) +{ + uint32 size = 12 + 8; + size += 12 + strlen(tex->name)+4 & ~3; + size += 12 + strlen(tex->mask)+4 & ~3; + size += 12 + 12 + 64 + 12; + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset); + size += ras->texelSize + ras->paletteSize; + size += 12 + tex->streamGetPluginSize(); + return size; +} + } } diff --git a/src/rwbase.cpp b/src/rwbase.cpp index a8c5355..89662ba 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -12,16 +12,16 @@ using namespace std; namespace rw { -int version = 0x36003; -int build = 0xFFFF; +int32 version = 0x36003; +int32 build = 0xFFFF; #ifdef RW_PS2 - int platform = PLATFORM_PS2; + int32 platform = PLATFORM_PS2; #elif RW_OPENGL - int platform = PLATFORM_OGL; + int32 platform = PLATFORM_OGL; #elif RW_D3D9 - int platform = PLATFORM_D3D9; + int32 platform = PLATFORM_D3D9; #else - int platform = PLATFORM_NULL; + int32 platform = PLATFORM_NULL; #endif char *debugFile = NULL; diff --git a/src/rwbase.h b/src/rwbase.h index 963d9b9..5e993f5 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -105,7 +105,9 @@ enum Platform // SOFTRAS PLATFORM_D3D8 = 8, PLATFORM_D3D9 = 9, - NUM_PLATFORMS + NUM_PLATFORMS, + + FOURCC_PS2 = 0x00325350 // 'PS2\0' }; enum PluginID diff --git a/src/rwps2.h b/src/rwps2.h index 513277b..961823f 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -172,11 +172,30 @@ void registerPDSPlugin(int32 n); struct Ps2Raster : NativeRaster { - int32 mipmap; + uint32 tex0[2]; + uint32 tex1[2]; + uint32 miptbp1[2]; + uint32 miptbp2[2]; + uint32 texelSize; + uint32 paletteSize; + uint32 gsSize; + int8 flags; + + uint8 *data; //tmp + uint32 dataSize; + + virtual void create(Raster *raster); + virtual uint8 *lock(Raster *raster, int32 level); + virtual void unlock(Raster *raster, int32 level); + virtual int32 getNumLevels(Raster *raster); }; extern int32 nativeRasterOffset; void registerNativeRaster(void); +Texture *readNativeTexture(Stream *stream); +void writeNativeTexture(Texture *tex, Stream *stream); +uint32 getSizeNativeTexture(Texture *tex); + } } diff --git a/tools/rsltest/rsltest.cpp b/tools/rsltest/rsltest.cpp index f590292..706ed87 100644 --- a/tools/rsltest/rsltest.cpp +++ b/tools/rsltest/rsltest.cpp @@ -265,7 +265,7 @@ getTexelPS2(RslRaster *raster, int32 n) void convertCLUT(uint8 *texels, uint32 w, uint32 h) { - uint8 map[4] = { 0, 16, 8, 24 }; + static uint8 map[4] = { 0x00, 0x10, 0x08, 0x18 }; for (uint32 i = 0; i < w*h; i++) texels[i] = (texels[i] & ~0x18) | map[(texels[i] & 0x18) >> 3]; } @@ -309,19 +309,32 @@ unswizzle16(uint16 *dst, uint16 *src, int32 w, int32 h) } } +bool32 unswizzle = 1; + void convertTo32(uint8 *out, uint8 *pal, uint8 *tex, uint32 w, uint32 h, uint32 d, bool32 swiz) { uint32 x; if(d == 32){ - memcpy(out, tex, w*h*4); - //unswizzle16((uint16*)out, (uint16*)tex, w, h); + //uint32 *dat = new uint32[w*h]; + //if(swiz && unswizzle) + // unswizzle8_hack(dat, (uint32*)tex, w, h); + //else + // memcpy(dat, tex, w*h*4); + //tex = (uint8*)dat; + for(uint32 i = 0; i < w*h; i++){ + out[i*4+0] = tex[i*4+0]; + out[i*4+1] = tex[i*4+1]; + out[i*4+2] = tex[i*4+2]; + out[i*4+3] = tex[i*4+3]*255/128; + } + //delete[] dat; } if(d == 16) return; // TODO if(d == 8){ uint8 *dat = new uint8[w*h]; - if(swiz) + if(swiz && unswizzle) unswizzle8(dat, tex, w, h); else memcpy(dat, tex, w*h); @@ -343,7 +356,7 @@ convertTo32(uint8 *out, uint8 *pal, uint8 *tex, dat[i*2+0] = tex[i] & 0xF; dat[i*2+1] = tex[i] >> 4; } - if(swiz){ + if(swiz && unswizzle){ uint8 *tmp = new uint8[w*h]; unswizzle8(tmp, dat, w, h); delete[] dat; @@ -385,8 +398,6 @@ RslTexture *dumpTextureCB(RslTexture *texture, void *pData) return texture; } -bool32 unswizzle = 1; - RslTexture* convertTexturePS2(RslTexture *texture, void *pData) { @@ -487,9 +498,9 @@ convertTexturePS2(RslTexture *texture, void *pData) else if(d == 32){ // texture is fucked, but pretend it isn't for(uint32 i = 0; i < w*h; i++){ - data[i*4+0] = texels[i*4+0]; + data[i*4+2] = texels[i*4+0]; data[i*4+1] = texels[i*4+1]; - data[i*4+2] = texels[i*4+2]; + data[i*4+0] = texels[i*4+2]; data[i*4+3] = texels[i*4+3]*255/128; } }else @@ -513,8 +524,9 @@ convertTXD(RslTexDictionary *txd) void usage(void) { - fprintf(stderr, "%s [-t] [-s] input [output.txd]\n", argv0); + fprintf(stderr, "%s [-v version] [-x] [-s] input [output.txd]\n", argv0); fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n"); + fprintf(stderr, "\t-x extract to tga\n"); fprintf(stderr, "\t-s don't unswizzle\n"); exit(1); } @@ -526,6 +538,7 @@ main(int argc, char *argv[]) rw::version = 0x34003; assert(sizeof(void*) == 4); + int extract = 0; ARGBEGIN{ case 'v': @@ -534,6 +547,9 @@ main(int argc, char *argv[]) case 's': unswizzle = 0; break; + case 'x': + extract++; + break; default: usage(); }ARGEND; @@ -643,7 +659,8 @@ main(int argc, char *argv[]) }else if(rslstr->ident == TEX_IDENT){ txd = (RslTexDictionary*)rslstr->data; writeTxd: - //RslTexDictionaryForAllTextures(txd, dumpTextureCB, NULL); + if(extract) + RslTexDictionaryForAllTextures(txd, dumpTextureCB, NULL); TexDictionary *rwtxd = convertTXD(txd); if(argc > 1) assert(stream.open(argv[1], "wb")); diff --git a/tools/txdwrite/txdwrite.cpp b/tools/txdwrite/txdwrite.cpp index 750e122..918fcc0 100644 --- a/tools/txdwrite/txdwrite.cpp +++ b/tools/txdwrite/txdwrite.cpp @@ -5,11 +5,26 @@ #include #include +#include #include +char *argv0; + using namespace std; using namespace rw; +struct { + char *str; + uint32 val; +} platforms[] = { + { "mobile", PLATFORM_OGL }, + { "ps2", PLATFORM_PS2 }, + { "xbox", PLATFORM_XBOX }, + { "d3d8", PLATFORM_D3D8 }, + { "d3d9", PLATFORM_D3D9 }, + { NULL, 0 } +}; + Raster* xboxToD3d8(Raster *raster) { @@ -64,43 +79,80 @@ xboxToD3d8(Raster *raster) return newras; } +void +usage(void) +{ + fprintf(stderr, "usage: %s [-v version] [-o platform] in.txd [out.txd]\n", argv0); + fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n"); + fprintf(stderr, "\t-o output platform. ps2, xbox, mobile, d3d8, d3d9\n"); + exit(1); +} + int main(int argc, char *argv[]) { gta::attachPlugins(); - rw::version = 0x33002; -// rw::platform = rw::PLATFORM_PS2; + rw::version = 0; + rw::platform = rw::PLATFORM_PS2; // rw::platform = rw::PLATFORM_OGL; // rw::platform = rw::PLATFORM_XBOX; // rw::platform = rw::PLATFORM_D3D8; // rw::platform = rw::PLATFORM_D3D9; + int outplatform = rw::PLATFORM_PS2; - if(argc < 2){ - printf("usage (%d): %s in.txd\n", rw::platform, argv[0]); - return 0; - } + char *s; + ARGBEGIN{ + case 'v': + sscanf(EARGF(usage()), "%x", &rw::version); + break; + case 'o': + s = EARGF(usage()); + for(int i = 0; platforms[i].str; i++){ + if(strcmp(platforms[i].str, s) == 0){ + outplatform = platforms[i].val; + goto found; + } + } + printf("unknown platform %s\n", s); + outplatform = PLATFORM_D3D8; + found: + break; + default: + usage(); + }ARGEND; + + if(argc < 1) + usage(); rw::StreamFile in; - if(in.open(argv[1], "rb") == NULL){ + if(in.open(argv[0], "rb") == NULL){ printf("couldn't open file %s\n", argv[1]); return 1; } - rw::findChunk(&in, rw::ID_TEXDICTIONARY, NULL, NULL); + ChunkHeaderInfo header; + readChunkHeaderInfo(&in, &header); + assert(header.type == ID_TEXDICTIONARY); rw::TexDictionary *txd; txd = rw::TexDictionary::streamRead(&in); assert(txd); in.close(); rw::currentTexDictionary = txd; - for(Texture *tex = txd->first; tex; tex = tex->next) - tex->raster = xboxToD3d8(tex->raster); + if(rw::version == 0){ + rw::version = header.version; + rw::build = header.build; + } + + if(outplatform == PLATFORM_D3D8) + for(Texture *tex = txd->first; tex; tex = tex->next) + tex->raster = xboxToD3d8(tex->raster); // for(Texture *tex = txd->first; tex; tex = tex->next) // tex->filterAddressing = (tex->filterAddressing&~0xF) | 0x2; rw::StreamFile out; - if(argc > 2) - out.open(argv[2], "wb"); + if(argc > 1) + out.open(argv[1], "wb"); else out.open("out.txd", "wb"); txd->streamWrite(&out);