mirror of
https://github.com/PCSX2/pcsx2-sourceforge.git
synced 2026-02-12 15:20:54 +01:00
391 lines
9.9 KiB
C
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
|
|
};
|