ps2 raster creation basically done

This commit is contained in:
aap 2017-08-19 23:09:45 +02:00
parent 75435b8934
commit 8e277cbe9c
5 changed files with 261 additions and 86 deletions

View File

@ -820,7 +820,7 @@ Texture::upload(void)
switch(r->format & 0xF00){
case Raster::C8888:
glTexImage2D(GL_TEXTURE_2D, 0, 4, r->width, r->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, r->texels);
0, GL_RGBA, GL_UNSIGNED_BYTE, r->pixels);
break;
default:
printf("unsupported raster format: %x\n", r->format);

View File

@ -918,7 +918,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf
raster->width = width;
raster->height = height;
raster->depth = depth;
raster->texels = raster->palette = nil;
raster->pixels = raster->palette = nil;
s_plglist.construct(raster);
// printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth);

View File

@ -42,7 +42,7 @@ enum Psm {
// i don't really understand this, stolen from RW
static void
ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
transferMinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
{
*minh = 1;
switch(psm){
@ -66,16 +66,17 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
*minw = 8; // everything else
break;
}
if(flags & 0x2 && psm == 0x13){ // PSMT8
if(flags & 0x2 && psm == PSMT8){
*minw = 16;
*minh = 4;
}
if(flags & 0x4 && psm == 0x14){ // PSMT4
if(flags & 0x4 && psm == PSMT4){
*minw = 32;
*minh = 4;
}
}
#define ALIGN(x,a) ((x) + (a)-1 & ~((a)-1))
#define ALIGN16(x) ((x) + 0xF & ~0xF)
#define ALIGN64(x) ((x) + 0x3F & ~0x3F)
#define NSIZE(dim,pagedim) (((dim) + (pagedim)-1)/(pagedim))
@ -362,6 +363,23 @@ static uint8 blockmap_PSMZ16S[32] = {
21, 23, 5, 7,
};
static uint8 blockmaprev_PSMCT32[32] = {
0, 1, 8, 9, 2, 3, 10, 11,
16, 17, 24, 25, 18, 19, 26, 27,
4, 5, 12, 13, 6, 7, 14, 15,
20, 21, 28, 29, 22, 23, 30, 31,
};
static uint8 blockmaprev_PSMCT16[32] = {
0, 4, 1, 5,
8, 12, 9, 13,
2, 6, 3, 7,
10, 14, 11, 15,
16, 20, 17, 21,
24, 28, 25, 29,
18, 22, 19, 23,
26, 30, 27, 31,
};
/* Suffixes used:
* _Px - pixels
* _W - width units (pixels/64)
@ -603,7 +621,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui
uint32 bufpage_B = bufferPage_B[0];
uint32 pixeloff;
for(n = 0; n < nlevels; n++){
// Calculate TRXPOS register
// Calculate TRXPOS register (DSAX and DSAY, shifted up later)
// Start of buffer on current page (x in pixels, y in blocks)
pixeloff = (bufferBase_B[n] - bufpage_B) * blockWidth_Px;
// y coordinate of first pixel
@ -612,7 +630,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui
xoff_Px = pixeloff % (bufwidth_W*64);
if(bufferWidth_W[n] == bufwidth_W &&
// Not quite sure what's the meaning of this.
// SSAY is 11 bits, but so is SSAX and it is not checked?
// DSAY is 11 bits, but so is DSAX and it is not checked?
yoff_Px < 0x800){
trxpos[n] = yoff_Px<<16 | xoff_Px;
}else{
@ -765,7 +783,7 @@ createTexRaster(Raster *raster)
uint64 bufferWidth[7]; // in number of pixels / 64
uint64 bufferBase[7]; // block address
uint32 trxpos[8];
uint32 trxpos_hi[8];
int32 width, height, depth;
int32 pageWidth, pageHeight;
int32 paletteWidth, paletteHeight, paletteDepth;
@ -926,7 +944,7 @@ createTexRaster(Raster *raster)
// Do the real work here
uint32 paletteBase;
uint32 totalSize;
calcOffsets(width, height, psm, bufferBase, bufferWidth, trxpos, &totalSize, &paletteBase);
calcOffsets(width, height, psm, bufferBase, bufferWidth, trxpos_hi, &totalSize, &paletteBase);
ras->paletteSize = paletteWidth*paletteHeight*paletteDepth;
ras->miptbp1 =
@ -1007,35 +1025,63 @@ createTexRaster(Raster *raster)
(raster->width*raster->height*raster->depth/8/0x10) >= 0x7FFF){
ras->dataSize = ras->paletteSize+ras->pixelSize;
uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40);
assert(data);
ras->data = data;
raster->texels = data;
raster->pixels = data;
if(ras->paletteSize)
raster->palette = data + ras->pixelSize;
if(raster->depth == 8)
ras->flags |= Ps2Raster::SWIZZLED8;
}else{
ras->flags |= Ps2Raster::HASGIFPACKETS;
//int32 cpsm = ras->tex0[1]>>19 & 0x3F;
ras->flags |= Ps2Raster::NEWSTYLE;
uint64 paltrxpos = 0;
uint32 dsax = trxpos_hi[numLevels-1] & 0x7FF;
uint32 dsay = trxpos_hi[numLevels-1]>>16 & 0x7FF;
// Set swizzle flags and calculate TRXPOS for palette
if(psm == PSMT8){
ras->flags |= Ps2Raster::SWIZZLED8;
// TODO: crazy stuff
if(cpsm == PSMCT32 && bufferWidth[numLevels-1] == 2){ // one page
// unswizzle the starting block of the last buffer and palette
uint32 bufbase_B = bufferBase[numLevels-1]&~0x1F | (uint64)blockmaprev_PSMCT32[bufferBase[numLevels-1]&0x1F];
uint32 palbase_B = ras->paletteBase&~0x1F | (uint64)blockmaprev_PSMCT32[ras->paletteBase&0x1F];
// find start of page of last level (16,16 are PSMT8 block dimensions)
uint32 page_B = bufbase_B - 8*(dsay/16) - dsax/16;
// find palette DSAX/Y (in PSMCT32!)
dsay = (palbase_B - page_B)/8 * 8; // block/blocksPerPageX * blockHeight
dsax = (palbase_B - page_B)*8 % 64; // block*blockWidth % pageWidth
if(dsay < 0x800)
paltrxpos = dsay<<16 | dsax;
}
}
if(psm == PSMT4){
// swizzle flag probably depends on version :/
// swizzle flag depends on version :/
// but which version? ....
if(rw::version > 0x31000)
if(rw::version > 0x31000){
ras->flags |= Ps2Raster::SWIZZLED4;
// TODO: crazy stuff
// Where can this come from? if anything we're using PSMCT16S
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];
uint32 palbase_B = ras->paletteBase&~0x1F | (uint64)blockmaprev_PSMCT16[ras->paletteBase&0x1F];
// find start of page of last level (32,16 are PSMT4 block dimensions)
uint32 page_B = bufbase_B - 4*(dsay/32) - dsax/16;
// find palette DSAX/Y (in PSMCT16!)
dsay = (palbase_B - page_B)/4 * 8; // block/blocksPerPageX * blockHeight
dsax = (palbase_B - page_B)*16 % 128; // block*blockWidth % pageWidth
if(dsay < 0x800)
paltrxpos = dsay<<16 | dsax;
}
}
}
ras->pixelSize = 0x50*numLevels; // GIF packets
int32 minW, minH;
ps2MinSize(psm, ras->flags, &minW, &minH);
transferMinSize(psm, ras->flags, &minW, &minH);
w = raster->width;
h = raster->height;
n = numLevels;
while(n--){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
mipw = max(w, minW);
miph = max(h, minH);
ras->pixelSize += ALIGN16(mipw*miph*raster->depth/8);
w /= 2;
h /= 2;
@ -1046,25 +1092,44 @@ createTexRaster(Raster *raster)
ras->paletteSize = 0x50 +
paletteDepth*paletteWidth*paletteHeight;
}
// TODO: allocate space for more DMA packets
// every upload as 4 qwords:
// One transfer per buffer width, 4 qwords:
// DMAcnt(2) [NOP, DIRECT]
// GIF tag A+D
// BITBLTBUF
// DMAref(pixel data) [NOP, DIRECT]
ras->dataSize = ras->paletteSize+ras->pixelSize;
uint32 extrasize = 0x10; // PixelPtr
int32 numTransfers = 0;
for(n = 0; n < numLevels; n++)
if(trxpos_hi[n] == 0){
extrasize += 0x40;
numTransfers++;
}
if(ras->paletteSize){
extrasize += 0x40;
numTransfers++;
}
// What happens here?
if(ras->paletteSize && paltrxpos == 0)
ras->dataSize = ALIGN(ras->pixelSize,128) + ALIGN(ras->paletteSize,64) + extrasize + 0x70;
else
ras->dataSize = ALIGN(ras->paletteSize+ras->pixelSize,64) + extrasize + 0x70;
uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40);
uint32 *xferchain = (uint32*)(data + 0x10);
assert(data);
ras->data = data;
raster->texels = data + 0x50;
Ps2Raster::PixelPtr *pp = (Ps2Raster::PixelPtr*)data;
pp->numTransfers = numTransfers;
pp->numTotalTransfers = numTransfers;
pp->pixels = (uint8*)ALIGN((uintptr)data + extrasize, 128);
raster->pixels = (uint8*)pp;
if(ras->paletteSize)
raster->palette = data + ras->pixelSize + 0x50;
uint32 *p = (uint32*)data;
raster->palette = pp->pixels + ALIGN(ras->pixelSize, 128) + 0x50;
uint32 *p = (uint32*)pp->pixels;
w = raster->width;
h = raster->height;
for(n = 0; n < numLevels; n++){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
mipw = max(w, minW);
miph = max(h, minH);
// GIF tag
*p++ = 3; // NLOOP = 3
@ -1073,8 +1138,14 @@ createTexRaster(Raster *raster)
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
if(ras->flags & Ps2Raster::SWIZZLED8 && psm == PSMT8 ||
ras->flags & Ps2Raster::SWIZZLED4 && psm == PSMT4){
*p++ = 0; // SSAX/Y is always 0
*p++ = (trxpos_hi[n] & ~0x10001)/2; // divide both DSAX/Y by 2
}else{
*p++ = 0;
*p++ = trxpos_hi[n];
}
*p++ = 0x51;
*p++ = 0;
@ -1097,18 +1168,62 @@ createTexRaster(Raster *raster)
*p++ = 0;
// GIF tag
uint32 sz = mipw*miph*raster->depth/8 + 0xF >> 4;
*p++ = sz;
uint32 sz = ALIGN16(mipw*miph*raster->depth/8)/16;
*p++ = sz & 0x7FFF;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
if(trxpos_hi[n] == 0){
// Add a transfer, see above for layout
*xferchain++ = 0x10000002; // DMAcnt, 2 qwords
*xferchain++ = 0;
*xferchain++ = 0; // VIF nop
*xferchain++ = 0x50000002; // VIF DIRECT 2 qwords
// GIF tag
*xferchain++ = 1; // NLOOP = 1
*xferchain++ = 0x10000000; // NREG = 1
*xferchain++ = 0xE; // A+D
*xferchain++ = 0;
// BITBLTBUF
if(ras->flags & Ps2Raster::SWIZZLED8 && psm == PSMT8){
// PSMT8 is swizzled to PSMCT32 and dimensions are halved
*xferchain++ = PSMCT32<<24 | bufferWidth[n]/2<<16; // src buffer
*xferchain++ = PSMCT32<<24 | bufferWidth[n]/2<<16 | bufferBase[n]; // dst buffer
}else if(ras->flags & Ps2Raster::SWIZZLED4 && psm == PSMT4){
// PSMT4 is swizzled to PSMCT16 and dimensions are halved
*xferchain++ = PSMCT16<<24 | bufferWidth[n]/2<<16; // src buffer
*xferchain++ = PSMCT16<<24 | bufferWidth[n]/2<<16 | bufferBase[n]; // dst buffer
}else{
*xferchain++ = psm<<24 | bufferWidth[n]<<16; // src buffer
*xferchain++ = psm<<24 | bufferWidth[n]<<16 | bufferBase[n]; // dst buffer
}
*xferchain++ = 0x50;
*xferchain++ = 0;
*xferchain++ = 0x30000000 | sz+5; // DMAref
// this obviously only works with 32 bit pointers, but it's only needed on the PS2 anyway
*xferchain++ = (uint32)(uintptr)p - 0x50;
*xferchain++ = 0; // VIF nop
*xferchain++ = 0x50000000 | sz+5; // VIF DIRECT 2 qwords
}else{
// Add to existing transfer
xferchain[-4] = 0x30000000 | (xferchain[-4]&0xFFFF) + sz+5; // last DMAref
xferchain[-1] = 0x50000000 | (xferchain[-1]&0xFFFF) + sz+5; // last DIRECT
}
p += sz*4;
w /= 2;
h /= 2;
}
if(ras->paletteSize){
// huh?
if(paltrxpos)
raster->palette = (uint8*)p + 0x50;
p = (uint32*)(raster->palette - 0x50);
// GIF tag
*p++ = 3; // NLOOP = 3
@ -1117,8 +1232,8 @@ createTexRaster(Raster *raster)
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
*(uint64*)p = paltrxpos;
p += 2;
*p++ = 0x51;
*p++ = 0;
@ -1135,13 +1250,54 @@ createTexRaster(Raster *raster)
*p++ = 0;
// GIF tag
uint32 sz = ras->paletteSize - 0x50 + 0xF >> 4;
*p++ = sz;
uint32 sz = ALIGN16(ras->paletteSize - 0x50)/16;
*p++ = sz & 0x7FFF;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
// Transfer
*xferchain++ = 0x10000002; // DMAcnt, 2 qwords
*xferchain++ = 0;
*xferchain++ = 0; // VIF nop
*xferchain++ = 0x50000002; // VIF DIRECT 2 qwords
// GIF tag
*xferchain++ = 1; // NLOOP = 1
*xferchain++ = 0x10000000; // NREG = 1
*xferchain++ = 0xE; // A+D
*xferchain++ = 0;
// BITBLTBUF
if(paltrxpos == 0){
*xferchain++ = cpsm<<24 | 1<<16; // src buffer
*xferchain++ = cpsm<<24 | 1<<16 | ras->paletteBase; // dst buffer
*xferchain++ = 0x50;
*xferchain++ = 0;
}else{
// copy last pixel bitbltbuf...if uploading palette separately it's still the same buffer
xferchain[0] = xferchain[-16];
xferchain[1] = xferchain[-15];
xferchain[2] = xferchain[-14];
xferchain[3] = xferchain[-13];
// Add to last transfer
xferchain[-16] = 0x30000000 | (xferchain[-16]&0xFFFF) + sz+5; // last DMAref
xferchain[-13] = 0x50000000 | (xferchain[-13]&0xFFFF) + sz+5; // last DIRECT
xferchain += 4;
pp->numTransfers--;
}
*xferchain++ = 0x30000000 | sz+5; // DMAref
// this obviously only works with 32 bit pointers, but it's only needed on the PS2 anyway
*xferchain++ = (uint32)(uintptr)p - 0x50;
*xferchain++ = 0; // VIF nop
*xferchain++ = 0x50000000 | sz+5; // VIF DIRECT 2 qwords
}
}
raster->originalPixels = raster->pixels;
raster->originalStride = raster->stride;
if(ras->flags & Ps2Raster::NEWSTYLE)
raster->pixels = ((Ps2Raster::PixelPtr*)raster->pixels)->pixels + 0x50;
}
void
@ -1151,9 +1307,15 @@ rasterCreate(Raster *raster)
return;
// init raster
raster->pixels = nil;
raster->palette = nil;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalPixels = raster->pixels;
if(raster->width == 0 || raster->height == 0){
raster->flags = Raster::DONTALLOCATE;
raster->stride = 0;
raster->originalStride = 0;
return;
}
@ -1203,7 +1365,7 @@ int32
rasterNumLevels(Raster *raster)
{
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
if(raster->texels == nil) return 0;
if(raster->pixels == nil) return 0;
if(raster->format & Raster::MIPMAP)
return MAXLEVEL(ras)+1;
return 1;
@ -1489,9 +1651,9 @@ streamExt.mipmapVal);
goto fail;
}
if(streamExt.type < 2){
stream->read(raster->texels, length);
stream->read(raster->pixels, length);
}else{
stream->read(raster->texels-0x50, natras->pixelSize);
stream->read(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, natras->pixelSize);
stream->read(raster->palette-0x50, natras->paletteSize);
}
//printf("\n");
@ -1528,7 +1690,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
streamExt.type = 0;
if(ras->flags == Ps2Raster::SWIZZLED8 && raster->depth == 8)
streamExt.type = 1;
if(ras->flags & Ps2Raster::HASGIFPACKETS)
if(ras->flags & Ps2Raster::NEWSTYLE)
streamExt.type = 2;
streamExt.tex0 = ras->tex0;
streamExt.paletteOffset = ras->paletteBase;
@ -1543,9 +1705,9 @@ writeNativeTexture(Texture *tex, Stream *stream)
writeChunkHeader(stream, ID_STRUCT, sz);
if(streamExt.type < 2){
stream->write(raster->texels, sz);
stream->write(raster->pixels, sz);
}else{
stream->write(raster->texels-0x50, ras->pixelSize);
stream->write(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, ras->pixelSize);
stream->write(raster->palette-0x50, ras->paletteSize);
}
}

View File

@ -183,9 +183,18 @@ void registerPluginPDSPipes(void);
struct Ps2Raster
{
enum Flags {
HASGIFPACKETS = 0x1,
SWIZZLED8 = 0x2,
SWIZZLED4 = 0x4,
NEWSTYLE = 0x1, // has GIF tags and transfer DMA chain
SWIZZLED8 = 0x2,
SWIZZLED4 = 0x4,
};
struct PixelPtr {
// RW has pixels as second element but we don't want this struct
// to be longer than 16 bytes
uint8 *pixels;
// palette can be allocated in last level, in that case numTransfers is
// one less than numTotalTransfers.
int32 numTransfers;
int32 numTotalTransfers;
};
uint64 tex0;

View File

@ -227,10 +227,14 @@ struct Raster
int32 format;
int32 width, height, depth;
int32 stride;
uint8 *texels;
uint8 *pixels;
uint8 *palette;
uint8 *originalPixels;
// TODO: use them (for locking mainly)
int32 originalWidth;
int32 originalHeight;
int32 originalStride;
// TODO:
// original pixels, width, height, stride (used for locking)
// parent raster and offset
static Raster *create(int32 width, int32 height, int32 depth,