1
0
mirror of https://github.com/libretro/RetroArch synced 2025-02-18 00:40:36 +00:00

Create Audio Driver from PS2

This commit is contained in:
Francisco Javier Trujillo Mata 2018-12-26 23:40:57 +01:00
parent 8b0f7051ac
commit 1591bc2db2
6 changed files with 294 additions and 13 deletions
Makefile.ps2
audio
frontend/drivers
griffin
libretro-common/vfs

@ -1,12 +1,12 @@
BUILD_PRX = 0
DEBUG = 0
DEBUG = 1
HAVE_KERNEL_PRX = 0
HAVE_LOGGER = 0
HAVE_FILE_LOGGER = 1
HAVE_THREADS = 0
BIG_STACK = 0
WHOLE_ARCHIVE_LINK = 0
PS2_IP = 192.168.2.150
PS2_IP = 192.168.1.150
#Configuration for IRX
EE_BIN2O = bin2o
@ -31,16 +31,16 @@ INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
INCDIR += -Ips2 -Ips2/include -Ilibretro-common/include
INCDIR += -Ideps -Ideps/stb -Ideps/libz -Ideps/7zip -Ideps/pthreads -Ideps/pthreads/platform/ps2 -Ideps/pthreads/platform/helper
GPVAL = -G0
CFLAGS = $(OPTIMIZE_LV) -ffast-math -fsingle-precision-constant
CFLAGS = $(OPTIMIZE_LV) -ffast-math -fsingle-precision-constant
ASFLAGS = $(CFLAGS)
RARCH_DEFINES += -DPS2 -DUSE_IOP_CTYPE_MACRO -D_MIPS_ARCH_R5900 -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DWANT_ZLIB
RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_IMAGEVIEWER -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
LIBDIR =
LDFLAGS = -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L. -s
LIBS += $(WHOLE_START) -lretro_ps2 $(WHOLE_END)
LIBS += -lgskit -ldmakit -lpad -lmc -lhdd -lsdl -lc -lfileXio -lpatches -lpoweroff -ldebug -lc
LIBS += -lgskit -ldmakit -laudsrv -lpad -lmc -lhdd -lsdl -lc -lfileXio -lpatches -lpoweroff -lc
#IRX modules
# IRX modules - modules have to be in IRX_DIR

