mirror of https://github.com/mgba-emu/mgba.git
DS GX: Start filling in software renderer
This commit is contained in:
parent
778eb8bc3b
commit
c6ff504e66
|
@ -18,6 +18,9 @@ CXX_GUARD_START
|
|||
|
||||
mLOG_DECLARE_CATEGORY(DS_GX);
|
||||
|
||||
#define DS_GX_POLYGON_BUFFER_SIZE 2048
|
||||
#define DS_GX_VERTEX_BUFFER_SIZE 6144
|
||||
|
||||
DECL_BITFIELD(DSRegGXSTAT, uint32_t);
|
||||
DECL_BIT(DSRegGXSTAT, TestBusy, 0);
|
||||
DECL_BIT(DSRegGXSTAT, BoxTestResult, 1);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef DS_GX_SOFTWARE_H
|
||||
#define DS_GX_SOFTWARE_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/internal/ds/gx.h>
|
||||
#include <mgba/internal/ds/video.h>
|
||||
#include <mgba-util/vector.h>
|
||||
|
||||
struct DSGXSoftwarePolygon {
|
||||
struct DSGXPolygon* poly;
|
||||
int32_t topY;
|
||||
int32_t bottomY;
|
||||
int32_t topZ;
|
||||
};
|
||||
|
||||
struct DSGXSoftwareEdge {
|
||||
struct DSGXPolygon* poly;
|
||||
int32_t y0;
|
||||
int32_t x0;
|
||||
int32_t w0;
|
||||
int32_t c0; // 6.6.6.6 ARGB
|
||||
int16_t s0;
|
||||
int16_t t0;
|
||||
|
||||
int32_t y1;
|
||||
int32_t x1;
|
||||
int32_t w1;
|
||||
int32_t c1; // 6.6.6.6 ARGB
|
||||
int16_t s1;
|
||||
int16_t t1;
|
||||
};
|
||||
|
||||
DECLARE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
|
||||
DECLARE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
|
||||
|
||||
struct DSGXSoftwareRenderer {
|
||||
struct DSGXRenderer d;
|
||||
|
||||
struct DSGXSoftwarePolygonList activePolys;
|
||||
struct DSGXSoftwareEdgeList activeEdges;
|
||||
|
||||
uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
|
||||
color_t* scanlineCache;
|
||||
|
||||
struct DSGXVertex* verts;
|
||||
};
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||
#include <mgba/internal/ds/ds.h>
|
||||
#include <mgba/internal/ds/extra/cli.h>
|
||||
#include <mgba/internal/ds/renderers/software.h>
|
||||
#include <mgba/internal/ds/gx/software.h>
|
||||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/patch.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
@ -21,6 +22,7 @@ struct DSCore {
|
|||
struct ARMCore* arm7;
|
||||
struct ARMCore* arm9;
|
||||
struct DSVideoSoftwareRenderer renderer;
|
||||
struct DSGXSoftwareRenderer gxRenderer;
|
||||
int keys;
|
||||
int cursorX;
|
||||
int cursorY;
|
||||
|
@ -58,6 +60,7 @@ static bool _DSCoreInit(struct mCore* core) {
|
|||
ARMInit(arm9);
|
||||
|
||||
DSVideoSoftwareRendererCreate(&dscore->renderer);
|
||||
DSGXSoftwareRendererCreate(&dscore->gxRenderer);
|
||||
dscore->renderer.outputBuffer = NULL;
|
||||
|
||||
dscore->keys = 0;
|
||||
|
@ -187,6 +190,9 @@ static void _DSCoreReset(struct mCore* core) {
|
|||
if (dscore->renderer.outputBuffer) {
|
||||
struct DSVideoRenderer* renderer = &dscore->renderer.d;
|
||||
DSVideoAssociateRenderer(&ds->video, renderer);
|
||||
|
||||
struct DSGXRenderer* gxRenderer = &dscore->gxRenderer.d;
|
||||
DSGXAssociateRenderer(&ds->gx, gxRenderer);
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
|
|
|
@ -12,8 +12,6 @@ mLOG_DEFINE_CATEGORY(DS_GX, "DS GX");
|
|||
|
||||
#define DS_GX_FIFO_SIZE 256
|
||||
#define DS_GX_PIPE_SIZE 4
|
||||
#define DS_GX_POLYGON_BUFFER_SIZE 2048
|
||||
#define DS_GX_VERTEX_BUFFER_SIZE 6144
|
||||
|
||||
static void DSGXDummyRendererInit(struct DSGXRenderer* renderer);
|
||||
static void DSGXDummyRendererReset(struct DSGXRenderer* renderer);
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/ds/gx/software.h>
|
||||
|
||||
#include <mgba-util/memory.h>
|
||||
|
||||
DEFINE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
|
||||
DEFINE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
|
||||
|
||||
static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
|
||||
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
|
||||
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
|
||||
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);
|
||||
|
||||
static int _edgeSort(const void* a, const void* b) {
|
||||
const struct DSGXSoftwareEdge* ea = a;
|
||||
const struct DSGXSoftwareEdge* eb = b;
|
||||
|
||||
if (ea->y0 < eb->y0) {
|
||||
return -1;
|
||||
}
|
||||
if (ea->y0 > eb->y0) {
|
||||
return 1;
|
||||
}
|
||||
if (ea->y1 < eb->y1) {
|
||||
return -1;
|
||||
}
|
||||
if (ea->y1 > eb->y1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
|
||||
renderer->d.init = DSGXSoftwareRendererInit;
|
||||
renderer->d.reset = DSGXSoftwareRendererReset;
|
||||
renderer->d.deinit = DSGXSoftwareRendererDeinit;
|
||||
renderer->d.setRAM = DSGXSoftwareRendererSetRAM;
|
||||
renderer->d.drawScanline = DSGXSoftwareRendererDrawScanline;
|
||||
renderer->d.getScanline = DSGXSoftwareRendererGetScanline;
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
DSGXSoftwarePolygonListInit(&softwareRenderer->activePolys, DS_GX_POLYGON_BUFFER_SIZE / 4);
|
||||
DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
|
||||
softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
// TODO
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
DSGXSoftwarePolygonListDeinit(&softwareRenderer->activePolys);
|
||||
DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);
|
||||
mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
|
||||
softwareRenderer->verts = verts;
|
||||
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
|
||||
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
|
||||
unsigned i;
|
||||
for (i = 0; i < polyCount; ++i) {
|
||||
struct DSGXSoftwarePolygon* poly = DSGXSoftwarePolygonListAppend(&softwareRenderer->activePolys);
|
||||
struct DSGXSoftwareEdge* edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
|
||||
poly->poly = &polys[i];
|
||||
|
||||
struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
|
||||
struct DSGXVertex* v1;
|
||||
|
||||
int v;
|
||||
for (v = 1; v < poly->poly->verts; ++v) {
|
||||
v1 = &verts[poly->poly->vertIds[v]];
|
||||
if (v0->vy <= v1->vy) {
|
||||
edge->y0 = v0->vy;
|
||||
edge->x0 = v0->vx;
|
||||
edge->w0 = v0->vw;
|
||||
edge->c0 = v0->color;
|
||||
edge->s0 = v0->s;
|
||||
edge->t0 = v0->t;
|
||||
|
||||
edge->y1 = v1->vy;
|
||||
edge->x1 = v1->vx;
|
||||
edge->w1 = v1->vw;
|
||||
edge->c1 = v1->color;
|
||||
edge->s1 = v1->s;
|
||||
edge->t1 = v1->t;
|
||||
} else {
|
||||
edge->y0 = v1->vy;
|
||||
edge->x0 = v1->vx;
|
||||
edge->w0 = v1->vw;
|
||||
edge->c0 = v1->color;
|
||||
edge->s0 = v1->s;
|
||||
edge->t0 = v1->t;
|
||||
|
||||
edge->y1 = v0->vy;
|
||||
edge->x1 = v0->vx;
|
||||
edge->w1 = v0->vw;
|
||||
edge->c1 = v0->color;
|
||||
edge->s1 = v0->s;
|
||||
edge->t1 = v0->t;
|
||||
}
|
||||
|
||||
edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
|
||||
v0 = v1;
|
||||
}
|
||||
|
||||
v1 = &verts[poly->poly->vertIds[0]];
|
||||
if (v0->vy <= v1->vy) {
|
||||
edge->y0 = v0->vy;
|
||||
edge->x0 = v0->vx;
|
||||
edge->w0 = v0->vw;
|
||||
edge->c0 = v0->color;
|
||||
edge->s0 = v0->s;
|
||||
edge->t0 = v0->t;
|
||||
|
||||
edge->y1 = v1->vy;
|
||||
edge->x1 = v1->vx;
|
||||
edge->w1 = v1->vw;
|
||||
edge->c1 = v1->color;
|
||||
edge->s1 = v1->s;
|
||||
edge->t1 = v1->t;
|
||||
} else {
|
||||
edge->y0 = v1->vy;
|
||||
edge->x0 = v1->vx;
|
||||
edge->w0 = v1->vw;
|
||||
edge->c0 = v1->color;
|
||||
edge->s0 = v1->s;
|
||||
edge->t0 = v1->t;
|
||||
|
||||
edge->y1 = v0->vy;
|
||||
edge->x1 = v0->vx;
|
||||
edge->w1 = v0->vw;
|
||||
edge->c1 = v0->color;
|
||||
edge->s1 = v0->s;
|
||||
edge->t1 = v0->t;
|
||||
}
|
||||
}
|
||||
qsort(DSGXSoftwareEdgeListGetPointer(&softwareRenderer->activeEdges, 0), DSGXSoftwareEdgeListSize(&softwareRenderer->activeEdges), sizeof(struct DSGXSoftwareEdge), _edgeSort);
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
// TODO
|
||||
}
|
||||
|
||||
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
|
||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||
y %= 48;
|
||||
*output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
||||
}
|
Loading…
Reference in New Issue