Core: Ability to enumerate and modify video and audio channels

This commit is contained in:
Vicki Pfau 2017-04-12 13:28:21 -07:00
parent 9ced6724c1
commit 58c9bcf67a
7 changed files with 153 additions and 84 deletions

View File

@ -89,6 +89,7 @@ Misc:
- Core: Restore sleep callback
- Qt: Add .gb/.gbc files to the extension list in Info.plist
- Feature: Make -l option explicit
- Core: Ability to enumerate and modify video and audio channels
0.5.2: (2016-12-31)
Bugfixes:

View File

@ -140,6 +140,11 @@ struct mCore {
size_t (*savedataClone)(struct mCore*, void** sram);
bool (*savedataRestore)(struct mCore*, const void* sram, size_t size, bool writeback);
size_t (*listVideoLayers)(const struct mCore*, const struct mCoreChannelInfo**);
size_t (*listAudioChannels)(const struct mCore*, const struct mCoreChannelInfo**);
void (*enableVideoLayer)(struct mCore*, size_t id, bool enable);
void (*enableAudioChannel)(struct mCore*, size_t id, bool enable);
};
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2

View File

@ -105,6 +105,13 @@ struct mRumble {
void (*setRumble)(struct mRumble*, int enable);
};
struct mCoreChannelInfo {
size_t id;
const char* internalName;
const char* visibleName;
const char* visibleType;
};
CXX_GUARD_END
#endif

View File

