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/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(¶ms);
|
GBAGUIInit(&runner, 0);
|
||||||
|
GBAGUIRunloop(&runner);
|
||||||
while (aptMainLoop()) {
|
GBAGUIDeinit(&runner);
|
||||||
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);
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
mappedMemoryFree(renderer.outputBuffer, 0);
|
mappedMemoryFree(renderer.outputBuffer, 0);
|
||||||
|
|
Loading…
Reference in New Issue