mirror of https://github.com/mgba-emu/mgba.git
DS GX: First pass at textures
This commit is contained in:
parent
4061d4d39c
commit
4320669d21
|
@ -35,6 +35,18 @@ DECL_BIT(DSRegGXSTAT, FIFOEmpty, 26);
|
|||
DECL_BIT(DSRegGXSTAT, Busy, 27);
|
||||
DECL_BITS(DSRegGXSTAT, DoIRQ, 30, 2);
|
||||
|
||||
DECL_BITFIELD(DSGXTexParams, uint32_t);
|
||||
DECL_BITS(DSGXTexParams, VRAMBase, 0, 16);
|
||||
DECL_BIT(DSGXTexParams, SRepeat, 16);
|
||||
DECL_BIT(DSGXTexParams, TRepeat, 17);
|
||||
DECL_BIT(DSGXTexParams, SMirror, 18);
|
||||
DECL_BIT(DSGXTexParams, TMirror, 19);
|
||||
DECL_BITS(DSGXTexParams, SSize, 20, 3);
|
||||
DECL_BITS(DSGXTexParams, TSize, 23, 3);
|
||||
DECL_BITS(DSGXTexParams, Format, 26, 3);
|
||||
DECL_BIT(DSGXTexParams, 0Transparent, 29);
|
||||
DECL_BITS(DSGXTexParams, CoordTfMode, 30, 2);
|
||||
|
||||
enum DSGXCommand {
|
||||
DS_GX_CMD_NOP = 0,
|
||||
DS_GX_CMD_MTX_MODE = 0x10,
|
||||
|
@ -91,20 +103,24 @@ struct DSGXVertex {
|
|||
int16_t y; // 4.12
|
||||
int16_t z; // 4.12
|
||||
|
||||
// Viewport coords
|
||||
int32_t vx; // 16.16
|
||||
int32_t vy; // 16.16
|
||||
int32_t vz; // 16.16
|
||||
int32_t vw; // 16.16
|
||||
|
||||
// Color/Texcoords
|
||||
uint16_t color; // 5.5.5
|
||||
int16_t s; // 12.4
|
||||
int16_t t; // 12.4
|
||||
|
||||
// Viewport coords
|
||||
int32_t vx;
|
||||
int32_t vy;
|
||||
int32_t vz;
|
||||
int32_t vw;
|
||||
int16_t vs; // 12.4
|
||||
int16_t vt; // 12.4
|
||||
};
|
||||
|
||||
struct DSGXPolygon {
|
||||
uint32_t polyParams;
|
||||
DSGXTexParams texParams;
|
||||
uint32_t palBase;
|
||||
int verts;
|
||||
unsigned vertIds[4];
|
||||
};
|
||||
|
@ -114,9 +130,13 @@ struct DSGXRenderer {
|
|||
void (*reset)(struct DSGXRenderer* renderer);
|
||||
void (*deinit)(struct DSGXRenderer* renderer);
|
||||
|
||||
void (*invalidateTex)(struct DSGXRenderer* renderer, int slot);
|
||||
void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
|
||||
void (*drawScanline)(struct DSGXRenderer* renderer, int y);
|
||||
void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output);
|
||||
|
||||
uint16_t* tex[4];
|
||||
uint16_t* texPal[6];
|
||||
};
|
||||
|
||||
struct DS;
|
||||
|
@ -142,6 +162,9 @@ struct DSGX {
|
|||
struct DSGXVertex* vertexBuffer[2];
|
||||
struct DSGXPolygon* polygonBuffer[2];
|
||||
|
||||
uint16_t* tex[4];
|
||||
uint16_t* texPal[6];
|
||||
|
||||
int mtxMode;
|
||||
int pvMatrixPointer;
|
||||
struct DSGXMatrix projMatrixStack;
|
||||
|
@ -165,6 +188,7 @@ struct DSGX {
|
|||
|
||||
int vertexMode;
|
||||
struct DSGXVertex currentVertex;
|
||||
struct DSGXPolygon nextPoly;
|
||||
struct DSGXPolygon currentPoly;
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,11 @@ CXX_GUARD_START
|
|||
|
||||
struct DSGXSoftwarePolygon {
|
||||
struct DSGXPolygon* poly;
|
||||
uint16_t* texBase;
|
||||
uint16_t* palBase;
|
||||
int texFormat;
|
||||
unsigned texW;
|
||||
unsigned texH;
|
||||
int32_t topY;
|
||||
int32_t bottomY;
|
||||
int32_t topZ;
|
||||
|
@ -54,6 +59,7 @@ struct DSGXSoftwareEndpoint {
|
|||
};
|
||||
|
||||
struct DSGXSoftwareSpan {
|
||||
struct DSGXSoftwarePolygon* poly;
|
||||
struct DSGXSoftwareEndpoint ep[2];
|
||||
};
|
||||
|
||||
|
|
87
src/ds/gx.c
87
src/ds/gx.c
|
@ -16,6 +16,7 @@ mLOG_DEFINE_CATEGORY(DS_GX, "DS GX");
|
|||
static void DSGXDummyRendererInit(struct DSGXRenderer* renderer);
|
||||
static void DSGXDummyRendererReset(struct DSGXRenderer* renderer);
|
||||
static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer);
|
||||
static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int slot);
|
||||
static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
|
||||
static void DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y);
|
||||
static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);
|
||||
|
@ -104,6 +105,7 @@ static struct DSGXRenderer dummyRenderer = {
|
|||
.init = DSGXDummyRendererInit,
|
||||
.reset = DSGXDummyRendererReset,
|
||||
.deinit = DSGXDummyRendererDeinit,
|
||||
.invalidateTex = DSGXDummyRendererInvalidateTex,
|
||||
.setRAM = DSGXDummyRendererSetRAM,
|
||||
.drawScanline = DSGXDummyRendererDrawScanline,
|
||||
.getScanline = DSGXDummyRendererGetScanline,
|
||||
|
@ -161,6 +163,44 @@ static int32_t _dotViewport(struct DSGXVertex* vertex, int32_t* col) {
|
|||
return sum >> 8LL;
|
||||
}
|
||||
|
||||
static int16_t _dotTexture(struct DSGXVertex* vertex, int mode, int32_t* col) {
|
||||
int64_t a;
|
||||
int64_t b;
|
||||
int64_t sum;
|
||||
switch (mode) {
|
||||
case 1:
|
||||
a = col[0];
|
||||
b = vertex->s;
|
||||
sum = a * b;
|
||||
a = col[4];
|
||||
b = vertex->t;
|
||||
sum += a * b;
|
||||
a = col[8];
|
||||
b = MTX_ONE >> 4;
|
||||
sum += a * b;
|
||||
a = col[12];
|
||||
b = MTX_ONE >> 4;
|
||||
sum += a * b;
|
||||
break;
|
||||
case 2:
|
||||
return 0;
|
||||
case 3:
|
||||
a = col[0];
|
||||
b = vertex->vx;
|
||||
sum = a * b;
|
||||
a = col[4];
|
||||
b = vertex->vy;
|
||||
sum += a * b;
|
||||
a = col[8];
|
||||
b = vertex->vz;
|
||||
sum += a * b;
|
||||
a = col[12];
|
||||
b = MTX_ONE;
|
||||
sum += a * b;
|
||||
}
|
||||
return sum >> 12;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -179,6 +219,22 @@ static void _emitVertex(struct DSGX* gx, uint16_t x, uint16_t y, uint16_t z) {
|
|||
gx->currentVertex.vy = (gx->currentVertex.vy + gx->currentVertex.vw) * (int64_t) (gx->viewportHeight << 12) / (gx->currentVertex.vw * 2) + (gx->viewportY1 << 12);
|
||||
gx->currentVertex.vw = 0x40000000 / gx->currentVertex.vw;
|
||||
|
||||
if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) > 0) {
|
||||
int32_t m12 = gx->texMatrix.m[12];
|
||||
int32_t m13 = gx->texMatrix.m[13];
|
||||
if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) > 1) {
|
||||
gx->texMatrix.m[12] = gx->currentVertex.vs;
|
||||
gx->texMatrix.m[13] = gx->currentVertex.vt;
|
||||
}
|
||||
gx->currentVertex.vs = _dotTexture(&gx->currentVertex, DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams), &gx->texMatrix.m[0]);
|
||||
gx->currentVertex.vt = _dotTexture(&gx->currentVertex, DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams), &gx->texMatrix.m[1]);
|
||||
gx->texMatrix.m[12] = m12;
|
||||
gx->texMatrix.m[13] = m13;
|
||||
} else {
|
||||
gx->currentVertex.vs = gx->currentVertex.s;
|
||||
gx->currentVertex.vt = gx->currentVertex.t;
|
||||
}
|
||||
|
||||
struct DSGXVertex* vbuf = gx->vertexBuffer[gx->bufferIndex];
|
||||
vbuf[gx->vertexIndex] = gx->currentVertex;
|
||||
|
||||
|
@ -671,14 +727,26 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
|
|||
_emitVertex(gx, gx->currentVertex.x + (x >> 6), gx->currentVertex.y + (y >> 6), gx->currentVertex.z + (z >> 6));
|
||||
}
|
||||
case DS_GX_CMD_POLYGON_ATTR:
|
||||
gx->currentPoly.polyParams = entry.params[0];
|
||||
gx->currentPoly.polyParams |= entry.params[1] << 8;
|
||||
gx->currentPoly.polyParams |= entry.params[2] << 16;
|
||||
gx->currentPoly.polyParams |= entry.params[3] << 24;
|
||||
gx->nextPoly.polyParams = entry.params[0];
|
||||
gx->nextPoly.polyParams |= entry.params[1] << 8;
|
||||
gx->nextPoly.polyParams |= entry.params[2] << 16;
|
||||
gx->nextPoly.polyParams |= entry.params[3] << 24;
|
||||
break;
|
||||
case DS_GX_CMD_TEXIMAGE_PARAM:
|
||||
gx->nextPoly.texParams = entry.params[0];
|
||||
gx->nextPoly.texParams |= entry.params[1] << 8;
|
||||
gx->nextPoly.texParams |= entry.params[2] << 16;
|
||||
gx->nextPoly.texParams |= entry.params[3] << 24;
|
||||
break;
|
||||
case DS_GX_CMD_PLTT_BASE:
|
||||
gx->nextPoly.palBase = entry.params[0];
|
||||
gx->nextPoly.palBase |= entry.params[1] << 8;
|
||||
gx->nextPoly.palBase |= entry.params[2] << 16;
|
||||
gx->nextPoly.palBase |= entry.params[3] << 24;
|
||||
break;
|
||||
case DS_GX_CMD_BEGIN_VTXS:
|
||||
gx->vertexMode = entry.params[0] & 3;
|
||||
gx->currentPoly.verts = 0;
|
||||
gx->currentPoly = gx->nextPoly;
|
||||
break;
|
||||
case DS_GX_CMD_END_VTXS:
|
||||
gx->vertexMode = -1;
|
||||
|
@ -777,11 +845,14 @@ void DSGXReset(struct DSGX* gx) {
|
|||
memset(&gx->outstandingEntry, 0, sizeof(gx->outstandingEntry));
|
||||
gx->activeParams = 0;
|
||||
memset(&gx->currentVertex, 0, sizeof(gx->currentVertex));
|
||||
memset(&gx->nextPoly, 0, sizeof(gx-> nextPoly));
|
||||
}
|
||||
|
||||
void DSGXAssociateRenderer(struct DSGX* gx, struct DSGXRenderer* renderer) {
|
||||
gx->renderer->deinit(gx->renderer);
|
||||
gx->renderer = renderer;
|
||||
memcpy(gx->renderer->tex, gx->tex, sizeof(gx->renderer->tex));
|
||||
memcpy(gx->renderer->texPal, gx->texPal, sizeof(gx->renderer->texPal));
|
||||
gx->renderer->init(gx->renderer);
|
||||
}
|
||||
|
||||
|
@ -1009,6 +1080,12 @@ static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer) {
|
|||
// Nothing to do
|
||||
}
|
||||
|
||||
static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int slot) {
|
||||
UNUSED(renderer);
|
||||
UNUSED(slot);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
|
||||
UNUSED(renderer);
|
||||
UNUSED(verts);
|
||||
|
|
|
@ -17,6 +17,7 @@ DEFINE_VECTOR(DSGXSoftwareSpanList, struct DSGXSoftwareSpan);
|
|||
static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
|
||||
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
|
||||
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
|
||||
static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot);
|
||||
static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
|
||||
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y);
|
||||
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);
|
||||
|
@ -38,6 +39,73 @@ static color_t _finishColor(uint8_t r, uint8_t g, uint8_t b) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static color_t _lookupColor(struct DSGXSoftwareEndpoint* ep, struct DSGXSoftwarePolygon* poly) {
|
||||
// TODO: Optimize
|
||||
uint16_t texel;
|
||||
|
||||
uint16_t s = ep->s >> 4;
|
||||
uint16_t t = ep->t >> 4;
|
||||
if (!DSGXTexParamsIsSRepeat(poly->poly->texParams)) {
|
||||
if (s < 0) {
|
||||
s = 0;
|
||||
} else if (s >= poly->texW) {
|
||||
s = poly->texW - 1;
|
||||
}
|
||||
} else if (DSGXTexParamsIsSMirror(poly->poly->texParams)) {
|
||||
if (s & poly->texW) {
|
||||
s = poly->texW - s;
|
||||
}
|
||||
s &= poly->texW - 1;
|
||||
} else {
|
||||
s &= poly->texW - 1;
|
||||
}
|
||||
if (!DSGXTexParamsIsTRepeat(poly->poly->texParams)) {
|
||||
if (t < 0) {
|
||||
t = 0;
|
||||
} else if (s >= poly->texH) {
|
||||
t = poly->texW - 1;
|
||||
}
|
||||
} else if (DSGXTexParamsIsTMirror(poly->poly->texParams)) {
|
||||
if (t & poly->texH) {
|
||||
t = poly->texH - t;
|
||||
}
|
||||
t &= poly->texH - 1;
|
||||
} else {
|
||||
t &= poly->texH - 1;
|
||||
}
|
||||
|
||||
uint16_t texelCoord = s + t * poly->texW;
|
||||
switch (poly->texFormat) {
|
||||
case 0:
|
||||
default:
|
||||
return _finishColor(ep->cr, ep->cg, ep->cb);
|
||||
case 1:
|
||||
return _finishColor(0, 0, 0x3F);
|
||||
case 2:
|
||||
return _finishColor(0, 0x3F, 0);
|
||||
case 3:
|
||||
texel = ((uint8_t*) poly->texBase)[texelCoord >> 1];
|
||||
if ((ep->s >> 4) & 0x1) {
|
||||
texel >>= 4;
|
||||
}
|
||||
texel &= 0xF;
|
||||
break;
|
||||
case 4:
|
||||
texel = ((uint8_t*) poly->texBase)[texelCoord];
|
||||
break;
|
||||
case 5:
|
||||
return _finishColor(0x3F, 0, 0x3F);
|
||||
case 6:
|
||||
return _finishColor(0x3F, 0x3F, 0);
|
||||
case 7:
|
||||
return _finishColor(0x3F, 0x3F, 0x3F);
|
||||
}
|
||||
uint8_t r, g, b;
|
||||
texel = poly->palBase[texel];
|
||||
_expandColor(texel, &r, &g, &b);
|
||||
return _finishColor(r, g, b);
|
||||
}
|
||||
|
||||
static int _edgeSort(const void* a, const void* b) {
|
||||
const struct DSGXSoftwareEdge* ea = a;
|
||||
const struct DSGXSoftwareEdge* eb = b;
|
||||
|
@ -142,6 +210,7 @@ void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
|
|||
renderer->d.init = DSGXSoftwareRendererInit;
|
||||
renderer->d.reset = DSGXSoftwareRendererReset;
|
||||
renderer->d.deinit = DSGXSoftwareRendererDeinit;
|
||||
renderer->d.invalidateTex = DSGXSoftwareRendererInvalidateTex;
|
||||
renderer->d.setRAM = DSGXSoftwareRendererSetRAM;
|
||||
renderer->d.drawScanline = DSGXSoftwareRendererDrawScanline;
|
||||
renderer->d.getScanline = DSGXSoftwareRendererGetScanline;
|
||||
|
@ -170,6 +239,11 @@ static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
|
|||
mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
// TODO
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
|
||||
|
@ -181,6 +255,20 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
|
|||
struct DSGXSoftwarePolygon* poly = DSGXSoftwarePolygonListAppend(&softwareRenderer->activePolys);
|
||||
struct DSGXSoftwareEdge* edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
|
||||
poly->poly = &polys[i];
|
||||
poly->texFormat = DSGXTexParamsGetFormat(poly->poly->texParams);
|
||||
poly->texW = 8 << DSGXTexParamsGetSSize(poly->poly->texParams);
|
||||
poly->texH = 8 << DSGXTexParamsGetTSize(poly->poly->texParams);
|
||||
switch (poly->texFormat) {
|
||||
case 0:
|
||||
case 7:
|
||||
poly->texBase = NULL;
|
||||
poly->palBase = NULL;
|
||||
break;
|
||||
default:
|
||||
poly->texBase = &renderer->tex[DSGXTexParamsGetVRAMBase(poly->poly->texParams) >> VRAM_BLOCK_OFFSET][(DSGXTexParamsGetVRAMBase(poly->poly->texParams) << 2) & 0xFFFF];
|
||||
poly->palBase = &renderer->texPal[poly->poly->palBase >> 11][(poly->poly->palBase << 3) & 0x1FFF];
|
||||
break;
|
||||
}
|
||||
edge->polyId = i;
|
||||
|
||||
struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
|
||||
|
@ -194,29 +282,29 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
|
|||
edge->x0 = v0->vx;
|
||||
edge->w0 = v0->vw;
|
||||
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
|
||||
edge->s0 = v0->s;
|
||||
edge->t0 = v0->t;
|
||||
edge->s0 = v0->vs;
|
||||
edge->t0 = v0->vt;
|
||||
|
||||
edge->y1 = SCREEN_SIZE - v1->vy;
|
||||
edge->x1 = v1->vx;
|
||||
edge->w1 = v1->vw;
|
||||
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
|
||||
edge->s1 = v1->s;
|
||||
edge->t1 = v1->t;
|
||||
edge->s1 = v1->vs;
|
||||
edge->t1 = v1->vt;
|
||||
} else {
|
||||
edge->y0 = SCREEN_SIZE - v1->vy;
|
||||
edge->x0 = v1->vx;
|
||||
edge->w0 = v1->vw;
|
||||
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
|
||||
edge->s0 = v1->s;
|
||||
edge->t0 = v1->t;
|
||||
edge->s0 = v1->vs;
|
||||
edge->t0 = v1->vt;
|
||||
|
||||
edge->y1 = SCREEN_SIZE - v0->vy;
|
||||
edge->x1 = v0->vx;
|
||||
edge->w1 = v0->vw;
|
||||
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
|
||||
edge->s1 = v0->s;
|
||||
edge->t1 = v0->t;
|
||||
edge->s1 = v0->vs;
|
||||
edge->t1 = v0->vt;
|
||||
}
|
||||
|
||||
edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
|
||||
|
@ -230,29 +318,29 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
|
|||
edge->x0 = v0->vx;
|
||||
edge->w0 = v0->vw;
|
||||
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
|
||||
edge->s0 = v0->s;
|
||||
edge->t0 = v0->t;
|
||||
edge->s0 = v0->vs;
|
||||
edge->t0 = v0->vt;
|
||||
|
||||
edge->y1 = SCREEN_SIZE - v1->vy;
|
||||
edge->x1 = v1->vx;
|
||||
edge->w1 = v1->vw;
|
||||
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
|
||||
edge->s1 = v1->s;
|
||||
edge->t1 = v1->t;
|
||||
edge->s1 = v1->vs;
|
||||
edge->t1 = v1->vt;
|
||||
} else {
|
||||
edge->y0 = SCREEN_SIZE - v1->vy;
|
||||
edge->x0 = v1->vx;
|
||||
edge->w0 = v1->vw;
|
||||
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
|
||||
edge->s0 = v1->s;
|
||||
edge->t0 = v1->t;
|
||||
edge->s0 = v1->vs;
|
||||
edge->t0 = v1->vt;
|
||||
|
||||
edge->y1 = SCREEN_SIZE - v0->vy;
|
||||
edge->x1 = v0->vx;
|
||||
edge->w1 = v0->vw;
|
||||
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
|
||||
edge->s1 = v0->s;
|
||||
edge->t1 = v0->t;
|
||||
edge->s1 = v0->vs;
|
||||
edge->t1 = v0->vt;
|
||||
}
|
||||
}
|
||||
qsort(DSGXSoftwareEdgeListGetPointer(&softwareRenderer->activeEdges, 0), DSGXSoftwareEdgeListSize(&softwareRenderer->activeEdges), sizeof(struct DSGXSoftwareEdge), _edgeSort);
|
||||
|
@ -280,7 +368,8 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
|
|||
softwareRenderer->bucket[poly] = NULL;
|
||||
} else if (!span) {
|
||||
span = DSGXSoftwareSpanListAppend(&softwareRenderer->activeSpans);
|
||||
memset(span, 0, sizeof(*span));
|
||||
memset(&span->ep[1], 0, sizeof(span->ep[1]));
|
||||
span->poly = DSGXSoftwarePolygonListGetPointer(&softwareRenderer->activePolys, poly);
|
||||
if (!_edgeToSpan(span, edge, 0, y)) {
|
||||
// Horizontal line
|
||||
DSGXSoftwareSpanListShift(&softwareRenderer->activeSpans, DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans) - 1, 1);
|
||||
|
@ -339,7 +428,7 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
|
|||
}
|
||||
if (span) {
|
||||
_lerpEndpoint(span, &ep, i);
|
||||
scanline[i] = _finishColor(ep.cr, ep.cg, ep.cb);
|
||||
scanline[i] = _lookupColor(&ep, span->poly);
|
||||
} else {
|
||||
scanline[i] = FLAG_UNWRITTEN; // TODO
|
||||
}
|
||||
|
|
|
@ -68,26 +68,26 @@ const struct DSVRAMBankInfo {
|
|||
{ 0x000, 0x40, MODE_LCDC },
|
||||
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x08, 0x80, 0x80 } },
|
||||
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x01, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
},
|
||||
{ // B
|
||||
{ 0x008, 0x40, MODE_LCDC },
|
||||
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x08, 0x80, 0x80 } },
|
||||
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x01, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
},
|
||||
{ // C
|
||||
{ 0x010, 0x40, MODE_LCDC },
|
||||
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||
{ 0x000, 0x40, MODE_7_VRAM, { 0x00, 0x08, 0x80, 0x80 } },
|
||||
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x01, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x08, MODE_B_BG },
|
||||
},
|
||||
{ // D
|
||||
{ 0x018, 0x40, MODE_LCDC },
|
||||
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||
{ 0x000, 0x40, MODE_7_VRAM, { 0x00, 0x08, 0x80, 0x80 } },
|
||||
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x01, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||
{ 0x000, 0x08, MODE_B_OBJ },
|
||||
},
|
||||
{ // E
|
||||
|
@ -418,6 +418,21 @@ void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldVa
|
|||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, true, 0);
|
||||
}
|
||||
break;
|
||||
case MODE_3D_TEX:
|
||||
if (ds->gx.tex[offset] == memory->vramBank[index]) {
|
||||
ds->gx.tex[offset] = NULL;
|
||||
ds->gx.renderer->tex[offset] = NULL;
|
||||
ds->gx.renderer->invalidateTex(ds->gx.renderer, offset);
|
||||
}
|
||||
break;
|
||||
case MODE_3D_TEX_PAL:
|
||||
for (i = 0; i < oldInfo.mirrorSize; ++i) {
|
||||
if (ds->gx.texPal[offset + i] == &memory->vramBank[index][i << 13]) {
|
||||
ds->gx.texPal[offset + i] = NULL;
|
||||
ds->gx.renderer->texPal[offset + i] = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODE_7_VRAM:
|
||||
for (i = 0; i < size; i += 16) {
|
||||
ds->memory.vram7[(offset + i) >> 4] = NULL;
|
||||
|
@ -491,6 +506,17 @@ void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldVa
|
|||
ds->video.renderer->vramBOBJExtPal = ds->video.vramBOBJExtPal;
|
||||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, true, 0);
|
||||
break;
|
||||
case MODE_3D_TEX:
|
||||
ds->gx.tex[offset] = memory->vramBank[index];
|
||||
ds->gx.renderer->tex[offset] = ds->gx.tex[offset];
|
||||
ds->gx.renderer->invalidateTex(ds->gx.renderer, offset);
|
||||
break;
|
||||
case MODE_3D_TEX_PAL:
|
||||
for (i = 0; i < info.mirrorSize; ++i) {
|
||||
ds->gx.texPal[offset + i] = &memory->vramBank[index][i << 13];
|
||||
ds->gx.renderer->texPal[offset + i] = ds->gx.texPal[offset + i];
|
||||
}
|
||||
break;
|
||||
case MODE_7_VRAM:
|
||||
for (i = 0; i < size; i += 16) {
|
||||
ds->memory.vram7[(offset + i) >> 4] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 5)];
|
||||
|
|
Loading…
Reference in New Issue