all repos — mgba @ 1cf587c6c326bca26fc15f038719448995c76b76

mGBA Game Boy Advance Emulator

src/ds/gx/software.c (view raw)

  1/* Copyright (c) 2013-2017 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/internal/ds/gx/software.h>
  7
  8#include <mgba-util/memory.h>
  9
 10DEFINE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
 11DEFINE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
 12
 13static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
 14static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
 15static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
 16static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
 17static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y);
 18static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);
 19
 20static int _edgeSort(const void* a, const void* b) {
 21	const struct DSGXSoftwareEdge* ea = a;
 22	const struct DSGXSoftwareEdge* eb = b;
 23
 24	if (ea->y0 < eb->y0) {
 25		return -1;
 26	}
 27	if (ea->y0 > eb->y0) {
 28		return 1;
 29	}
 30	if (ea->y1 < eb->y1) {
 31		return -1;
 32	}
 33	if (ea->y1 > eb->y1) {
 34		return 1;
 35	}
 36	return 0;
 37}
 38
 39void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
 40	renderer->d.init = DSGXSoftwareRendererInit;
 41	renderer->d.reset = DSGXSoftwareRendererReset;
 42	renderer->d.deinit = DSGXSoftwareRendererDeinit;
 43	renderer->d.setRAM = DSGXSoftwareRendererSetRAM;
 44	renderer->d.drawScanline = DSGXSoftwareRendererDrawScanline;
 45	renderer->d.getScanline = DSGXSoftwareRendererGetScanline;
 46}
 47
 48static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) {
 49	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
 50	DSGXSoftwarePolygonListInit(&softwareRenderer->activePolys, DS_GX_POLYGON_BUFFER_SIZE / 4);
 51	DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
 52	softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
 53}
 54
 55static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
 56	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
 57	// TODO
 58}
 59
 60static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
 61	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
 62	DSGXSoftwarePolygonListDeinit(&softwareRenderer->activePolys);
 63	DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);	
 64	mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
 65}
 66
 67static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
 68	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
 69
 70	softwareRenderer->verts = verts;
 71	DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
 72	DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
 73	unsigned i;
 74	for (i = 0; i < polyCount; ++i) {
 75		struct DSGXSoftwarePolygon* poly = DSGXSoftwarePolygonListAppend(&softwareRenderer->activePolys);
 76		struct DSGXSoftwareEdge* edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
 77		poly->poly = &polys[i];
 78
 79		struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
 80		struct DSGXVertex* v1;
 81
 82		int v;
 83		for (v = 1; v < poly->poly->verts; ++v) {
 84			v1 = &verts[poly->poly->vertIds[v]];
 85			if (v0->vy <= v1->vy) {
 86				edge->y0 = v0->vy;
 87				edge->x0 = v0->vx;
 88				edge->w0 = v0->vw;
 89				edge->c0 = v0->color;
 90				edge->s0 = v0->s;
 91				edge->t0 = v0->t;
 92
 93				edge->y1 = v1->vy;
 94				edge->x1 = v1->vx;
 95				edge->w1 = v1->vw;
 96				edge->c1 = v1->color;
 97				edge->s1 = v1->s;
 98				edge->t1 = v1->t;
 99			} else {
100				edge->y0 = v1->vy;
101				edge->x0 = v1->vx;
102				edge->w0 = v1->vw;
103				edge->c0 = v1->color;
104				edge->s0 = v1->s;
105				edge->t0 = v1->t;
106
107				edge->y1 = v0->vy;
108				edge->x1 = v0->vx;
109				edge->w1 = v0->vw;
110				edge->c1 = v0->color;
111				edge->s1 = v0->s;
112				edge->t1 = v0->t;
113			}
114
115			edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
116			v0 = v1;
117		}
118
119		v1 = &verts[poly->poly->vertIds[0]];
120		if (v0->vy <= v1->vy) {
121			edge->y0 = v0->vy;
122			edge->x0 = v0->vx;
123			edge->w0 = v0->vw;
124			edge->c0 = v0->color;
125			edge->s0 = v0->s;
126			edge->t0 = v0->t;
127
128			edge->y1 = v1->vy;
129			edge->x1 = v1->vx;
130			edge->w1 = v1->vw;
131			edge->c1 = v1->color;
132			edge->s1 = v1->s;
133			edge->t1 = v1->t;
134		} else {
135			edge->y0 = v1->vy;
136			edge->x0 = v1->vx;
137			edge->w0 = v1->vw;
138			edge->c0 = v1->color;
139			edge->s0 = v1->s;
140			edge->t0 = v1->t;
141
142			edge->y1 = v0->vy;
143			edge->x1 = v0->vx;
144			edge->w1 = v0->vw;
145			edge->c1 = v0->color;
146			edge->s1 = v0->s;
147			edge->t1 = v0->t;
148		}
149	}
150	qsort(DSGXSoftwareEdgeListGetPointer(&softwareRenderer->activeEdges, 0), DSGXSoftwareEdgeListSize(&softwareRenderer->activeEdges), sizeof(struct DSGXSoftwareEdge), _edgeSort);
151}
152
153static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
154	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
155	// TODO
156}
157
158static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
159	struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
160	y %= 48;
161	*output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
162}