all repos — mgba @ ca42faae3c397fb480966637ba99bdda85e7a644

mGBA Game Boy Advance Emulator

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}