mirror of https://github.com/mgba-emu/mgba.git
3DS: Use runner
This commit is contained in:
parent
3157a3d949
commit
cc1fb12d2f
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "gba/renderers/video-software.h"
|
||||
#include "gba/context/context.h"
|
||||
#include "gba/context/gui-runner.h"
|
||||
#include "gba/video.h"
|
||||
#include "util/gui.h"
|
||||
#include "util/gui/file-select.h"
|
||||
|
@ -21,24 +22,111 @@
|
|||
|
||||
FS_archive sdmcArchive;
|
||||
|
||||
struct GBA3DSRotationSource {
|
||||
static struct GBA3DSRotationSource {
|
||||
struct GBARotationSource d;
|
||||
accelVector accel;
|
||||
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);
|
||||
static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
|
||||
static struct VFile* logFile;
|
||||
|
||||
static void _drawStart(void) {
|
||||
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||
}
|
||||
|
||||
static void _drawEnd(void) {
|
||||
sf2d_end_frame();
|
||||
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) {
|
||||
hidScanInput();
|
||||
int keys = 0;
|
||||
|
@ -90,10 +178,8 @@ static int32_t _readGyroZ(struct GBARotationSource* source) {
|
|||
}
|
||||
|
||||
int main() {
|
||||
bool hasSound = !csndInit();
|
||||
hasSound = !csndInit();
|
||||
|
||||
struct GBAContext context;
|
||||
struct GBA3DSRotationSource rotation;
|
||||
rotation.d.sample = _sampleRotation;
|
||||
rotation.d.readTiltX = _readTiltX;
|
||||
rotation.d.readTiltY = _readTiltY;
|
||||
|
@ -103,9 +189,6 @@ int main() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int16_t* audioLeft = 0;
|
||||
int16_t* audioRight = 0;
|
||||
size_t audioPos = 0;
|
||||
if (hasSound) {
|
||||
audioLeft = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t));
|
||||
audioRight = linearAlloc(AUDIO_SAMPLES * 2 * sizeof(int16_t));
|
||||
|
@ -113,7 +196,7 @@ int main() {
|
|||
|
||||
sf2d_init();
|
||||
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);
|
||||
|
||||
sdmcArchive = (FS_archive) {
|
||||
|
@ -126,109 +209,36 @@ int main() {
|
|||
logFile = VFileOpen("/mgba.log", O_WRONLY | O_CREAT | O_TRUNC);
|
||||
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) {
|
||||
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 = {
|
||||
320, 240,
|
||||
font, "/", _drawStart, _drawEnd, _pollInput, 0, 0,
|
||||
|
||||
GUI_PARAMS_TRAIL
|
||||
};
|
||||
GUIInit(¶ms);
|
||||
|
||||
while (aptMainLoop()) {
|
||||
char path[256];
|
||||
if (!GUISelectFile(¶ms, 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);
|
||||
GBAGUIInit(&runner, 0);
|
||||
GBAGUIRunloop(&runner);
|
||||
GBAGUIDeinit(&runner);
|
||||
|
||||
cleanup:
|
||||
mappedMemoryFree(renderer.outputBuffer, 0);
|
||||
|
|
Loading…
Reference in New Issue