PSP2: Use GBAContext

This commit is contained in:
Jeffrey Pfau 2015-08-22 00:41:24 -07:00
parent 540e1ff1e6
commit c9b01e0aff
3 changed files with 94 additions and 140 deletions

View File

@ -72,7 +72,9 @@ int main() {
if (!selectFile(&params, "cache0:", path, sizeof(path), "gba")) { if (!selectFile(&params, "cache0:", path, sizeof(path), "gba")) {
break; break;
} }
GBAPSP2LoadROM(path); if (!GBAPSP2LoadROM(path)) {
continue;
}
GBAPSP2Runloop(); GBAPSP2Runloop();
GBAPSP2UnloadROM(); GBAPSP2UnloadROM();
} }

View File

@ -8,8 +8,7 @@
#include "gba/gba.h" #include "gba/gba.h"
#include "gba/input.h" #include "gba/input.h"
#include "gba/audio.h" #include "gba/audio.h"
#include "gba/supervisor/overrides.h" #include "gba/supervisor/context.h"
#include "gba/video.h"
#include "gba/renderers/video-software.h" #include "gba/renderers/video-software.h"
#include "util/circle-buffer.h" #include "util/circle-buffer.h"
@ -27,13 +26,8 @@
#include <vita2d.h> #include <vita2d.h>
static char gameName[13]; static struct GBAContext context;
static struct GBA* gba;
static struct ARMCore* cpu;
static struct VFile* rom;
static struct VFile* save;
static struct GBAVideoSoftwareRenderer renderer; static struct GBAVideoSoftwareRenderer renderer;
static struct GBAInputMap inputMap;
static vita2d_texture* tex; static vita2d_texture* tex;
static Thread audioThread; static Thread audioThread;
@ -81,172 +75,130 @@ static THREAD_ENTRY _audioThread(void* context) {
} }
void GBAPSP2Setup() { void GBAPSP2Setup() {
GBAInputMapInit(&inputMap); GBAContextInit(&context, 0);
_mapVitaKey(&inputMap, PSP2_CTRL_CROSS, GBA_KEY_A); struct GBAOptions opts = {
_mapVitaKey(&inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B); .useBios = true,
_mapVitaKey(&inputMap, PSP2_CTRL_START, GBA_KEY_START); .logLevel = 0,
_mapVitaKey(&inputMap, PSP2_CTRL_SELECT, GBA_KEY_SELECT); .idleOptimization = IDLE_LOOP_DETECT
_mapVitaKey(&inputMap, PSP2_CTRL_UP, GBA_KEY_UP); };
_mapVitaKey(&inputMap, PSP2_CTRL_DOWN, GBA_KEY_DOWN); GBAConfigLoadDefaults(&context.config, &opts);
_mapVitaKey(&inputMap, PSP2_CTRL_LEFT, GBA_KEY_LEFT); _mapVitaKey(&context.inputMap, PSP2_CTRL_CROSS, GBA_KEY_A);
_mapVitaKey(&inputMap, PSP2_CTRL_RIGHT, GBA_KEY_RIGHT); _mapVitaKey(&context.inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B);
_mapVitaKey(&inputMap, PSP2_CTRL_LTRIGGER, GBA_KEY_L); _mapVitaKey(&context.inputMap, PSP2_CTRL_START, GBA_KEY_START);
_mapVitaKey(&inputMap, PSP2_CTRL_RTRIGGER, GBA_KEY_R); _mapVitaKey(&context.inputMap, PSP2_CTRL_SELECT, GBA_KEY_SELECT);
_mapVitaKey(&context.inputMap, PSP2_CTRL_UP, GBA_KEY_UP);
_mapVitaKey(&context.inputMap, PSP2_CTRL_DOWN, GBA_KEY_DOWN);
_mapVitaKey(&context.inputMap, PSP2_CTRL_LEFT, GBA_KEY_LEFT);
_mapVitaKey(&context.inputMap, PSP2_CTRL_RIGHT, GBA_KEY_RIGHT);
_mapVitaKey(&context.inputMap, PSP2_CTRL_LTRIGGER, GBA_KEY_L);
_mapVitaKey(&context.inputMap, PSP2_CTRL_RTRIGGER, GBA_KEY_R);
struct GBAAxis desc = { GBA_KEY_DOWN, GBA_KEY_UP, 192, 64 }; struct GBAAxis desc = { GBA_KEY_DOWN, GBA_KEY_UP, 192, 64 };
GBAInputBindAxis(&inputMap, PSP2_INPUT, 0, &desc); GBAInputBindAxis(&context.inputMap, PSP2_INPUT, 0, &desc);
desc = (struct GBAAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 }; desc = (struct GBAAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 };
GBAInputBindAxis(&inputMap, PSP2_INPUT, 1, &desc); GBAInputBindAxis(&context.inputMap, PSP2_INPUT, 1, &desc);
tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
GBAVideoSoftwareRendererCreate(&renderer);
renderer.outputBuffer = vita2d_texture_get_datap(tex); renderer.outputBuffer = vita2d_texture_get_datap(tex);
renderer.outputBufferStride = 256; renderer.outputBufferStride = 256;
GBAVideoAssociateRenderer(&context.gba->video, &renderer.d);
printf("%s starting", projectName);
} }
void GBAPSP2LoadROM(const char* path) { bool GBAPSP2LoadROM(const char* path) {
GBAVideoSoftwareRendererCreate(&renderer); if (!GBAContextLoadROM(&context, path, true)) {
printf("%s failed to load!", path);
gba = anonymousMemoryMap(sizeof(struct GBA)); return false;
cpu = anonymousMemoryMap(sizeof(struct ARMCore)); }
printf("%s loaded, starting...", path);
printf("GBA: %08X", gba); GBAContextStart(&context);
printf("CPU: %08X", cpu); char gameTitle[13];
GBAGetGameTitle(context.gba, gameTitle);
rom = VFileOpenSce(path, PSP2_O_RDONLY, 0666); printf("%s started!", gameTitle);
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); double ratio = GBAAudioCalculateRatio(1, 60, 1);
blip_set_rates(gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); blip_set_rates(context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio);
blip_set_rates(gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio); blip_set_rates(context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000 * ratio);
CircleBufferInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE * sizeof(struct GBAStereoSample)); CircleBufferInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE * sizeof(struct GBAStereoSample));
MutexInit(&audioContext.mutex); MutexInit(&audioContext.mutex);
ConditionInit(&audioContext.cond); ConditionInit(&audioContext.cond);
audioContext.running = true; audioContext.running = true;
ThreadCreate(&audioThread, _audioThread, &audioContext); ThreadCreate(&audioThread, _audioThread, &audioContext);
return true;
printf("%s all set and ready to roll.", projectName);
} }
void GBAPSP2Runloop(void) { void GBAPSP2Runloop(void) {
int activeKeys = 0; int activeKeys = 0;
gba->keySource = &activeKeys;
bool fsToggle = false; bool fsToggle = false;
int frameCounter = 0;
while (true) { while (true) {
ARMRunLoop(cpu); 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;
}
if (frameCounter != gba->video.frameCounter) { activeKeys = GBAInputMapKeyBits(&context.inputMap, PSP2_INPUT, pad.buttons, 0);
SceCtrlData pad; enum GBAKey angles = GBAInputMapAxis(&context.inputMap, PSP2_INPUT, 0, pad.ly);
sceCtrlPeekBufferPositive(0, &pad, 1); if (angles != GBA_KEY_NONE) {
if (pad.buttons & PSP2_CTRL_TRIANGLE) { activeKeys |= 1 << angles;
}
angles = GBAInputMapAxis(&context.inputMap, PSP2_INPUT, 1, pad.lx);
if (angles != GBA_KEY_NONE) {
activeKeys |= 1 << angles;
}
angles = GBAInputMapAxis(&context.inputMap, PSP2_INPUT, 2, pad.ry);
if (angles != GBA_KEY_NONE) {
activeKeys |= 1 << angles;
}
angles = GBAInputMapAxis(&context.inputMap, PSP2_INPUT, 3, pad.rx);
if (angles != GBA_KEY_NONE) {
activeKeys |= 1 << angles;
}
GBAContextFrame(&context, activeKeys);
MutexLock(&audioContext.mutex);
while (blip_samples_avail(context.gba->audio.left) >= PSP2_SAMPLES) {
if (CircleBufferSize(&audioContext.buffer) + PSP2_SAMPLES * sizeof(struct GBAStereoSample) > CircleBufferCapacity(&audioContext.buffer)) {
break; break;
} }
if (pad.buttons & PSP2_CTRL_SQUARE) { struct GBAStereoSample samples[PSP2_SAMPLES];
if (!fsToggle) { blip_read_samples(context.gba->audio.left, &samples[0].left, PSP2_SAMPLES, true);
fullscreen = !fullscreen; blip_read_samples(context.gba->audio.right, &samples[0].right, PSP2_SAMPLES, true);
} int i;
fsToggle = true; for (i = 0; i < PSP2_SAMPLES; ++i) {
} else { CircleBufferWrite16(&audioContext.buffer, samples[i].left);
fsToggle = false; CircleBufferWrite16(&audioContext.buffer, samples[i].right);
} }
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;
} }
ConditionWake(&audioContext.cond);
MutexUnlock(&audioContext.mutex);
vita2d_start_drawing();
vita2d_clear_screen();
GBAPSP2Draw();
vita2d_end_drawing();
vita2d_swap_buffers();
} }
} }
void GBAPSP2UnloadROM(void) { void GBAPSP2UnloadROM(void) {
printf("%s shutting down...", projectName); GBAContextStop(&context);
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) { void GBAPSP2Teardown(void) {
GBAInputMapDeinit(&inputMap); GBAContextDeinit(&context);
vita2d_free_texture(tex); vita2d_free_texture(tex);
} }

View File

@ -11,7 +11,7 @@
void GBAPSP2Setup(void); void GBAPSP2Setup(void);
void GBAPSP2Teardown(void); void GBAPSP2Teardown(void);
void GBAPSP2LoadROM(const char* path); bool GBAPSP2LoadROM(const char* path);
void GBAPSP2Runloop(void); void GBAPSP2Runloop(void);
void GBAPSP2UnloadROM(void); void GBAPSP2UnloadROM(void);