all repos — mgba @ 7a3c7c14888216135c8973d73d3eda537b1a25ab

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#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}