@ -20,6 +20,19 @@
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
const static struct mCoreChannelInfo _GBVideoLayers[] = {
{ 0, "bg", "Background", NULL },
{ 1, "obj", "Objects", NULL },
{ 2, "win", "Window", NULL },
};
const static struct mCoreChannelInfo _GBAudioChannels[] = {
{ 0, "ch0", "Channel 0", "Square/Sweep" },
{ 1, "ch1", "Channel 1", "Square" },
{ 2, "ch2", "Channel 2", "PCM" },
{ 3, "ch3", "Channel 3", "Noise" },
};
struct GBCore {
struct mCore d;
struct GBVideoSoftwareRenderer renderer;
@ -579,6 +592,37 @@ static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t
return true;
}
static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
UNUSED(core);
*info = _GBVideoLayers;
return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers);
}
static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
UNUSED(core);
*info = _GBAudioChannels;
return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels);
}
static void _GBCoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
struct GB* gb = core->board;
// TODO
}
static void _GBCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
struct GB* gb = core->board;
switch (id) {
case 0:
case 1:
case 2:
case 3:
gb->audio.forceDisableCh[id] = !enable;
break;
default:
break;
}
}
struct mCore* GBCoreCreate(void) {
struct GBCore* gbcore = malloc(sizeof(*gbcore));
struct mCore* core = &gbcore->d;
@ -647,5 +691,9 @@ struct mCore* GBCoreCreate(void) {
core->cheatDevice = _GBCoreCheatDevice;
core->savedataClone = _GBCoreSavedataClone;
core->savedataRestore = _GBCoreSavedataRestore;
core->listVideoLayers = _GBCoreListVideoLayers;
core->listAudioChannels = _GBCoreListAudioChannels;
core->enableVideoLayer = _GBCoreEnableVideoLayer;
core->enableAudioChannel = _GBCoreEnableAudioChannel;
return core;
}

View File

@ -22,6 +22,23 @@
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
const static struct mCoreChannelInfo _GBAVideoLayers[] = {
{ 0, "bg0", "Background 0", NULL },
{ 1, "bg1", "Background 1", NULL },
{ 2, "bg2", "Background 2", NULL },
{ 3, "bg3", "Background 3", NULL },
{ 4, "obj", "Objects", NULL },
};
const static struct mCoreChannelInfo _GBAAudioChannels[] = {
{ 0, "ch0", "PSG Channel 0", "Square/Sweep" },
{ 1, "ch1", "PSG Channel 1", "Square" },
{ 2, "ch2", "PSG Channel 2", "PCM" },
{ 3, "ch3", "PSG Channel 3", "Noise" },
{ 4, "chA", "FIFO Channel A", NULL },
{ 5, "chB", "FIFO Channel B", NULL },
};
struct GBACore {
struct mCore d;
struct GBAVideoSoftwareRenderer renderer;
@ -581,6 +598,54 @@ static bool _GBACoreSavedataRestore(struct mCore* core, const void* sram, size_t
return success;
}
static size_t _GBACoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
UNUSED(core);
*info = _GBAVideoLayers;
return sizeof(_GBAVideoLayers) / sizeof(*_GBAVideoLayers);
}
static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
UNUSED(core);
*info = _GBAAudioChannels;
return sizeof(_GBAAudioChannels) / sizeof(*_GBAAudioChannels);
}
static void _GBACoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
struct GBA* gba = core->board;
switch (id) {
case 0:
case 1:
case 2:
case 3:
gba->video.renderer->disableBG[id] = !enable;
break;
case 4:
gba->video.renderer->disableOBJ = !enable;
break;
default:
break;
}
}
static void _GBACoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
struct GBA* gba = core->board;
switch (id) {
case 0:
case 1:
case 2:
case 3:
gba->audio.psg.forceDisableCh[id] = !enable;
break;
case 4:
gba->audio.forceDisableChA = !enable;
case 5:
gba->audio.forceDisableChB = !enable;
break;
default:
break;
}
}
struct mCore* GBACoreCreate(void) {
struct GBACore* gbacore = malloc(sizeof(*gbacore));
struct mCore* core = &gbacore->d;
@ -649,5 +714,9 @@ struct mCore* GBACoreCreate(void) {
core->cheatDevice = _GBACoreCheatDevice;
core->savedataClone = _GBACoreSavedataClone;
core->savedataRestore = _GBACoreSavedataRestore;
core->listVideoLayers = _GBACoreListVideoLayers;
core->listAudioChannels = _GBACoreListAudioChannels;
core->enableVideoLayer = _GBACoreEnableVideoLayer;
core->enableAudioChannel = _GBACoreEnableAudioChannel;
return core;
}

View File

@ -57,8 +57,8 @@ GameController::GameController(QObject* parent)
, m_turboForced(false)
, m_turboSpeed(-1)
, m_wasPaused(false)
, m_audioChannels{ true, true, true, true, true, true }
, m_videoLayers{ true, true, true, true, true }
, m_audioChannels()
, m_videoLayers()
, m_autofire{}
, m_autofireStatus{}
, m_inputController(nullptr)
@ -90,35 +90,17 @@ GameController::GameController(QObject* parent)
context->core->setPeripheral(context->core, mPERIPH_ROTATION, controller->m_inputController->rotationSource());
context->core->setPeripheral(context->core, mPERIPH_RUMBLE, controller->m_inputController->rumble());
#ifdef M_CORE_GBA
GBA* gba = static_cast<GBA*>(context->core->board);
#endif
#ifdef M_CORE_GB
GB* gb = static_cast<GB*>(context->core->board);
#endif
for (size_t i = 0; i < controller->m_audioChannels.size(); ++i) {
context->core->enableAudioChannel(context->core, i, controller->m_audioChannels[i]);
}
for (size_t i = 0; i < controller->m_videoLayers.size(); ++i) {
context->core->enableVideoLayer(context->core, i, controller->m_videoLayers[i]);
}
switch (context->core->platform(context->core)) {
#ifdef M_CORE_GBA
case PLATFORM_GBA:
context->core->setPeripheral(context->core, mPERIPH_GBA_LUMINANCE, &controller->m_lux);
gba->audio.psg.forceDisableCh[0] = !controller->m_audioChannels[0];
gba->audio.psg.forceDisableCh[1] = !controller->m_audioChannels[1];
gba->audio.psg.forceDisableCh[2] = !controller->m_audioChannels[2];
gba->audio.psg.forceDisableCh[3] = !controller->m_audioChannels[3];
gba->audio.forceDisableChA = !controller->m_audioChannels[4];
gba->audio.forceDisableChB = !controller->m_audioChannels[5];
gba->video.renderer->disableBG[0] = !controller->m_videoLayers[0];
gba->video.renderer->disableBG[1] = !controller->m_videoLayers[1];
gba->video.renderer->disableBG[2] = !controller->m_videoLayers[2];
gba->video.renderer->disableBG[3] = !controller->m_videoLayers[3];
gba->video.renderer->disableOBJ = !controller->m_videoLayers[4];
break;
#endif
#ifdef M_CORE_GB
case PLATFORM_GB:
gb->audio.forceDisableCh[0] = !controller->m_audioChannels[0];
gb->audio.forceDisableCh[1] = !controller->m_audioChannels[1];
gb->audio.forceDisableCh[2] = !controller->m_audioChannels[2];
gb->audio.forceDisableCh[3] = !controller->m_audioChannels[3];
break;
#endif
default:
@ -866,47 +848,13 @@ void GameController::setAudioChannelEnabled(int channel, bool enable) {
if (channel > 5 || channel < 0) {
return;
}
#ifdef M_CORE_GBA
GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
#endif
#ifdef M_CORE_GB
GB* gb = static_cast<GB*>(m_threadContext.core->board);
#endif
m_audioChannels.reserve(channel + 1);
while (m_audioChannels.size() <= channel) {
m_audioChannels.append(true);
}
m_audioChannels[channel] = enable;
if (isLoaded()) {
switch (channel) {
case 0:
case 1:
case 2:
case 3:
switch (m_threadContext.core->platform(m_threadContext.core)) {
#ifdef M_CORE_GBA
case PLATFORM_GBA:
gba->audio.psg.forceDisableCh[channel] = !enable;
break;
#endif
#ifdef M_CORE_GB
case PLATFORM_GB:
gb->audio.forceDisableCh[channel] = !enable;
break;
#endif
default:
break;
}
break;
#ifdef M_CORE_GBA
case 4:
if (m_threadContext.core->platform(m_threadContext.core) == PLATFORM_GBA) {
gba->audio.forceDisableChA = !enable;
}
break;
case 5:
if (m_threadContext.core->platform(m_threadContext.core) == PLATFORM_GBA) {
gba->audio.forceDisableChB = !enable;
}
break;
#endif
}
m_threadContext.core->enableAudioChannel(m_threadContext.core, channel, enable);
}
}
@ -925,23 +873,14 @@ void GameController::setVideoLayerEnabled(int layer, bool enable) {
if (layer > 4 || layer < 0) {
return;
}
m_videoLayers[layer] = enable;
#ifdef M_CORE_GBA
if (isLoaded() && m_threadContext.core->platform(m_threadContext.core) == PLATFORM_GBA) {
GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
switch (layer) {
case 0:
case 1:
case 2:
case 3:
gba->video.renderer->disableBG[layer] = !enable;
break;
case 4:
gba->video.renderer->disableOBJ = !enable;
break;
}
m_videoLayers.reserve(layer + 1);
while (m_videoLayers.size() <= layer) {
m_videoLayers.append(true);
}
m_videoLayers[layer] = enable;
if (isLoaded()) {
m_threadContext.core->enableVideoLayer(m_threadContext.core, layer, enable);
}
#endif
}
void GameController::setFPSTarget(float fps) {

View File

@ -222,8 +222,8 @@ private:
std::shared_ptr<mTileCache> m_tileCache;
bool m_audioChannels[6];
bool m_videoLayers[5];
QList<bool> m_audioChannels;
QList<bool> m_videoLayers;
bool m_autofire[GBA_KEY_MAX];
int m_autofireStatus[GBA_KEY_MAX];