mirror of
https://github.com/aap/librw.git
synced 2024-11-24 20:55:41 +00:00
fixes to rasters and images
This commit is contained in:
parent
49ca300b88
commit
fa6277be34
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user