src/platform/3ds/main.c (view raw)
1/* Copyright (c) 2013-2015 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 "gba/gba.h"
7#include "gba/video.h"
8
9#include "gba/renderers/video-software.h"
10#include "util/memory.h"
11
12#include "3ds-vfs.h"
13
14#include <3ds.h>
15
16static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
17static Handle logFile;
18
19int main() {
20 srvInit();
21 aptInit();
22 hidInit(0);
23 gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, false);
24 fsInit();
25
26 FS_archive sdmcArchive = (FS_archive) {
27 ARCH_SDMC,
28 (FS_path) { PATH_EMPTY, 1, (u8*)"" },
29 0, 0
30 };
31 FSUSER_OpenArchive(0, &sdmcArchive);
32 FSUSER_OpenFile(0, &logFile, sdmcArchive, FS_makePath(PATH_CHAR, "/mgba.log"), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
33
34 struct GBAVideoSoftwareRenderer renderer;
35 GBAVideoSoftwareRendererCreate(&renderer);
36
37 size_t stride = VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL;
38 color_t* videoBuffer = anonymousMemoryMap(stride * VIDEO_VERTICAL_PIXELS);
39 struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA));
40 struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore));
41 int activeKeys = 0;
42
43 renderer.outputBuffer = videoBuffer;
44 renderer.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
45
46 struct VFile* rom = VFileOpen3DS(&sdmcArchive, "/rom.gba", FS_OPEN_READ);
47
48 struct VFile* save = VFileOpen3DS(&sdmcArchive, "/rom.sav", FS_OPEN_WRITE | FS_OPEN_CREATE);
49
50 GBACreate(gba);
51 ARMSetComponents(cpu, &gba->d, 0, 0);
52 ARMInit(cpu);
53
54 gba->keySource = &activeKeys;
55 gba->sync = 0;
56
57 GBAVideoAssociateRenderer(&gba->video, &renderer.d);
58
59 GBALoadROM(gba, rom, save, 0);
60
61 gba->logHandler = GBA3DSLog;
62
63 ARMReset(cpu);
64
65 int frameCounter = 0;
66 while (aptMainLoop()) {
67 ARMRunLoop(cpu);
68
69 if (frameCounter != gba->video.frameCounter) {
70 u16 width, height;
71 u16* screen = (u16*) gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, &height, &width);
72 u32 startX = (width - VIDEO_HORIZONTAL_PIXELS) / 2;
73 u32 startY = (height + VIDEO_VERTICAL_PIXELS) / 2 - 1;
74 u32 x, y;
75 for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) {
76 for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
77 screen[startY - y + (startX + x) * height] = videoBuffer[y * VIDEO_HORIZONTAL_PIXELS + x];
78 }
79 }
80 gfxFlushBuffers();
81 gfxSwapBuffersGpu();
82 gspWaitForVBlank();
83 hidScanInput();
84 activeKeys = hidKeysHeld() & 0x3FF;
85 if (hidKeysDown() & KEY_X) {
86 break;
87 }
88 frameCounter = gba->video.frameCounter;
89 }
90 }
91
92 ARMDeinit(cpu);
93 GBADestroy(gba);
94
95 rom->close(rom);
96 save->close(save);
97
98 mappedMemoryFree(gba, 0);
99 mappedMemoryFree(cpu, 0);
100
101 mappedMemoryFree(videoBuffer, 0);
102
103 FSFILE_Close(logFile);
104
105 fsExit();
106 gfxExit();
107 hidExit();
108 aptExit();
109 srvExit();
110 return 0;
111}
112
113static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {
114 UNUSED(thread);
115 UNUSED(level);
116 char out[256];
117 u64 size;
118 u32 written;
119 size_t len = vsnprintf(out, sizeof(out), format, args);
120 if (len >= 256) {
121 len = 255;
122 }
123 out[len] = '\n';
124 FSFILE_GetSize(logFile, &size);
125 FSFILE_Write(logFile, &written, size, out, len + 1, FS_WRITE_FLUSH);
126}