diff options
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/in_tsbutton.c | 6 | ||||
m--------- | frontend/libpicofe | 0 | ||||
-rw-r--r-- | frontend/libretro.c | 54 | ||||
-rw-r--r-- | frontend/main.c | 30 | ||||
-rw-r--r-- | frontend/menu.c | 25 | ||||
-rw-r--r-- | frontend/plat_dummy.c | 2 | ||||
-rw-r--r-- | frontend/plat_pandora.c | 34 | ||||
-rw-r--r-- | frontend/plat_pollux.c | 39 | ||||
-rw-r--r-- | frontend/plat_sdl.c | 39 | ||||
-rw-r--r-- | frontend/plugin.c | 22 |
10 files changed, 187 insertions, 64 deletions
diff --git a/frontend/in_tsbutton.c b/frontend/in_tsbutton.c index aee6852..b3e4158 100644 --- a/frontend/in_tsbutton.c +++ b/frontend/in_tsbutton.c @@ -30,7 +30,7 @@ static const char * const in_tsbutton_keys[IN_TSBUTTON_COUNT] = { "TS1", "TS2", "TS3", "TS4", }; -static void in_tsbutton_probe(void) +static void in_tsbutton_probe(const in_drv_t *drv) { struct tsdev *dev = tsdev; if (dev == NULL) { @@ -43,7 +43,7 @@ static void in_tsbutton_probe(void) } static const char * const * -in_tsbutton_get_key_names(int *count) +in_tsbutton_get_key_names(const in_drv_t *drv, int *count) { *count = IN_TSBUTTON_COUNT; return in_tsbutton_keys; @@ -133,6 +133,6 @@ static const in_drv_t in_tsbutton_drv = { void in_tsbutton_init(void) { tsbutton_down_id = last_tsbutton_id = -1; - in_register_driver(&in_tsbutton_drv, NULL); + in_register_driver(&in_tsbutton_drv, NULL, NULL); } diff --git a/frontend/libpicofe b/frontend/libpicofe -Subproject da0cc55643353ab15725194be64a3d8460fe48b +Subproject d1453cf7e6d5d6758cc5d72c6d3af7d37156bf7 diff --git a/frontend/libretro.c b/frontend/libretro.c index cd889c2..74b5dbf 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -19,6 +19,7 @@ #include "../libpcsxcore/cdriso.h" #include "../libpcsxcore/cheat.h" #include "../plugins/dfsound/out.h" +#include "../plugins/dfsound/spu_config.h" #include "../plugins/dfinput/externals.h" #include "cspace.h" #include "main.h" @@ -40,7 +41,6 @@ static int vout_doffs_old, vout_fb_dirty; static bool vout_can_dupe; static bool duping_enable; -static int samples_sent, samples_to_send; static int plugins_opened; static int is_pal_mode; @@ -197,7 +197,7 @@ void pl_timing_prepare(int is_pal) is_pal_mode = is_pal; } -void plat_trigger_vibrate(int pad, uint32_t low, uint32_t high) +void plat_trigger_vibrate(int pad, int low, int high) { rumble.set_rumble_state(pad, RETRO_RUMBLE_STRONG, high << 8); rumble.set_rumble_state(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0); @@ -219,16 +219,13 @@ static void snd_finish(void) static int snd_busy(void) { - if (samples_to_send > samples_sent) - return 0; /* give more samples */ - else - return 1; + return 0; } static void snd_feed(void *buf, int bytes) { - audio_batch_cb(buf, bytes / 4); - samples_sent += bytes / 4; + if (audio_batch_cb != NULL) + audio_batch_cb(buf, bytes / 4); } void out_register_libretro(struct out_driver *drv) @@ -251,12 +248,14 @@ void retro_set_environment(retro_environment_t cb) #ifndef DRC_DISABLE { "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" }, #endif -#if defined(__ARM_NEON__) || defined(NEON_PC) +#ifdef __ARM_NEON__ { "pcsx_rearmed_neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, { "pcsx_rearmed_neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, { "pcsx_rearmed_neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, #endif { "pcsx_rearmed_duping_enable", "Frame duping; on|off" }, + { "pcsx_rearmed_spu_reverb", "Sound: Reverb; on|off" }, + { "pcsx_rearmed_spu_interpolation", "Sound: Interpolation; simple|gaussian|cubic|off" }, { NULL, NULL }, }; @@ -991,7 +990,7 @@ static void update_variables(bool in_flight) in_type2 = PSE_PAD_TYPE_ANALOGPAD; } -#if defined(__ARM_NEON__) || defined(NEON_PC) +#ifdef __ARM_NEON__ var.value = "NULL"; var.key = "pcsx_rearmed_neon_interlace_enable"; @@ -1059,6 +1058,32 @@ static void update_variables(bool in_flight) } #endif + var.value = "NULL"; + var.key = "pcsx_rearmed_spu_reverb"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "off") == 0) + spu_config.iUseReverb = false; + else if (strcmp(var.value, "on") == 0) + spu_config.iUseReverb = true; + } + + var.value = "NULL"; + var.key = "pcsx_rearmed_spu_interpolation"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "simple") == 0) + spu_config.iUseInterpolation = 1; + else if (strcmp(var.value, "gaussian") == 0) + spu_config.iUseInterpolation = 2; + else if (strcmp(var.value, "cubic") == 0) + spu_config.iUseInterpolation = 3; + else if (strcmp(var.value, "off") == 0) + spu_config.iUseInterpolation = 0; + } + if (in_flight) { // inform core things about possible config changes plugin_call_rearmed_cbs(); @@ -1102,8 +1127,6 @@ void retro_run(void) stop = 0; psxCpu->Execute(); - samples_to_send += is_pal_mode ? 44100 / 50 : 44100 / 60; - video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf : NULL, vout_width, vout_height, vout_width * 2); vout_fb_dirty = 0; @@ -1174,7 +1197,7 @@ void retro_init(void) const char *bios[] = { "scph1001", "scph5501", "scph7001" }; const char *dir; char path[256]; - int i, ret, level; + int i, ret; bool found_bios = false; ret = emu_core_preinit(); @@ -1218,9 +1241,6 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg); } - level = 1; - environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); - environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &vout_can_dupe); environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble); @@ -1228,7 +1248,7 @@ void retro_init(void) /* Set how much slower PSX CPU runs * 100 (so that 200 is 2 times) * we have to do this because cache misses and some IO penalties * are not emulated. Warning: changing this may break compatibility. */ -#ifdef __ARM_ARCH_7A__ +#if !defined(__arm__) || defined(__ARM_ARCH_7A__) cycle_multiplier = 175; #else cycle_multiplier = 200; diff --git a/frontend/main.c b/frontend/main.c index 2ef5f52..426ef13 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -25,6 +25,7 @@ #include "../libpcsxcore/cheat.h" #include "../libpcsxcore/new_dynarec/new_dynarec.h" #include "../plugins/cdrcimg/cdrcimg.h" +#include "../plugins/dfsound/spu_config.h" #include "revision.h" #ifndef NO_FRONTEND @@ -44,12 +45,6 @@ static void check_memcards(void); void StartDebugger(); void StopDebugger(); -// sound plugin -extern int iUseReverb; -extern int iUseInterpolation; -extern int iXAPitch; -extern int iVolume; - int ready_to_go, g_emu_want_quit, g_emu_resetting; unsigned long gpuDisp; char cfgfile_basename[MAXPATHLEN]; @@ -141,13 +136,15 @@ void emu_set_default_config(void) pl_rearmed_cbs.gpu_peopsgl.iVRamSize = 64; pl_rearmed_cbs.gpu_peopsgl.iTexGarbageCollection = 1; - iUseReverb = 2; - iUseInterpolation = 1; - iXAPitch = 0; - iVolume = 768; -#ifndef __ARM_ARCH_7A__ /* XXX */ - iUseReverb = 0; - iUseInterpolation = 0; + spu_config.iUseReverb = 1; + spu_config.iUseInterpolation = 1; + spu_config.iXAPitch = 0; + spu_config.iVolume = 768; + spu_config.iTempo = 0; +#if defined(__arm__) && !defined(__ARM_ARCH_7A__) /* XXX */ + spu_config.iUseReverb = 0; + spu_config.iUseInterpolation = 0; + spu_config.iTempo = 1; #endif new_dynarec_hacks = 0; cycle_multiplier = 200; @@ -251,7 +248,11 @@ do_state_slot: } case SACTION_VOLUME_UP: case SACTION_VOLUME_DOWN: - plat_target_step_volume(emu_action == SACTION_VOLUME_UP); + { + static int volume; + plat_target_step_volume(&volume, + emu_action == SACTION_VOLUME_UP ? 1 : -1); + } return; case SACTION_MINIMIZE: if (GPU_close != NULL) @@ -849,6 +850,7 @@ static int _OpenPlugins(void) { ret = SPU_open(); if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; } SPU_registerCallback(SPUirq); + SPU_registerScheduleCb(SPUschedule); // pcsx-rearmed: we handle gpu elsewhere //ret = GPU_open(&gpuDisp, "PCSX", NULL); //if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; } diff --git a/frontend/menu.c b/frontend/menu.c index 199020d..1562735 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -37,6 +37,7 @@ #include "../libpcsxcore/cheat.h" #include "../libpcsxcore/new_dynarec/new_dynarec.h" #include "../plugins/dfinput/externals.h" +#include "../plugins/dfsound/spu_config.h" #include "psemu_plugin_defs.h" #include "revision.h" @@ -102,12 +103,6 @@ int soft_filter; #define DEFAULT_PSX_CLOCK_S "50" #endif -// sound plugin -extern int iUseReverb; -extern int iUseInterpolation; -extern int iXAPitch; -extern int iVolume; - static const char *bioses[24]; static const char *gpu_plugins[16]; static const char *spu_plugins[16]; @@ -318,7 +313,7 @@ static void menu_sync_config(void) allow_abs_only_old = in_evdev_allow_abs_only; } - iVolume = 768 + 128 * volume_boost; + spu_config.iVolume = 768 + 128 * volume_boost; pl_rearmed_cbs.frameskip = frameskip - 1; pl_timing_prepare(Config.PsxType); } @@ -431,9 +426,10 @@ static const struct { CE_INTVAL_P(gpu_peopsgl.iVRamSize), CE_INTVAL_P(gpu_peopsgl.iTexGarbageCollection), CE_INTVAL_P(gpu_peopsgl.dwActFixes), - CE_INTVAL_V(iUseReverb, 3), - CE_INTVAL_V(iXAPitch, 3), - CE_INTVAL_V(iUseInterpolation, 3), + CE_INTVAL(spu_config.iUseReverb), + CE_INTVAL(spu_config.iXAPitch), + CE_INTVAL(spu_config.iUseInterpolation), + CE_INTVAL(spu_config.iTempo), CE_INTVAL(config_save_counter), CE_INTVAL(in_evdev_allow_abs_only), CE_INTVAL(volume_boost), @@ -1400,13 +1396,16 @@ static int menu_loop_plugin_gpu_peopsgl(int id, int keys) static const char *men_spu_interp[] = { "None", "Simple", "Gaussian", "Cubic", NULL }; static const char h_spu_volboost[] = "Large values cause distortion"; +static const char h_spu_tempo[] = "Slows down audio if emu is too slow\n" + "This is inaccurate and breaks games"; static menu_entry e_menu_plugin_spu[] = { mee_range_h ("Volume boost", 0, volume_boost, -5, 30, h_spu_volboost), - mee_onoff ("Reverb", 0, iUseReverb, 2), - mee_enum ("Interpolation", 0, iUseInterpolation, men_spu_interp), - mee_onoff ("Adjust XA pitch", 0, iXAPitch, 1), + mee_onoff ("Reverb", 0, spu_config.iUseReverb, 1), + mee_enum ("Interpolation", 0, spu_config.iUseInterpolation, men_spu_interp), + mee_onoff ("Adjust XA pitch", 0, spu_config.iXAPitch, 1), + mee_onoff_h ("Adjust tempo", 0, spu_config.iTempo, 1, h_spu_tempo), mee_end, }; diff --git a/frontend/plat_dummy.c b/frontend/plat_dummy.c index baed0d5..b490cff 100644 --- a/frontend/plat_dummy.c +++ b/frontend/plat_dummy.c @@ -54,7 +54,7 @@ void *plat_prepare_screenshot(int *w, int *h, int *bpp) return 0; } -void plat_trigger_vibrate(int is_strong) +void plat_trigger_vibrate(int pad, int low, int high) { } diff --git a/frontend/plat_pandora.c b/frontend/plat_pandora.c index d44513c..41dc2fe 100644 --- a/frontend/plat_pandora.c +++ b/frontend/plat_pandora.c @@ -45,12 +45,42 @@ static const struct in_default_bind in_evdev_defbinds[] = { { 0, 0, 0 } }; +static const struct menu_keymap key_pbtn_map[] = +{ + { KEY_UP, PBTN_UP }, + { KEY_DOWN, PBTN_DOWN }, + { KEY_LEFT, PBTN_LEFT }, + { KEY_RIGHT, PBTN_RIGHT }, + /* Pandora */ + { KEY_END, PBTN_MOK }, + { KEY_PAGEDOWN, PBTN_MBACK }, + { KEY_HOME, PBTN_MA2 }, + { KEY_PAGEUP, PBTN_MA3 }, + { KEY_LEFTCTRL, PBTN_MENU }, + { KEY_RIGHTSHIFT, PBTN_L }, + { KEY_RIGHTCTRL, PBTN_R }, + /* "normal" keyboards */ + { KEY_ENTER, PBTN_MOK }, + { KEY_ESC, PBTN_MBACK }, + { KEY_SEMICOLON, PBTN_MA2 }, + { KEY_APOSTROPHE, PBTN_MA3 }, + { KEY_BACKSLASH, PBTN_MENU }, + { KEY_LEFTBRACE, PBTN_L }, + { KEY_RIGHTBRACE, PBTN_R }, +}; + +static const struct in_pdata pandora_evdev_pdata = { + .defbinds = in_evdev_defbinds, + .key_map = key_pbtn_map, + .kmap_size = sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]), +}; + int plat_init(void) { plat_omap_init(); plat_target_init(); - in_evdev_init(in_evdev_defbinds); + in_evdev_init(&pandora_evdev_pdata); in_probe(); plat_target_setup_input(); @@ -76,6 +106,6 @@ void plat_gvideo_open(int is_pal) plat_omap_gvideo_open(); } -void plat_trigger_vibrate(int is_strong) +void plat_trigger_vibrate(int pad, int low, int high) { } diff --git a/frontend/plat_pollux.c b/frontend/plat_pollux.c index 252feba..33e9417 100644 --- a/frontend/plat_pollux.c +++ b/frontend/plat_pollux.c @@ -84,6 +84,36 @@ static const struct in_default_bind in_evdev_defbinds[] = { { 0, 0, 0 }, }; +static const struct menu_keymap key_pbtn_map[] = +{ + { KEY_UP, PBTN_UP }, + { KEY_DOWN, PBTN_DOWN }, + { KEY_LEFT, PBTN_LEFT }, + { KEY_RIGHT, PBTN_RIGHT }, + /* Caanoo */ + { BTN_THUMB2, PBTN_MOK }, + { BTN_THUMB, PBTN_MBACK }, + { BTN_TRIGGER, PBTN_MA2 }, + { BTN_TOP, PBTN_MA3 }, + { BTN_BASE, PBTN_MENU }, + { BTN_TOP2, PBTN_L }, + { BTN_PINKIE, PBTN_R }, + /* "normal" keyboards */ + { KEY_ENTER, PBTN_MOK }, + { KEY_ESC, PBTN_MBACK }, + { KEY_SEMICOLON, PBTN_MA2 }, + { KEY_APOSTROPHE, PBTN_MA3 }, + { KEY_BACKSLASH, PBTN_MENU }, + { KEY_LEFTBRACE, PBTN_L }, + { KEY_RIGHTBRACE, PBTN_R }, +}; + +static const struct in_pdata gp2x_evdev_pdata = { + .defbinds = in_evdev_defbinds, + .key_map = key_pbtn_map, + .kmap_size = sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]), +}; + static void *fb_flip(void) { memregl[0x406C>>2] = memregl[0x446C>>2] = fb_paddrs[fb_work_buf]; @@ -533,7 +563,7 @@ void plat_init(void) DMA_REG(0x0c) = 0x20000; // pending IRQ clear in_tsbutton_init(); - in_evdev_init(in_evdev_defbinds); + in_evdev_init(&gp2x_evdev_pdata); if (gp2x_dev_id == GP2X_DEV_CAANOO) caanoo_init(); else @@ -674,10 +704,15 @@ static int haptic_init(void) return 0; } -void plat_trigger_vibrate(int is_strong) +void plat_trigger_vibrate(int pad, int low, int high) { + int is_strong; int ret; + if (low == 0 && high == 0) + return; + is_strong = (high >= 0xf0); + if (hapticdev == -2) return; // it's broken if (hapticdev < 0) { diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 247437e..5e11cf8 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -53,6 +53,41 @@ static const struct in_default_bind in_sdl_defbinds[] = { { 0, 0, 0 } }; +const struct menu_keymap in_sdl_key_map[] = +{ + { SDLK_UP, PBTN_UP }, + { SDLK_DOWN, PBTN_DOWN }, + { SDLK_LEFT, PBTN_LEFT }, + { SDLK_RIGHT, PBTN_RIGHT }, + { SDLK_RETURN, PBTN_MOK }, + { SDLK_ESCAPE, PBTN_MBACK }, + { SDLK_SEMICOLON, PBTN_MA2 }, + { SDLK_QUOTE, PBTN_MA3 }, + { SDLK_LEFTBRACKET, PBTN_L }, + { SDLK_RIGHTBRACKET, PBTN_R }, +}; + +const struct menu_keymap in_sdl_joy_map[] = +{ + { SDLK_UP, PBTN_UP }, + { SDLK_DOWN, PBTN_DOWN }, + { SDLK_LEFT, PBTN_LEFT }, + { SDLK_RIGHT, PBTN_RIGHT }, + /* joystick */ + { SDLK_WORLD_0, PBTN_MOK }, + { SDLK_WORLD_1, PBTN_MBACK }, + { SDLK_WORLD_2, PBTN_MA2 }, + { SDLK_WORLD_3, PBTN_MA3 }, +}; + +static const struct in_pdata in_sdl_platform_data = { + .defbinds = in_sdl_defbinds, + .key_map = in_sdl_key_map, + .kmap_size = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]), + .joy_map = in_sdl_joy_map, + .jmap_size = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]), +}; + static int psx_w, psx_h; static void *shadow_fb, *menubg_img; static int in_menu; @@ -122,7 +157,7 @@ void plat_init(void) exit(1); } - in_sdl_init(in_sdl_defbinds, plat_sdl_event_handler); + in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); in_probe(); pl_rearmed_cbs.only_16bpp = 1; pl_rearmed_cbs.pl_get_layer_pos = get_layer_pos; @@ -301,7 +336,7 @@ void *plat_prepare_screenshot(int *w, int *h, int *bpp) return 0; } -void plat_trigger_vibrate(int is_strong) +void plat_trigger_vibrate(int pad, int low, int high) { } diff --git a/frontend/plugin.c b/frontend/plugin.c index 7e8e5c3..cf3d575 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -25,19 +25,20 @@ extern long SPUinit(void); extern long SPUshutdown(void); extern long SPUclose(void); extern void SPUplaySample(unsigned char); -extern void SPUwriteRegister(unsigned long, unsigned short); +extern void SPUwriteRegister(unsigned long, unsigned short, unsigned int); extern unsigned short SPUreadRegister(unsigned long); extern void SPUwriteDMA(unsigned short); extern unsigned short SPUreadDMA(void); -extern void SPUwriteDMAMem(unsigned short *, int); -extern void SPUreadDMAMem(unsigned short *, int); +extern void SPUwriteDMAMem(unsigned short *, int, unsigned int); +extern void SPUreadDMAMem(unsigned short *, int, unsigned int); extern void SPUplayADPCMchannel(void *); -extern void SPUregisterCallback(void (*callback)(void)); +extern void SPUregisterCallback(void (*cb)(void)); +extern void SPUregisterScheduleCb(void (*cb)(unsigned int)); extern long SPUconfigure(void); extern long SPUtest(void); extern void SPUabout(void); -extern long SPUfreeze(unsigned int, void *); -extern void SPUasync(unsigned int); +extern long SPUfreeze(unsigned int, void *, unsigned int); +extern void SPUasync(unsigned int, unsigned int); extern int SPUplayCDDAchannel(short *, int); /* PAD */ @@ -135,6 +136,7 @@ static const struct { DIRECT_SPU(SPUplayADPCMchannel), DIRECT_SPU(SPUfreeze), DIRECT_SPU(SPUregisterCallback), + DIRECT_SPU(SPUregisterScheduleCb), DIRECT_SPU(SPUasync), DIRECT_SPU(SPUplayCDDAchannel), /* PAD */ @@ -254,14 +256,14 @@ pc_hook_func (GPU_readDataMem, (uint32_t *a0, int a1), (a0, a1), PC pc_hook_func_ret(long, GPU_dmaChain, (uint32_t *a0, int32_t a1), (a0, a1), PCNT_GPU) pc_hook_func (GPU_updateLace, (void), (), PCNT_GPU) -pc_hook_func (SPU_writeRegister, (unsigned long a0, unsigned short a1), (a0, a1), PCNT_SPU) +pc_hook_func (SPU_writeRegister, (unsigned long a0, unsigned short a1, uint32_t a2), (a0, a1, a2), PCNT_SPU) pc_hook_func_ret(unsigned short,SPU_readRegister, (unsigned long a0), (a0), PCNT_SPU) pc_hook_func (SPU_writeDMA, (unsigned short a0), (a0), PCNT_SPU) pc_hook_func_ret(unsigned short,SPU_readDMA, (void), (), PCNT_SPU) -pc_hook_func (SPU_writeDMAMem, (unsigned short *a0, int a1), (a0, a1), PCNT_SPU) -pc_hook_func (SPU_readDMAMem, (unsigned short *a0, int a1), (a0, a1), PCNT_SPU) +pc_hook_func (SPU_writeDMAMem, (unsigned short *a0, int a1, uint32_t a2), (a0, a1, a2), PCNT_SPU) +pc_hook_func (SPU_readDMAMem, (unsigned short *a0, int a1, uint32_t a2), (a0, a1, a2), PCNT_SPU) pc_hook_func (SPU_playADPCMchannel, (void *a0), (a0), PCNT_SPU) -pc_hook_func (SPU_async, (unsigned int a0), (a0), PCNT_SPU) +pc_hook_func (SPU_async, (uint32_t a0, uint32_t a1), (a0, a1), PCNT_SPU) pc_hook_func_ret(int, SPU_playCDDAchannel, (short *a0, int a1), (a0, a1), PCNT_SPU) #define hook_it(name) { \ |