mirror of https://github.com/mgba-emu/mgba.git
GBA: Add GBACore
This commit is contained in:
parent
28268a601b
commit
33a4c45f3f
|
@ -23,6 +23,7 @@ typedef uint32_t color_t;
|
||||||
#define BYTES_PER_PIXEL 4
|
#define BYTES_PER_PIXEL 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct blip_t;
|
||||||
struct mCoreSync;
|
struct mCoreSync;
|
||||||
struct mCore {
|
struct mCore {
|
||||||
void* cpu;
|
void* cpu;
|
||||||
|
@ -40,6 +41,8 @@ struct mCore {
|
||||||
void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height);
|
void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height);
|
||||||
void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride);
|
void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride);
|
||||||
|
|
||||||
|
struct blip_t* (*getAudioChannel)(struct mCore*, int ch);
|
||||||
|
|
||||||
bool (*isROM)(struct VFile* vf);
|
bool (*isROM)(struct VFile* vf);
|
||||||
bool (*loadROM)(struct mCore*, struct VFile* vf);
|
bool (*loadROM)(struct mCore*, struct VFile* vf);
|
||||||
bool (*loadSave)(struct mCore*, struct VFile* vf);
|
bool (*loadSave)(struct mCore*, struct VFile* vf);
|
||||||
|
|
|
@ -72,6 +72,18 @@ static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t st
|
||||||
gbcore->renderer.outputBufferStride = stride;
|
gbcore->renderer.outputBufferStride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) {
|
||||||
|
struct GB* gb = core->board;
|
||||||
|
switch (ch) {
|
||||||
|
case 0:
|
||||||
|
return gb->audio.left;
|
||||||
|
case 1:
|
||||||
|
return gb->audio.right;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
|
static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
|
||||||
return GBLoadROM(core->board, vf);
|
return GBLoadROM(core->board, vf);
|
||||||
}
|
}
|
||||||
|
@ -158,6 +170,7 @@ struct mCore* GBCoreCreate(void) {
|
||||||
core->setSync = _GBCoreSetSync;
|
core->setSync = _GBCoreSetSync;
|
||||||
core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
|
core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
|
||||||
core->setVideoBuffer = _GBCoreSetVideoBuffer;
|
core->setVideoBuffer = _GBCoreSetVideoBuffer;
|
||||||
|
core->getAudioChannel = _GBCoreGetAudioChannel;
|
||||||
core->isROM = GBIsROM;
|
core->isROM = GBIsROM;
|
||||||
core->loadROM = _GBCoreLoadROM;
|
core->loadROM = _GBCoreLoadROM;
|
||||||
core->loadSave = _GBCoreLoadSave;
|
core->loadSave = _GBCoreLoadSave;
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* Copyright (c) 2013-2016 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 "core.h"
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/log.h"
|
||||||
|
#include "gba/gba.h"
|
||||||
|
#include "gba/renderers/video-software.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
|
struct GBACore {
|
||||||
|
struct mCore d;
|
||||||
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
|
int keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _GBACoreInit(struct mCore* core) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
|
||||||
|
struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore));
|
||||||
|
struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA));
|
||||||
|
if (!cpu || !gba) {
|
||||||
|
free(cpu);
|
||||||
|
free(gba);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
core->cpu = cpu;
|
||||||
|
core->board = gba;
|
||||||
|
|
||||||
|
GBACreate(gba);
|
||||||
|
// TODO: Restore debugger and cheats
|
||||||
|
ARMSetComponents(cpu, &gba->d, 0, 0);
|
||||||
|
ARMInit(cpu);
|
||||||
|
|
||||||
|
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
|
||||||
|
GBAVideoAssociateRenderer(&gba->video, &gbacore->renderer.d);
|
||||||
|
|
||||||
|
gba->keySource = &gbacore->keys;
|
||||||
|
|
||||||
|
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||||
|
mDirectorySetInit(&core->dirs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreDeinit(struct mCore* core) {
|
||||||
|
ARMDeinit(core->cpu);
|
||||||
|
GBADestroy(core->board);
|
||||||
|
mappedMemoryFree(core->cpu, sizeof(struct ARMCore));
|
||||||
|
mappedMemoryFree(core->board, sizeof(struct GBA));
|
||||||
|
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||||
|
mDirectorySetDeinit(&core->dirs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreSetSync(struct mCore* core, struct mCoreSync* sync) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
gba->sync = sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
|
||||||
|
UNUSED(core);
|
||||||
|
*width = VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
*height = VIDEO_VERTICAL_PIXELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
gbacore->renderer.outputBuffer = buffer;
|
||||||
|
gbacore->renderer.outputBufferStride = stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
switch (ch) {
|
||||||
|
case 0:
|
||||||
|
return gba->audio.psg.left;
|
||||||
|
case 1:
|
||||||
|
return gba->audio.psg.right;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
|
||||||
|
return GBALoadROM2(core->board, vf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _GBACoreLoadSave(struct mCore* core, struct VFile* vf) {
|
||||||
|
return GBALoadSave(core->board, vf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _GBACoreLoadPatch(struct mCore* core, struct VFile* vf) {
|
||||||
|
// TODO
|
||||||
|
UNUSED(core);
|
||||||
|
UNUSED(vf);
|
||||||
|
mLOG(GBA, STUB, "Patches are not yet supported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreUnloadROM(struct mCore* core) {
|
||||||
|
return GBAUnloadROM(core->board);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreReset(struct mCore* core) {
|
||||||
|
ARMReset(core->cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreRunFrame(struct mCore* core) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
int32_t frameCounter = gba->video.frameCounter;
|
||||||
|
while (gba->video.frameCounter == frameCounter) {
|
||||||
|
ARMRunLoop(core->cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreRunLoop(struct mCore* core) {
|
||||||
|
ARMRunLoop(core->cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreStep(struct mCore* core) {
|
||||||
|
ARMRun(core->cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
gbacore->keys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
gbacore->keys |= keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
gbacore->keys &= ~keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t _GBACoreFrameCounter(struct mCore* core) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
return gba->video.frameCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t _GBACoreFrameCycles(struct mCore* core) {
|
||||||
|
UNUSED(core);
|
||||||
|
return VIDEO_TOTAL_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t _GBACoreFrequency(struct mCore* core) {
|
||||||
|
UNUSED(core);
|
||||||
|
return GBA_ARM7TDMI_FREQUENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
gba->rtcSource = rtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mCore* GBACoreCreate(void) {
|
||||||
|
struct GBACore* gbacore = malloc(sizeof(*gbacore));
|
||||||
|
struct mCore* core = &gbacore->d;
|
||||||
|
core->cpu = 0;
|
||||||
|
core->board = 0;
|
||||||
|
core->init = _GBACoreInit;
|
||||||
|
core->deinit = _GBACoreDeinit;
|
||||||
|
core->setSync = _GBACoreSetSync;
|
||||||
|
core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions;
|
||||||
|
core->setVideoBuffer = _GBACoreSetVideoBuffer;
|
||||||
|
core->getAudioChannel = _GBACoreGetAudioChannel;
|
||||||
|
core->isROM = GBAIsROM;
|
||||||
|
core->loadROM = _GBACoreLoadROM;
|
||||||
|
core->loadSave = _GBACoreLoadSave;
|
||||||
|
core->loadPatch = _GBACoreLoadPatch;
|
||||||
|
core->unloadROM = _GBACoreUnloadROM;
|
||||||
|
core->reset = _GBACoreReset;
|
||||||
|
core->runFrame = _GBACoreRunFrame;
|
||||||
|
core->runLoop = _GBACoreRunLoop;
|
||||||
|
core->step = _GBACoreStep;
|
||||||
|
core->setKeys = _GBACoreSetKeys;
|
||||||
|
core->addKeys = _GBACoreAddKeys;
|
||||||
|
core->clearKeys = _GBACoreClearKeys;
|
||||||
|
core->frameCounter = _GBACoreFrameCounter;
|
||||||
|
core->frameCycles = _GBACoreFrameCycles;
|
||||||
|
core->frequency = _GBACoreFrequency;
|
||||||
|
core->setRTC = _GBACoreSetRTC;
|
||||||
|
return core;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/* Copyright (c) 2013-2016 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 GBA_CORE_H
|
||||||
|
#define GBA_CORE_H
|
||||||
|
|
||||||
|
struct mCore;
|
||||||
|
struct mCore* GBACoreCreate(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -22,6 +22,8 @@
|
||||||
#include "util/patch.h"
|
#include "util/patch.h"
|
||||||
#include "util/vfs.h"
|
#include "util/vfs.h"
|
||||||
|
|
||||||
|
mLOG_DEFINE_CATEGORY(GBA, "GBA");
|
||||||
|
|
||||||
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
||||||
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
||||||
|
|
||||||
|
@ -443,7 +445,7 @@ bool GBALoadMB(struct GBA* gba, struct VFile* vf, const char* fname) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) {
|
bool GBALoadROM2(struct GBA* gba, struct VFile* vf) {
|
||||||
GBAUnloadROM(gba);
|
GBAUnloadROM(gba);
|
||||||
gba->romVf = vf;
|
gba->romVf = vf;
|
||||||
gba->pristineRomSize = vf->size(vf);
|
gba->pristineRomSize = vf->size(vf);
|
||||||
|
@ -466,14 +468,26 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char
|
||||||
}
|
}
|
||||||
gba->yankedRomSize = 0;
|
gba->yankedRomSize = 0;
|
||||||
gba->memory.rom = gba->pristineRom;
|
gba->memory.rom = gba->pristineRom;
|
||||||
gba->activeFile = fname;
|
|
||||||
gba->memory.romSize = gba->pristineRomSize;
|
gba->memory.romSize = gba->pristineRomSize;
|
||||||
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
|
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
|
||||||
gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
|
gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
|
||||||
GBASavedataInit(&gba->memory.savedata, sav);
|
|
||||||
GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
|
GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
|
||||||
return true;
|
|
||||||
// TODO: error check
|
// TODO: error check
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) {
|
||||||
|
if (!GBALoadROM2(gba, vf)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gba->activeFile = fname;
|
||||||
|
GBALoadSave(gba, sav);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GBALoadSave(struct GBA* gba, struct VFile* sav) {
|
||||||
|
GBASavedataInit(&gba->memory.savedata, sav);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAYankROM(struct GBA* gba) {
|
void GBAYankROM(struct GBA* gba) {
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm/arm.h"
|
||||||
|
#include "core/log.h"
|
||||||
#include "debugger/debugger.h"
|
#include "debugger/debugger.h"
|
||||||
|
|
||||||
#include "gba/interface.h"
|
#include "gba/interface.h"
|
||||||
|
@ -59,6 +60,8 @@ struct GBAThread;
|
||||||
struct Patch;
|
struct Patch;
|
||||||
struct VFile;
|
struct VFile;
|
||||||
|
|
||||||
|
mLOG_DECLARE_CATEGORY(GBA);
|
||||||
|
|
||||||
DECL_BITFIELD(GBATimerFlags, uint32_t);
|
DECL_BITFIELD(GBATimerFlags, uint32_t);
|
||||||
DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4);
|
DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4);
|
||||||
DECL_BIT(GBATimerFlags, CountUp, 4);
|
DECL_BIT(GBATimerFlags, CountUp, 4);
|
||||||
|
@ -171,6 +174,8 @@ void GBASetBreakpoint(struct GBA* gba, struct ARMComponent* component, uint32_t
|
||||||
void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
||||||
|
|
||||||
bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname);
|
bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname);
|
||||||
|
bool GBALoadROM2(struct GBA* gba, struct VFile* vf);
|
||||||
|
bool GBALoadSave(struct GBA* gba, struct VFile* sav);
|
||||||
void GBAYankROM(struct GBA* gba);
|
void GBAYankROM(struct GBA* gba);
|
||||||
void GBAUnloadROM(struct GBA* gba);
|
void GBAUnloadROM(struct GBA* gba);
|
||||||
void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
|
void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
|
||||||
|
|
|
@ -20,7 +20,7 @@ AudioProcessorSDL::AudioProcessorSDL(QObject* parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProcessorSDL::~AudioProcessorSDL() {
|
AudioProcessorSDL::~AudioProcessorSDL() {
|
||||||
GBSDLDeinitAudio(&m_audio);
|
mSDLDeinitAudio(&m_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioProcessorSDL::start() {
|
bool AudioProcessorSDL::start() {
|
||||||
|
@ -30,26 +30,26 @@ bool AudioProcessorSDL::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_audio.thread) {
|
if (m_audio.thread) {
|
||||||
GBSDLResumeAudio(&m_audio);
|
mSDLResumeAudio(&m_audio);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (!m_audio.samples) {
|
if (!m_audio.samples) {
|
||||||
m_audio.samples = input()->audioBuffers;
|
m_audio.samples = input()->audioBuffers;
|
||||||
}
|
}
|
||||||
return GBSDLInitAudio(&m_audio, input());
|
return mSDLInitAudio(&m_audio, input());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessorSDL::pause() {
|
void AudioProcessorSDL::pause() {
|
||||||
GBSDLPauseAudio(&m_audio);
|
mSDLPauseAudio(&m_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessorSDL::setBufferSamples(int samples) {
|
void AudioProcessorSDL::setBufferSamples(int samples) {
|
||||||
AudioProcessor::setBufferSamples(samples);
|
AudioProcessor::setBufferSamples(samples);
|
||||||
m_audio.samples = samples;
|
m_audio.samples = samples;
|
||||||
if (m_audio.thread) {
|
if (m_audio.thread) {
|
||||||
GBSDLDeinitAudio(&m_audio);
|
mSDLDeinitAudio(&m_audio);
|
||||||
GBSDLInitAudio(&m_audio, input());
|
mSDLInitAudio(&m_audio, input());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ void AudioProcessorSDL::inputParametersChanged() {
|
||||||
void AudioProcessorSDL::requestSampleRate(unsigned rate) {
|
void AudioProcessorSDL::requestSampleRate(unsigned rate) {
|
||||||
m_audio.sampleRate = rate;
|
m_audio.sampleRate = rate;
|
||||||
if (m_audio.thread) {
|
if (m_audio.thread) {
|
||||||
GBSDLDeinitAudio(&m_audio);
|
mSDLDeinitAudio(&m_audio);
|
||||||
GBSDLInitAudio(&m_audio, input());
|
mSDLInitAudio(&m_audio, input());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public slots:
|
||||||
virtual void requestSampleRate(unsigned) override;
|
virtual void requestSampleRate(unsigned) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GBSDLAudio m_audio;
|
mSDLAudio m_audio;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ endif()
|
||||||
if(BUILD_PANDORA)
|
if(BUILD_PANDORA)
|
||||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/pandora-sdl.c)
|
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/pandora-sdl.c)
|
||||||
else()
|
else()
|
||||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl.c)
|
#list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl.c)
|
||||||
if(BUILD_GL)
|
if(BUILD_GL)
|
||||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c)
|
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c)
|
||||||
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
|
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
|
||||||
|
|
|
@ -8,13 +8,7 @@
|
||||||
#include "gl-common.h"
|
#include "gl-common.h"
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#ifdef M_CORE_GBA
|
#include "core/thread.h"
|
||||||
#include "gba/supervisor/thread.h"
|
|
||||||
#endif
|
|
||||||
#ifdef M_CORE_GB
|
|
||||||
#include "gb/core.h"
|
|
||||||
#include "gb/gb.h"
|
|
||||||
#endif
|
|
||||||
#include "platform/opengl/gl.h"
|
#include "platform/opengl/gl.h"
|
||||||
|
|
||||||
#define GB_GBA_CENTER ((VIDEO_HORIZONTAL_PIXELS - GB_VIDEO_HORIZONTAL_PIXELS + VIDEO_HORIZONTAL_PIXELS * (VIDEO_VERTICAL_PIXELS - GB_VIDEO_VERTICAL_PIXELS)) / 2)
|
#define GB_GBA_CENTER ((VIDEO_HORIZONTAL_PIXELS - GB_VIDEO_HORIZONTAL_PIXELS + VIDEO_HORIZONTAL_PIXELS * (VIDEO_VERTICAL_PIXELS - GB_VIDEO_VERTICAL_PIXELS)) / 2)
|
||||||
|
@ -27,28 +21,32 @@ static void _doViewport(int w, int h, struct VideoBackend* v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
|
#include "gba/gba.h"
|
||||||
|
|
||||||
static bool mSDLGLInitGBA(struct mSDLRenderer* renderer);
|
static bool mSDLGLInitGBA(struct mSDLRenderer* renderer);
|
||||||
static void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user);
|
|
||||||
static void mSDLGLDeinitGBA(struct mSDLRenderer* renderer);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
|
#include "gb/gb.h"
|
||||||
|
|
||||||
static bool mSDLGLInitGB(struct mSDLRenderer* renderer);
|
static bool mSDLGLInitGB(struct mSDLRenderer* renderer);
|
||||||
static void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user);
|
|
||||||
static void mSDLGLDeinitGB(struct mSDLRenderer* renderer);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user);
|
||||||
|
static void mSDLGLDeinit(struct mSDLRenderer* renderer);
|
||||||
|
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
void mSDLGLCreate(struct mSDLRenderer* renderer) {
|
void mSDLGLCreateGBA(struct mSDLRenderer* renderer) {
|
||||||
renderer->init = mSDLGLInitGBA;
|
renderer->init = mSDLGLInitGBA;
|
||||||
renderer->deinit = mSDLGLDeinitGBA;
|
renderer->deinit = mSDLGLDeinit;
|
||||||
renderer->runloop = mSDLGLRunloopGBA;
|
renderer->runloop = mSDLGLRunloop;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
|
bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
|
||||||
mSDLGLCommonInit(renderer);
|
mSDLGLCommonInit(renderer);
|
||||||
|
|
||||||
renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
||||||
renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
|
memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
||||||
|
renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, VIDEO_HORIZONTAL_PIXELS);
|
||||||
|
|
||||||
GBAGLContextCreate(&renderer->gl);
|
GBAGLContextCreate(&renderer->gl);
|
||||||
renderer->gl.d.user = renderer;
|
renderer->gl.d.user = renderer;
|
||||||
|
@ -60,53 +58,13 @@ bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
|
||||||
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user) {
|
|
||||||
struct GBAThread* context = user;
|
|
||||||
SDL_Event event;
|
|
||||||
struct VideoBackend* v = &renderer->gl.d;
|
|
||||||
renderer->audio.psg = &context->gba->audio.psg;
|
|
||||||
|
|
||||||
while (context->state < THREAD_EXITING) {
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
mSDLHandleEventGBA(context, &renderer->player, &event);
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
// Event handling can change the size of the screen
|
|
||||||
if (renderer->player.windowUpdated) {
|
|
||||||
SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
|
|
||||||
_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
|
|
||||||
renderer->player.windowUpdated = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCoreSyncWaitFrameStart(&context->sync)) {
|
|
||||||
v->postFrame(v, renderer->d.outputBuffer);
|
|
||||||
}
|
|
||||||
mCoreSyncWaitFrameEnd(&context->sync);
|
|
||||||
v->drawFrame(v);
|
|
||||||
v->swap(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer->audio.psg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mSDLGLDeinitGBA(struct mSDLRenderer* renderer) {
|
|
||||||
if (renderer->gl.d.deinit) {
|
|
||||||
renderer->gl.d.deinit(&renderer->gl.d);
|
|
||||||
}
|
|
||||||
free(renderer->d.outputBuffer);
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
SDL_GL_DeleteContext(renderer->glCtx);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
|
void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
|
||||||
renderer->init = mSDLGLInitGB;
|
renderer->init = mSDLGLInitGB;
|
||||||
renderer->deinit = mSDLGLDeinitGB;
|
renderer->deinit = mSDLGLDeinit;
|
||||||
renderer->runloop = mSDLGLRunloopGB;
|
renderer->runloop = mSDLGLRunloop;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
|
bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
|
||||||
|
@ -127,12 +85,12 @@ bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
|
||||||
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
|
void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user) {
|
||||||
struct mCoreThread* context = user;
|
struct mCoreThread* context = user;
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
struct VideoBackend* v = &renderer->gl.d;
|
struct VideoBackend* v = &renderer->gl.d;
|
||||||
renderer->audio.psg = &((struct GB*) renderer->core->board)->audio;
|
|
||||||
|
|
||||||
while (context->state < THREAD_EXITING) {
|
while (context->state < THREAD_EXITING) {
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
|
@ -154,10 +112,9 @@ void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
|
||||||
v->drawFrame(v);
|
v->drawFrame(v);
|
||||||
v->swap(v);
|
v->swap(v);
|
||||||
}
|
}
|
||||||
renderer->audio.psg = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
|
void mSDLGLDeinit(struct mSDLRenderer* renderer) {
|
||||||
if (renderer->gl.d.deinit) {
|
if (renderer->gl.d.deinit) {
|
||||||
renderer->gl.d.deinit(&renderer->gl.d);
|
renderer->gl.d.deinit(&renderer->gl.d);
|
||||||
}
|
}
|
||||||
|
@ -166,4 +123,3 @@ void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
|
||||||
SDL_GL_DeleteContext(renderer->glCtx);
|
SDL_GL_DeleteContext(renderer->glCtx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/config.h"
|
#include "core/config.h"
|
||||||
|
#include "core/input.h"
|
||||||
#include "core/thread.h"
|
#include "core/thread.h"
|
||||||
|
#include "gba/input.h"
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
|
#include "gba/core.h"
|
||||||
#include "gba/gba.h"
|
#include "gba/gba.h"
|
||||||
#include "gba/supervisor/thread.h"
|
#include "gba/supervisor/thread.h"
|
||||||
#include "gba/video.h"
|
#include "gba/video.h"
|
||||||
|
@ -52,9 +55,7 @@ static void mSDLDeinit(struct mSDLRenderer* renderer);
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
static int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config);
|
static int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config);
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GB
|
static int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args);
|
||||||
static int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -119,9 +120,9 @@ int main(int argc, char** argv) {
|
||||||
if (!opts.height) {
|
if (!opts.height) {
|
||||||
opts.height = VIDEO_VERTICAL_PIXELS;
|
opts.height = VIDEO_VERTICAL_PIXELS;
|
||||||
}
|
}
|
||||||
GBAVideoSoftwareRendererCreate(&renderer.d);
|
renderer.core = GBACoreCreate();
|
||||||
#ifdef BUILD_GL
|
#ifdef BUILD_GL
|
||||||
mSDLGLCreate(&renderer);
|
mSDLGLCreateGBA(&renderer);
|
||||||
#elif defined(BUILD_GLES2) || defined(USE_EPOXY)
|
#elif defined(BUILD_GLES2) || defined(USE_EPOXY)
|
||||||
mSDLGLES2Create(&renderer);
|
mSDLGLES2Create(&renderer);
|
||||||
#else
|
#else
|
||||||
|
@ -149,7 +150,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
printf("Could not run game. Are you sure the file exists and is a Game Boy Advance game?\n");
|
printf("Could not run game. Are you sure the file exists and is a compatible game?\n");
|
||||||
freeArguments(&args);
|
freeArguments(&args);
|
||||||
mCoreConfigFreeOpts(&opts);
|
mCoreConfigFreeOpts(&opts);
|
||||||
mCoreConfigDeinit(&config);
|
mCoreConfigDeinit(&config);
|
||||||
|
@ -197,17 +198,8 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (platform) {
|
// TODO: Use opts and config
|
||||||
case PLATFORM_GBA:
|
ret = mSDLRun(&renderer, &args);
|
||||||
ret = mSDLRunGBA(&renderer, &args, &opts, &config);
|
|
||||||
break;
|
|
||||||
case PLATFORM_GB:
|
|
||||||
ret = mSDLRunGB(&renderer, &args);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mSDLDetachPlayer(&renderer.events, &renderer.player);
|
mSDLDetachPlayer(&renderer.events, &renderer.player);
|
||||||
mInputMapDeinit(&inputMap);
|
mInputMapDeinit(&inputMap);
|
||||||
|
|
||||||
|
@ -223,7 +215,6 @@ int main(int argc, char** argv) {
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config) {
|
int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config) {
|
||||||
struct GBAThread context = {
|
struct GBAThread context = {
|
||||||
.renderer = &renderer->d.d,
|
|
||||||
.userData = renderer
|
.userData = renderer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -240,7 +231,7 @@ int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct
|
||||||
if (opts->sampleRate) {
|
if (opts->sampleRate) {
|
||||||
renderer->audio.sampleRate = opts->sampleRate;
|
renderer->audio.sampleRate = opts->sampleRate;
|
||||||
}
|
}
|
||||||
if (!GBSDLInitAudio(&renderer->audio, &context)) {
|
if (!mSDLInitAudio(&renderer->audio, &context)) {
|
||||||
didFail = true;
|
didFail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,9 +241,7 @@ int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct
|
||||||
mSDLSuspendScreensaver(&renderer->events);
|
mSDLSuspendScreensaver(&renderer->events);
|
||||||
#endif
|
#endif
|
||||||
if (GBAThreadStart(&context)) {
|
if (GBAThreadStart(&context)) {
|
||||||
renderer->audio.psg = &context.gba->audio.psg;
|
|
||||||
renderer->runloop(renderer, &context);
|
renderer->runloop(renderer, &context);
|
||||||
renderer->audio.psg = 0;
|
|
||||||
GBAThreadJoin(&context);
|
GBAThreadJoin(&context);
|
||||||
} else {
|
} else {
|
||||||
didFail = true;
|
didFail = true;
|
||||||
|
@ -276,8 +265,7 @@ int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef M_CORE_GB
|
int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args) {
|
||||||
int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args) {
|
|
||||||
struct mCoreThread thread = {
|
struct mCoreThread thread = {
|
||||||
.core = renderer->core,
|
.core = renderer->core,
|
||||||
.sync = {
|
.sync = {
|
||||||
|
@ -292,18 +280,18 @@ int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args) {
|
||||||
renderer->audio.samples = 1024;
|
renderer->audio.samples = 1024;
|
||||||
renderer->audio.sampleRate = 44100;
|
renderer->audio.sampleRate = 44100;
|
||||||
|
|
||||||
bool didFail = !GBSDLInitAudio(&renderer->audio, 0);
|
bool didFail = !mSDLInitAudio(&renderer->audio, 0);
|
||||||
if (!didFail) {
|
if (!didFail) {
|
||||||
|
renderer->audio.core = renderer->core;
|
||||||
renderer->audio.sync = &thread.sync;
|
renderer->audio.sync = &thread.sync;
|
||||||
|
|
||||||
if (mCoreThreadStart(&thread)) {
|
if (mCoreThreadStart(&thread)) {
|
||||||
renderer->audio.psg = 0;
|
mSDLResumeAudio(&renderer->audio);
|
||||||
GBSDLResumeAudio(&renderer->audio);
|
|
||||||
renderer->runloop(renderer, &thread);
|
renderer->runloop(renderer, &thread);
|
||||||
mCoreThreadJoin(&thread);
|
mCoreThreadJoin(&thread);
|
||||||
} else {
|
} else {
|
||||||
didFail = true;
|
didFail = true;
|
||||||
printf("Could not run game. Are you sure the file exists and is a Game Boy game?\n");
|
printf("Could not run game. Are you sure the file exists and is a compatible game?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCoreThreadHasCrashed(&thread)) {
|
if (mCoreThreadHasCrashed(&thread)) {
|
||||||
|
@ -314,7 +302,6 @@ int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args) {
|
||||||
renderer->core->unloadROM(renderer->core);
|
renderer->core->unloadROM(renderer->core);
|
||||||
return didFail;
|
return didFail;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool mSDLInit(struct mSDLRenderer* renderer) {
|
static bool mSDLInit(struct mSDLRenderer* renderer) {
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
@ -327,7 +314,7 @@ static bool mSDLInit(struct mSDLRenderer* renderer) {
|
||||||
|
|
||||||
static void mSDLDeinit(struct mSDLRenderer* renderer) {
|
static void mSDLDeinit(struct mSDLRenderer* renderer) {
|
||||||
mSDLDeinitEvents(&renderer->events);
|
mSDLDeinitEvents(&renderer->events);
|
||||||
GBSDLDeinitAudio(&renderer->audio);
|
mSDLDeinitAudio(&renderer->audio);
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_DestroyWindow(renderer->window);
|
SDL_DestroyWindow(renderer->window);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,11 +44,8 @@ struct mCore;
|
||||||
struct mSDLRenderer {
|
struct mSDLRenderer {
|
||||||
struct mCore* core;
|
struct mCore* core;
|
||||||
color_t* outputBuffer;
|
color_t* outputBuffer;
|
||||||
#ifdef M_CORE_GBA
|
|
||||||
// TODO: Remove
|
struct mSDLAudio audio;
|
||||||
struct GBAVideoSoftwareRenderer d;
|
|
||||||
#endif
|
|
||||||
struct GBSDLAudio audio;
|
|
||||||
struct mSDLEvents events;
|
struct mSDLEvents events;
|
||||||
struct mSDLPlayer player;
|
struct mSDLPlayer player;
|
||||||
|
|
||||||
|
@ -101,7 +98,7 @@ struct mSDLRenderer {
|
||||||
void mSDLSWCreate(struct mSDLRenderer* renderer);
|
void mSDLSWCreate(struct mSDLRenderer* renderer);
|
||||||
|
|
||||||
#ifdef BUILD_GL
|
#ifdef BUILD_GL
|
||||||
void mSDLGLCreate(struct mSDLRenderer* renderer);
|
void mSDLGLCreateGBA(struct mSDLRenderer* renderer);
|
||||||
void mSDLGLCreateGB(struct mSDLRenderer* renderer);
|
void mSDLGLCreateGB(struct mSDLRenderer* renderer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
#define BUFFER_SIZE (GBA_AUDIO_SAMPLES >> 2)
|
#define BUFFER_SIZE (GBA_AUDIO_SAMPLES >> 2)
|
||||||
|
|
||||||
static void _GBSDLAudioCallback(void* context, Uint8* data, int len);
|
static void _mSDLAudioCallback(void* context, Uint8* data, int len);
|
||||||
|
|
||||||
bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread* threadContext) {
|
bool mSDLInitAudio(struct mSDLAudio* context, struct GBAThread* threadContext) {
|
||||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||||
GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system: %s", SDL_GetError());
|
GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
|
@ -24,7 +24,7 @@ bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread* threadContext)
|
||||||
context->desiredSpec.format = AUDIO_S16SYS;
|
context->desiredSpec.format = AUDIO_S16SYS;
|
||||||
context->desiredSpec.channels = 2;
|
context->desiredSpec.channels = 2;
|
||||||
context->desiredSpec.samples = context->samples;
|
context->desiredSpec.samples = context->samples;
|
||||||
context->desiredSpec.callback = _GBSDLAudioCallback;
|
context->desiredSpec.callback = _mSDLAudioCallback;
|
||||||
context->desiredSpec.userdata = context;
|
context->desiredSpec.userdata = context;
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
@ -37,7 +37,7 @@ bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread* threadContext)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
context->samples = context->obtainedSpec.samples;
|
context->samples = context->obtainedSpec.samples;
|
||||||
context->psg = 0;
|
context->core = 0;
|
||||||
context->thread = 0;
|
context->thread = 0;
|
||||||
|
|
||||||
if (threadContext) {
|
if (threadContext) {
|
||||||
|
@ -59,9 +59,8 @@ bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread* threadContext)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBSDLDeinitAudio(struct GBSDLAudio* context) {
|
void mSDLDeinitAudio(struct mSDLAudio* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
context->psg = 0;
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_PauseAudioDevice(context->deviceId, 1);
|
SDL_PauseAudioDevice(context->deviceId, 1);
|
||||||
SDL_CloseAudioDevice(context->deviceId);
|
SDL_CloseAudioDevice(context->deviceId);
|
||||||
|
@ -72,7 +71,7 @@ void GBSDLDeinitAudio(struct GBSDLAudio* context) {
|
||||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBSDLPauseAudio(struct GBSDLAudio* context) {
|
void mSDLPauseAudio(struct mSDLAudio* context) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_PauseAudioDevice(context->deviceId, 1);
|
SDL_PauseAudioDevice(context->deviceId, 1);
|
||||||
#else
|
#else
|
||||||
|
@ -81,7 +80,7 @@ void GBSDLPauseAudio(struct GBSDLAudio* context) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBSDLResumeAudio(struct GBSDLAudio* context) {
|
void mSDLResumeAudio(struct mSDLAudio* context) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_PauseAudioDevice(context->deviceId, 0);
|
SDL_PauseAudioDevice(context->deviceId, 0);
|
||||||
#else
|
#else
|
||||||
|
@ -90,31 +89,39 @@ void GBSDLResumeAudio(struct GBSDLAudio* context) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBSDLAudioCallback(void* context, Uint8* data, int len) {
|
static void _mSDLAudioCallback(void* context, Uint8* data, int len) {
|
||||||
struct GBSDLAudio* audioContext = context;
|
struct mSDLAudio* audioContext = context;
|
||||||
if (!context || (!audioContext->psg && !audioContext->thread)) {
|
if (!context || (!audioContext->core && !audioContext->thread)) {
|
||||||
memset(data, 0, len);
|
memset(data, 0, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct GBAudio* psg = audioContext->psg;
|
blip_t* left = NULL;
|
||||||
if (!psg) {
|
blip_t* right = NULL;
|
||||||
psg = &audioContext->thread->gba->audio.psg;
|
int32_t clockRate;
|
||||||
|
if (audioContext->core) {
|
||||||
|
left = audioContext->core->getAudioChannel(audioContext->core, 0);
|
||||||
|
right = audioContext->core->getAudioChannel(audioContext->core, 1);
|
||||||
|
clockRate = audioContext->core->frequency(audioContext->core);
|
||||||
|
} else if (audioContext->thread) {
|
||||||
|
left = audioContext->thread->gba->audio.psg.left;
|
||||||
|
right = audioContext->thread->gba->audio.psg.right;
|
||||||
|
clockRate = GBA_ARM7TDMI_FREQUENCY;
|
||||||
}
|
}
|
||||||
double fauxClock = 1;
|
double fauxClock = 1;
|
||||||
if (audioContext->thread) {
|
if (audioContext->thread) {
|
||||||
fauxClock = GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1);
|
fauxClock = GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1);
|
||||||
mCoreSyncLockAudio(&audioContext->thread->sync);
|
mCoreSyncLockAudio(&audioContext->thread->sync);
|
||||||
}
|
}
|
||||||
blip_set_rates(psg->left, psg->clockRate, audioContext->obtainedSpec.freq * fauxClock);
|
blip_set_rates(left, clockRate, audioContext->obtainedSpec.freq * fauxClock);
|
||||||
blip_set_rates(psg->right, psg->clockRate, audioContext->obtainedSpec.freq * fauxClock);
|
blip_set_rates(right, clockRate, audioContext->obtainedSpec.freq * fauxClock);
|
||||||
len /= 2 * audioContext->obtainedSpec.channels;
|
len /= 2 * audioContext->obtainedSpec.channels;
|
||||||
int available = blip_samples_avail(psg->left);
|
int available = blip_samples_avail(left);
|
||||||
if (available > len) {
|
if (available > len) {
|
||||||
available = len;
|
available = len;
|
||||||
}
|
}
|
||||||
blip_read_samples(psg->left, (short*) data, available, audioContext->obtainedSpec.channels == 2);
|
blip_read_samples(left, (short*) data, available, audioContext->obtainedSpec.channels == 2);
|
||||||
if (audioContext->obtainedSpec.channels == 2) {
|
if (audioContext->obtainedSpec.channels == 2) {
|
||||||
blip_read_samples(psg->right, ((short*) data) + 1, available, 1);
|
blip_read_samples(right, ((short*) data) + 1, available, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioContext->sync) {
|
if (audioContext->sync) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
struct GBSDLAudio {
|
struct mSDLAudio {
|
||||||
// Input
|
// Input
|
||||||
size_t samples;
|
size_t samples;
|
||||||
unsigned sampleRate;
|
unsigned sampleRate;
|
||||||
|
@ -22,14 +22,14 @@ struct GBSDLAudio {
|
||||||
SDL_AudioDeviceID deviceId;
|
SDL_AudioDeviceID deviceId;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct GBAudio* psg;
|
struct mCore* core;
|
||||||
struct GBAThread* thread;
|
struct GBAThread* thread;
|
||||||
struct mCoreSync* sync;
|
struct mCoreSync* sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread*);
|
bool mSDLInitAudio(struct mSDLAudio* context, struct GBAThread*);
|
||||||
void GBSDLDeinitAudio(struct GBSDLAudio* context);
|
void mSDLDeinitAudio(struct mSDLAudio* context);
|
||||||
void GBSDLPauseAudio(struct GBSDLAudio* context);
|
void mSDLPauseAudio(struct mSDLAudio* context);
|
||||||
void GBSDLResumeAudio(struct GBSDLAudio* context);
|
void mSDLResumeAudio(struct mSDLAudio* context);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue