Files
2007-11-11 02:55:00 +00:00

391 lines
9.9 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 <string.h>
#include "GS.h"
#include "Soft.h"
#include "Mem.h"
__inline void stepGSvertex() {
int i;
gs.primC--;
for (i=0; i<gs.primC; i++) {
gs.gsvertex[i].x = gs.gsvertex[i+1].x;
gs.gsvertex[i].y = gs.gsvertex[i+1].y;
gs.gsvertex[i].z = gs.gsvertex[i+1].z;
gs.gsvertex[i].f = gs.gsvertex[i+1].f;
if (prim->tme) {
if (prim->fst) {
gs.gsvertex[i].u = gs.gsvertex[i+1].u;
gs.gsvertex[i].v = gs.gsvertex[i+1].v;
} else {
gs.gsvertex[i].s = gs.gsvertex[i+1].s;
gs.gsvertex[i].t = gs.gsvertex[i+1].t;
gs.gsvertex[i].q = gs.gsvertex[i+1].q;
}
}
if (prim->iip) {
gs.gsvertex[i].rgba = gs.gsvertex[i+1].rgba;
}
}
}
__inline void stepGSfanvertex() {
gs.primC--;
gs.gsvertex[1].x = gs.gsvertex[2].x;
gs.gsvertex[1].y = gs.gsvertex[2].y;
gs.gsvertex[1].z = gs.gsvertex[2].z;
gs.gsvertex[1].f = gs.gsvertex[2].f;
if (prim->tme) {
if (prim->fst) {
gs.gsvertex[1].u = gs.gsvertex[2].u;
gs.gsvertex[1].v = gs.gsvertex[2].v;
} else {
gs.gsvertex[1].s = gs.gsvertex[2].s;
gs.gsvertex[1].t = gs.gsvertex[2].t;
gs.gsvertex[1].q = gs.gsvertex[2].q;
}
}
if (prim->iip) {
gs.gsvertex[1].rgba = gs.gsvertex[2].rgba;
}
}
__inline void STQtoUV(Vertex *v, float q) {
#ifdef GS_LOG
GS_LOG("STQtoUV %f, %f, %f (tw=%d, th=%d)\n",
*(float*)&v->s, *(float*)&v->t, q, tex0->tw, tex0->th);
#endif
if (v->s == 0xffffffff) { printf("v->s == nan\n"); }
if (v->t == 0xffffffff) { printf("v->t == nan\n"); }
if (q == 0xffffffff) { printf("v->q == nan\n"); }
if (q == 0) {
v->u = (int)((float)(tex0->tw-1) * (*(float*)&v->s));
v->v = (int)((float)(tex0->th-1) * (*(float*)&v->t));
} else {
v->u = (int)((float)(tex0->tw-1) * (*(float*)&v->s / q));
v->v = (int)((float)(tex0->th-1) * (*(float*)&v->t / q));
}
if (v->u > tex0->tw) {
#ifdef GS_LOG
GS_LOG("*warning*: U > TW\n");
#endif
}
if (v->v > tex0->th) {
#ifdef GS_LOG
GS_LOG("*warning*: V > TH\n");
#endif
}
}
void _primPoint(Vertex *vertex) {
Vertex v;
memcpy(&v, vertex, sizeof(Vertex));
#ifdef GS_LOG
GS_LOG("primPoint %dx%d %lx\n",
v.x, v.y, gs.rgba);
#endif
v.x -= offset->x; v.y -= offset->y;
if (v.x < scissor->x0) return;
if (v.y < scissor->y0) return;
if (v.x > scissor->x1) return;
if (v.y > scissor->y1) return;
if (v.x < 0) return;
if (v.x >= gsfb->fbw) return;
if (v.y < 0) return;
if (v.y >= gsfb->fbh) return;
writePixel32(v.x, v.y, gs.rgba, gsfb->fbp, gsfb->fbw);
}
void primPoint(Vertex *vertex) {
if (vertex && norender == 0) _primPoint(vertex);
memset(gs.gsvertex, 0, sizeof(Vertex));
gs.primC = 0;
}
void _primLine(Vertex *vertex) {
Vertex v[2];
memcpy(v, vertex, sizeof(Vertex) * 2);
v[0].x -= offset->x; v[0].y -= offset->y;
v[1].x -= offset->x; v[1].y -= offset->y;
#ifdef GS_LOG
GS_LOG("primLine %dx%d %lx, %dx%d %lx\n",
v[0].x, v[0].y, v[0].rgba,
v[1].x, v[1].y, v[1].rgba);
#endif
if (prim->iip == 0) {
if (test->zte)
drawLineF_Z(v);
else drawLineF(v);
} else {
if (test->zte)
drawLineG_Z(v);
else drawLineG(v);
}
}
void primLine(Vertex *vertex) {
if (vertex && norender == 0) _primLine(vertex);
memset(gs.gsvertex, 0, sizeof(Vertex)*2);
gs.primC = 0;
}
void primLineStrip(Vertex *vertex) {
if (vertex && norender == 0) _primLine(vertex);
stepGSvertex();
}
void _primTriangle(Vertex *vertex) {
Vertex v[3];
memcpy(v, vertex, sizeof(Vertex) * 3);
v[0].x -= offset->x; v[0].y -= offset->y;
v[1].x -= offset->x; v[1].y -= offset->y;
v[2].x -= offset->x; v[2].y -= offset->y;
#ifdef GS_LOG
GS_LOG("primTriangle%s%s %dx%dx%x %lx - %dx%dx%x %lx - %dx%dx%x %lx (offset %dx%d)\n",
prim->iip == 0 ? "F" : "G",
prim->tme == 0 ? "" : "T",
v[0].x, v[0].y, v[0].z, v[0].rgba,
v[1].x, v[1].y, v[1].z, v[1].rgba,
v[2].x, v[2].y, v[2].z, v[2].rgba,
offset->x, offset->y);
#endif
if (wireframe) {
drawLineF(&v[0]);
drawLineF(&v[1]);
memcpy(&v[1], &v[2], sizeof(Vertex));
drawLineF(&v[0]);
return;
}
if (prim->tme) {
if (tex0->tw == 0 || tex0->th == 0) return;
if (prim->fst == 0) {
#ifdef GS_LOG
GS_LOG("stq: %fx%fx%f - %fx%fx%f - %fx%fx%f (tex0.tw=%d, tex0.th=%d)\n",
*(float*)&v[0].s, *(float*)&v[0].t, *(float*)&v[0].q,
*(float*)&v[1].s, *(float*)&v[1].t, *(float*)&v[1].q,
*(float*)&v[2].s, *(float*)&v[2].t, *(float*)&v[2].q,
tex0->tw, tex0->th);
#endif
if (prim->iip) {
STQtoUV(&v[0], *(float*)&v[0].q);
STQtoUV(&v[1], *(float*)&v[1].q);
STQtoUV(&v[2], *(float*)&v[2].q);
} else {
STQtoUV(&v[0], *(float*)&gs.q);
STQtoUV(&v[1], *(float*)&gs.q);
STQtoUV(&v[2], *(float*)&gs.q);
}
}
#ifdef GS_LOG
GS_LOG("uv: %dx%d - %dx%d - %dx%d (tex0.tw=%d, tex0.th=%d)\n",
v[0].u, v[0].v,
v[1].u, v[1].v, v[2].u, v[2].v,
tex0->tw, tex0->th);
#endif
#ifdef GS_LOG
GS_LOG("uv: %dx%d - %dx%d - %dx%d (tex0.tw=%d, tex0.th=%d)\n",
v[0].u, v[0].v,
v[1].u, v[1].v, v[2].u, v[2].v,
tex0->tw, tex0->th);
#endif
if (prim->iip) {
if (test->zte) {
switch (tex0->tfx) {
case TEX_DECAL: drawTriangleGTDecal_Z(v); break;
case TEX_MODULATE: drawTriangleGTModulate_Z(v); break;
case TEX_HIGHLIGHT: drawTriangleGTHighlight_Z(v); break;
case TEX_HIGHLIGHT2: drawTriangleGTHighlight2_Z(v); break;
}
} else {
switch (tex0->tfx) {
case TEX_DECAL: drawTriangleGTDecal(v); break;
case TEX_MODULATE: drawTriangleGTModulate(v); break;
case TEX_HIGHLIGHT: drawTriangleGTHighlight(v); break;
case TEX_HIGHLIGHT2: drawTriangleGTHighlight2(v); break;
}
}
} else {
if(test->zte) {
switch (tex0->tfx) {
case TEX_DECAL: drawTriangleFTDecal_Z(v); break;
case TEX_MODULATE: drawTriangleFTModulate_Z(v); break;
case TEX_HIGHLIGHT: drawTriangleFTHighlight_Z(v); break;
case TEX_HIGHLIGHT2: drawTriangleFTHighlight2_Z(v); break;
}
} else {
switch (tex0->tfx) {
case TEX_DECAL: drawTriangleFTDecal(v); break;
case TEX_MODULATE: drawTriangleFTModulate(v); break;
case TEX_HIGHLIGHT: drawTriangleFTHighlight(v); break;
case TEX_HIGHLIGHT2: drawTriangleFTHighlight2(v); break;
}
}
}
} else {
if (prim->iip) {
if(test->zte)
drawTriangleG_Z(v);
else
drawTriangleG(v);
} else {
if(test->zte)
drawTriangleF_Z(v);
else
drawTriangleF(v);
}
}
}
void primTriangle(Vertex *vertex) {
if (vertex && norender == 0) _primTriangle(vertex);
memset(gs.gsvertex, 0, sizeof(Vertex)*3);
gs.primC = 0;
// if (conf.log) { DXupdate(); Sleep(250); }
}
void primTriangleStrip(Vertex *vertex) {
if (vertex && norender == 0) _primTriangle(vertex);
stepGSvertex();
// if (conf.log) { DXupdate(); Sleep(250); }
}
void primTriangleFan(Vertex *vertex) {
if (vertex && norender == 0) _primTriangle(vertex);
stepGSfanvertex();
// if (conf.log) { DXupdate(); Sleep(250); }
}
void _primSprite(Vertex *vertex) {
Vertex v[2];
memcpy(v, vertex, sizeof(Vertex) * 2);
#ifdef GS_LOG
GS_LOG("primSprite%s %dx%d %lx - %dx%d %lx (offset %dx%d) (tex %dx%d %dx%d)\n",
prim->tme == 0 ? "" : "T",
v[0].x, v[0].y, v[0].rgba,
v[1].x, v[1].y, v[1].rgba,
offset->x, offset->y,
v[0].u, v[0].v,
v[1].u, v[1].v);
#endif
v[0].x -= offset->x; v[0].y -= offset->y;
v[1].x -= offset->x; v[1].y -= offset->y;
if (v[0].x > v[1].x) {
int x;
x = v[0].x; v[0].x = v[1].x; v[1].x = x;
if (prim->tme) {
float f;
x = v[0].u; v[0].u = v[1].u; v[1].u = x;
f = v[0].s; v[0].s = v[1].s; v[1].s = f;
}
}
if (v[0].y > v[1].y) {
int y;
y = v[0].y; v[0].y = v[1].y; v[1].y = y;
if (prim->tme) {
float f;
y = v[0].v; v[0].v = v[1].v; v[1].v = y;
f = v[0].t; v[0].t = v[1].t; v[1].t = f;
}
}
if (prim->tme) {
if (tex0->tw == 0 || tex0->th == 0) return;
if (prim->fst == 0) {
STQtoUV(&v[0], *(float*)&gs.q);
STQtoUV(&v[1], *(float*)&gs.q);
}
if(test->zte) { // If z buffer enabled
switch (tex0->tfx) {
case TEX_DECAL: drawSpriteTDecal_Z(v); break;
case TEX_MODULATE: drawSpriteTModulate_Z(v); break;
case TEX_HIGHLIGHT: drawSpriteTHighlight_Z(v); break;
case TEX_HIGHLIGHT2: drawSpriteTHighlight2_Z(v); break;
}
} else {
switch (tex0->tfx) {
case TEX_DECAL: drawSpriteTDecal(v); break;
case TEX_MODULATE: drawSpriteTModulate(v); break;
case TEX_HIGHLIGHT: drawSpriteTHighlight(v); break;
case TEX_HIGHLIGHT2: drawSpriteTHighlight2(v); break;
}
}
} else {
if(test->zte) // If z buffer enabled
drawSprite_Z(v);
else
drawSprite(v);
}
}
void primSprite(Vertex *vertex) {
if (vertex && norender == 0) _primSprite(vertex);
memset(gs.gsvertex, 0, sizeof(Vertex)*2);
gs.primC = 0;
// if (conf.log) { DXupdate(); Sleep(250); }
}
void primNull(Vertex *v) {
}
void (*primTable[8])(Vertex *v) = {
primPoint, primLine, primLineStrip,
primTriangle, primTriangleStrip, primTriangleFan,
primSprite, primNull
};