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
7#include "gba/renderers/video-software.h"
8#include "gba/supervisor/context.h"
9#include "gba/video.h"
10#include "util/memory.h"
11
12#include "3ds-vfs.h"
13
14#include <3ds.h>
15
16FS_archive sdmcArchive;
17
18static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
19static Handle logFile;
20
21int main() {
22 struct GBAContext context;
23 srvInit();
24 aptInit();
25 hidInit(0);
26 gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, false);
27 fsInit();
28 sdmcArchive = (FS_archive) {
29 ARCH_SDMC,
30 (FS_path) { PATH_EMPTY, 1, (const u8*)"" },
31 0, 0
32 };
33 FSUSER_OpenArchive(0, &sdmcArchive);
34 FSUSER_OpenFile(0, &logFile, sdmcArchive, FS_makePath(PATH_CHAR, "/mgba.log"), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
35
36 GBAContextInit(&context, 0);
37 struct GBAOptions opts = {
38 .useBios = true,
39 .logLevel = 0,
40 .idleOptimization = IDLE_LOOP_REMOVE
41 };
42 GBAConfigLoadDefaults(&context.config, &opts);
43 context.gba->logHandler = GBA3DSLog;
44
45 struct GBAVideoSoftwareRenderer renderer;
46 GBAVideoSoftwareRendererCreate(&renderer);
47 size_t stride = VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL;
48 color_t* videoBuffer = anonymousMemoryMap(stride * VIDEO_VERTICAL_PIXELS);
49 renderer.outputBuffer = videoBuffer;
50 renderer.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
51 GBAVideoAssociateRenderer(&context.gba->video, &renderer.d);
52
53 GBAContextLoadROM(&context, "/rom.gba", true);
54 GBAContextStart(&context);
55
56 while (aptMainLoop()) {
57 hidScanInput();
58 int activeKeys = hidKeysHeld() & 0x3FF;
59 if (hidKeysDown() & KEY_X) {
60 break;
61 }
62 GBAContextFrame(&context, activeKeys);
63
64 u16 width, height;
65 u16* screen = (u16*) gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, &height, &width);
66 u32 startX = (width - VIDEO_HORIZONTAL_PIXELS) / 2;
67 u32 startY = (height + VIDEO_VERTICAL_PIXELS) / 2 - 1;
68 u32 x, y;
69 for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) {
70 for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
71 screen[startY - y + (startX + x) * height] = videoBuffer[y * VIDEO_HORIZONTAL_PIXELS + x];
72 }
73 }
74 gfxFlushBuffers();
75 gfxSwapBuffers();
76 gspWaitForVBlank1();
77 }
78
79 GBAContextStop(&context);
80 GBAContextDeinit(&context);
81
82 mappedMemoryFree(videoBuffer, 0);
83
84 FSFILE_Close(logFile);
85
86 fsExit();
87 gfxExit();
88 hidExit();
89 aptExit();
90 srvExit();
91 return 0;
92}
93
94static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {
95 UNUSED(thread);
96 UNUSED(level);
97 char out[256];
98 u64 size;
99 u32 written;
100 size_t len = vsnprintf(out, sizeof(out), format, args);
101 if (len >= 256) {
102 len = 255;
103 }
104 out[len] = '\n';
105 FSFILE_GetSize(logFile, &size);
106 FSFILE_Write(logFile, &written, size, out, len + 1, FS_WRITE_FLUSH);
107}