Files
RMG/Source/RMG-Audio/main.cpp
T
2025-09-23 14:41:42 +02:00

301 lines
7.5 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-sdl-audio - main.c *
* Mupen64Plus homepage: https://mupen64plus.org/ *
* Copyright (C) 2007-2009 Richard Goedeken *
* Copyright (C) 2007-2008 Ebenblues *
* Copyright (C) 2003 JttL *
* Copyright (C) 2002 Hacktarux *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <SDL3/SDL.h>
#include <SDL3/SDL_audio.h>
#include <stdio.h>
#include <stdarg.h>
#include "main.hpp"
#include "sdl_backend.hpp"
#define M64P_PLUGIN_PROTOTYPES 1
#include <RMG-Core/m64p/api/m64p_common.h>
#include <RMG-Core/m64p/api/m64p_plugin.h>
#include <RMG-Core/m64p/api/m64p_custom.h>
#include <RMG-Core/Settings.hpp>
#include "UserInterface//MainDialog.hpp"
/* version info */
#define SDL_AUDIO_PLUGIN_VERSION 0x020509
#define AUDIO_PLUGIN_API_VERSION 0x020000
/* local variables */
static void (*l_DebugCallback)(void *, int, const char *) = nullptr;
static void *l_DebugCallContext = nullptr;
static int l_PluginInit = 0;
static struct sdl_backend* l_sdl_backend = nullptr;
/* Read header for type definition */
static AUDIO_INFO l_AudioInfo;
// volume to scale the audio by, range of 0..100
// if muted, this holds the volume when not muted
static int l_Volume = 80;
// Muted or not
static bool l_Muted = 0;
/* Helper functions */
static void apply_volume_settings(void)
{
float volume = 0;
if (!l_Muted)
{
volume = l_Volume / 100.0f;
}
if (l_sdl_backend != nullptr)
{
sdl_apply_volume(l_sdl_backend, volume);
}
}
static void load_volume_settings(void)
{
l_Muted = CoreSettingsGetBoolValue(SettingsID::Audio_Muted);
l_Volume = CoreSettingsGetIntValue(SettingsID::Audio_Volume);
}
/* Global functions */
void DebugMessage(int level, const char *message, ...)
{
char msgbuf[1024];
va_list args;
if (l_DebugCallback == nullptr)
return;
va_start(args, message);
vsprintf(msgbuf, message, args);
(*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
va_end(args);
}
/* Mupen64Plus plugin functions */
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
void (*DebugCallback)(void *, int, const char *))
{
ptr_CoreGetAPIVersions CoreAPIVersionFunc;
int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
float fConfigParamsVersion = 0.0f;
if (l_PluginInit)
return M64ERR_ALREADY_INIT;
/* first thing is to set the callback function for debug info */
l_DebugCallback = DebugCallback;
l_DebugCallContext = Context;
/* load settings */
load_volume_settings();
l_PluginInit = 1;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL PluginShutdown(void)
{
if (!l_PluginInit)
return M64ERR_NOT_INIT;
/* reset some local variables */
l_DebugCallback = nullptr;
l_DebugCallContext = nullptr;
l_PluginInit = 0;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
{
if (PluginType != nullptr)
{
*PluginType = M64PLUGIN_AUDIO;
}
if (PluginVersion != nullptr)
{
*PluginVersion = SDL_AUDIO_PLUGIN_VERSION;
}
if (APIVersion != nullptr)
{
*APIVersion = AUDIO_PLUGIN_API_VERSION;
}
if (PluginNamePtr != nullptr)
{
*PluginNamePtr = "Rosalie's Mupen GUI - Audio Plugin";
}
if (Capabilities != nullptr)
{
*Capabilities = 0;
}
return M64ERR_SUCCESS;
}
/* ----------- Custom Functions ------------ */
EXPORT m64p_error CALL PluginConfig(void* parent)
{
if (!l_PluginInit)
{
return M64ERR_NOT_INIT;
}
UserInterface::MainDialog dialog((QWidget*)parent);
dialog.exec();
// apply volume settings
load_volume_settings();
apply_volume_settings();
return M64ERR_SUCCESS;
}
/* ----------- Audio Functions ------------- */
static unsigned int vi_clock_from_system_type(int system_type)
{
switch (system_type)
{
default:
DebugMessage(M64MSG_WARNING, "Invalid system_type %d. Assuming NTSC", system_type);
/* fallback */
case SYSTEM_NTSC: return 48681812;
case SYSTEM_PAL: return 49656530;
case SYSTEM_MPAL: return 48628316;
}
}
static unsigned int dacrate2freq(unsigned int vi_clock, uint32_t dacrate)
{
return vi_clock / (dacrate + 1);
}
EXPORT void CALL AiDacrateChanged(int SystemType)
{
if (!l_PluginInit || l_sdl_backend == nullptr)
return;
unsigned int frequency = dacrate2freq(vi_clock_from_system_type(SystemType), *l_AudioInfo.AI_DACRATE_REG);
sdl_set_frequency(l_sdl_backend, frequency);
apply_volume_settings();
}
EXPORT void CALL AiLenChanged(void)
{
if (!l_PluginInit || l_sdl_backend == nullptr)
return;
sdl_push_samples(l_sdl_backend, l_AudioInfo.RDRAM + (*l_AudioInfo.AI_DRAM_ADDR_REG & 0xffffff), *l_AudioInfo.AI_LEN_REG);
}
EXPORT int CALL InitiateAudio(AUDIO_INFO Audio_Info)
{
if (!l_PluginInit)
return 0;
l_AudioInfo = Audio_Info;
return 1;
}
EXPORT int CALL RomOpen(void)
{
if (!l_PluginInit || l_sdl_backend != nullptr)
return 0;
l_sdl_backend = init_sdl_backend();
apply_volume_settings();
return 1;
}
EXPORT void CALL RomClosed(void)
{
if (!l_PluginInit)
return;
release_sdl_backend(l_sdl_backend);
l_sdl_backend = nullptr;
}
EXPORT void CALL ProcessAList(void)
{
}
EXPORT void CALL SetSpeedFactor(int percentage)
{
if (!l_PluginInit || l_sdl_backend == nullptr)
return;
sdl_set_speed_factor(l_sdl_backend, percentage);
}
EXPORT void CALL VolumeMute(void)
{
l_Muted = !l_Muted;
apply_volume_settings();
}
EXPORT void CALL VolumeUp(void)
{
l_Volume += 10;
apply_volume_settings();
}
EXPORT void CALL VolumeDown(void)
{
l_Volume -= 10;
apply_volume_settings();
}
EXPORT int CALL VolumeGetLevel(void)
{
return l_Muted ? 0 : l_Volume;
}
EXPORT void CALL VolumeSetLevel(int level)
{
l_Volume = level;
apply_volume_settings();
}
EXPORT const char * CALL VolumeGetString(void)
{
return "";
}