src/core/video-proxy.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/core/video-proxy.h>
7
8#include <mgba-util/memory.h>
9
10static inline size_t _roundUp(size_t value, int shift) {
11 value += (1 << shift) - 1;
12 return value >> shift;
13}
14
15void mVideoProxyRendererInit(struct mVideoProxy* proxy) {
16 proxy->palette = anonymousMemoryMap(proxy->paletteSize);
17 proxy->vram = anonymousMemoryMap(proxy->vramSize);
18 proxy->oam = anonymousMemoryMap(proxy->oamSize);
19
20 proxy->vramDirtyBitmap = calloc(_roundUp(proxy->vramSize, 17), sizeof(uint32_t));
21 proxy->oamDirtyBitmap = calloc(_roundUp(proxy->oamSize, 6), sizeof(uint32_t));
22}
23
24void mVideoProxyRendererDeinit(struct mVideoProxy* proxy) {
25 mappedMemoryFree(proxy->palette, proxy->paletteSize);
26 mappedMemoryFree(proxy->vram, proxy->vramSize);
27 mappedMemoryFree(proxy->oam, proxy->oamSize);
28
29 free(proxy->vramDirtyBitmap);
30 free(proxy->oamDirtyBitmap);
31}
32
33void mVideoProxyRendererReset(struct mVideoProxy* proxy) {
34 memset(proxy->vramDirtyBitmap, 0, sizeof(uint32_t) * _roundUp(proxy->vramSize, 17));
35 memset(proxy->oamDirtyBitmap, 0, sizeof(uint32_t) * _roundUp(proxy->oamSize, 6));
36}
37
38void mVideoProxyRendererWriteVideoRegister(struct mVideoProxy* proxy, uint32_t address, uint16_t value) {
39 struct mVideoProxyDirtyInfo dirty = {
40 DIRTY_REGISTER,
41 address,
42 value,
43 0xDEADBEEF,
44 };
45 proxy->writeData(proxy, &dirty, sizeof(dirty));
46}
47
48void mVideoProxyRendererWriteVRAM(struct mVideoProxy* proxy, uint32_t address) {
49 int bit = 1 << (address >> 12);
50 if (proxy->vramDirtyBitmap[address >> 17] & bit) {
51 return;
52 }
53 proxy->vramDirtyBitmap[address >> 17] |= bit;
54}
55
56void mVideoProxyRendererWritePalette(struct mVideoProxy* proxy, uint32_t address, uint16_t value) {
57 struct mVideoProxyDirtyInfo dirty = {
58 DIRTY_PALETTE,
59 address,
60 value,
61 0xDEADBEEF,
62 };
63 proxy->writeData(proxy, &dirty, sizeof(dirty));
64}
65
66void mVideoProxyRendererWriteOAM(struct mVideoProxy* proxy, uint32_t address, uint16_t value) {
67 struct mVideoProxyDirtyInfo dirty = {
68 DIRTY_OAM,
69 address,
70 value,
71 0xDEADBEEF,
72 };
73 proxy->writeData(proxy, &dirty, sizeof(dirty));
74}
75
76void mVideoProxyRendererDrawScanline(struct mVideoProxy* proxy, int y) {
77 size_t i;
78 for (i = 0; i < _roundUp(proxy->vramSize, 17); ++i) {
79 if (proxy->vramDirtyBitmap[i]) {
80 uint32_t bitmap = proxy->vramDirtyBitmap[i];
81 proxy->vramDirtyBitmap[i] = 0;
82 int j;
83 for (j = 0; j < 32; ++j) {
84 if (!(bitmap & (1 << j))) {
85 continue;
86 }
87 struct mVideoProxyDirtyInfo dirty = {
88 DIRTY_VRAM,
89 j * 0x1000,
90 0xABCD,
91 0xDEADBEEF,
92 };
93 proxy->writeData(proxy, &dirty, sizeof(dirty));
94 proxy->writeData(proxy, proxy->vramBlock(proxy, j * 0x1000), 0x1000);
95 }
96 }
97 }
98 struct mVideoProxyDirtyInfo dirty = {
99 DIRTY_SCANLINE,
100 y,
101 0,
102 0xDEADBEEF,
103 };
104 proxy->writeData(proxy, &dirty, sizeof(dirty));
105}
106
107void mVideoProxyRendererFlush(struct mVideoProxy* proxy) {
108 struct mVideoProxyDirtyInfo dirty = {
109 DIRTY_FLUSH,
110 0,
111 0,
112 0xDEADBEEF,
113 };
114 proxy->writeData(proxy, &dirty, sizeof(dirty));
115}
116
117bool mVideoProxyRendererRun(struct mVideoProxy* proxy) {
118 struct mVideoProxyDirtyInfo item = {0};
119 while (proxy->readData(proxy, &item, sizeof(item), false)) {
120 switch (item.type) {
121 case DIRTY_REGISTER:
122 case DIRTY_PALETTE:
123 case DIRTY_OAM:
124 case DIRTY_VRAM:
125 case DIRTY_SCANLINE:
126 case DIRTY_FLUSH:
127 if (!proxy->parsePacket(proxy, &item)) {
128 return true;
129 }
130 break;
131 default:
132 return false;
133 }
134 }
135 return true;
136}