fixes to rasters and images

This commit is contained in:
aap 2020-07-23 22:35:58 +02:00
parent 49ca300b88
commit fa6277be34
4 changed files with 115 additions and 53 deletions

View File

@ -907,14 +907,14 @@ rasterToImage(Raster *raster)
} }
} }
out = image->pixels; uint8 *dst = image->pixels;
in = raster->lock(0, Raster::LOCKREAD); in = raster->lock(0, Raster::LOCKREAD);
if(pallength) if(pallength)
memcpy(out, in, raster->width*raster->height); memcpy(dst, in, raster->width*raster->height);
else else{
// TODO: stride for(int32 y = 0; y < image->height; y++){
for(int32 y = 0; y < image->height; y++) out = dst;
for(int32 x = 0; x < image->width; x++) for(int32 x = 0; x < image->width; x++){
switch(raster->format & 0xF00){ switch(raster->format & 0xF00){
case Raster::C8888: case Raster::C8888:
out[0] = in[2]; out[0] = in[2];
@ -922,30 +922,33 @@ rasterToImage(Raster *raster)
out[2] = in[0]; out[2] = in[0];
out[3] = in[3]; out[3] = in[3];
in += 4; in += 4;
out += 4;
break; break;
case Raster::C888: case Raster::C888:
out[0] = in[2]; out[0] = in[2];
out[1] = in[1]; out[1] = in[1];
out[2] = in[0]; out[2] = in[0];
in += 4; in += 4;
out += 3;
break; break;
case Raster::C1555: case Raster::C1555:
out[0] = in[0]; out[0] = in[0];
out[1] = in[1]; out[1] = in[1];
in += 2; in += 2;
out += 2;
break; break;
case Raster::C555: case Raster::C555:
out[0] = in[0]; out[0] = in[0];
out[1] = in[1] | 0x80; out[1] = in[1] | 0x80;
in += 2; in += 2;
out += 2;
break; break;
} }
out += image->bpp;
}
dst += image->stride;
}
}
raster->unlock(0); raster->unlock(0);
image->compressPalette();
return image; return image;
} }

View File

@ -346,6 +346,23 @@ Image::setPalette(uint8 *palette)
this->flags |= 2; 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 bool32
Image::hasAlpha(void) Image::hasAlpha(void)
{ {
@ -356,7 +373,7 @@ Image::hasAlpha(void)
uint8 *line = pixels; uint8 *line = pixels;
for(int x = 0; x < this->width; x++){ for(int x = 0; x < this->width; x++){
ret &= line[3]; ret &= line[3];
line += 4; line += this->bpp;
} }
pixels += this->stride; pixels += this->stride;
} }
@ -367,7 +384,7 @@ Image::hasAlpha(void)
uint8 *line = pixels; uint8 *line = pixels;
for(int x = 0; x < this->width; x++){ for(int x = 0; x < this->width; x++){
ret &= line[1] & 0x80; ret &= line[1] & 0x80;
line += 2; line += this->bpp;
} }
pixels += this->stride; pixels += this->stride;
} }
@ -377,7 +394,7 @@ Image::hasAlpha(void)
uint8 *line = pixels; uint8 *line = pixels;
for(int x = 0; x < this->width; x++){ for(int x = 0; x < this->width; x++){
ret &= this->palette[*line*4+3]; ret &= this->palette[*line*4+3];
line++; line += this->bpp;
} }
pixels += this->stride; pixels += this->stride;
} }

View File

