Merge pull request #7877 from fjtrujy/feature/PS2AudioSupport

PS2 Audio Support
This commit is contained in:
Twinaphex 2019-01-03 13:21:55 +01:00 committed by GitHub
commit 56bf1c53ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 315 additions and 32 deletions

View File

@ -2,11 +2,10 @@ BUILD_PRX = 0
DEBUG = 0
HAVE_KERNEL_PRX = 0
HAVE_LOGGER = 0
HAVE_FILE_LOGGER = 1
HAVE_FILE_LOGGER = 0
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
@ -22,29 +21,23 @@ else
OPTIMIZE_LV := -O2
endif
ifeq ($(WHOLE_ARCHIVE_LINK), 1)
WHOLE_START := -Wl,--whole-archive
WHOLE_END := -Wl,--no-whole-archive
endif
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 += -lretro_ps2 -lgskit -ldmakit -laudsrv -lpad -lmc -lhdd -lsdl -lfileXio -lpatches -lpoweroff
#IRX modules
# IRX modules - modules have to be in IRX_DIR
IRX = iomanX.irx fileXio.irx usbd.irx usbhdfsd.irx freesd.irx audsrv.irx poweroff.irx ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx
IRX = iomanX.irx fileXio.irx mcman.irx mcserv.irx usbd.irx usbhdfsd.irx freesd.irx audsrv.irx poweroff.irx ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx
IRX_OBJ = $(IRX:.irx=.o)
EE_OBJS += $(IRX_OBJ)
@ -108,10 +101,7 @@ $(EE_IRX_OBJ):
include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal
#Linking with C++
$(EE_BIN): $(EE_OBJS) $(PS2SDK)/ee/startup/crt0.o
$(EE_CXX) $(EE_NO_CRT) -T$(PS2SDK)/ee/startup/linkfile $(EE_CXXFLAGS) \
-o $(EE_BIN) $(PS2SDK)/ee/startup/crt0.o $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(EE_OBJS) $(CRTEND_OBJ) $(CRTN_OBJ) $(EE_LDFLAGS) $(EE_LIBS)

View File

@ -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,

269
audio/drivers/ps2_audio.c Normal file
View File

@ -0,0 +1,269 @@
/* 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 <kernel.h>
#include <audsrv.h>
#include "../audio_driver.h"
typedef struct ps2_audio {
fifo_buffer_t* buffer;
bool nonblocking;
volatile bool running;
int worker_thread;
int lock;
int cond_lock;
} ps2_audio_t;
static ps2_audio_t *backup_ps2;
static u8 audioThreadStack[4 * 1024] __attribute__ ((aligned(16)));
#define AUDIO_OUT_BUFFER 2 * 1024
#define AUDIO_BUFFER 64 * 1024
#define AUDIO_CHANNELS 2
#define AUDIO_BITS 16
#define AUDIO_PRIORITY 0x7F /* LOWER VALUE GRATHER PRIORITY*/
static void audioMainLoop(void *data) {
char out_tmp[AUDIO_OUT_BUFFER];
ps2_audio_t* ps2 = backup_ps2;
while (ps2->running) {
WaitSema(ps2->lock);
size_t size = MIN(fifo_read_avail(ps2->buffer), sizeof(out_tmp));
fifo_read(ps2->buffer, out_tmp, size);
iSignalSema(ps2->lock);
iSignalSema(ps2->cond_lock);
audsrv_wait_audio(size);
audsrv_play_audio(out_tmp, size);
}
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=AUDIO_PRIORITY;
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 = AUDIO_BITS;
format.freq = rate;
format.channels = AUDIO_CHANNELS;
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) {
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) {
return false;
}
static size_t ps2_audio_write_avail(void *data) {
size_t size = 0;
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (ps2 && ps2->running) {
WaitSema(ps2->lock);
size_t size = AUDIO_BUFFER - fifo_read_avail(ps2->buffer);
iSignalSema(ps2->lock);
}
return size;
}
static size_t ps2_audio_buffer_size(void *data) {
return AUDIO_BUFFER ;
}
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,
ps2_audio_write_avail,
ps2_audio_buffer_size
};

View File

@ -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{
@ -73,6 +72,12 @@ extern unsigned int usbd_irx_size;
extern unsigned char usbhdfsd_irx_start[];
extern unsigned int usbhdfsd_irx_size;
extern unsigned char mcman_irx_start[];
extern unsigned int mcman_irx_size;
extern unsigned char mcserv_irx_start[];
extern unsigned int mcserv_irx_size;
static unsigned char HDDModulesLoaded=0;
char eboot_path[512];
@ -306,26 +311,33 @@ static void frontend_ps2_init(void *data)
SifInitRpc(0);
sbv_patch_enable_lmb();
// Controllers
SifLoadModule("rom0:SIO2MAN", 0, NULL);
SifLoadModule("rom0:PADMAN", 0, NULL);
// I/O Files
SifExecModuleBuffer(iomanX_irx_start, iomanX_irx_size, 0, NULL, NULL);
SifExecModuleBuffer(fileXio_irx_start, fileXio_irx_size, 0, NULL, NULL);
// Memory Card
SifExecModuleBuffer(mcman_irx_start, mcman_irx_size, 0, NULL, NULL);
SifExecModuleBuffer(mcserv_irx_start, mcserv_irx_size, 0, NULL, NULL);
SifLoadModule("rom0:SIO2MAN", 0, NULL);
SifLoadModule("rom0:MCMAN", 0, NULL);
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");

View File

@ -25,6 +25,9 @@
#define GS_TEXT GS_SETREG_RGBAQ(0x80,0x80,0x80,0x80,0x00) // turn white GS Screen
#define GS_BLACK GS_SETREG_RGBAQ(0x00,0x00,0x00,0x00,0x00) // turn white GS Screen
#define NTSC_WIDTH 640
#define NTSC_HEIGHT 448
typedef struct ps2_video
{
GSGLOBAL *gsGlobal;
@ -44,11 +47,17 @@ typedef struct ps2_video
static GSGLOBAL *init_GSGlobal(void) {
GSGLOBAL *gsGlobal = gsKit_init_global();
gsGlobal->PSM = GS_PSM_CT16;
gsGlobal->Mode = GS_MODE_NTSC;
gsGlobal->Interlace = GS_INTERLACED;
gsGlobal->Field = GS_FIELD;
gsGlobal->Width = NTSC_WIDTH;
gsGlobal->Height = NTSC_HEIGHT;
gsGlobal->PSM = GS_PSM_CT16;
gsGlobal->PSMZ = GS_PSMZ_16;
gsGlobal->DoubleBuffering = GS_SETTING_OFF;
gsGlobal->ZBuffering = GS_SETTING_OFF;
gsGlobal->PrimAlphaEnable = GS_SETTING_OFF;
gsGlobal->PrimAlphaEnable = GS_SETTING_OFF;
dmaKit_init(D_CTRL_RELE_OFF,D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC,
D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF);

View File

@ -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"

View File

@ -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