pcsx2/plugins/gs/GSsoft/Src/Texts.c

545 lines
12 KiB
C

/* GSsoft
* Copyright (C) 2002-2005 GSsoft Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <math.h>
#include "GS.h"
#include "Texts.h"
#include "Mem.h"
#include "Cache.h"
u32 clud[256];
void copy_clut32_8(u32 *clud) {
int x, y;
int cy;
int i;
for (y=0, cy=0; y < 8; y++) {
// GS_LOG("clut1[%d];\n", cy);
for(x=0, i=0; x < 8; x++, i++) {
clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64);
// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]);
}
for(x=16; x < 24; x++, i++) {
clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64);
// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]);
}
cy++;
// GS_LOG("clut2[%d];\n", cy);
for(x=8, i=0; x < 16; x++, i++) {
clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64);
// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]);
}
for(x=24; x < 32; x++, i++) {
clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64);
// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]);
}
cy++;
}
}
void copy_clut32_4(u32 *clud) {
int x, y;
for (y = 0; y < 2; y++) {
for(x = 0; x < 8; x++) {
clud[y*8 + x] = readPixel32(x, y, tex0->cbp, 64);
// GS_LOG("clut[%d] = %x\n", x, clud[y*8 + x]);
}
}
}
u32 _readPixel16(int x, int y, u32 bp, u32 bw) {
u32 c = readPixel16(x, y, bp, bw);
u32 p;
p = ((c & 0x7c00) << 9) |
((c & 0x03e0) << 6) |
((c & 0x001f) << 3);
if (gs.texa.aem) {
if (c & 0x8000) {
p|= gs.texa.ta[1] << 24;
} else {
if (p) p|= gs.texa.ta[0] << 24;
}
} else {
p|= gs.texa.ta[(c & 0x8000) >> 15] << 24;
}
return p;
}
u32 _readPixel16S(int x, int y, u32 bp, u32 bw) {
u32 c = readPixel16S(x, y, bp, bw);
u32 p;
p = ((c & 0x7c00) << 9) |
((c & 0x03e0) << 6) |
((c & 0x001f) << 3);
if (gs.texa.aem) {
if (c & 0x8000) {
p|= gs.texa.ta[1] << 24;
} else {
if (p) p|= gs.texa.ta[0] << 24;
}
} else {
p|= gs.texa.ta[(c & 0x8000) >> 15] << 24;
}
return p;
}
u32 _readPixel24(int x, int y, u32 bp, u32 bw) {
u32 c = readPixel24(x, y, bp, bw);
if (gs.texa.aem) {
if (c) c|= gs.texa.ta[0] << 24;
} else {
c|= gs.texa.ta[0] << 24;
}
return c;
}
void copy_clut16S_8_1(u32 *clup) {
int x, y;
int cy;
int i;
for (y=0, cy=0; y < 8; y++) {
for(x=0, i=0; x < 8; x++, i++) {
clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64);
}
for(x=16; x < 24; x++, i++) {
clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64);
}
cy++;
for(x=8, i=0; x < 16; x++, i++) {
clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64);
}
for(x=24; x < 32; x++, i++) {
clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64);
}
cy++;
}
}
void copy_clut16S_8_2(u32 *clup) {
int i;
for (i=0; i < 256; i++) {
clud[i] = _readPixel16S(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw);
}
}
void copy_clut16_8_1(u32 *clup) {
int x, y;
int cy;
int i;
for (y=0, cy=0; y < 8; y++) {
for(x=0, i=0; x < 8; x++, i++) {
clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64);
}
for(x=16; x < 24; x++, i++) {
clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64);
}
cy++;
for(x=8, i=0; x < 16; x++, i++) {
clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64);
}
for(x=24; x < 32; x++, i++) {
clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64);
}
cy++;
}
}
void copy_clut16_8_2(u32 *clup) {
int i;
for (i=0; i < 256; i++) {
clud[i] = _readPixel16(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw);
}
}
void copy_clut16_4_1(u32 *clud) {
int x, y;
for (y = 0; y < 2; y++) {
for(x = 0; x < 8; x++) {
clud[y*8 + x] = _readPixel16(x, y, tex0->cbp, 64);
}
}
}
void copy_clut16_4_2(u32 *clup) {
int i;
for (i=0; i < 16; i++) {
clud[i] = _readPixel16(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw);
}
}
void copy_clut16S_4_1(u32 *clud) {
int x, y;
for (y = 0; y < 2; y++) {
for(x = 0; x < 8; x++) {
clud[y*8 + x] = _readPixel16S(x, y, tex0->cbp, 64);
}
}
}
void copy_clut16S_4_2(u32 *clup) {
int i;
for (i=0; i < 16; i++) {
clud[i] = _readPixel16S(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw);
}
}
void wrapUV(int *u, int *v) {
switch (clamp->wms) {
case 0: // REPEAT
*u = *u % tex0->tw;
break;
case 1: // CLAMP
if (*u < 0) *u = 0;
if (*u >= tex0->tw) *u = tex0->tw - 1;
break;
case 2: // REGION_CLAMP
if (*u < clamp->minu) *u = clamp->minu;
if (*u > clamp->maxu) *u = clamp->maxu;
break;
case 3: // REGION_REPEAT
printf("REGION_REPEAT\n");
*u = (*u & clamp->minu) | clamp->maxu;
break;
}
switch (clamp->wmt) {
case 0: // REPEAT
*v = *v % tex0->th;
break;
case 1: // CLAMP
if (*v < 0) *v = 0;
if (*v >= tex0->th) *v = tex0->th - 1;
break;
case 2: // REGION_CLAMP
if (*v < clamp->minv) *v = clamp->minv;
if (*v > clamp->maxv) *v = clamp->maxv;
break;
case 3: // REGION_REPEAT
printf("REGION_REPEAT\n");
*v = (*v & clamp->minv) | clamp->maxv;
break;
}
}
u32 _GetTexturePixel32_T32B(int u, int v) {
wrapUV(&u, &v);
return readPixel32(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_T24B(int u, int v) {
wrapUV(&u, &v);
return _readPixel24(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_T16B(int u, int v) {
wrapUV(&u, &v);
return _readPixel16(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_T16SB(int u, int v) {
wrapUV(&u, &v);
return _readPixel16S(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_T8B(int u, int v) {
wrapUV(&u, &v);
return clud[readPixel8(u, v, tex0->tbp0, tex0->tbw)];
}
u32 _GetTexturePixel32_T4B(int u, int v) {
wrapUV(&u, &v);
return clud[readPixel4(u, v, tex0->tbp0, tex0->tbw)];
}
u32 _GetTexturePixel32_T8HB(int u, int v) {
wrapUV(&u, &v);
return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw)];
}
u32 _GetTexturePixel32_T4HLB(int u, int v) {
wrapUV(&u, &v);
return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw) & 0xf];
}
u32 _GetTexturePixel32_T4HHB(int u, int v) {
wrapUV(&u, &v);
return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw) >> 4];
}
u32 _GetTexturePixel32_Z32B(int u, int v) {
wrapUV(&u, &v);
return readPixel32Z(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_Z24B(int u, int v) {
wrapUV(&u, &v);
return readPixel24Z(u, v, tex0->tbp0, tex0->tbw);
}
/*u32 _GetTexturePixel32_Z16B(int u, int v) {
wrapUV(&u, &v);
return readPixel24Z(u, v, tex0->tbp0, tex0->tbw);
}
u32 _GetTexturePixel32_Z16SB(int u, int v) {
wrapUV(&u, &v);
return readPixel24Z(u, v, tex0->tbp0, tex0->tbw);
}*/
void _SetGetTexturePixelB() {
switch (tex0->psm) {
case 0x00: // PSMCT32
GetTexturePixel32 = _GetTexturePixel32_T32B; break;
case 0x01: // PSMCT24
GetTexturePixel32 = _GetTexturePixel32_T24B; break;
case 0x02: // PSMCT16
GetTexturePixel32 = _GetTexturePixel32_T16B; break;
case 0x0A: // PSMCT16S
GetTexturePixel32 = _GetTexturePixel32_T16SB;break;
case 0x13: // PSMT8
GetTexturePixel32 = _GetTexturePixel32_T8B; break;
case 0x14: // PSMT4
GetTexturePixel32 = _GetTexturePixel32_T4B; break;
case 0x1B: // PSMT8H
GetTexturePixel32 = _GetTexturePixel32_T8HB; break;
case 0x24: // PSMT4HL
GetTexturePixel32 = _GetTexturePixel32_T4HLB; break;
case 0x2C: // PSMT4HH
GetTexturePixel32 = _GetTexturePixel32_T4HHB; break;
case 0x30: // PSMZ32
GetTexturePixel32 = _GetTexturePixel32_Z32B; break;
/* case 0x31: // PSMZ24
GetTexturePixel32 = _GetTexturePixel32_Z24B; break;
case 0x32: // PSMZ16
GetTexturePixel32 = _GetTexturePixel32_Z16B; break;
case 0x3A: // PSMZ16S
GetTexturePixel32 = _GetTexturePixel32_Z16SB; break;*/
default:
printf("unhandled psm : %x\n", tex0->psm);
GetTexturePixel32 = _GetTexturePixel32_T32B; break;
}
}
void SetTexture() {
int clutf=0;
switch (tex0->psm) {
case 0x13: // PSMT8
case 0x1B: // PSMT8H
clutf = 8; break;
case 0x14: // PSMT4
case 0x24: // PSMT4HL
case 0x2C: // PSMT4HH
clutf = 4; break;
}
if (clutf == 8) {
if (tex0->cpsm == 0) {
copy_clut32_8(clud);
}
if (tex0->cpsm == 0x2) {
if (tex0->csm == 0) {
copy_clut16_8_1(clud);
} else {
copy_clut16_8_2(clud);
}
}
if (tex0->cpsm == 0xa) {
if (tex0->csm == 0) {
copy_clut16S_8_1(clud);
} else {
copy_clut16S_8_2(clud);
}
}
}
if (clutf == 4) {
if (tex0->cpsm == 0) {
copy_clut32_4(clud);
}
if (tex0->cpsm == 0x2) {
if (tex0->csm == 0) {
copy_clut16_4_1(clud);
} else {
copy_clut16_4_2(clud);
}
}
if (tex0->cpsm == 0xa) {
if (tex0->csm == 0) {
copy_clut16S_4_1(clud);
} else {
copy_clut16S_4_2(clud);
}
}
}
/* if (tex0->tbp0 & 0x1f)*/ {
_SetGetTexturePixelB();
} /*else
switch (tex0->psm) {
case 0x00: // PSMCT32
GetTexturePixel32 = _GetTexturePixel32_T32; break;
case 0x01: // PSMCT24
GetTexturePixel32 = _GetTexturePixel32_T24; break;
case 0x02: // PSMCT16
case 0x0A: // PSMCT16S
GetTexturePixel32 = _GetTexturePixel32_T16; break;
case 0x13: // PSMT8
GetTexturePixel32 = _GetTexturePixel32_T8; break;
case 0x14: // PSMT4
GetTexturePixel32 = _GetTexturePixel32_T4; break;
case 0x1B: // PSMT8H
GetTexturePixel32 = _GetTexturePixel32_T8H; break;
case 0x24: // PSMT4HL
GetTexturePixel32 = _GetTexturePixel32_T4HL;break;
case 0x2C: // PSMT4HH
GetTexturePixel32 = _GetTexturePixel32_T4HH;break;
default:
printf("unhandled psm : %x\n", tex0->psm);
GetTexturePixel32 = _GetTexturePixel32_T32; break;
}*/
if (conf.cache) {
if (CacheSetTexture() == 0) {
GetTexturePixel32 = CacheGetTexturePixel32;
}
}
// if (tex0->tbp0 == 0x75680)
if (conf.dumptexts) DumpTexture();
}
u32 TextureSizeGS(int width, int height, int psm) {
switch (psm) {
case 0x00: // PSMCT32
case 0x01: // PSMCT24
case 0x1B: // PSMT8H
case 0x24: // PSMT4HL
case 0x2C: // PSMT4HH
return (width*height*4);
case 0x02: // PSMCT16
case 0x0A: // PSMCT16S
return (width*height*2);
case 0x13: // PSMT8
return (width*height );
case 0x14: // PSMT4
return (width*height/2);
default:
printf("unsupported PSM %d\n", psm);
return 0;
}
}
void DumpTexture() {
FILE *bmpfile;
char filename[256];
unsigned char header[0x36];
long size;
unsigned char line[1024*3];
int w,h;
short i,j;
unsigned char empty[2]={0,0};
u32 color;
u32 snapshotnr = 0;
w = tex0->tw;
h = tex0->th-20;
size = w*h*3 + 0x38;
printf("DumpTexture %d, %d\n", w, h);
// fill in proper values for BMP
// hardcoded BMP header
memset(header,0,0x36);
header[0]='B';
header[1]='M';
header[2]=size&0xff;
header[3]=(size>>8)&0xff;
header[4]=(size>>16)&0xff;
header[5]=(size>>24)&0xff;
header[0x0a]=0x36;
header[0x0e]=0x28;
header[0x12]=w%256;
header[0x13]=w/256;
header[0x16]=h%256;
header[0x17]=h/256;
header[0x1a]=0x01;
header[0x1c]=0x18;
header[0x26]=0x12;
header[0x27]=0x0B;
header[0x2A]=0x12;
header[0x2B]=0x0B;
// increment snapshot value & try to get filename
for (;;) {
snapshotnr++;
sprintf(filename,"tex%03d_%x.bmp", snapshotnr, tex0->tbp0);
bmpfile=fopen(filename,"rb");
if (bmpfile == NULL) break;
fclose(bmpfile);
}
// try opening new snapshot file
if((bmpfile=fopen(filename,"wb"))==NULL)
return;
fwrite(header,0x36,1,bmpfile);
for(i=h-1;i>=0;i--) {
for(j=0;j<w;j++) {
color = GetTexturePixel32(j, i);
line[j*3+2]=(color )&0xff;
line[j*3+1]=(color>> 8)&0xff;
line[j*3+0]=(color>>16)&0xff;
}
fwrite(line,w*3,1,bmpfile);
}
fwrite(empty,0x2,1,bmpfile);
fclose(bmpfile);
}