@ -184,9 +184,10 @@ getRasterFormat(Raster *raster)
palformat = Raster::PAL8; palformat = Raster::PAL8;
break; break;
case 24: case 24:
pixelformat = Raster::C888; // unsafe
palformat = 0; // pixelformat = Raster::C888;
break; // palformat = 0;
// break;
case 32: case 32:
pixelformat = Raster::C8888; pixelformat = Raster::C8888;
palformat = 0; palformat = 0;
@ -236,6 +237,7 @@ getRasterFormat(Raster *raster)
} }
raster->depth = 32; raster->depth = 32;
}else if(pixelformat == Raster::C888){ }else if(pixelformat == Raster::C888){
assert(0 && "24 bit rasters not supported");
if(raster->depth && raster->depth != 24){ if(raster->depth && raster->depth != 24){
RWERROR((ERR_INVRASTER)); RWERROR((ERR_INVRASTER));
return 0; return 0;
@ -805,7 +807,13 @@ rasterCreateTexture(Raster *raster)
width = raster->width; width = raster->width;
height = raster->height; height = raster->height;
depth = raster->depth; 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... // RW doesn't seem to check this, hm...
if(raster->flags & Raster::DONTALLOCATE) if(raster->flags & Raster::DONTALLOCATE)
@ -999,10 +1007,11 @@ rasterCreateTexture(Raster *raster)
// If there is still room, use it! // If there is still room, use it!
// If dimensions don't fill a page, we have at least // If dimensions don't fill a page, we have at least
// half a page left, enough for any palette // 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 || if(pageWidth*nPagW > width ||
pageHeight*nPagH > height) pageHeight*nPagH > height){
ras->paletteBase = (ras->totalSize - 256) / WD2BLK; ras->paletteBase = (ras->totalSize - 256) / WD2BLK;
else{ }else{
// Otherwise allocate more space... // Otherwise allocate more space...
ras->paletteBase = ras->totalSize / WD2BLK; ras->paletteBase = ras->totalSize / WD2BLK;
// ...using the same calculation as above. // ...using the same calculation as above.
@ -1069,6 +1078,7 @@ rasterCreateTexture(Raster *raster)
if(rw::version > 0x31000){ if(rw::version > 0x31000){
ras->flags |= Ps2Raster::SWIZZLED4; ras->flags |= Ps2Raster::SWIZZLED4;
// Where can this come from? if anything we're using PSMCT16S // Where can this come from? if anything we're using PSMCT16S
// Looks like they wanted to swizzle palettes too...
if(cpsm == PSMCT16){ if(cpsm == PSMCT16){
// unswizzle the starting block of the last buffer and palette // unswizzle the starting block of the last buffer and palette
uint32 bufbase_B = bufferBase[numLevels-1]&~0x1F | (uint64)blockmaprev_PSMCT16[bufferBase[numLevels-1]&0x1F]; 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) rasterLock(Raster *raster, int32 level, int32 lockMode)
{ {
Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
assert(raster->depth != 24);
if(level > 0){ if(level > 0){
int32 minw, minh; int32 minw, minh;
@ -1581,15 +1592,10 @@ imageFindRasterFormat(Image *img, int32 type,
switch(depth){ switch(depth){
case 32: case 32:
if(img->hasAlpha())
format = Raster::C8888;
else{
format = Raster::C888;
depth = 24;
}
break;
case 24: case 24:
format = Raster::C888; // C888 24 bit is unsafe
format = Raster::C8888;
depth = 32;
break; break;
case 16: case 16:
format = Raster::C1555; format = Raster::C1555;
@ -1622,14 +1628,12 @@ rasterFromImage(Raster *raster, Image *image)
int32 pallength = 0; int32 pallength = 0;
switch(image->depth){ switch(image->depth){
case 24:
case 32: case 32:
if(raster->format != Raster::C8888 && if(raster->format != Raster::C8888 &&
raster->format != Raster::C888) raster->format != Raster::C888) // unsafe already
goto err; goto err;
break; break;
case 24:
if(raster->format != Raster::C888) goto err;
break;
case 16: case 16:
if(raster->format != Raster::C1555) goto err; if(raster->format != Raster::C1555) goto err;
break; break;
@ -1647,6 +1651,12 @@ rasterFromImage(Raster *raster, Image *image)
return 0; return 0;
} }
// unsafe
if((raster->format&0xF00) == Raster::C888){
RWERROR((ERR_INVRASTER));
return 0;
}
uint8 *in, *out; uint8 *in, *out;
if(image->depth <= 8){ if(image->depth <= 8){
in = image->palette; in = image->palette;
@ -1673,27 +1683,24 @@ rasterFromImage(Raster *raster, Image *image)
for(int32 y = 0; y < image->height; y++){ for(int32 y = 0; y < image->height; y++){
in = src; in = src;
for(int32 x = 0; x < image->width; x++){ for(int32 x = 0; x < image->width; x++){
switch(raster->format & 0xF00){ switch(image->depth){
case Raster::C8888: case 16:
out[0] = in[0]; conv_ARGB1555_from_ABGR1555(out, in);
out[1] = in[1]; out += 2;
out[2] = in[2];
out[3] = in[3]*128/255;
out += 4;
break; break;
case Raster::C888: case 24:
out[0] = in[0]; out[0] = in[0];
out[1] = in[1]; out[1] = in[1];
out[2] = in[2]; out[2] = in[2];
out[3] = 0x80; out[3] = 0x80;
out += 4; out += 4;
break; break;
case Raster::C1555: case 32:
conv_ARGB1555_from_ABGR1555(out, in); out[0] = in[0];
out += 2; out[1] = in[1];
break; out[2] = in[2];
default: out[3] = in[3]*128/255;
assert(0 && "unknown ps2 raster format"); out += 4;
break; break;
} }
in += image->bpp; in += image->bpp;
@ -1990,7 +1997,7 @@ struct StreamRasterExt
int32 height; int32 height;
int32 depth; int32 depth;
uint16 rasterFormat; uint16 rasterFormat;
int16 type; int16 version;
uint64 tex0; uint64 tex0;
uint32 paletteOffset; uint32 paletteOffset;
uint32 tex1low; uint32 tex1low;
@ -2054,7 +2061,7 @@ streamExt.width,
streamExt.height, streamExt.height,
streamExt.depth, streamExt.depth,
streamExt.rasterFormat, streamExt.rasterFormat,
streamExt.type, streamExt.version,
streamExt.tex0, streamExt.tex0,
streamExt.paletteOffset, streamExt.paletteOffset,
streamExt.tex1low, streamExt.tex1low,
@ -2065,7 +2072,7 @@ streamExt.paletteSize,
streamExt.totalSize, streamExt.totalSize,
streamExt.mipmapVal); streamExt.mipmapVal);
*/ */
noNewStyleRasters = streamExt.type < 2; noNewStyleRasters = streamExt.version < 2;
rw::version = version; rw::version = version;
raster = Raster::create(streamExt.width, streamExt.height, raster = Raster::create(streamExt.width, streamExt.height,
streamExt.depth, streamExt.rasterFormat, streamExt.depth, streamExt.rasterFormat,
@ -2088,8 +2095,12 @@ streamExt.mipmapVal);
assert(natras->pixelSize >= streamExt.pixelSize); assert(natras->pixelSize >= streamExt.pixelSize);
assert(natras->paletteSize >= streamExt.paletteSize); 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); //printf("TEX0: %016llX\n %016llX\n", natras->tex0, streamExt.tex0);
//printTEX0(natras->tex0);
//printTEX0(streamExt.tex0);
//fflush(stdout);
//}
//if(natras->tex1low != streamExt.tex1low) //if(natras->tex1low != streamExt.tex1low)
//printf("TEX1: %08X\n %08X\n", natras->tex1low, streamExt.tex1low); //printf("TEX1: %08X\n %08X\n", natras->tex1low, streamExt.tex1low);
//if(natras->miptbp1 != streamExt.miptbp1) //if(natras->miptbp1 != streamExt.miptbp1)
@ -2104,13 +2115,26 @@ streamExt.mipmapVal);
//printf("PLS: %08X\n %08X\n", natras->paletteSize, streamExt.paletteSize); //printf("PLS: %08X\n %08X\n", natras->paletteSize, streamExt.paletteSize);
//if(natras->totalSize != streamExt.totalSize) //if(natras->totalSize != streamExt.totalSize)
//printf("TSZ: %08X\n %08X\n", 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; natras->tex0 = streamExt.tex0;
assert(natras->paletteBase == streamExt.paletteOffset);
natras->paletteBase = streamExt.paletteOffset; natras->paletteBase = streamExt.paletteOffset;
assert(natras->tex1low == streamExt.tex1low);
natras->tex1low = streamExt.tex1low; natras->tex1low = streamExt.tex1low;
assert(natras->miptbp1 == streamExt.miptbp1);
natras->miptbp1 = streamExt.miptbp1; natras->miptbp1 = streamExt.miptbp1;
assert(natras->miptbp2 == streamExt.miptbp2);
natras->miptbp2 = streamExt.miptbp2; natras->miptbp2 = streamExt.miptbp2;
assert(natras->pixelSize == streamExt.pixelSize);
natras->pixelSize = streamExt.pixelSize; natras->pixelSize = streamExt.pixelSize;
assert(natras->paletteSize == streamExt.paletteSize);
natras->paletteSize = streamExt.paletteSize; natras->paletteSize = streamExt.paletteSize;
assert(natras->totalSize == streamExt.totalSize);
natras->totalSize = streamExt.totalSize; natras->totalSize = streamExt.totalSize;
natras->kl = streamExt.mipmapVal; natras->kl = streamExt.mipmapVal;
//printf("%X %X\n", natras->paletteBase, natras->tex1low); //printf("%X %X\n", natras->paletteBase, natras->tex1low);
@ -2122,11 +2146,28 @@ streamExt.mipmapVal);
calcTEX1(raster, &tex1, tex->filterAddressing & 0xF); calcTEX1(raster, &tex1, tex->filterAddressing & 0xF);
// printTEX1(tex1); // 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)){ if(!findChunk(stream, ID_STRUCT, &length, nil)){
RWERROR((ERR_CHUNK, "STRUCT")); RWERROR((ERR_CHUNK, "STRUCT"));
goto fail; goto fail;
} }
if(streamExt.type < 2){ if(streamExt.version < 2){
stream->read8(raster->pixels, length); stream->read8(raster->pixels, length);
}else{ }else{
stream->read8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, natras->pixelSize); stream->read8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, natras->pixelSize);
@ -2163,11 +2204,11 @@ writeNativeTexture(Texture *tex, Stream *stream)
streamExt.height = raster->height; streamExt.height = raster->height;
streamExt.depth = raster->depth; streamExt.depth = raster->depth;
streamExt.rasterFormat = raster->format | raster->type; streamExt.rasterFormat = raster->format | raster->type;
streamExt.type = 0; streamExt.version = 0;
if(ras->flags == Ps2Raster::SWIZZLED8 && raster->depth == 8) if(ras->flags == Ps2Raster::SWIZZLED8 && raster->depth == 8)
streamExt.type = 1; streamExt.version = 1;
if(ras->flags & Ps2Raster::NEWSTYLE) if(ras->flags & Ps2Raster::NEWSTYLE)
streamExt.type = 2; streamExt.version = 2;
streamExt.tex0 = ras->tex0; streamExt.tex0 = ras->tex0;
streamExt.paletteOffset = ras->paletteBase; streamExt.paletteOffset = ras->paletteBase;
streamExt.tex1low = ras->tex1low; streamExt.tex1low = ras->tex1low;
@ -2181,7 +2222,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
stream->write8(&streamExt, 64); stream->write8(&streamExt, 64);
writeChunkHeader(stream, ID_STRUCT, sz); writeChunkHeader(stream, ID_STRUCT, sz);
if(streamExt.type < 2){ if(streamExt.version < 2){
stream->write8(raster->pixels, sz); stream->write8(raster->pixels, sz);
}else{ }else{
stream->write8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, ras->pixelSize); stream->write8(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, ras->pixelSize);

View File

@ -141,6 +141,7 @@ struct Image
void setPixels(uint8 *pixels); void setPixels(uint8 *pixels);
void setPixelsDXT(int32 type, uint8 *pixels); void setPixelsDXT(int32 type, uint8 *pixels);
void setPalette(uint8 *palette); void setPalette(uint8 *palette);
void compressPalette(void); // turn 8 bit into 4 bit if possible
bool32 hasAlpha(void); bool32 hasAlpha(void);
void convertTo32(void); void convertTo32(void);
void palettize(int32 depth); void palettize(int32 depth);