all repos — mgba @ 08c6943c93a54c87f02fef408d560a3d96c5b3f1

mGBA Game Boy Advance Emulator

PSP2: Move running functionality into separate file
Jeffrey Pfau jeffrey@endrift.com
Mon, 27 Jul 2015 20:36:17 -0700
commit

08c6943c93a54c87f02fef408d560a3d96c5b3f1

parent

68e70b61f19b1e2b34e39be0c4dff35a84f2d313

3 files changed, 290 insertions(+), 229 deletions(-)

jump to
M src/platform/psp2/main.csrc/platform/psp2/main.c

@@ -3,242 +3,20 @@ *

* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "gba/gba.h" -#include "gba/input.h" -#include "gba/audio.h" -#include "gba/supervisor/overrides.h" -#include "gba/video.h" +#include "psp2-context.h" -#include "gba/renderers/video-software.h" -#include "util/circle-buffer.h" -#include "util/memory.h" -#include "util/threading.h" -#include "util/vfs.h" -#include "platform/psp2/sce-vfs.h" -#include "third-party/blip_buf/blip_buf.h" - -#include <psp2/audioout.h> -#include <psp2/ctrl.h> -#include <psp2/display.h> -#include <psp2/gxm.h> -#include <psp2/moduleinfo.h> #include <psp2/kernel/processmgr.h> -#include <psp2/kernel/sysmem.h> - -#include <vita2d.h> +#include <psp2/moduleinfo.h> PSP2_MODULE_INFO(0, 0, "mGBA"); -#define PSP2_HORIZONTAL_PIXELS 960 -#define PSP2_VERTICAL_PIXELS 544 -#define PSP2_INPUT 0x50535032 -#define PSP2_SAMPLES 64 -#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 19) - -struct GBAPSP2AudioContext { - struct CircleBuffer buffer; - Mutex mutex; - Condition cond; - bool running; -}; - -static void _mapVitaKey(struct GBAInputMap* map, int pspKey, enum GBAKey key) { - GBAInputBindKey(map, PSP2_INPUT, __builtin_ctz(pspKey), key); -} - -static THREAD_ENTRY _audioThread(void* context) { - struct GBAPSP2AudioContext* audio = (struct GBAPSP2AudioContext*) context; - struct GBAStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE]; - int audioPort = sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_AUDIO_BUFFER_SIZE, 48000, PSP2_AUDIO_OUT_MODE_STEREO); - while (audio->running) { - MutexLock(&audio->mutex); - int len = CircleBufferSize(&audio->buffer); - len /= sizeof(buffer[0]); - if (len > PSP2_AUDIO_BUFFER_SIZE) { - len = PSP2_AUDIO_BUFFER_SIZE; - } - if (len > 0) { - len &= ~(PSP2_AUDIO_MIN_LEN - 1); - CircleBufferRead(&audio->buffer, buffer, len * sizeof(buffer[0])); - MutexUnlock(&audio->mutex); - sceAudioOutSetConfig(audioPort, len, -1, -1); - sceAudioOutOutput(audioPort, buffer); - MutexLock(&audio->mutex); - } - ConditionWait(&audio->cond, &audio->mutex); - MutexUnlock(&audio->mutex); - } - sceAudioOutReleasePort(audioPort); - return 0; -} - int main() { printf("%s initializing", projectName); - bool running = true; - bool fullscreen = false; - bool fsToggle = false; - - struct GBAVideoSoftwareRenderer renderer; - GBAVideoSoftwareRendererCreate(&renderer); - - struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA)); - struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore)); - - printf("GBA: %08X", gba); - printf("CPU: %08X", cpu); - int activeKeys = 0; - - struct GBAInputMap inputMap; - GBAInputMapInit(&inputMap); - _mapVitaKey(&inputMap, PSP2_CTRL_CROSS, GBA_KEY_A); - _mapVitaKey(&inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B); - _mapVitaKey(&inputMap, PSP2_CTRL_START, GBA_KEY_START); - _mapVitaKey(&inputMap, PSP2_CTRL_SELECT, GBA_KEY_SELECT); - _mapVitaKey(&inputMap, PSP2_CTRL_UP, GBA_KEY_UP); - _mapVitaKey(&inputMap, PSP2_CTRL_DOWN, GBA_KEY_DOWN); - _mapVitaKey(&inputMap, PSP2_CTRL_LEFT, GBA_KEY_LEFT); - _mapVitaKey(&inputMap, PSP2_CTRL_RIGHT, GBA_KEY_RIGHT); - _mapVitaKey(&inputMap, PSP2_CTRL_LTRIGGER, GBA_KEY_L); - _mapVitaKey(&inputMap, PSP2_CTRL_RTRIGGER, GBA_KEY_R); - - struct GBAAxis desc = { GBA_KEY_DOWN, GBA_KEY_UP, 192, 64 }; - GBAInputBindAxis(&inputMap, PSP2_INPUT, 0, &desc); - desc = (struct GBAAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 }; - GBAInputBindAxis(&inputMap, PSP2_INPUT, 1, &desc); - - vita2d_init(); - vita2d_texture* tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); - - renderer.outputBuffer = vita2d_texture_get_datap(tex); - renderer.outputBufferStride = 256; - - struct VFile* rom = VFileOpenSce("cache0:/VitaDefilerClient/Documents/GBA/rom.gba", PSP2_O_RDONLY, 0666); - struct VFile* save = VFileOpenSce("cache0:/VitaDefilerClient/Documents/GBA/rom.sav", PSP2_O_RDWR | PSP2_O_CREAT, 0666); - - printf("ROM: %08X", rom); - printf("Save: %08X", save); - - GBACreate(gba); - ARMSetComponents(cpu, &gba->d, 0, 0); - ARMInit(cpu); - printf("%s initialized.", "CPU"); - - gba->keySource = &activeKeys; - gba->sync = 0; - - GBAVideoAssociateRenderer(&gba->video, &renderer.d); - - GBALoadROM(gba, rom, save, 0); - GBAOverrideApplyDefaults(gba); - printf("%s loaded.", "ROM"); - - ARMReset(cpu); - double ratio = GBAAudioCalculateRatio(1, 60, 1); - blip_set_rates(gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); - blip_set_rates(gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); - - struct GBAPSP2AudioContext audioContext; - CircleBufferInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE * sizeof(struct GBAStereoSample)); - MutexInit(&audioContext.mutex); - ConditionInit(&audioContext.cond); - audioContext.running = true; - Thread audioThread; - ThreadCreate(&audioThread, _audioThread, &audioContext); - - printf("%s all set and ready to roll.", projectName); - - int frameCounter = 0; - while (running) { - ARMRunLoop(cpu); - - if (frameCounter != gba->video.frameCounter) { - SceCtrlData pad; - sceCtrlPeekBufferPositive(0, &pad, 1); - if (pad.buttons & PSP2_CTRL_TRIANGLE) { - running = false; - break; - } - if (pad.buttons & PSP2_CTRL_SQUARE) { - if (!fsToggle) { - fullscreen = !fullscreen; - } - fsToggle = true; - } else { - fsToggle = false; - } - - activeKeys = GBAInputMapKeyBits(&inputMap, PSP2_INPUT, pad.buttons, 0); - enum GBAKey angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 0, pad.ly); - if (angles != GBA_KEY_NONE) { - activeKeys |= 1 << angles; - } - angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 1, pad.lx); - if (angles != GBA_KEY_NONE) { - activeKeys |= 1 << angles; - } - angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 2, pad.ry); - if (angles != GBA_KEY_NONE) { - activeKeys |= 1 << angles; - } - angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 3, pad.rx); - if (angles != GBA_KEY_NONE) { - activeKeys |= 1 << angles; - } - - MutexLock(&audioContext.mutex); - while (blip_samples_avail(gba->audio.left) >= PSP2_SAMPLES) { - if (CircleBufferSize(&audioContext.buffer) + PSP2_SAMPLES * sizeof(struct GBAStereoSample) > CircleBufferCapacity(&audioContext.buffer)) { - break; - } - struct GBAStereoSample samples[PSP2_SAMPLES]; - blip_read_samples(gba->audio.left, &samples[0].left, PSP2_SAMPLES, true); - blip_read_samples(gba->audio.right, &samples[0].right, PSP2_SAMPLES, true); - int i; - for (i = 0; i < PSP2_SAMPLES; ++i) { - CircleBufferWrite16(&audioContext.buffer, samples[i].left); - CircleBufferWrite16(&audioContext.buffer, samples[i].right); - } - } - ConditionWake(&audioContext.cond); - MutexUnlock(&audioContext.mutex); - - vita2d_start_drawing(); - vita2d_clear_screen(); - if (fullscreen) { - vita2d_draw_texture_scale(tex, 0, 0, 960.0f / 240.0f, 544.0f / 160.0f); - } else { - vita2d_draw_texture_scale(tex, 120, 32, 3.0f, 3.0f); - } - vita2d_end_drawing(); - vita2d_swap_buffers(); - - frameCounter = gba->video.frameCounter; - } - } - printf("%s shutting down...", projectName); - - ARMDeinit(cpu); - GBADestroy(gba); - - rom->close(rom); - save->close(save); - - GBAInputMapDeinit(&inputMap); - - MutexLock(&audioContext.mutex); - audioContext.running = false; - ConditionWake(&audioContext.cond); - MutexUnlock(&audioContext.mutex); - ThreadJoin(audioThread); - CircleBufferDeinit(&audioContext.buffer); - MutexDeinit(&audioContext.mutex); - ConditionDeinit(&audioContext.cond); - - mappedMemoryFree(gba, 0); - mappedMemoryFree(cpu, 0); - - vita2d_fini(); - vita2d_free_texture(tex); + GBAPSP2Setup(); + GBAPSP2LoadROM("cache0:/VitaDefilerClient/Documents/GBA/rom.gba"); + GBAPSP2Runloop(); + GBAPSP2UnloadROM(); + GBAPSP2Teardown(); sceKernelExitProcess(0); return 0;
A src/platform/psp2/psp2-context.c

