DS GX: Pay down tech debt around coordinates
@@ -109,9 +109,7 @@ #pragma pack(pop)
struct DSGXVertex { // World coords - int16_t x; // 4.12 - int16_t y; // 4.12 - int16_t z; // 4.12 + int16_t coord[3]; // 4.12 // Color/Texcoords uint16_t color; // 5.5.5@@ -119,10 +117,7 @@ int16_t s; // 12.4
int16_t t; // 12.4 // Viewport coords - int32_t vx; - int32_t vy; - int32_t vz; - int32_t vw; + int32_t viewCoord[4]; int16_t vs; // 12.4 int16_t vt; // 12.4 };
@@ -49,9 +49,7 @@ int16_t t1;
}; struct DSGXSoftwareEndpoint { - int32_t x; // 20.12 - int32_t z; - int32_t w; + int32_t coord[4]; // 20.12 int64_t wRecip; uint8_t cr; uint8_t cg;@@ -91,7 +89,7 @@ int32_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
uint8_t stencilBuffer[DS_VIDEO_HORIZONTAL_PIXELS]; color_t* scanlineCache; bool flushPending; - bool wSort; + int sort; struct DSGXVertex* verts; };
@@ -25,15 +25,6 @@ static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry);
static bool _boxTestVertex(struct DSGX* gx, struct DSGXVertex* vertex); -enum CSCode { - CS_LEFT = 1, - CS_RIGHT = 2, - CS_BOTTOM = 4, - CS_TOP = 8, - CS_NEAR = 16, - CS_FAR = 32 -}; - static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = { [DS_GX_CMD_NOP] = 0, [DS_GX_CMD_MTX_MODE] = 2,@@ -195,22 +186,22 @@ x += x0;
return x; } -static int _cohenSutherlandCode(const struct DSGX* gx, const struct DSGXVertex* v) { +static int _cohenSutherlandCode(const struct DSGXVertex* v) { int code = 0; - if (v->vx < -v->vw) { - code |= CS_LEFT; - } else if (v->vx > v->vw) { - code |= CS_RIGHT; + if (v->viewCoord[0] < -v->viewCoord[3]) { + code |= 1 << 0; + } else if (v->viewCoord[0] > v->viewCoord[3]) { + code |= 2 << 0; } - if (v->vy < -v->vw) { - code |= CS_BOTTOM; - } else if (v->vy > v->vw) { - code |= CS_TOP; + if (v->viewCoord[1] < -v->viewCoord[3]) { + code |= 1 << 2; + } else if (v->viewCoord[1] > v->viewCoord[3]) { + code |= 2 << 2; } - if (v->vz < -v->vw) { - code |= CS_NEAR; - } else if (v->vz > v->vw) { - code |= CS_FAR; + if (v->viewCoord[2] < -v->viewCoord[3]) { + code |= 1 << 4; + } else if (v->viewCoord[2] > v->viewCoord[3]) { + code |= 2 << 4; } return code; }@@ -230,31 +221,19 @@ cg0 = _lerp(cg0, cg1, q, r) & 0x1F;
cb0 = _lerp(cb0, cb1, q, r) & 0x1F; out->color = cr0 | (cg0 << 5) | (cb0 << 10); - out->vx = _lerp(v0->vx, v1->vx, q, r); - out->vy = _lerp(v0->vy, v1->vy, q, r); - out->vz = _lerp(v0->vz, v1->vz, q, r); - out->vw = _lerp(v0->vw, v1->vw, q, r); + out->viewCoord[0] = _lerp(v0->viewCoord[0], v1->viewCoord[0], q, r); + out->viewCoord[1] = _lerp(v0->viewCoord[1], v1->viewCoord[1], q, r); + out->viewCoord[2] = _lerp(v0->viewCoord[2], v1->viewCoord[2], q, r); + out->viewCoord[3] = _lerp(v0->viewCoord[3], v1->viewCoord[3], q, r); out->vs = _lerp(v0->vs, v1->vs, q, r); out->vt = _lerp(v0->vt, v1->vt, q, r); return true; } -static bool _lerpVertexX(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) { - int32_t q = v0->vw - sign * v0->vx; - int64_t r = q - (v1->vw - sign * v1->vx); - return _lerpVertex(v0, v1, out, q, r); -} - -static bool _lerpVertexY(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) { - int32_t q = v0->vw - sign * v0->vy; - int64_t r = q - (v1->vw - sign * v1->vy); - return _lerpVertex(v0, v1, out, q, r); -} - -static bool _lerpVertexZ(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) { - int32_t q = v0->vw - sign * v0->vz; - int64_t r = q - (v1->vw - sign * v1->vz); +static bool _lerpVertexP(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int plane, int sign) { + int32_t q = v0->viewCoord[3] - sign * v0->viewCoord[plane]; + int64_t r = q - (v1->viewCoord[3] - sign * v1->viewCoord[plane]); return _lerpVertex(v0, v1, out, q, r); }@@ -284,10 +263,10 @@ } else {
v1 = &gx->pendingVertices[poly->vertIds[v + 1 - poly->verts]]; v2 = &gx->pendingVertices[poly->vertIds[v + 2 - poly->verts]]; } - nx = ((int64_t) v0->vy * v2->vw - (int64_t) v0->vw * v2->vy) >> 24; - ny = ((int64_t) v0->vw * v2->vx - (int64_t) v0->vx * v2->vw) >> 24; - nz = ((int64_t) v0->vx * v2->vy - (int64_t) v0->vy * v2->vx) >> 24; - dot += nx * v1->vx + ny * v1->vy + nz * v1->vw; + nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]) >> 24; + ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]) >> 24; + nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]) >> 24; + dot += nx * v1->viewCoord[0] + ny * v1->viewCoord[1] + nz * v1->viewCoord[3]; } if (!DSGXPolygonAttrsIsBackFace(poly->polyParams) && dot < 0) { return false;@@ -299,7 +278,7 @@ }
// Collect offscreen vertices for (v = 0; v < poly->verts; ++v) { - offscreenVerts[v] = _cohenSutherlandCode(gx, &gx->pendingVertices[poly->vertIds[v]]); + offscreenVerts[v] = _cohenSutherlandCode(&gx->pendingVertices[poly->vertIds[v]]); oldVerts[v] = poly->vertIds[v]; if (offscreenVerts[v]) { ++nOffscreen;@@ -335,61 +314,11 @@ }
int newV; - // Clip near - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_NEAR)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - struct DSGXVertex* in = &inList[v]; - struct DSGXVertex* in2; - struct DSGXVertex* out; - int iv; - - if (v > 0) { - iv = v - 1; - } else { - iv = poly->verts - 1; - } - if (!(offscreenVerts[iv] & CS_NEAR)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexZ(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - - if (v < poly->verts - 1) { - iv = v + 1; - } else { - iv = 0; - } - if (!(offscreenVerts[iv] & CS_NEAR)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexZ(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - } - } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); - - // Clip far - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_FAR)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - if (!(offscreenVerts[v] & CS_NEAR)) { + int plane; + for (plane = 5; plane >= 0; --plane) { + newV = 0; + for (v = 0; v < poly->verts; ++v) { + if (!(offscreenVerts[v] & (1 << plane))) { outList[newV] = inList[v]; outOffscreenVerts[newV] = offscreenVerts[v]; ++newV;@@ -404,11 +333,11 @@ iv = v - 1;
} else { iv = poly->verts - 1; } - if (!(offscreenVerts[iv] & CS_FAR)) { + if (!(offscreenVerts[iv] & (1 << plane))) { in2 = &inList[iv]; out = &outList[newV]; - if (_lerpVertexZ(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); + if (_lerpVertexP(in, in2, out, plane >> 1, -1 + (plane & 1) * 2)) { + outOffscreenVerts[newV] = _cohenSutherlandCode(out); ++newV; } }@@ -418,204 +347,20 @@ iv = v + 1;
} else { iv = 0; } - if (!(offscreenVerts[iv] & CS_FAR)) { + if (!(offscreenVerts[iv] & (1 << plane))) { in2 = &inList[iv]; out = &outList[newV]; - if (_lerpVertexZ(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); + if (_lerpVertexP(in, in2, out, plane >> 1, -1 + (plane & 1) * 2)) { + outOffscreenVerts[newV] = _cohenSutherlandCode(out); ++newV; } } } } + poly->verts = newV; + memcpy(inList, outList, newV * sizeof(*inList)); + memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); - - // Clip left - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_LEFT)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - struct DSGXVertex* in = &inList[v]; - struct DSGXVertex* in2; - struct DSGXVertex* out; - int iv; - - if (v > 0) { - iv = v - 1; - } else { - iv = poly->verts - 1; - } - if (!(offscreenVerts[iv] & CS_LEFT)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexX(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - - if (v < poly->verts - 1) { - iv = v + 1; - } else { - iv = 0; - } - if (!(offscreenVerts[iv] & CS_LEFT)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexX(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - } - } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); - - // Clip right - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_RIGHT)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - struct DSGXVertex* in = &inList[v]; - struct DSGXVertex* in2; - struct DSGXVertex* out; - int iv; - - if (v > 0) { - iv = v - 1; - } else { - iv = poly->verts - 1; - } - if (!(offscreenVerts[iv] & CS_RIGHT)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexX(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - - if (v < poly->verts - 1) { - iv = v + 1; - } else { - iv = 0; - } - if (!(offscreenVerts[iv] & CS_RIGHT)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexX(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - } - } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); - - // Clip bottom - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_BOTTOM)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - struct DSGXVertex* in = &inList[v]; - struct DSGXVertex* in2; - struct DSGXVertex* out; - int iv; - - if (v > 0) { - iv = v - 1; - } else { - iv = poly->verts - 1; - } - if (!(offscreenVerts[iv] & CS_BOTTOM)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexY(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - - if (v < poly->verts - 1) { - iv = v + 1; - } else { - iv = 0; - } - if (!(offscreenVerts[iv] & CS_BOTTOM)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexY(in, in2, out, -1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - } - } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); - - // Clip top - newV = 0; - for (v = 0; v < poly->verts; ++v) { - if (!(offscreenVerts[v] & CS_TOP)) { - outList[newV] = inList[v]; - outOffscreenVerts[newV] = offscreenVerts[v]; - ++newV; - } else { - struct DSGXVertex* in = &inList[v]; - struct DSGXVertex* in2; - struct DSGXVertex* out; - int iv; - - if (v > 0) { - iv = v - 1; - } else { - iv = poly->verts - 1; - } - if (!(offscreenVerts[iv] & CS_TOP)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexY(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - - if (v < poly->verts - 1) { - iv = v + 1; - } else { - iv = 0; - } - if (!(offscreenVerts[iv] & CS_TOP)) { - in2 = &inList[iv]; - out = &outList[newV]; - if (_lerpVertexY(in, in2, out, 1)) { - outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out); - ++newV; - } - } - } - } - poly->verts = newV; - memcpy(inList, outList, newV * sizeof(*inList)); - memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts)); for (v = 0; v < poly->verts; ++v) { if (gx->vertexIndex == DS_GX_VERTEX_BUFFER_SIZE) {@@ -635,13 +380,13 @@ int64_t a;
int64_t b; int64_t sum; a = col[0]; - b = vertex->x; + b = vertex->coord[0]; sum = a * b; a = col[4]; - b = vertex->y; + b = vertex->coord[1]; sum += a * b; a = col[8]; - b = vertex->z; + b = vertex->coord[2]; sum += a * b; a = col[12]; b = MTX_ONE;@@ -672,13 +417,13 @@ case 2:
return 0; case 3: a = col[0]; - b = vertex->vx << 8; + b = vertex->viewCoord[0] << 8; sum = a * b; a = col[4]; - b = vertex->vy << 8; + b = vertex->viewCoord[1] << 8; sum += a * b; a = col[8]; - b = vertex->vz << 8; + b = vertex->viewCoord[2] << 8; sum += a * b; a = col[12]; b = MTX_ONE;@@ -720,13 +465,13 @@ static void _emitVertex(struct DSGX* gx, uint16_t x, uint16_t y, uint16_t z) {
if (gx->vertexMode < 0 || gx->vertexIndex == DS_GX_VERTEX_BUFFER_SIZE || gx->polygonIndex == DS_GX_POLYGON_BUFFER_SIZE) { return; } - gx->currentVertex.x = x; - gx->currentVertex.y = y; - gx->currentVertex.z = z; - gx->currentVertex.vx = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[0]); - gx->currentVertex.vy = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[1]); - gx->currentVertex.vz = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[2]); - gx->currentVertex.vw = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[3]); + gx->currentVertex.coord[0] = x; + gx->currentVertex.coord[1] = y; + gx->currentVertex.coord[2] = z; + gx->currentVertex.viewCoord[0] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[0]); + gx->currentVertex.viewCoord[1] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[1]); + gx->currentVertex.viewCoord[2] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[2]); + gx->currentVertex.viewCoord[3] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[3]); if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) == 0) { gx->currentVertex.vs = gx->currentVertex.s;@@ -861,49 +606,47 @@ int16_t d = gx->activeEntries[2].params[2];
d |= gx->activeEntries[2].params[3] << 8; struct DSGXVertex vertex = { - .x = x, - .y = y, - .z = z + .coord = { x, y, z } }; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x += w; + vertex.coord[0] += w; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x = x; - vertex.y += h; + vertex.coord[0] = x; + vertex.coord[1] += h; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x += w; + vertex.coord[0] += w; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x = x; - vertex.y = y; - vertex.z += d; + vertex.coord[0] = x; + vertex.coord[1] = y; + vertex.coord[2] += d; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x += w; + vertex.coord[0] += w; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x = x; - vertex.y += h; + vertex.coord[0] = x; + vertex.coord[1] += h; if (_boxTestVertex(gx, &vertex)) { return true; } - vertex.x += w; + vertex.coord[0] += w; if (_boxTestVertex(gx, &vertex)) { return true; }@@ -1391,7 +1134,7 @@ int16_t x = entry.params[0];
x |= entry.params[1] << 8; int16_t y = entry.params[2]; y |= entry.params[3] << 8; - _emitVertex(gx, x, y, gx->currentVertex.z); + _emitVertex(gx, x, y, gx->currentVertex.coord[2]); break; } case DS_GX_CMD_VTX_XZ: {@@ -1399,7 +1142,7 @@ int16_t x = entry.params[0];
x |= entry.params[1] << 8; int16_t z = entry.params[2]; z |= entry.params[3] << 8; - _emitVertex(gx, x, gx->currentVertex.y, z); + _emitVertex(gx, x, gx->currentVertex.coord[1], z); break; } case DS_GX_CMD_VTX_YZ: {@@ -1407,7 +1150,7 @@ int16_t y = entry.params[0];
y |= entry.params[1] << 8; int16_t z = entry.params[2]; z |= entry.params[3] << 8; - _emitVertex(gx, gx->currentVertex.x, y, z); + _emitVertex(gx, gx->currentVertex.coord[0], y, z); break; } case DS_GX_CMD_VTX_DIFF: {@@ -1418,7 +1161,9 @@ xyz |= entry.params[3] << 24;
int16_t x = (xyz << 6) & 0xFFC0; int16_t y = (xyz >> 4) & 0xFFC0; int16_t z = (xyz >> 14) & 0xFFC0; - _emitVertex(gx, gx->currentVertex.x + (x >> 6), gx->currentVertex.y + (y >> 6), gx->currentVertex.z + (z >> 6)); + _emitVertex(gx, gx->currentVertex.coord[0] + (x >> 6), + gx->currentVertex.coord[1] + (y >> 6), + gx->currentVertex.coord[2] + (z >> 6)); break; } case DS_GX_CMD_DIF_AMB:
@@ -300,16 +300,16 @@ } else if (yw > height) {
return false; } - span->ep[index].x = (((int64_t) (edge->x1 - edge->x0) * yw) / height) + edge->x0; + span->ep[index].coord[0] = (((int64_t) (edge->x1 - edge->x0) * yw) / height) + edge->x0; if (index) { - if (span->ep[0].x == span->ep[index].x) { + if (span->ep[0].coord[0] == span->ep[index].coord[0]) { return false; } - if (span->ep[0].x > span->ep[index].x) { - int32_t temp = span->ep[index].x; + if (span->ep[0].coord[0] > span->ep[index].coord[0]) { + int32_t temp = span->ep[index].coord[0]; span->ep[index] = span->ep[0]; - span->ep[0].x = temp; + span->ep[0].coord[0] = temp; index = 0; } }@@ -329,11 +329,11 @@ div = wb / height;
w += div; w += w0; - span->ep[index].w = 0x7FFFFFFFFFFFFFFF / w; + span->ep[index].coord[3] = 0x7FFFFFFFFFFFFFFF / w; span->ep[index].wRecip = w; int32_t qr = (yw << 12) / height; - span->ep[index].z = _interpolate(edge->z0, edge->z1, w0, w1, w, qr); + span->ep[index].coord[2] = _interpolate(edge->z0, edge->z1, w0, w1, w, qr); span->ep[index].cr = _interpolate(edge->cr0, edge->cr1, w0, w1, w, qr); span->ep[index].cg = _interpolate(edge->cg0, edge->cg1, w0, w1, w, qr); span->ep[index].cb = _interpolate(edge->cb0, edge->cb1, w0, w1, w, qr);@@ -344,10 +344,10 @@ return true;
} static void _createStep(struct DSGXSoftwareSpan* span) { - int32_t width = (span->ep[1].x - span->ep[0].x) >> 7; + int32_t width = (span->ep[1].coord[0] - span->ep[0].coord[0]) >> 7; span->ep[0].stepW = span->ep[0].wRecip; - span->ep[0].stepZ = span->ep[0].z * span->ep[0].wRecip; + span->ep[0].stepZ = span->ep[0].coord[2] * span->ep[0].wRecip; span->ep[0].stepR = span->ep[0].cr * span->ep[0].wRecip; span->ep[0].stepG = span->ep[0].cg * span->ep[0].wRecip; span->ep[0].stepB = span->ep[0].cb * span->ep[0].wRecip;@@ -355,7 +355,7 @@ span->ep[0].stepS = span->ep[0].s * span->ep[0].wRecip;
span->ep[0].stepT = span->ep[0].t * span->ep[0].wRecip; span->ep[1].stepW = span->ep[1].wRecip; - span->ep[1].stepZ = span->ep[1].z * span->ep[1].wRecip; + span->ep[1].stepZ = span->ep[1].coord[2] * span->ep[1].wRecip; span->ep[1].stepR = span->ep[1].cr * span->ep[1].wRecip; span->ep[1].stepG = span->ep[1].cg * span->ep[1].wRecip; span->ep[1].stepB = span->ep[1].cb * span->ep[1].wRecip;@@ -365,7 +365,7 @@
if (!width) { return; } - span->step.x = span->ep[1].x - span->ep[0].x; + span->step.coord[0] = span->ep[1].coord[0] - span->ep[0].coord[0]; span->step.stepW = (span->ep[1].stepW - span->ep[0].stepW) / width; span->step.stepZ = (span->ep[1].stepZ - span->ep[0].stepZ) / width; span->step.stepR = (span->ep[1].stepR - span->ep[0].stepR) / width;@@ -377,32 +377,32 @@ }
static void _stepEndpoint(struct DSGXSoftwareSpan* span) { int i = 28; - int32_t nextX = (span->ep[0].x & ~0xFFF) + 0x1000; - span->ep[0].x += 0x80 * i; - while (span->ep[0].x < nextX) { - span->ep[0].x += 0x80; + int32_t nextX = (span->ep[0].coord[0] & ~0xFFF) + 0x1000; + span->ep[0].coord[0] += 0x80 * i; + while (span->ep[0].coord[0] < nextX) { + span->ep[0].coord[0] += 0x80; ++i; } span->ep[0].wRecip += span->step.stepW * i; - span->ep[0].w = (0x7FFFFFFFFFFFFFFF / span->ep[0].wRecip) + 1; + span->ep[0].coord[3] = (0x7FFFFFFFFFFFFFFF / span->ep[0].wRecip) + 1; span->ep[0].stepZ += span->step.stepZ * i; - span->ep[0].z = _divideBy(span->ep[0].stepZ, span->ep[0].w); + span->ep[0].coord[2] = _divideBy(span->ep[0].stepZ, span->ep[0].coord[3]); span->ep[0].stepR += span->step.stepR * i; - span->ep[0].cr = _divideBy(span->ep[0].stepR, span->ep[0].w); + span->ep[0].cr = _divideBy(span->ep[0].stepR, span->ep[0].coord[3]); span->ep[0].stepG += span->step.stepG * i; - span->ep[0].cg = _divideBy(span->ep[0].stepG, span->ep[0].w); + span->ep[0].cg = _divideBy(span->ep[0].stepG, span->ep[0].coord[3]); span->ep[0].stepB += span->step.stepB * i; - span->ep[0].cb = _divideBy(span->ep[0].stepB, span->ep[0].w); + span->ep[0].cb = _divideBy(span->ep[0].stepB, span->ep[0].coord[3]); span->ep[0].stepS += span->step.stepS * i; - span->ep[0].s = _divideBy(span->ep[0].stepS, span->ep[0].w); + span->ep[0].s = _divideBy(span->ep[0].stepS, span->ep[0].coord[3]); span->ep[0].stepT += span->step.stepT * i; - span->ep[0].t = _divideBy(span->ep[0].stepT, span->ep[0].w); + span->ep[0].t = _divideBy(span->ep[0].stepT, span->ep[0].coord[3]); } void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {@@ -475,44 +475,44 @@
struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]]; struct DSGXVertex* v1; - int32_t v0x = (v0->vx + v0->vw) * (int64_t) (renderer->viewportWidth << 12) / (v0->vw * 2) + (renderer->viewportX << 12); - int32_t v0y = (-v0->vy + v0->vw) * (int64_t) (renderer->viewportHeight << 12) / (v0->vw * 2) + (renderer->viewportY << 12); + int32_t v0x = (v0->viewCoord[0] + v0->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v0->viewCoord[3] * 2) + (renderer->viewportX << 12); + int32_t v0y = (-v0->viewCoord[1] + v0->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v0->viewCoord[3] * 2) + (renderer->viewportY << 12); int v; for (v = 1; v < poly->poly->verts; ++v) { v1 = &verts[poly->poly->vertIds[v]]; - int32_t v1x = (v1->vx + v1->vw) * (int64_t) (renderer->viewportWidth << 12) / (v1->vw * 2) + (renderer->viewportX << 12); - int32_t v1y = (-v1->vy + v1->vw) * (int64_t) (renderer->viewportHeight << 12) / (v1->vw * 2) + (renderer->viewportY << 12); + int32_t v1x = (v1->viewCoord[0] + v1->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportX << 12); + int32_t v1y = (-v1->viewCoord[1] + v1->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportY << 12); if (v0y <= v1y) { edge->y0 = v0y; edge->x0 = v0x; - edge->z0 = v0->vz; - edge->w0 = v0->vw; + edge->z0 = v0->viewCoord[2]; + edge->w0 = v0->viewCoord[3]; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs; edge->t0 = v0->vt; edge->y1 = v1y; edge->x1 = v1x; - edge->z1 = v1->vz; - edge->w1 = v1->vw; + edge->z1 = v1->viewCoord[2]; + edge->w1 = v1->viewCoord[3]; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs; edge->t1 = v1->vt; } else { edge->y0 = v1y; edge->x0 = v1x; - edge->z0 = v1->vz; - edge->w0 = v1->vw; + edge->z0 = v1->viewCoord[2]; + edge->w0 = v1->viewCoord[3]; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs; edge->t0 = v1->vt; edge->y1 = v0y; edge->x1 = v0x; - edge->z1 = v0->vz; - edge->w1 = v0->vw; + edge->z1 = v0->viewCoord[2]; + edge->w1 = v0->viewCoord[3]; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs; edge->t1 = v0->vt;@@ -526,38 +526,38 @@ v0y = v1y;
} v1 = &verts[poly->poly->vertIds[0]]; - int32_t v1x = (v1->vx + v1->vw) * (int64_t) (renderer->viewportWidth << 12) / (v1->vw * 2) + (renderer->viewportX << 12); - int32_t v1y = (-v1->vy + v1->vw) * (int64_t) (renderer->viewportHeight << 12) / (v1->vw * 2) + (renderer->viewportY << 12); + int32_t v1x = (v1->viewCoord[0] + v1->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportX << 12); + int32_t v1y = (-v1->viewCoord[1] + v1->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportY << 12); if (v0y <= v1y) { edge->y0 = v0y; edge->x0 = v0x; - edge->z0 = v0->vz; - edge->w0 = v0->vw; + edge->z0 = v0->viewCoord[2]; + edge->w0 = v0->viewCoord[3]; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs; edge->t0 = v0->vt; edge->y1 = v1y; edge->x1 = v1x; - edge->z1 = v1->vz; - edge->w1 = v1->vw; + edge->z1 = v1->viewCoord[2]; + edge->w1 = v1->viewCoord[3]; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs; edge->t1 = v1->vt; } else { edge->y0 = v1y; edge->x0 = v1x; - edge->z0 = v1->vz; - edge->w0 = v1->vw; + edge->z0 = v1->viewCoord[2]; + edge->w0 = v1->viewCoord[3]; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs; edge->t0 = v1->vt; edge->y1 = v0y; edge->x1 = v0x; - edge->z1 = v0->vz; - edge->w1 = v0->vw; + edge->z1 = v0->viewCoord[2]; + edge->w1 = v0->viewCoord[3]; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs; edge->t1 = v0->vt;@@ -568,7 +568,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; softwareRenderer->flushPending = true; - softwareRenderer->wSort = wSort; + softwareRenderer->sort = wSort ? 3 : 2; softwareRenderer->verts = verts; DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys); DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);@@ -631,7 +631,7 @@ }
unsigned poly = edge->polyId; struct DSGXSoftwareSpan* span = softwareRenderer->bucket[poly]; - if (span && !span->ep[1].w) { + if (span && !span->ep[1].coord[3]) { if (_edgeToSpan(span, edge, 1, y << 12)) { _createStep(span); softwareRenderer->bucket[poly] = NULL;@@ -663,11 +663,11 @@
for (i = 0; i < DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans); ++i) { struct DSGXSoftwareSpan* span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, i); - int32_t x = span->ep[0].x >> 12; + int32_t x = span->ep[0].coord[0] >> 12; if (x < 0) { x = 0; } - for (; x < (span->ep[1].x >> 12) && x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) { + for (; x < (span->ep[1].coord[0] >> 12) && x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) { color_t color = _lookupColor(softwareRenderer, &span->ep[0], span->poly); _stepEndpoint(span); unsigned a = color >> 27;@@ -682,24 +682,13 @@ if (span->poly->blendFormat == 3) {
s |= 0x40; } if (a == 0x1F) { - if (softwareRenderer->wSort) { - if (span->ep[0].w < softwareRenderer->depthBuffer[x]) { - if (!(s & 0x40) || !(softwareRenderer->stencilBuffer[x] & s & 0x40)) { - softwareRenderer->depthBuffer[x] = span->ep[0].w; - scanline[x] = color; - s &= ~0x40; - } - softwareRenderer->stencilBuffer[x] = s; + if (span->ep[0].coord[softwareRenderer->sort] < softwareRenderer->depthBuffer[x]) { + if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) { + softwareRenderer->depthBuffer[x] = span->ep[0].coord[softwareRenderer->sort]; + scanline[x] = color; + s &= ~0x40; } - } else { - if (span->ep[0].z < softwareRenderer->depthBuffer[x]) { - if (!(s & 0x40) || !(softwareRenderer->stencilBuffer[x] & s & 0x40)) { - softwareRenderer->depthBuffer[x] = span->ep[0].z; - scanline[x] = color; - s &= ~0x40; - } - softwareRenderer->stencilBuffer[x] = s; - } + softwareRenderer->stencilBuffer[x] = s; } } else if (a) { // TODO: Disable alpha?@@ -708,28 +697,15 @@ color = _mix32(a, color, 0x1F - a, current);
color |= ab << 27; } if (softwareRenderer->stencilBuffer[x] != s) { - if (softwareRenderer->wSort) { - if (span->ep[0].w < softwareRenderer->depthBuffer[x]) { - if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) { - if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) { - softwareRenderer->depthBuffer[x] = span->ep[0].w; - } - scanline[x] = color; - s &= ~0x40; - } - softwareRenderer->stencilBuffer[x] = s; - } - } else { - if (span->ep[0].z < softwareRenderer->depthBuffer[x]) { - if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) { - if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) { - softwareRenderer->depthBuffer[x] = span->ep[0].z; - } - scanline[x] = color; - s &= ~0x40; + if (span->ep[0].coord[softwareRenderer->sort] < softwareRenderer->depthBuffer[x]) { + if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) { + if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) { + softwareRenderer->depthBuffer[x] = span->ep[0].coord[softwareRenderer->sort]; } - softwareRenderer->stencilBuffer[x] = s; + scanline[x] = color; + s &= ~0x40; } + softwareRenderer->stencilBuffer[x] = s; } } }