diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 2278723..0344585 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -907,14 +907,14 @@ rasterToImage(Raster *raster) } } - out = image->pixels; + uint8 *dst = image->pixels; in = raster->lock(0, Raster::LOCKREAD); if(pallength) - memcpy(out, in, raster->width*raster->height); - else - // TODO: stride - for(int32 y = 0; y < image->height; y++) - for(int32 x = 0; x < image->width; x++) + memcpy(dst, in, raster->width*raster->height); + else{ + for(int32 y = 0; y < image->height; y++){ + out = dst; + for(int32 x = 0; x < image->width; x++){ switch(raster->format & 0xF00){ case Raster::C8888: out[0] = in[2]; @@ -922,30 +922,33 @@ rasterToImage(Raster *raster) out[2] = in[0]; out[3] = in[3]; in += 4; - out += 4; break; case Raster::C888: out[0] = in[2]; out[1] = in[1]; out[2] = in[0]; in += 4; - out += 3; break; case Raster::C1555: out[0] = in[0]; out[1] = in[1]; in += 2; - out += 2; break; case Raster::C555: out[0] = in[0]; out[1] = in[1] | 0x80; in += 2; - out += 2; break; } + out += image->bpp; + } + dst += image->stride; + } + } raster->unlock(0); + image->compressPalette(); + return image; } diff --git a/src/image.cpp b/src/image.cpp index 4ddf82f..632ca97 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -346,6 +346,23 @@ Image::setPalette(uint8 *palette) this->flags |= 2; } +void +Image::compressPalette(void) +{ + if(this->depth != 8) + return; + uint8 *pixels = this->pixels; + for(int y = 0; y < this->height; y++){ + uint8 *line = pixels; + for(int x = 0; x < this->width; x++){ + if(*line > 0xF) return; + line += this->bpp; + } + pixels += this->stride; + } + this->depth = 4; +} + bool32 Image::hasAlpha(void) { @@ -356,7 +373,7 @@ Image::hasAlpha(void) uint8 *line = pixels; for(int x = 0; x < this->width; x++){ ret &= line[3]; - line += 4; + line += this->bpp; } pixels += this->stride; } @@ -367,7 +384,7 @@ Image::hasAlpha(void) uint8 *line = pixels; for(int x = 0; x < this->width; x++){ ret &= line[1] & 0x80; - line += 2; + line += this->bpp; } pixels += this->stride; } @@ -377,7 +394,7 @@ Image::hasAlpha(void) uint8 *line = pixels; for(int x = 0; x < this->width; x++){ ret &= this->palette[*line*4+3]; - line++; + line += this->bpp; } pixels += this->stride; } diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 1b19df2..d419a57 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -184,9 +184,10 @@ getRasterFormat(Raster *raster) palformat = Raster::PAL8; break; case 24: - pixelformat = Raster::C888; - palformat = 0; - break; + // unsafe + // pixelformat = Raster::C888; + // palformat = 0; + // break; case 32: pixelformat = Raster::C8888; palformat = 0; @@ -236,6 +237,7 @@ getRasterFormat(Raster *raster) } raster->depth = 32; }else if(pixelformat == Raster::C888){ + assert(0 && "24 bit rasters not supported"); if(raster->depth && raster->depth != 24){ RWERROR((ERR_INVRASTER)); return 0; @@ -805,7 +807,13 @@ rasterCreateTexture(Raster *raster) width = raster->width; height = raster->height; depth = raster->depth; + // RW's code does not seem to quite work with 24 bit rasters + // so make sure we're not generating them for safety + assert(depth != 24); + ras->flags = 0; + ras->data = nil; + ras->dataSize = 0; // RW doesn't seem to check this, hm... if(raster->flags & Raster::DONTALLOCATE) @@ -999,10 +1007,11 @@ rasterCreateTexture(Raster *raster) // If there is still room, use it! // If dimensions don't fill a page, we have at least // half a page left, enough for any palette +//TODO: this was not always done it seems but even gta3's 3.1 seems to?? if(pageWidth*nPagW > width || - pageHeight*nPagH > height) + pageHeight*nPagH > height){ ras->paletteBase = (ras->totalSize - 256) / WD2BLK; - else{ + }else{ // Otherwise allocate more space... ras->paletteBase = ras->totalSize / WD2BLK; // ...using the same calculation as above. @@ -1069,6 +1078,7 @@ rasterCreateTexture(Raster *raster) if(rw::version > 0x31000){ ras->flags |= Ps2Raster::SWIZZLED4; // Where can this come from? if anything we're using PSMCT16S + // Looks like they wanted to swizzle palettes too... if(cpsm == PSMCT16){ // unswizzle the starting block of the last buffer and palette uint32 bufbase_B = bufferBase[numLevels-1]&~0x1F | (uint64)blockmaprev_PSMCT16[bufferBase[numLevels-1]&0x1F]; @@ -1464,6 +1474,7 @@ uint8* rasterLock(Raster *raster, int32 level, int32 lockMode) { Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + assert(raster->depth != 24); if(level > 0){ int32 minw, minh; @@ -1581,15 +1592,10 @@ imageFindRasterFormat(Image *img, int32 type, switch(depth){ case 32: - if(img->hasAlpha()) - format = Raster::C8888; - else{ - format = Raster::C888; - depth = 24; - } - break; case 24: - format = Raster::C888; + // C888 24 bit is unsafe + format = Raster::C8888; + depth = 32; break; case 16: format = Raster::C1555; @@ -1622,14 +1628,12 @@ rasterFromImage(Raster *raster, Image *image) int32 pallength = 0; switch(image->depth){ + case 24: case 32: if(raster->format != Raster::C8888 && - raster->format != Raster::C888) + raster->format != Raster::C888) // unsafe already goto err; break; - case 24: - if(raster->format != Raster::C888) goto err; - break; case 16: if(raster->format != Raster::C1555) goto err; break; @@ -1647,6 +1651,12 @@ rasterFromImage(Raster *raster, Image *image) return 0; } + // unsafe + if((raster->format&0xF00) == Raster::C888){ + RWERROR((ERR_INVRASTER)); + return 0; + } + uint8 *in, *out; if(image->depth <= 8){ in = image->palette; @@ -1673,27 +1683,24 @@ rasterFromImage(Raster *raster, Image *image) for(int32 y = 0; y < image->height; y++){ in = src; for(int32 x = 0; x < image->width; x++){ - switch(raster->format & 0xF00){ - case Raster::C8888: - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]*128/255; - out += 4; + switch(image->depth){ + case 16: + conv_ARGB1555_from_ABGR1555(out, in); + out += 2; break; - case Raster::C888: + case 24: out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = 0x80; out += 4; break; - case Raster::C1555: - conv_ARGB1555_from_ABGR1555(out, in); - out += 2; - break; - default: - assert(0 && "unknown ps2 raster format"); + case 32: + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]*128/255; + out += 4; break; } in += image->bpp; @@ -1990,7 +1997,7 @@ struct StreamRasterExt int32 height; int32 depth; uint16 rasterFormat; - int16 type; + int16 version; uint64 tex0; uint32 paletteOffset; uint32 tex1low; @@ -2054,7 +2061,7 @@ streamExt.width, streamExt.height, streamExt.depth, streamExt.rasterFormat, -streamExt.type, +streamExt.version, streamExt.tex0, streamExt.paletteOffset, streamExt.tex1low, @@ -2065,7 +2072,7 @@ streamExt.paletteSize, streamExt.totalSize, streamExt.mipmapVal); */ - noNewStyleRasters = streamExt.type < 2; + noNewStyleRasters = streamExt.version < 2; rw::version = version; raster = Raster::create(streamExt.width, streamExt.height, streamExt.depth, streamExt.rasterFormat, @@ -2088,8 +2095,12 @@ streamExt.mipmapVal); assert(natras->pixelSize >= streamExt.pixelSize); assert(natras->paletteSize >= streamExt.paletteSize); -//if(natras->tex0 != streamExt.tex0) +//if(natras->tex0 != streamExt.tex0){ //printf("TEX0: %016llX\n %016llX\n", natras->tex0, streamExt.tex0); +//printTEX0(natras->tex0); +//printTEX0(streamExt.tex0); +//fflush(stdout); +//} //if(natras->tex1low != streamExt.tex1low) //printf("TEX1: %08X\n %08X\n", natras->tex1low, streamExt.tex1low); //if(natras->miptbp1 != streamExt.miptbp1) @@ -2104,13 +2115,26 @@ streamExt.mipmapVal); //printf("PLS: %08X\n %08X\n", natras->paletteSize, streamExt.paletteSize); //if(natras->totalSize != streamExt.totalSize) //printf("TSZ: %08X\n %08X\n", natras->totalSize, streamExt.totalSize); + + // junk addresses, no need to store them + streamExt.tex0 &= ~0x3FFFULL; + streamExt.tex0 &= ~(0x3FFFULL << 37); + + assert(natras->tex0 == streamExt.tex0); natras->tex0 = streamExt.tex0; + assert(natras->paletteBase == streamExt.paletteOffset); natras->paletteBase = streamExt.paletteOffset; + assert(natras->tex1low == streamExt.tex1low); natras->tex1low = streamExt.tex1low; + assert(natras->miptbp1 == streamExt.miptbp1); natras->miptbp1 = streamExt.miptbp1; + assert(natras->miptbp2 == streamExt.miptbp2); natras->miptbp2 = streamExt.miptbp2; + assert(natras->pixelSize == streamExt.pixelSize); natras->pixelSize = streamExt.pixelSize; + assert(natras->paletteSize == streamExt.paletteSize); natras->paletteSize = streamExt.paletteSize; + assert(natras->totalSize == streamExt.totalSize); natras->totalSize = streamExt.totalSize; natras->kl = streamExt.mipmapVal; //printf("%X %X\n", natras->paletteBase, natras->tex1low); @@ -2122,11 +2146,28 @@ streamExt.mipmapVal); calcTEX1(raster, &tex1, tex->filterAddressing & 0xF); // printTEX1(tex1); + // this is weird stuff + if(streamExt.version < 2){ + if(streamExt.version == 1){ + // Version 1 has swizzled 8 bit textures + if(!(natras->flags & Ps2Raster::NEWSTYLE)) + natras->flags |= Ps2Raster::SWIZZLED8; + else + assert(0 && "can't happen"); + }else{ + // Version 0 has no swizzling at all + if(!(natras->flags & Ps2Raster::NEWSTYLE)) + natras->flags &= ~Ps2Raster::SWIZZLED8; + else + assert(0 && "can't happen"); + } + } + if(!findChunk(stream, ID_STRUCT, &length, nil)){ RWERROR((ERR_CHUNK, "STRUCT")); goto fail; } - if(streamExt.type < 2){ + if(streamExt.version < 2){ stream->read8(raster->pixels, length); }else{ stream->read8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, natras->pixelSize); @@ -2163,11 +2204,11 @@ writeNativeTexture(Texture *tex, Stream *stream) streamExt.height = raster->height; streamExt.depth = raster->depth; streamExt.rasterFormat = raster->format | raster->type; - streamExt.type = 0; + streamExt.version = 0; if(ras->flags == Ps2Raster::SWIZZLED8 && raster->depth == 8) - streamExt.type = 1; + streamExt.version = 1; if(ras->flags & Ps2Raster::NEWSTYLE) - streamExt.type = 2; + streamExt.version = 2; streamExt.tex0 = ras->tex0; streamExt.paletteOffset = ras->paletteBase; streamExt.tex1low = ras->tex1low; @@ -2181,7 +2222,7 @@ writeNativeTexture(Texture *tex, Stream *stream) stream->write8(&streamExt, 64); writeChunkHeader(stream, ID_STRUCT, sz); - if(streamExt.type < 2){ + if(streamExt.version < 2){ stream->write8(raster->pixels, sz); }else{ stream->write8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, ras->pixelSize); diff --git a/src/rwobjects.h b/src/rwobjects.h index 9fcab59..3965a16 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -141,6 +141,7 @@ struct Image void setPixels(uint8 *pixels); void setPixelsDXT(int32 type, uint8 *pixels); void setPalette(uint8 *palette); + void compressPalette(void); // turn 8 bit into 4 bit if possible bool32 hasAlpha(void); void convertTo32(void); void palettize(int32 depth);