@@ -0,0 +1,263 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "psp2-context.h" + +#include "gba/gba.h" +#include "gba/input.h" +#include "gba/audio.h" +#include "gba/supervisor/overrides.h" +#include "gba/video.h" + +#include "gba/renderers/video-software.h" +#include "util/circle-buffer.h" +#include "util/memory.h" +#include "util/threading.h" +#include "util/vfs.h" +#include "platform/psp2/sce-vfs.h" +#include "third-party/blip_buf/blip_buf.h" + +#include <psp2/audioout.h> +#include <psp2/ctrl.h> +#include <psp2/display.h> +#include <psp2/gxm.h> +#include <psp2/kernel/sysmem.h> + +#include <vita2d.h> + +static char gameName[13]; +static struct GBA* gba; +static struct ARMCore* cpu; +static struct VFile* rom; +static struct VFile* save; +static struct GBAVideoSoftwareRenderer renderer; +static struct GBAInputMap inputMap; +static vita2d_texture* tex; +static Thread audioThread; + +static bool fullscreen = false; + +#define PSP2_HORIZONTAL_PIXELS 960 +#define PSP2_VERTICAL_PIXELS 544 +#define PSP2_INPUT 0x50535032 +#define PSP2_SAMPLES 64 +#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 19) + +static struct GBAPSP2AudioContext { + struct CircleBuffer buffer; + Mutex mutex; + Condition cond; + bool running; +} audioContext; + +static void _mapVitaKey(struct GBAInputMap* map, int pspKey, enum GBAKey key) { + GBAInputBindKey(map, PSP2_INPUT, __builtin_ctz(pspKey), key); +} + +static THREAD_ENTRY _audioThread(void* context) { + struct GBAPSP2AudioContext* audio = (struct GBAPSP2AudioContext*) context; + struct GBAStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE]; + int audioPort = sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_AUDIO_BUFFER_SIZE, 48000, PSP2_AUDIO_OUT_MODE_STEREO); + while (audio->running) { + MutexLock(&audio->mutex); + int len = CircleBufferSize(&audio->buffer); + len /= sizeof(buffer[0]); + if (len > PSP2_AUDIO_BUFFER_SIZE) { + len = PSP2_AUDIO_BUFFER_SIZE; + } + if (len > 0) { + len &= ~(PSP2_AUDIO_MIN_LEN - 1); + CircleBufferRead(&audio->buffer, buffer, len * sizeof(buffer[0])); + MutexUnlock(&audio->mutex); + sceAudioOutSetConfig(audioPort, len, -1, -1); + sceAudioOutOutput(audioPort, buffer); + MutexLock(&audio->mutex); + } + ConditionWait(&audio->cond, &audio->mutex); + MutexUnlock(&audio->mutex); + } + sceAudioOutReleasePort(audioPort); + return 0; +} + +void GBAPSP2Setup() { + GBAInputMapInit(&inputMap); + _mapVitaKey(&inputMap, PSP2_CTRL_CROSS, GBA_KEY_A); + _mapVitaKey(&inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B); + _mapVitaKey(&inputMap, PSP2_CTRL_START, GBA_KEY_START); + _mapVitaKey(&inputMap, PSP2_CTRL_SELECT, GBA_KEY_SELECT); + _mapVitaKey(&inputMap, PSP2_CTRL_UP, GBA_KEY_UP); + _mapVitaKey(&inputMap, PSP2_CTRL_DOWN, GBA_KEY_DOWN); + _mapVitaKey(&inputMap, PSP2_CTRL_LEFT, GBA_KEY_LEFT); + _mapVitaKey(&inputMap, PSP2_CTRL_RIGHT, GBA_KEY_RIGHT); + _mapVitaKey(&inputMap, PSP2_CTRL_LTRIGGER, GBA_KEY_L); + _mapVitaKey(&inputMap, PSP2_CTRL_RTRIGGER, GBA_KEY_R); + + struct GBAAxis desc = { GBA_KEY_DOWN, GBA_KEY_UP, 192, 64 }; + GBAInputBindAxis(&inputMap, PSP2_INPUT, 0, &desc); + desc = (struct GBAAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 }; + GBAInputBindAxis(&inputMap, PSP2_INPUT, 1, &desc); + + vita2d_init(); + tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); + + renderer.outputBuffer = vita2d_texture_get_datap(tex); + renderer.outputBufferStride = 256; +} + +void GBAPSP2LoadROM(const char* path) { + GBAVideoSoftwareRendererCreate(&renderer); + + gba = anonymousMemoryMap(sizeof(struct GBA)); + cpu = anonymousMemoryMap(sizeof(struct ARMCore)); + + printf("GBA: %08X", gba); + printf("CPU: %08X", cpu); + + rom = VFileOpenSce(path, PSP2_O_RDONLY, 0666); + save = VDirOptionalOpenFile(0, path, 0, ".sav", PSP2_O_RDWR | PSP2_O_CREAT); + + printf("ROM: %08X", rom); + printf("Save: %08X", save); + + GBACreate(gba); + ARMSetComponents(cpu, &gba->d, 0, 0); + ARMInit(cpu); + printf("%s initialized.", "CPU"); + + gba->sync = 0; + + GBAVideoAssociateRenderer(&gba->video, &renderer.d); + + GBALoadROM(gba, rom, save, 0); + GBAOverrideApplyDefaults(gba); + GBAGetGameTitle(gba, gameName); + printf("ROM loaded: %s", gameName); + + ARMReset(cpu); + double ratio = GBAAudioCalculateRatio(1, 60, 1); + blip_set_rates(gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); + blip_set_rates(gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); + + CircleBufferInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE * sizeof(struct GBAStereoSample)); + MutexInit(&audioContext.mutex); + ConditionInit(&audioContext.cond); + audioContext.running = true; + ThreadCreate(&audioThread, _audioThread, &audioContext); + + printf("%s all set and ready to roll.", projectName); +} + +void GBAPSP2Runloop(void) { + int activeKeys = 0; + gba->keySource = &activeKeys; + + bool fsToggle = false; + int frameCounter = 0; + while (true) { + ARMRunLoop(cpu); + + if (frameCounter != gba->video.frameCounter) { + SceCtrlData pad; + sceCtrlPeekBufferPositive(0, &pad, 1); + if (pad.buttons & PSP2_CTRL_TRIANGLE) { + break; + } + if (pad.buttons & PSP2_CTRL_SQUARE) { + if (!fsToggle) { + fullscreen = !fullscreen; + } + fsToggle = true; + } else { + fsToggle = false; + } + + activeKeys = GBAInputMapKeyBits(&inputMap, PSP2_INPUT, pad.buttons, 0); + enum GBAKey angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 0, pad.ly); + if (angles != GBA_KEY_NONE) { + activeKeys |= 1 << angles; + } + angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 1, pad.lx); + if (angles != GBA_KEY_NONE) { + activeKeys |= 1 << angles; + } + angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 2, pad.ry); + if (angles != GBA_KEY_NONE) { + activeKeys |= 1 << angles; + } + angles = GBAInputMapAxis(&inputMap, PSP2_INPUT, 3, pad.rx); + if (angles != GBA_KEY_NONE) { + activeKeys |= 1 << angles; + } + + MutexLock(&audioContext.mutex); + while (blip_samples_avail(gba->audio.left) >= PSP2_SAMPLES) { + if (CircleBufferSize(&audioContext.buffer) + PSP2_SAMPLES * sizeof(struct GBAStereoSample) > CircleBufferCapacity(&audioContext.buffer)) { + break; + } + struct GBAStereoSample samples[PSP2_SAMPLES]; + blip_read_samples(gba->audio.left, &samples[0].left, PSP2_SAMPLES, true); + blip_read_samples(gba->audio.right, &samples[0].right, PSP2_SAMPLES, true); + int i; + for (i = 0; i < PSP2_SAMPLES; ++i) { + CircleBufferWrite16(&audioContext.buffer, samples[i].left); + CircleBufferWrite16(&audioContext.buffer, samples[i].right); + } + } + ConditionWake(&audioContext.cond); + MutexUnlock(&audioContext.mutex); + + vita2d_start_drawing(); + vita2d_clear_screen(); + GBAPSP2Draw(); + vita2d_end_drawing(); + vita2d_swap_buffers(); + + frameCounter = gba->video.frameCounter; + } + } +} + +void GBAPSP2UnloadROM(void) { + printf("%s shutting down...", projectName); + + ARMDeinit(cpu); + GBADestroy(gba); + + rom->close(rom); + save->close(save); + + MutexLock(&audioContext.mutex); + audioContext.running = false; + ConditionWake(&audioContext.cond); + MutexUnlock(&audioContext.mutex); + ThreadJoin(audioThread); + CircleBufferDeinit(&audioContext.buffer); + MutexDeinit(&audioContext.mutex); + ConditionDeinit(&audioContext.cond); + + mappedMemoryFree(gba, 0); + mappedMemoryFree(cpu, 0); + + gba = 0; + cpu = 0; + rom = 0; + save = 0; +} + +void GBAPSP2Teardown(void) { + GBAInputMapDeinit(&inputMap); + + vita2d_free_texture(tex); + vita2d_fini(); +} + +void GBAPSP2Draw(void) { + if (fullscreen) { + vita2d_draw_texture_scale(tex, 0, 0, 960.0f / 240.0f, 544.0f / 160.0f); + } else { + vita2d_draw_texture_scale(tex, 120, 32, 3.0f, 3.0f); + } +}
A src/platform/psp2/psp2-context.h

@@ -0,0 +1,20 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef PSP2_CONTEXT_H +#define PSP2_CONTEXT_H + +#include "util/common.h" + +void GBAPSP2Setup(void); +void GBAPSP2Teardown(void); + +void GBAPSP2LoadROM(const char* path); +void GBAPSP2Runloop(void); +void GBAPSP2UnloadROM(void); + +void GBAPSP2Draw(void); + +#endif