@ -122,6 +122,9 @@ static const audio_driver_t *audio_drivers[] = {
#if defined(PSP) || defined(VITA)
&audio_psp,
#endif
#if defined(PS2)
&audio_ps2,
#endif
#ifdef _3DS
&audio_ctr_csnd,
&audio_ctr_dsp,

275
audio/drivers/ps2_audio.c Normal file

@ -0,0 +1,275 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2014-2017 - Francisco Javier Trujillo Mata
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <rthreads/rthreads.h>
#include <queues/fifo_queue.h>
#include <kernel.h>
#include <audsrv.h>
#include "../audio_driver.h"
typedef struct ps2_audio
{
bool nonblocking;
fifo_buffer_t* buffer;
volatile bool running;
int worker_thread;
int lock;
int cond_lock;
} ps2_audio_t;
static ps2_audio_t *backup_ps2;
static u8 audioThreadStack[512 * 16] __attribute__ ((aligned(16)));
#define AUDIO_OUT_BUFFER 2 * 1024
#define AUDIO_BUFFER 64 * 1024
static void audioMainLoop(void *data)
{
ps2_audio_t* ps2 = backup_ps2;
char out_tmp[AUDIO_OUT_BUFFER];
while (ps2->running)
{
WaitSema(ps2->lock);
if (fifo_read_avail(ps2->buffer) >= sizeof(out_tmp)) {
fifo_read(ps2->buffer, out_tmp, sizeof(out_tmp));
} else {
memset(out_tmp, 0, sizeof(out_tmp));
}
iSignalSema(ps2->lock);
iSignalSema(ps2->cond_lock);
int ret;
audsrv_wait_audio(sizeof(out_tmp));
ret = audsrv_play_audio(out_tmp, sizeof(out_tmp));
}
audsrv_stop_audio();
ExitDeleteThread();
}
static void audioCreateThread(ps2_audio_t *ps2) {
int ret;
ee_thread_t thread;
thread.func=&audioMainLoop;
thread.stack=audioThreadStack;
thread.stack_size=sizeof(audioThreadStack);
thread.gp_reg=&_gp;
thread.initial_priority=0x50;
thread.attr=thread.option=0;
/*Backup the PS2 content to be used in the thread */
backup_ps2 = ps2;
ps2->running = true;
ps2->worker_thread = CreateThread(&thread);
if (ps2->worker_thread >= 0) {
ret = StartThread(ps2->worker_thread, NULL);
if (ret < 0) {
printf("sound_init: StartThread returned %d\n", ret);
}
} else {
printf("CreateThread failed: %d\n", ps2->worker_thread);
}
}
static void audioStopNDeleteThread(ps2_audio_t *ps2) {
ps2->running = false;
if (ps2->worker_thread) {
ps2->worker_thread = 0;
}
}
static void audioConfigure(ps2_audio_t *ps2, unsigned rate) {
int err;
struct audsrv_fmt_t format;
format.bits = 16;
format.freq = rate;
format.channels = 2;
err = audsrv_set_format(&format);
if (err) {
printf("set format returned %d\n", err);
printf("audsrv returned error string: %s\n", audsrv_get_error_string());
}
audsrv_set_volume(MAX_VOLUME);
}
static void audioCreateSemas(ps2_audio_t *ps2) {
ee_sema_t lock_info;
lock_info.max_count = 1;
lock_info.init_count = 1;
lock_info.option = 0;
ps2->lock = CreateSema(&lock_info);
ee_sema_t cond_lock_info;
cond_lock_info.init_count = 1;
cond_lock_info.max_count = 1;
cond_lock_info.option = 0;
ps2->cond_lock = CreateSema(&cond_lock_info);
}
static void *ps2_audio_init(const char *device,
unsigned rate, unsigned latency,
unsigned block_frames,
unsigned *new_rate)
{
ps2_audio_t *ps2 = (ps2_audio_t*)calloc(1, sizeof(ps2_audio_t));
if (!ps2)
return NULL;
ps2->buffer = fifo_new(AUDIO_BUFFER);
audioConfigure(ps2, rate);
audioCreateSemas(ps2);
audioCreateThread(ps2);
return ps2;
}
static void ps2_audio_free(void *data)
{
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if(!ps2)
return;
if(ps2->running){
audioStopNDeleteThread(ps2);
if (ps2->lock) {
iDeleteSema(ps2->lock);
ps2->lock = 0;
}
if (ps2->cond_lock) {
iDeleteSema(ps2->cond_lock);
ps2->cond_lock = 0;
}
}
fifo_free(ps2->buffer);
free(ps2);
}
static ssize_t ps2_audio_write(void *data, const void *buf, size_t size)
{
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (!ps2->running)
return -1;
if (ps2->nonblocking)
{
if (fifo_write_avail(ps2->buffer) < size)
return 0;
}
while (fifo_write_avail(ps2->buffer) < size) {
WaitSema(ps2->cond_lock);
}
WaitSema(ps2->lock);
fifo_write(ps2->buffer, buf, size);
iSignalSema(ps2->lock);
return size;
}
static bool ps2_audio_alive(void *data)
{
bool alive = false;
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (ps2) {
alive = ps2->running;
}
return alive;
}
static bool ps2_audio_stop(void *data)
{
bool stop = true;
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (ps2) {
audioStopNDeleteThread(ps2);
audsrv_stop_audio();
}
return stop;
}
static bool ps2_audio_start(void *data, bool is_shutdown)
{
bool start = true;
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if(ps2) {
if (!ps2->running && !ps2->worker_thread) {
audioCreateThread(ps2);
}
}
return start;
}
static void ps2_audio_set_nonblock_state(void *data, bool toggle)
{
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (ps2) {
ps2->nonblocking = toggle;
}
}
static bool ps2_audio_use_float(void *data)
{
(void)data;
return false;
}
audio_driver_t audio_ps2 = {
ps2_audio_init,
ps2_audio_write,
ps2_audio_stop,
ps2_audio_start,
ps2_audio_alive,
ps2_audio_set_nonblock_state,
ps2_audio_free,
ps2_audio_use_float,
"ps2",
NULL,
NULL,
NULL,
NULL
};

@ -20,12 +20,11 @@
#include <loadfile.h>
#include <unistd.h>
#include <sbv_patches.h>
#include <fileXio_rpc.h>
#include <audsrv.h>
#include <sifrpc.h>
#include <iopcontrol.h>
#include <libpwroff.h>
#include <SDL/SDL.h>
#include <audsrv.h>
enum BootDeviceIDs{
@ -306,6 +305,7 @@ static void frontend_ps2_init(void *data)
SifInitRpc(0);
sbv_patch_enable_lmb();
// I/O Files
SifExecModuleBuffer(iomanX_irx_start, iomanX_irx_size, 0, NULL, NULL);
SifExecModuleBuffer(fileXio_irx_start, fileXio_irx_size, 0, NULL, NULL);
@ -314,18 +314,21 @@ static void frontend_ps2_init(void *data)
SifLoadModule("rom0:MCSERV", 0, NULL);
SifLoadModule("rom0:PADMAN", 0, NULL);
// USB
SifExecModuleBuffer(usbd_irx_start, usbd_irx_size, 0, NULL, NULL);
SifExecModuleBuffer(usbhdfsd_irx_start, usbhdfsd_irx_size, 0, NULL, NULL);
// Audio
SifExecModuleBuffer(freesd_irx_start, freesd_irx_size, 0, NULL, NULL);
SifExecModuleBuffer(audsrv_irx_start, audsrv_irx_size, 0, NULL, NULL);
fileXioInit();
audsrv_init();
SDL_Init(SDL_INIT_TIMER);
//Initializes audsrv library
if(audsrv_init()) {
RARCH_ERR("audsrv library not initalizated\n");
}
retro_sleep(100);
#if defined(HAVE_FILE_LOGGER)
retro_main_log_file_init("retroarch.log");

@ -773,7 +773,7 @@ AUDIO
#elif defined(PSP) || defined(VITA)
#include "../audio/drivers/psp_audio.c"
#elif defined(PS2)
// #include "../audio/drivers/ps2_audio.c"
#include "../audio/drivers/ps2_audio.c"
#elif defined(_3DS)
#include "../audio/drivers/ctr_csnd_audio.c"
#include "../audio/drivers/ctr_dsp_audio.c"

@ -294,7 +294,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
*/
/* TODO: this is only useful for a few platforms, find which and add ifdef */
stream->fp = fp;
#if !defined(PS2)
#if !defined(PS2) // TODO: PS2 IMPROVEMENT
stream->buf = (char*)calloc(1, 0x4000);
setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
#endif