3DS: Use runner

This commit is contained in:
Jeffrey Pfau 2015-08-30 17:11:05 -07:00
parent 3157a3d949
commit cc1fb12d2f
1 changed files with 113 additions and 103 deletions

View File

@ -6,6 +6,7 @@
#include "gba/renderers/video-software.h" #include "gba/renderers/video-software.h"
#include "gba/context/context.h" #include "gba/context/context.h"
#include "gba/context/gui-runner.h"
#include "gba/video.h" #include "gba/video.h"
#include "util/gui.h" #include "util/gui.h"
#include "util/gui/file-select.h" #include "util/gui/file-select.h"
@ -21,24 +22,111 @@
FS_archive sdmcArchive; FS_archive sdmcArchive;
struct GBA3DSRotationSource { static struct GBA3DSRotationSource {
struct GBARotationSource d; struct GBARotationSource d;
accelVector accel; accelVector accel;
angularRate gyro; angularRate gyro;
}; } rotation;
static struct VFile* logFile;
static bool hasSound;
// TODO: Move into context
static struct GBAVideoSoftwareRenderer renderer;
static int16_t* audioLeft = 0;
static int16_t* audioRight = 0;
static sf2d_texture* tex;
static size_t audioPos = 0;
extern bool allocateRomBuffer(void); extern bool allocateRomBuffer(void);
static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args); static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
static struct VFile* logFile;
static void _drawStart(void) { static void _drawStart(void) {
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
} }
static void _drawEnd(void) { static void _drawEnd(void) {
sf2d_end_frame(); sf2d_end_frame();
sf2d_swapbuffers(); sf2d_swapbuffers();
} }
static void _setup(struct GBAGUIRunner* runner) {
struct GBAOptions opts = {
.useBios = true,
.logLevel = 0,
.idleOptimization = IDLE_LOOP_DETECT
};
GBAConfigLoadDefaults(&runner->context.config, &opts);
runner->context.gba->logHandler = GBA3DSLog;
runner->context.gba->rotationSource = &rotation.d;
GBAVideoSoftwareRendererCreate(&renderer);
renderer.outputBuffer = anonymousMemoryMap(256 * VIDEO_VERTICAL_PIXELS * 2);
renderer.outputBufferStride = 256;
runner->context.renderer = &renderer.d;
}
static void _gameLoaded(struct GBAGUIRunner* runner) {
if (runner->context.gba->memory.hw.devices & HW_TILT) {
HIDUSER_EnableAccelerometer();
}
if (runner->context.gba->memory.hw.devices & HW_GYRO) {
HIDUSER_EnableGyroscope();
}
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
blip_set_rates(runner->context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 0x8000);
blip_set_rates(runner->context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 0x8000);
#endif
memset(audioLeft, 0, AUDIO_SAMPLES * 2 * sizeof(int16_t));
memset(audioRight, 0, AUDIO_SAMPLES * 2 * sizeof(int16_t));
}
static void _gameUnloaded(struct GBAGUIRunner* runner) {
CSND_SetPlayState(8, 0);
CSND_SetPlayState(9, 0);
csndExecCmds(0);
if (runner->context.gba->memory.hw.devices & HW_TILT) {
HIDUSER_DisableAccelerometer();
}
if (runner->context.gba->memory.hw.devices & HW_GYRO) {
HIDUSER_DisableGyroscope();
}
}
static void _drawFrame(struct GBAGUIRunner* runner, bool faded) {
GX_SetDisplayTransfer(0, renderer.outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202);
GSPGPU_FlushDataCache(0, tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2);
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
if (hasSound) {
memset(&audioLeft[audioPos], 0, AUDIO_SAMPLES);
memset(&audioRight[audioPos], 0, AUDIO_SAMPLES);
size_t samples = blip_read_samples(runner->context.gba->audio.left, &audioLeft[audioPos], AUDIO_SAMPLES, false);
blip_read_samples(runner->context.gba->audio.right, &audioRight[audioPos], AUDIO_SAMPLES, false);
size_t audioPosNew = (audioPos + AUDIO_SAMPLES) % (AUDIO_SAMPLES * 2);
GSPGPU_FlushDataCache(0, (void*) audioLeft, AUDIO_SAMPLES * 2 * sizeof(int16_t));
GSPGPU_FlushDataCache(0, (void*) audioRight, AUDIO_SAMPLES * 2 * sizeof(int16_t));
csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 0x8000, 1.0, -1.0, &audioLeft[audioPos], &audioLeft[audioPosNew], samples * 2);
csndPlaySound(0x9, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 0x8000, 1.0, 1.0, &audioRight[audioPos], &audioLeft[audioPosNew], samples * 2);
audioPos = audioPosNew;
} else {
blip_clear(runner->context.gba->audio.left);
blip_clear(runner->context.gba->audio.right);
}
#endif
gspWaitForPPF();
_drawStart();
sf2d_draw_texture_scale_blend(tex, 40, 296, 1, -1, 0xFFFFFF3F | (faded ? 0 : 0xC0));
_drawEnd();
}
static uint16_t _pollGameInput(struct GBAGUIRunner* runner) {
hidScanInput();
uint32_t activeKeys = hidKeysHeld() & 0xF00003FF;
activeKeys |= activeKeys >> 24;
return activeKeys;
}
static int _pollInput(void) { static int _pollInput(void) {
hidScanInput(); hidScanInput();
int keys = 0; int keys = 0;
@ -90,10 +178,8 @@ static int32_t _readGyroZ(struct GBARotationSource* source) {
} }
int main() { int main() {
bool hasSound = !csndInit(); hasSound = !csndInit();
struct GBAContext context;
struct GBA3DSRotationSource rotation;
rotation.d.sample = _sampleRotation; rotation.d.sample = _sampleRotation;
rotation.d.readTiltX = _readTiltX; rotation.d.readTiltX = _readTiltX;
rotation.d.readTiltY = _readTiltY; rotation.d.readTiltY = _readTiltY;
@ -103,9 +189,6 @@ int main() {
return 1; return 1;
} }
int16_t* audioLeft = 0;
int16_t* audioRight = 0;
size_t audioPos = 0;
if (hasSound) { if (hasSound) {
audioLeft = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t)); audioLeft = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t));
audioRight = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t)); audioRight = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t));
@ -113,7 +196,7 @@ int main() {
sf2d_init(); sf2d_init();
sf2d_set_clear_color(0); sf2d_set_clear_color(0);
sf2d_texture* tex = sf2d_create_texture(256, 256, TEXFMT_RGB565, SF2D_PLACE_RAM); tex = sf2d_create_texture(256, 256, TEXFMT_RGB565, SF2D_PLACE_RAM);
memset(tex->data, 0, 256 * 256 * 2); memset(tex->data, 0, 256 * 256 * 2);
sdmcArchive = (FS_archive) { sdmcArchive = (FS_archive) {
@ -126,109 +209,36 @@ int main() {
logFile = VFileOpen("/mgba.log", O_WRONLY | O_CREAT | O_TRUNC); logFile = VFileOpen("/mgba.log", O_WRONLY | O_CREAT | O_TRUNC);
struct GUIFont* font = GUIFontCreate(); struct GUIFont* font = GUIFontCreate();
GBAContextInit(&context, 0);
struct GBAOptions opts = {
.useBios = true,
.logLevel = 0,
.idleOptimization = IDLE_LOOP_DETECT
};
GBAConfigLoadDefaults(&context.config, &opts);
context.gba->logHandler = GBA3DSLog;
context.gba->rotationSource = &rotation.d;
struct GBAVideoSoftwareRenderer renderer;
GBAVideoSoftwareRendererCreate(&renderer);
renderer.outputBuffer = anonymousMemoryMap(256 * VIDEO_VERTICAL_PIXELS * 2);
renderer.outputBufferStride = 256;
context.renderer = &renderer.d;
if (!font) { if (!font) {
goto cleanup; goto cleanup;
} }
struct GBAGUIRunner runner = {
.params = {
320, 240,
font, "/",
_drawStart, _drawEnd, _pollInput,
0, 0,
GUI_PARAMS_TRAIL
},
.setup = _setup,
.teardown = 0,
.gameLoaded = _gameLoaded,
.gameUnloaded = _gameUnloaded,
.prepareForFrame = 0,
.drawFrame = _drawFrame,
.pollGameInput = _pollGameInput
};
struct GUIParams params = { struct GUIParams params = {
320, 240, 320, 240,
font, "/", _drawStart, _drawEnd, _pollInput, 0, 0, font, "/", _drawStart, _drawEnd, _pollInput, 0, 0,
GUI_PARAMS_TRAIL GUI_PARAMS_TRAIL
}; };
GUIInit(&params); GBAGUIInit(&runner, 0);
GBAGUIRunloop(&runner);
while (aptMainLoop()) { GBAGUIDeinit(&runner);
char path[256];
if (!GUISelectFile(&params, path, sizeof(path), GBAIsROM)) {
break;
}
_drawStart();
GUIFontPrintf(font, 160, (GUIFontHeight(font) + 240) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
_drawEnd();
if (!GBAContextLoadROM(&context, path, true)) {
continue;
}
if (!GBAContextStart(&context)) {
continue;
}
if (context.gba->memory.hw.devices & HW_TILT) {
HIDUSER_EnableAccelerometer();
}
if (context.gba->memory.hw.devices & HW_GYRO) {
HIDUSER_EnableGyroscope();
}
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
blip_set_rates(context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 0x8000);
blip_set_rates(context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 0x8000);
#endif
memset(audioLeft, 0, AUDIO_SAMPLES * 2 * sizeof(int16_t));
memset(audioRight, 0, AUDIO_SAMPLES * 2 * sizeof(int16_t));
while (aptMainLoop()) {
hidScanInput();
uint32_t activeKeys = hidKeysHeld() & 0xF00003FF;
activeKeys |= activeKeys >> 24;
if (hidKeysDown() & KEY_X) {
break;
}
GBAContextFrame(&context, activeKeys);
GX_SetDisplayTransfer(0, renderer.outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202);
GSPGPU_FlushDataCache(0, tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2);
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
if (hasSound) {
memset(&audioLeft[audioPos], 0, AUDIO_SAMPLES);
memset(&audioRight[audioPos], 0, AUDIO_SAMPLES);
size_t samples = blip_read_samples(context.gba->audio.left, &audioLeft[audioPos], AUDIO_SAMPLES, false);
blip_read_samples(context.gba->audio.right, &audioRight[audioPos], AUDIO_SAMPLES, false);
size_t audioPosNew = (audioPos + AUDIO_SAMPLES) % (AUDIO_SAMPLES * 2);
GSPGPU_FlushDataCache(0, (void*) audioLeft, AUDIO_SAMPLES * 2 * sizeof(int16_t));
GSPGPU_FlushDataCache(0, (void*) audioRight, AUDIO_SAMPLES * 2 * sizeof(int16_t));
csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 0x8000, 1.0, -1.0, &audioLeft[audioPos], &audioLeft[audioPosNew], samples * 2);
csndPlaySound(0x9, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 0x8000, 1.0, 1.0, &audioRight[audioPos], &audioLeft[audioPosNew], samples * 2);
audioPos = audioPosNew;
} else {
blip_clear(context.gba->audio.left);
blip_clear(context.gba->audio.right);
}
#endif
gspWaitForPPF();
_drawStart();
sf2d_draw_texture_scale(tex, 40, 296, 1, -1);
_drawEnd();
}
GBAContextStop(&context);
CSND_SetPlayState(8, 0);
CSND_SetPlayState(9, 0);
csndExecCmds(0);
if (context.gba->memory.hw.devices & HW_TILT) {
HIDUSER_DisableAccelerometer();
}
if (context.gba->memory.hw.devices & HW_GYRO) {
HIDUSER_DisableGyroscope();
}
}
GBAContextDeinit(&context);
cleanup: cleanup:
mappedMemoryFree(renderer.outputBuffer, 0); mappedMemoryFree(renderer.outputBuffer, 0);