From 4a64abfaefbe45b5654067d13dc8dca74a011291 Mon Sep 17 00:00:00 2001 From: JoseAaronLopezGarcia Date: Sun, 23 Jul 2023 19:42:33 +0200 Subject: [PATCH] soundless ps1 on vita standalone --- Makefile | 5 + common/include/systemctrl.h | 10 + core/compat/vita/Makefile | 2 +- core/compat/vita/popspatch.c | 33 +- core/compat/vita/syspatch.c | 81 ++- core/compat/vitapops/syspatch.c | 27 +- core/popcorn/main.c | 96 +-- core/systemctrl/src/hooknids.c | 2 +- core/systemctrl/src/mediasync.c | 2 +- extras/menus/arkMenu/include/exit_mgr.h | 1 - extras/menus/arkMenu/src/common.cpp | 1 - extras/menus/arkMenu/src/iso.cpp | 1 - extras/modules/peops/Makefile | 37 +- extras/modules/peops/README | 2 - extras/modules/peops/audio.c | 152 ++-- extras/modules/peops/audio.h | 24 +- extras/modules/peops/common.h | 36 +- extras/modules/peops/exports.exp | 1 - extras/modules/peops/gamesettings.c | 51 -- extras/modules/peops/gamesettings.h | 46 -- extras/modules/peops/imports.S | 8 - extras/modules/peops/main.c | 256 +++---- extras/modules/peops/main.h | 31 +- extras/modules/peops/prospu.c | 597 ---------------- extras/modules/peops/psp.c | 70 +- extras/modules/peops/psp.h | 25 +- extras/modules/peops/spu/adsr.c | 2 - extras/modules/peops/spu/adsr.h | 658 +---------------- extras/modules/peops/spu/alsa.c | 162 ----- extras/modules/peops/spu/arm_utils.S | 164 ----- extras/modules/peops/spu/decode_xa.c | 464 ++++++------ extras/modules/peops/spu/decode_xa.h | 18 +- extras/modules/peops/spu/dma.c | 99 --- extras/modules/peops/spu/dma.h | 31 - extras/modules/peops/spu/externals.h | 31 +- extras/modules/peops/spu/freeze.c | 339 --------- extras/modules/peops/spu/gauss_i.h | 256 +++---- extras/modules/peops/spu/nullsnd.c | 142 ---- extras/modules/peops/spu/oss.c | 167 ----- extras/modules/peops/spu/out.c | 51 -- extras/modules/peops/spu/out.h | 12 - extras/modules/peops/spu/psemuxa.h | 28 - extras/modules/peops/spu/pulseaudio.c | 357 --------- extras/modules/peops/spu/registers.c | 914 +++++++++++------------- extras/modules/peops/spu/registers.h | 26 +- extras/modules/peops/spu/reverb.c | 14 +- extras/modules/peops/spu/reverb.h | 468 +----------- extras/modules/peops/spu/sdl.c | 143 ---- extras/modules/peops/spu/spu.c | 511 +++---------- extras/modules/peops/spu/xa.c | 747 +++++++++---------- extras/modules/peops/spu/xa.h | 446 +----------- loader/live/user/psxloader/main.c | 4 + 52 files changed, 1783 insertions(+), 6068 deletions(-) delete mode 100644 extras/modules/peops/README delete mode 100644 extras/modules/peops/gamesettings.c delete mode 100644 extras/modules/peops/gamesettings.h delete mode 100644 extras/modules/peops/imports.S delete mode 100644 extras/modules/peops/prospu.c delete mode 100644 extras/modules/peops/spu/alsa.c delete mode 100644 extras/modules/peops/spu/arm_utils.S delete mode 100644 extras/modules/peops/spu/dma.c delete mode 100644 extras/modules/peops/spu/dma.h delete mode 100644 extras/modules/peops/spu/freeze.c delete mode 100644 extras/modules/peops/spu/nullsnd.c delete mode 100644 extras/modules/peops/spu/oss.c delete mode 100644 extras/modules/peops/spu/out.c delete mode 100644 extras/modules/peops/spu/out.h delete mode 100644 extras/modules/peops/spu/psemuxa.h delete mode 100644 extras/modules/peops/spu/pulseaudio.c delete mode 100644 extras/modules/peops/spu/sdl.c diff --git a/Makefile b/Makefile index 4887868e1..6d1f9ac9e 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ SUBDIRS = libs \ extras/menus/xMenu \ extras/menus/advancedvsh \ extras/menus/provsh \ + extras/modules/peops \ extras/modules/xmbctrl \ extras/modules/usbdevice \ extras/modules/idsregeneration @@ -97,7 +98,10 @@ copy-bin: $(Q)cp extras/modules/idsregeneration/idsregeneration.prx dist/ARK_01234/IDSREG.PRX # idsregeneration $(Q)cp extras/modules/usbdevice/usbdevice.prx dist/ARK_01234/USBDEV.PRX # USB Device Driver $(Q)cp extras/installer/EBOOT.PBP dist/PSP/ARK_Full_Installer # Full installer + $(Q)cp extras/modules/peops/peops.prx dist/ARK_01234/PS1SPU.PRX $(Q)cp contrib/UPDATER.TXT dist/ARK_01234/ + $(Q)cp contrib/PSP/popsman.prx dist/ARK_01234/POPSMAN.PRX + $(Q)cp contrib/PSP/pops_01g.prx dist/ARK_01234/POPS.PRX $(Q)cp -r extras/menus/arkMenu/themes dist/ $(Q)rm -rf dist/themes/translations $(Q)cp contrib/README.TXT dist/ @@ -178,6 +182,7 @@ clean: $(Q)$(MAKE) $@ -C extras/menus/advancedvsh $(Q)$(MAKE) $@ -C extras/menus/provsh $(Q)$(MAKE) $@ -C extras/menus/xMenu + $(Q)$(MAKE) $@ -C extras/modules/peops $(Q)$(MAKE) $@ -C extras/modules/xmbctrl $(Q)$(MAKE) $@ -C extras/modules/usbdevice $(Q)$(MAKE) $@ -C extras/modules/ipl_update diff --git a/common/include/systemctrl.h b/common/include/systemctrl.h index c49a4ba49..4f1d260f3 100644 --- a/common/include/systemctrl.h +++ b/common/include/systemctrl.h @@ -77,6 +77,16 @@ unsigned int sctrlModuleTextAddr(char * modname); // Load Execute Module via Kernel Internal Function int sctrlKernelLoadExecVSHWithApitype(int apitype, const char * file, struct SceKernelLoadExecVSHParam * param); +/** + * Restart the vsh. + * + * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL + * + * @returns < 0 on some errors. + * +*/ +int sctrlKernelExitVSH(struct SceKernelLoadExecVSHParam *param); + // Register Prologue Module Start Handler STMOD_HANDLER sctrlHENSetStartModuleHandler(STMOD_HANDLER new_handler); diff --git a/core/compat/vita/Makefile b/core/compat/vita/Makefile index fcc1de73e..e8f1a376c 100644 --- a/core/compat/vita/Makefile +++ b/core/compat/vita/Makefile @@ -39,7 +39,7 @@ USE_KERNEL_LIBS=1 LIBDIR = $(ARKROOT)/libs LDFLAGS = -nostartfiles -LIBS = -lpspsemaphore -lpspsystemctrl_kernel +LIBS = -lpspsemaphore -lpspsystemctrl_kernel -lgraphics -lcolordebugger PSP_FW_VERSION = 660 diff --git a/core/compat/vita/popspatch.c b/core/compat/vita/popspatch.c index d6c0d2aa9..1b1affe39 100644 --- a/core/compat/vita/popspatch.c +++ b/core/compat/vita/popspatch.c @@ -9,7 +9,6 @@ extern ARKConfig* ark_config; // SPU Status static int running = 0; -static int spu_plugin = -1; // spu thread UID // SPU Background Thread int spuThread(SceSize args, void * argp) @@ -58,7 +57,7 @@ void _sceMeAudio_DE630CD2(void * loopCore, void * stack) // Flush Cache // flushCache(); - + // Elevate Permission Level unsigned int k1 = pspSdkSetK1(0); int thid = sceKernelCreateThread("SPUThread", spuThread, 0x10, 32 * 1024, 0, NULL); @@ -91,13 +90,13 @@ static int myKernelLoadModule(char * fname, int flag, void * opt) strcat(path, "PS1SPU.PRX"); result = sceKernelLoadModule(path, 0, NULL); - spu_plugin = result; // remember spu plugin UID - - static char g_DiscID[32]; - u16 paramType = 0; - u32 paramLength = sizeof(g_DiscID); - sctrlGetInitPARAM("DISC_ID", ¶mType, ¶mLength, g_DiscID); - startResult = sceKernelStartModule(result, strlen(g_DiscID) + 1, g_DiscID, &status, NULL); + if (result >= 0){ + static char g_DiscID[32]; + u16 paramType = 0; + u32 paramLength = sizeof(g_DiscID); + sctrlGetInitPARAM("DISC_ID", ¶mType, ¶mLength, g_DiscID); + startResult = sceKernelStartModule(result, strlen(g_DiscID) + 1, g_DiscID, &status, NULL); + } #ifdef DEBUG printk("%s: fname %s load 0x%08X, start 0x%08X -> 0x%08X\r\n", __func__, path, result, startResult, status); @@ -108,20 +107,20 @@ static int myKernelLoadModule(char * fname, int flag, void * opt) strcat(path, "POPS.PRX"); result = sceKernelLoadModule(path, flag, opt); - if (result<0) result = sceKernelLoadModule("flash0:/kd/pops_660.prx", flag, opt); // load pops modules from injected flash0 - if (result<0) result = sceKernelLoadModule(fname, flag, opt); // passthrough + //if (result<0) result = sceKernelLoadModule("flash0:/kd/pops_660.prx", flag, opt); // load pops modules from injected flash0 + //if (result<0) result = sceKernelLoadModule(fname, flag, opt); // passthrough #ifdef DEBUG printk("%s: fname %s flag 0x%08X -> 0x%08X\r\n", __func__, fname, flag, result); #endif //PRTSTR1("Load result: %p", result); - sceKernelDelayThread(3000000); + //sceKernelDelayThread(3000000); return result; } -void patchVitaPopsman(SceModule2* mod){ +void patchPspPopsman(SceModule2* mod){ u32 text_addr = mod->text_addr; u32 top_addr = text_addr + mod->text_size; @@ -138,6 +137,7 @@ void patchVitaPopsman(SceModule2* mod){ _sw(LI_V0(0), text_addr + 0x35AC + 4); _sw(JR_RA, text_addr + 0x31EC); _sw(LI_V0(0), text_addr + 0x31EC + 4); + // Coldbird hacks _sw(JR_RA, text_addr + 0x0000342C); _sw(LI_V0(0), text_addr + 0x0000342C + 4); @@ -148,11 +148,10 @@ void patchVitaPopsman(SceModule2* mod){ _sw(JAL(myKernelLoadModule), text_addr + 0x00001EE0); } -void patchVitaPopsSpu(SceModule2 * mod) +void patchPspPopsSpu(SceModule2 * mod) { // Fetch Text Address unsigned int text_addr = mod->text_addr; // Replace Media Engine SPU Background Thread Starter - //if (spu_plugin<0) // don't patch pops if spu plugin loaded - hookImportByNID(mod, "sceMeAudio", 0xDE630CD2, _sceMeAudio_DE630CD2); -} + int res = hookImportByNID(mod, "sceMeAudio", 0xDE630CD2, _sceMeAudio_DE630CD2); +} \ No newline at end of file diff --git a/core/compat/vita/syspatch.c b/core/compat/vita/syspatch.c index 6940575dc..06d0304d8 100644 --- a/core/compat/vita/syspatch.c +++ b/core/compat/vita/syspatch.c @@ -18,6 +18,8 @@ extern void exitLauncher(); extern SEConfig* se_config; +int (* DisplaySetFrameBuf)(void*, int, int, int) = NULL; + KernelFunctions _ktbl = { // for vita flash patcher .KernelDcacheInvalidateRange = &sceKernelDcacheInvalidateRange, .KernelIcacheInvalidateAll = &sceKernelIcacheInvalidateAll, @@ -132,13 +134,31 @@ int sceAudioOutput2ReleaseFixed(){ return _sceAudioOutput2Release(); } +static void breakPoint(){ + _sw(0x44000000, 0xBC800100); + colorDebug(0xFF00); + _sw(0, 0); +} + void ARKVitaOnModuleStart(SceModule2 * mod){ // System fully booted Status static int booted = 0; + + patchFileManagerImports(mod); patchGameInfoGetter(mod); + if (strcmp(mod->modname, "sceThreadMan") == 0){ + _sw(JAL(breakPoint), mod->text_addr+0x00017930); + goto flush; + } + + if(strcmp(mod->modname, "sceDisplay_Service") == 0) { + DisplaySetFrameBuf = (void*)sctrlHENFindFunction("sceDisplay_Service", "sceDisplay", 0x289D82FE); + goto flush; + } + // Patch sceKernelExitGame Syscalls if(strcmp(mod->modname, "sceLoadExec") == 0) { @@ -155,22 +175,21 @@ void ARKVitaOnModuleStart(SceModule2 * mod){ goto flush; } - /* - // Patch Vita Popsman + // Patch PSP Popsman if (strcmp(mod->modname, "scePops_Manager") == 0){ - patchVitaPopsman(mod); + patchPspPopsman(mod); // Hook scePopsManExitVSHKernel - sctrlHENPatchSyscall((void *)sctrlHENFindFunction("scePops_Manager", "scePopsMan", 0x0090B2C8), K_EXTRACT_IMPORT(exitLauncher)); + //sctrlHENPatchSyscall((void *)sctrlHENFindFunction("scePops_Manager", "scePopsMan", 0x0090B2C8), K_EXTRACT_IMPORT(exitLauncher)); goto flush; } - // Patch POPS SPU + // Patch PSP POPS SPU if (strcmp(mod->modname, "pops") == 0) { - patchVitaPopsSpu(mod); + //breakPoint(); + patchPspPopsSpu(mod); goto flush; } - */ // VLF Module Patches if(strcmp(mod->modname, "VLF_Module") == 0) @@ -224,10 +243,58 @@ void ARKVitaOnModuleStart(SceModule2 * mod){ if(previous) previous(mod); } +int (*prev_start)(int modid, SceSize argsize, void * argp, int * modstatus, SceKernelSMOption * opt) = NULL; +int StartModuleHandler(int modid, SceSize argsize, void * argp, int * modstatus, SceKernelSMOption * opt){ + + SceModule2* mod = (SceModule2*) sceKernelFindModuleByUID(modid); + + /* + if (DisplaySetFrameBuf){ + static int screen_init = 0; + if (!screen_init){ + initScreen(DisplaySetFrameBuf); + screen_init = 1; + } + cls(); + PRTSTR1("mod: %s", mod->modname); + } + */ + + struct { + char* name; + char* path; + } pops_files[] = { + {"scePops_Manager", "POPSMAN.PRX"}, + {"sceMediaSync", "MEDIASYNC.PRX"}, + }; + + for (int i=0; i < sizeof(pops_files)/sizeof(pops_files[0]); i++){ + if (strcmp(mod->modname, pops_files[i].name) == 0){ + char path[ARK_PATH_SIZE]; + strcpy(path, ark_config->arkpath); + strcat(path, pops_files[i].path); + SceIoStat stat; + int res = sceIoGetstat(path, &stat); + if (res>=0){ + sceKernelUnloadModule(modid); + modid = sceKernelLoadModule(path, 0, NULL); + return sceKernelStartModule(modid, argsize, argp, modstatus, opt); + } + } + } + + // forward to previous or default StartModule + if (prev_start) return prev_start(modid, argsize, argp, modstatus, opt); + return -1; +} + void PROVitaSysPatch(){ SceModule2* mod = NULL; // filesystem patches initFileSystem(); // patch loadexec to use inferno for UMD drive emulation (needed for some homebrews to load) patchLoadExecUMDemu(); + + // Register custom start module + prev_start = sctrlSetStartModuleExtra(StartModuleHandler); } diff --git a/core/compat/vitapops/syspatch.c b/core/compat/vitapops/syspatch.c index 95371d6e8..3b4e2945c 100644 --- a/core/compat/vitapops/syspatch.c +++ b/core/compat/vitapops/syspatch.c @@ -302,7 +302,7 @@ int kermitSendRequestLog(void* a0, int a1, int a2, int a3, int a4, void* a5){ if (!logging){ logging = 1; - sprintf(tmp, "mode: %d, cmd: %d\n", a1, a2); + sprintf(tmp, "sceKermitSendRequest - mode: %d, cmd: %d\n", a1, a2); int fd = sceIoOpen("ms0:/kermit.log", PSP_O_WRONLY|PSP_O_APPEND|PSP_O_CREAT, 0777); sceIoWrite(fd, tmp, strlen(tmp)); sceIoClose(fd); @@ -312,13 +312,33 @@ int kermitSendRequestLog(void* a0, int a1, int a2, int a3, int a4, void* a5){ return sceKermitSendRequest(a0, a1, a2, a3, a4, a5); } +int (*sceKermitPeripheral_driver_8C7903E7)() = NULL; +int sceKermitPeripheral_driver_log(void* a0, int a1, int a2, int a3, int a4, void* a5, u32 a6, u32 a7){ + + static volatile int logging = 0; + static char tmp[64]; + + //if (a1 == 9 && a2 == 1042) return 0; + + if (!logging){ + logging = 1; + sprintf(tmp, "sceKermitPeripheral_driver_8C7903E7 - mode: %d, cmd: %d\n", a1, a2); + int fd = sceIoOpen("ms0:/kermit.log", PSP_O_WRONLY|PSP_O_APPEND|PSP_O_CREAT, 0777); + sceIoWrite(fd, tmp, strlen(tmp)); + sceIoClose(fd); + logging = 0; + } + + return sceKermitPeripheral_driver_8C7903E7(a0, a1, a2, a3, a4, a5, a6, a7); +} + void ARKVitaPopsOnModuleStart(SceModule2 * mod){ static int booted = 0; /* if (strcmp(mod->modname, "sceIOFileManager") != 0 && strcmp(mod->modname, "sceKermitMsfs_driver") != 0){ - hookImportByNID(mod, "sceKermit_driver", 0x36666181, kermitSendRequestLog); + } */ @@ -358,6 +378,9 @@ void ARKVitaPopsOnModuleStart(SceModule2 * mod){ */ if (strcmp(mod->modname, "scePops_Manager") == 0){ + sceKermitPeripheral_driver_8C7903E7 = sctrlHENFindFunction("sceKermitPeripheral_Driver", "sceKermitPeripheral_driver", 0x8C7903E7); + hookImportByNID(mod, "sceKermitPeripheral_driver", 0x36666181, sceKermitPeripheral_driver_log); + hookImportByNID(mod, "sceKermit_driver", 0x36666181, kermitSendRequestLog); patchPopsMan(mod); goto flush; } diff --git a/core/popcorn/main.c b/core/popcorn/main.c index 0e146b549..6d3b9b097 100644 --- a/core/popcorn/main.c +++ b/core/popcorn/main.c @@ -39,8 +39,6 @@ static int g_isCustomPBP; static int g_keysBinFound; static SceUID g_plain_doc_fd = -1; -static char g_DiscID[32]; - #define PGD_ID "XX0000-XXXX00000_00-XXXXXXXXXX000XXX" #define ACT_DAT "flash2:/act.dat" #define RIF_MAGIC_FD 0x10000 @@ -546,41 +544,6 @@ static int myIoClose(SceUID fd) return ret; } -static int _sceDrmBBCipherUpdate(void *ckey, unsigned char *data, int size) -{ - return 0; -} - -static int _sceDrmBBCipherInit(void *ckey, int type, int mode, unsigned char *header_key, unsigned char *version_key, unsigned int seed) -{ - return 0; -} - -static int _sceDrmBBMacInit(void *mkey, int type) -{ - return 0; -} - -static int _sceDrmBBMacUpdate(void *mkey, unsigned char *buf, int size) -{ - return 0; -} - -static int _sceDrmBBCipherFinal(void *ckey) -{ - return 0; -} - -static int _sceDrmBBMacFinal(void *mkey, unsigned char *buf, unsigned char *vkey) -{ - return 0; -} - -static int _sceDrmBBMacFinal2(void *mkey, unsigned char *out, unsigned char *vkey) -{ - return 0; -} - static struct FunctionHook g_ioHooks[] = { { 0x109F50BC, &myIoOpen, }, { 0x27EB27B8, &myIoLseek, }, @@ -592,13 +555,13 @@ static struct FunctionHook g_ioHooks[] = { }; static struct FunctionHook g_amctrlHooks[] = { - { 0x1CCB66D2, &_sceDrmBBCipherInit, }, - { 0x0785C974, &_sceDrmBBCipherUpdate, }, - { 0x9951C50F, &_sceDrmBBCipherFinal, }, - { 0x525B8218, &_sceDrmBBMacInit, }, - { 0x58163FBE, &_sceDrmBBMacUpdate, }, - { 0xEF95A213, &_sceDrmBBMacFinal, }, - { 0xF5186D8E, &_sceDrmBBMacFinal2, }, + { 0x1CCB66D2, NULL}, + { 0x0785C974, NULL}, + { 0x9951C50F, NULL}, + { 0x525B8218, NULL}, + { 0x58163FBE, NULL}, + { 0xEF95A213, NULL}, + { 0xF5186D8E, NULL}, }; static int (*sceNpDrmGetVersionKey)(unsigned char * key, unsigned char * act, unsigned char * rif, unsigned int flags); @@ -699,46 +662,37 @@ void patchPopsMgr(void) sceNpDrmGetVersionKey = (void*)sctrlHENFindFunction("scePspNpDrm_Driver", "scePspNpDrm_driver", 0x0F9547E6); scePspNpDrm_driver_9A34AC9F = (void*)sctrlHENFindFunction("scePspNpDrm_Driver", "scePspNpDrm_driver", 0x9A34AC9F); + hookImportByNID(mod, "scePspNpDrm_driver", 0x0F9547E6, _sceNpDrmGetVersionKey); + hookImportByNID(mod, "scePspNpDrm_driver", 0x9A34AC9F, _scePspNpDrm_driver_9A34AC9F); for(i=0; itext_size && _getRifPath==NULL; addr+=4){ - u32 data = _lw(addr); - if (data == 0x2C830001 && _lw(addr+4) == 0x2CA70001){ - _getRifPath = (void*)(addr-4); - break; + + if (g_isCustomPBP) + { + for(i=0; itext_size && patches; addr+=4){ u32 data = _lw(addr); - if (data == JAL(_getRifPath)){ - _sw(JAL(&getRifPatch), addr); + if (data == 0x34C20016){ + _getRifPath = (void*)(addr-32); // found getRifPath + } + else if (data == JAL(_getRifPath)){ + _sw(JAL(&getRifPatch), addr); // redirect calls to getRifPath patches--; } else if (data == 0x0000000D){ _sw(NOP, addr); // remove the check in scePopsManLoadModule that only allows loading module below the FW 3.XX patches--; } - else if (data == JUMP(scePspNpDrm_driver_9A34AC9F)){ - _sw(JUMP(_scePspNpDrm_driver_9A34AC9F), addr); // hook scePspNpDrm_driver_9A34AC9F call - patches--; - } - else if (data == JUMP(sceNpDrmGetVersionKey)){ - _sw(JUMP(_sceNpDrmGetVersionKey), addr); // hook sceNpDrmGetVersionKey call - patches--; - } - } - if (g_isCustomPBP) - { - for(i=0; i= 0 && func_int <= 0xFFFF) + if(func_int <= 0xFFFF) { // Create Dummy Return _sw(JR_RA, stub); diff --git a/core/systemctrl/src/mediasync.c b/core/systemctrl/src/mediasync.c index 951a7ef56..81176994b 100644 --- a/core/systemctrl/src/mediasync.c +++ b/core/systemctrl/src/mediasync.c @@ -61,7 +61,7 @@ void patchMediaSync(SceModule2* mod) else if (data == 0x24040034){ _sw(0x00001021, addr-8); // MEDIASYNC_KD_FOLDER_PATCH patches--; - } + } } } diff --git a/extras/menus/arkMenu/include/exit_mgr.h b/extras/menus/arkMenu/include/exit_mgr.h index 4b3677936..2b4fc4335 100644 --- a/extras/menus/arkMenu/include/exit_mgr.h +++ b/extras/menus/arkMenu/include/exit_mgr.h @@ -6,7 +6,6 @@ #include "common.h" extern "C"{ - void sctrlKernelExitVSH(void*); void scePowerRequestColdReset(int); void scePowerRequestStandby(); } diff --git a/extras/menus/arkMenu/src/common.cpp b/extras/menus/arkMenu/src/common.cpp index 61c1e3873..2f67b3146 100644 --- a/extras/menus/arkMenu/src/common.cpp +++ b/extras/menus/arkMenu/src/common.cpp @@ -20,7 +20,6 @@ bool common::is_recovery = false; extern "C"{ int kuKernelGetModel(); - int sctrlKernelExitVSH(void*); } static ARKConfig ark_config = {0}; diff --git a/extras/menus/arkMenu/src/iso.cpp b/extras/menus/arkMenu/src/iso.cpp index 115717051..1217c6134 100644 --- a/extras/menus/arkMenu/src/iso.cpp +++ b/extras/menus/arkMenu/src/iso.cpp @@ -12,7 +12,6 @@ static u8 g_ciso_dec_buf[DAX_COMP_BUF] __attribute__((aligned(64))); static u32 g_cso_idx_cache[CISO_IDX_MAX_ENTRIES]; extern "C"{ - int sctrlKernelExitVSH(void*); int sctrlDeflateDecompress(void*, void*, int); int lzo1x_decompress(void*, unsigned int, void*, unsigned int*, void*); int LZ4_decompress_fast(const char*, char*, int); diff --git a/extras/modules/peops/Makefile b/extras/modules/peops/Makefile index 3450cbe93..636f696e8 100644 --- a/extras/modules/peops/Makefile +++ b/extras/modules/peops/Makefile @@ -1,40 +1,23 @@ TARGET = peops +OBJS = main.o psp.o audio.o $(SPU_OBJS) exports.o SPU_OBJS = spu/decode_xa.o spu/spu.o spu/registers.o -C_OBJS = main.o psp.o audio.o $(SPU_OBJS) imports.o exports.o gamesettings.o -OBJS = $(C_OBJS) - -all: $(TARGET).prx INCDIR = $(ARKROOT)/common/include -CFLAGS = -std=c99 -O2 -Os -G0 -Wall -fshort-wchar -fno-pic -mno-check-zero-division - -POPSMAN_VERSION ?= VERSION_PSP -POPS_VERSION ?= VERSION_PSP - -# POPS Version -CFLAGS += -DPOPSMAN_VERSION=$(POPSMAN_VERSION) -DPOPS_VERSION=$(POPS_VERSION) - -ifdef DEBUG -CFLAGS += -DDEBUG=$(DEBUG) -endif - -PSP_FW_VERSION = 660 - +CFLAGS = -O2 -Os -G0 -Wall -fshort-wchar -fno-pic -mno-check-zero-division CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS) BUILD_PRX = 1 PRX_EXPORTS = exports.exp -#USE_KERNEL_LIBC = 1 -#USE_KERNEL_LIBS = 1 +USE_PSPSDK_LIBC = 1 +USE_PSPSDK_LIBS = 1 LIBDIR = $(ARKROOT)/libs -LDFLAGS = -nostartfiles -LIBS = -lpspsystemctrl_user -lpspaudio -lgraphics +LIBS = -lpspsystemctrl_user -lpspaudio + +all: + psp-packer peops.prx -include $(ARKROOT)/common/make/global.mak -PSPSDK=$(shell psp-config --pspsdk-path) -#include $(PSPSDK)/lib/build.mak -include $(PSPSDK)/lib/build_prx.mak -include $(ARKROOT)/common/make/beauty.mak +PSPSDK = $(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build_prx.mak \ No newline at end of file diff --git a/extras/modules/peops/README b/extras/modules/peops/README deleted file mode 100644 index 55c20e960..000000000 --- a/extras/modules/peops/README +++ /dev/null @@ -1,2 +0,0 @@ -PEOPS PSX SPU Plugin. -This plugin adds partially working sound to PSX games. diff --git a/extras/modules/peops/audio.c b/extras/modules/peops/audio.c index d6cec1c96..c76cb42e1 100644 --- a/extras/modules/peops/audio.c +++ b/extras/modules/peops/audio.c @@ -1,19 +1,19 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or + 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 3 of the License, or - 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. + 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 - (at your option) any later version. - along with this program. If not, see . + You should have received a copy of the GNU General Public License + (at your option) any later version. + along with this program. If not, see . */ #include @@ -21,7 +21,7 @@ #include "spu/stdafx.h" #include "spu/externals.h" -#define BUFFER_SIZE 22050 +#define BUFFER_SIZE 22050 #define PSP_NUM_AUDIO_SAMPLES 1024 short *pSndBuffer = NULL; @@ -33,106 +33,106 @@ int channel = -1; static void FillAudio(unsigned char *stream, int len) { - short *p = (short *)stream; - - len /= sizeof(short); - - while(iReadPos != iWritePos && len > 0) - { - *p++ = pSndBuffer[iReadPos++]; - if(iReadPos >= iBufSize) iReadPos = 0; - --len; - } - - // Fill remaining space with zero - while(len > 0) - { - *p++ = 0; - --len; - } + short *p = (short *)stream; + + len /= sizeof(short); + + while(iReadPos != iWritePos && len > 0) + { + *p++ = pSndBuffer[iReadPos++]; + if(iReadPos >= iBufSize) iReadPos = 0; + --len; + } + + // Fill remaining space with zero + while(len > 0) + { + *p++ = 0; + --len; + } } int audio_thread(SceSize args, void *argp) { - static unsigned char buf[PSP_NUM_AUDIO_SAMPLES * 4] __attribute__((aligned(64))); + static unsigned char buf[PSP_NUM_AUDIO_SAMPLES * 4] __attribute__((aligned(64))); - while(1) - { - FillAudio(buf, sizeof(buf)); - sceAudioOutputPannedBlocking(channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, buf); - } + while(1) + { + FillAudio(buf, sizeof(buf)); + sceAudioOutputPannedBlocking(channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, buf); + } - return 0; + return 0; } void SetupSound(void) { - if(pSndBuffer != NULL) return; + if(pSndBuffer != NULL) return; - channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, PSP_NUM_AUDIO_SAMPLES, PSP_AUDIO_FORMAT_STEREO); + channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, PSP_NUM_AUDIO_SAMPLES, PSP_AUDIO_FORMAT_STEREO); - audio_thid = sceKernelCreateThread("audio_thread", audio_thread, 0x10, 0x1000, 0, NULL); - if(audio_thid >= 0) sceKernelStartThread(audio_thid, 0, NULL); + audio_thid = sceKernelCreateThread("audio_thread", audio_thread, 0x10, 0x1000, 0, NULL); + if(audio_thid >= 0) sceKernelStartThread(audio_thid, 0, NULL); - iBufSize = BUFFER_SIZE; + iBufSize = BUFFER_SIZE; - pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); - if(pSndBuffer == NULL) - { - return; - } + pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); + if(pSndBuffer == NULL) + { + return; + } - iReadPos = 0; - iWritePos = 0; + iReadPos = 0; + iWritePos = 0; } void RemoveSound(void) { - if(pSndBuffer == NULL) return; + if(pSndBuffer == NULL) return; - if(audio_thid >= 0) - { - sceKernelTerminateDeleteThread(audio_thid); - } + if(audio_thid >= 0) + { + sceKernelTerminateDeleteThread(audio_thid); + } - if(channel >= 0) - { - sceAudioChRelease(channel); - } + if(channel >= 0) + { + sceAudioChRelease(channel); + } - free(pSndBuffer); - pSndBuffer = NULL; + free(pSndBuffer); + pSndBuffer = NULL; } unsigned long SoundGetBytesBuffered(void) { - int size; + int size; - if(pSndBuffer == NULL) return SOUNDSIZE; + if(pSndBuffer == NULL) return SOUNDSIZE; - size = iReadPos - iWritePos; - if(size <= 0) size += iBufSize; + size = iReadPos - iWritePos; + if(size <= 0) size += iBufSize; - if(size < iBufSize / 2) return SOUNDSIZE; + if(size < iBufSize / 2) return SOUNDSIZE; - return 0; + return 0; } void SoundFeedStreamData(unsigned char *pSound, long lBytes) { - short *p = (short *)pSound; + short *p = (short *)pSound; - if(pSndBuffer == NULL) return; + if(pSndBuffer == NULL) return; - while(lBytes > 0) - { - if(((iWritePos + 1) % iBufSize) == iReadPos) break; + while(lBytes > 0) + { + if(((iWritePos + 1) % iBufSize) == iReadPos) break; - pSndBuffer[iWritePos] = *p++; + pSndBuffer[iWritePos] = *p++; - ++iWritePos; - if(iWritePos >= iBufSize) iWritePos = 0; + ++iWritePos; + if(iWritePos >= iBufSize) iWritePos = 0; - lBytes -= sizeof(short); - } + lBytes -= sizeof(short); + } } \ No newline at end of file diff --git a/extras/modules/peops/audio.h b/extras/modules/peops/audio.h index 16c70db09..180cbec3e 100644 --- a/extras/modules/peops/audio.h +++ b/extras/modules/peops/audio.h @@ -1,19 +1,19 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or - (at your option) any later version. + 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 3 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. + 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, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifndef __AUDIO_H__ diff --git a/extras/modules/peops/common.h b/extras/modules/peops/common.h index 9b91055fb..4b60d9fd9 100644 --- a/extras/modules/peops/common.h +++ b/extras/modules/peops/common.h @@ -1,10 +1,40 @@ #ifndef COMMON_H -#define COMMON_H +#define COMMON_H #include #include #include -#include -#include + +#define MAKE_JUMP(a, f) _sw(0x08000000 | (((u32)(f) & 0x0FFFFFFC) >> 2), a); +#define MAKE_CALL(a, f) _sw(0x0C000000 | (((u32)(f) >> 2) & 0x03FFFFFF), a); + +//by Davee +#define HIJACK_FUNCTION(a, f, ptr) \ +{ \ + u32 func = a; \ + static u32 patch_buffer[3]; \ + _sw(_lw(func), (u32)patch_buffer); \ + _sw(_lw(func + 4), (u32)patch_buffer + 8);\ + MAKE_JUMP((u32)patch_buffer + 4, func + 8); \ + _sw(0x08000000 | (((u32)(f) >> 2) & 0x03FFFFFF), func); \ + _sw(0, func + 4); \ + ptr = (void *)patch_buffer; \ +} + +typedef struct +{ + /* PEOPS SPU configuration */ + int enablepeopsspu; + int volume; + int reverb; + int interpolation; + int enablexaplaying; + int changexapitch; + int spuirqwait; + int spuupdatemode; + int sputhreadpriority; +} PeopsConfig; + +extern PeopsConfig config; #endif diff --git a/extras/modules/peops/exports.exp b/extras/modules/peops/exports.exp index 05654d8c7..08306972b 100644 --- a/extras/modules/peops/exports.exp +++ b/extras/modules/peops/exports.exp @@ -2,7 +2,6 @@ PSP_BEGIN_EXPORTS PSP_EXPORT_START(syslib, 0, 0x8000) PSP_EXPORT_FUNC(module_start) -PSP_EXPORT_FUNC(module_stop) PSP_EXPORT_VAR(module_info) PSP_EXPORT_END diff --git a/extras/modules/peops/gamesettings.c b/extras/modules/peops/gamesettings.c deleted file mode 100644 index 14d3bc8ca..000000000 --- a/extras/modules/peops/gamesettings.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "gamesettings.h" - -long strhash(char* str){ - ssize_t len = strlen(str) - 1; - ssize_t i = len; - unsigned char* p = str; - - long x = *p << 7; - - while (--i >= 0) - x = (1000003*x) ^ *p++; - - x ^= (len); - - return (x == -1)? -2 : x; -} - -void loadGameSettings(char* gameid, PeopsConfig* conf){ - long hash = strhash(gameid); - memset(conf, 0, sizeof(PeopsConfig)); - - // Reset PEOPS to default settings - conf->enablepeopsspu = 1; - conf->volume = 3; - conf->reverb = 1; - conf->interpolation = 2; - conf->enablexaplaying = 1; - conf->changexapitch = 1; - conf->spuirqwait = 1; - conf->spuupdatemode = 0; - conf->sputhreadpriority = 0; - - /* - if (ark_config->override_peops_config){ - memcpy(conf, &(ark_config->peops_config), sizeof(*conf)); - return; - } - */ - - switch (hash){ - case -5548781341825711198: // Bloody Roar (SCUS-94199) - NTSC-U - conf->reverb = REVERB_ROOM; - conf->interpolation = 2; - conf->enablexaplaying = 1; - conf->changexapitch = 1; - conf->spuirqwait = 1; - conf->spuupdatemode = SPU_WAITVBLANK; - conf->sputhreadpriority = SPU_PRIORITY_MEDIUM; - break; - } -} diff --git a/extras/modules/peops/gamesettings.h b/extras/modules/peops/gamesettings.h deleted file mode 100644 index 5ef19bc68..000000000 --- a/extras/modules/peops/gamesettings.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef GAME_SETTINGS_H -#define GAME_SETTINGS_H - -#include "common.h" - -typedef struct{ /* PEOPS SPU configuration */ - int enablepeopsspu; - int volume; - int reverb; - int interpolation; - int enablexaplaying; - int changexapitch; - int spuirqwait; - int spuupdatemode; - int sputhreadpriority; -} PeopsConfig; - -enum ReverbType{ - REVERB_OFF = 0x0000, - REVERB_ROOM = 0x007D, - REVERB_STUDIO_SMALL = 0x0033, - REVERB_STUDIO_MEDIUM = 0x00B1, - REVERB_STUDIO_LARGE = 0x00E3, - REVERB_HALL = 0x01A5, - REVERB_SPACE_ECHO = 0x033D, - REVERB_ECHO_DELAY = 0x0001, - REVERB_HALF_ECHO = 0x0017, -}; - -enum SPU_UpdateMode{ - SPU_WAITVBLANK = 0, - SPU_DELAY2 = 1, - SPU_DELAY20 = 2, -}; - -enum SPU_Priorities{ - SPU_PRIORITY_VERY_LOW = 0, - SPU_PRIORITY_LOW = 1, - SPU_PRIORITY_MEDIUM = 2, - SPU_PRIORITY_HIGH = 3, - SPU_PRIORITY_VERY_HIGH = 4, -}; - -void loadGameSettings(char* gameid, PeopsConfig* conf); - -#endif diff --git a/extras/modules/peops/imports.S b/extras/modules/peops/imports.S deleted file mode 100644 index 0c1a41640..000000000 --- a/extras/modules/peops/imports.S +++ /dev/null @@ -1,8 +0,0 @@ - .set noreorder - -#include "pspimport.s" - - IMPORT_START "scePaf",0x00090011 - IMPORT_FUNC "scePaf",0xD9E2D6E1,memset - IMPORT_FUNC "scePaf",0xB4652CFE,memcpy - IMPORT_FUNC "scePaf",0x4CF09BA2,strcmp \ No newline at end of file diff --git a/extras/modules/peops/main.c b/extras/modules/peops/main.c index 560d99a9e..853b6a2b7 100644 --- a/extras/modules/peops/main.c +++ b/extras/modules/peops/main.c @@ -1,199 +1,161 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or + 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 3 of the License, or - 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. + 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 - (at your option) any later version. - along with this program. If not, see . + You should have received a copy of the GNU General Public License + (at your option) any later version. + along with this program. If not, see . */ #include +#include #include "main.h" -#include "systemctrl.h" -#include "systemctrl_private.h" -#include "module2.h" -#include "macros.h" #include "spu/stdafx.h" -PSP_MODULE_INFO("peops", 0, 1, 0); - -STMOD_HANDLER previous; +PSP_MODULE_INFO("peops", 0x0007, 1, 0); PeopsConfig config; -void (* libspuWrite)(int reg, int val, int type); -void (* libspuCdrWrite)(int reg, int val); -void (* libspuXaFunction)(char *sector, int mode); +void (* spuWriteRegister)(int reg, int val, int type); +void (* cdrTransferSector)(u8 *sector, int mode); +void (* cdrWriteRegister)(int reg, int val); int cdr_is_first_sector = 1; xa_decode_t cdr_xa; -SceUID spu_thid = -1; - void SPUwait() { - switch(config.spuupdatemode) - { - case 0: - sceDisplayWaitVblankStart(); - break; - - case 1: - sceKernelDelayThread(2 * 1000); - break; - - case 2: - sceKernelDelayThread(20 * 1000); - break; - } + switch(config.spuupdatemode) + { + case 0: + sceDisplayWaitVblankStart(); + break; + + case 1: + sceKernelDelayThread(2 * 1000); + break; + + case 2: + sceKernelDelayThread(20 * 1000); + break; + } } int spu_thread(SceSize args, void *argp) { - while(1) - { - SPUupdate(); - SPUwait(); - } + while(1) + { + SPUupdate(); + SPUwait(); + } - return 0; + return 0; } -int priorities[] = { 17, 24, 32, 40, 48 }; -#define N_PRIORITIES (sizeof(priorities) / sizeof(int)) - void sceMeAudioInitPatched(int (* function)(), void *stack) { - SPUinit(); - SPUopen(); + SPUinit(); + SPUopen(); - int priority = priorities[config.sputhreadpriority % N_PRIORITIES]; + static int priorities[] = { 17, 24, 32, 40, 48 }; - spu_thid = sceKernelCreateThread("spu_thread", spu_thread, priority, 0x4000, 0, NULL); - if(spu_thid >= 0) sceKernelStartThread(spu_thid, 0, NULL); + SceUID thid = sceKernelCreateThread("spu_thread", spu_thread, priorities[config.sputhreadpriority % (sizeof(priorities) / sizeof(int))], 0x4000, 0, NULL); + if(thid >= 0) sceKernelStartThread(thid, 0, NULL); } -void libspuWritePatched(int reg, int val, int type) +void sceMeAudioNotifyPatched(int a0) { - SPUwriteRegister(reg, val); - libspuWrite(reg, val, type); + *(u8 *)0x49F40290 = 0; + (*(u8 *)0x49F40291)++; + *(u8 *)0x49F40293 = -2; } -void libspuCdrWritePatched(int reg, int val) +void spuWriteRegisterPatched(int reg, int val, int type) { - if(reg == 0x1F801801) - { - if(val == 6 || val == 27) - { - cdr_is_first_sector = 1; - } - } - - libspuCdrWrite(reg, val); + SPUwriteRegister(reg, val); + spuWriteRegister(reg, val, type); } -void libspuXaFunctionPatched(char *sector, int mode) +void cdrTransferSectorPatched(u8 *sector, int mode) { - u8 *buf = (u8 *)sector + 0xC; - - if(mode == 2) - { - if(cdr_is_first_sector != -1) - { - if(buf[4 + 2] & 0x4) - { - int ret = xa_decode_sector(&cdr_xa, buf + 4, cdr_is_first_sector); - if(ret == 0) - { - SPUplayADPCMchannel(&cdr_xa); - cdr_is_first_sector = 0; - } - else - { - cdr_is_first_sector = -1; - } - } - } - } - - libspuXaFunction(sector, mode); + if(mode == 1) + { + SPUplayCDDAchannel(sector, 0x930); + } + else if(mode == 2) + { + if(cdr_is_first_sector != -1) + { + u8 *buf = sector + 0xC; + + if(buf[4 + 2] & 0x4) + { + int ret = xa_decode_sector(&cdr_xa, buf + 4, cdr_is_first_sector); + if(ret == 0) + { + SPUplayADPCMchannel(&cdr_xa); + cdr_is_first_sector = 0; + } + else + { + cdr_is_first_sector = -1; + } + } + } + } + + cdrTransferSector(sector, mode); } -void OnModuleStart(SceModule2 *mod) +void cdrWriteRegisterPatched(int reg, int val) { - char *modname = mod->modname; - u32 text_addr = mod->text_addr; - - if(strcmp(modname, "pops") == 0) - { - MAKE_JUMP_PATCH(text_addr + 0x1A038, sceMeAudioInitPatched); - - HIJACK_FUNCTION(text_addr + 0x7F00, libspuWritePatched, libspuWrite); + if(reg == 0x1F801801) + { + if(val == 6 || val == 27) + { + cdr_is_first_sector = 1; + } + } + + cdrWriteRegister(reg, val); +} - if(config.enablexaplaying) - { - HIJACK_FUNCTION(text_addr + 0xD1B0, libspuCdrWritePatched, libspuCdrWrite); - HIJACK_FUNCTION(text_addr + 0x83E8, libspuXaFunctionPatched, libspuXaFunction); - } +void PatchPops(u32 text_addr) +{ + MAKE_CALL(text_addr + 0x1A038, sceMeAudioInitPatched); - sceKernelDcacheWritebackAll(); - } + REDIRECT_FUNCTION(text_addr + 0x3D264, sceMeAudioNotifyPatched); - if(previous) - previous(mod); -} + HIJACK_FUNCTION(text_addr + 0x7F00, spuWriteRegisterPatched, spuWriteRegister); + HIJACK_FUNCTION(text_addr + 0x83E8, cdrTransferSectorPatched, cdrTransferSector); + HIJACK_FUNCTION(text_addr + 0xD1B0, cdrWriteRegisterPatched, cdrWriteRegister); -void load_game_profile(char * gameid) -{ - - #ifdef DEBUG - // Output Pointer (just in case) - printk("gameid pointer: %08X\n", (u32)gameid); - - // Output Debug Message - printk("Loading PEOPS audio profile for %s\n", gameid); - #endif - - loadGameSettings(gameid, &config); + sceKernelDcacheWritebackAll(); } int module_start(SceSize args, void *argp) { - load_game_profile((char *)argp); - - /* - SceUID fd = sceIoOpen("ms0:/peopsconf.bin", PSP_O_RDONLY, 0777); - - if (fd>=0){ - sceIoRead(fd, &config, sizeof(config)); - sceIoClose(fd); - } - */ - - previous = sctrlHENSetStartModuleHandler(OnModuleStart); - return 0; -} -int module_stop(SceSize args, void *argp) -{ - if(spu_thid >= 0) - { - sceKernelTerminateDeleteThread(spu_thid); - sceKernelWaitThreadEnd(spu_thid, NULL); - } - - SPUclose(); - SPUshutdown(); - - return 0; -} + config.enablepeopsspu = 1; + config.volume = 3; + config.reverb = 1; + config.interpolation = 2; + config.enablexaplaying = 1; + config.changexapitch = 1; + config.spuirqwait = 1; + config.spuupdatemode = 0; + config.sputhreadpriority = 0; + + PatchPops(*(u32 *)argp); + return 0; +} \ No newline at end of file diff --git a/extras/modules/peops/main.h b/extras/modules/peops/main.h index 51147301c..7e613393c 100644 --- a/extras/modules/peops/main.h +++ b/extras/modules/peops/main.h @@ -1,19 +1,19 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or - (at your option) any later version. + 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 3 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. + 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, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifndef __MAIN_H__ @@ -21,16 +21,13 @@ #include "spu/stdafx.h" -extern PeopsConfig config; - void CALLBACK SPUupdate(void); void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); +void CALLBACK SPUplayCDDAchannel(unsigned char *pcm, int nbytes); void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val); -unsigned short CALLBACK SPUreadRegister(unsigned long reg); -void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); long CALLBACK SPUinit(void); long SPUopen(void); long CALLBACK SPUshutdown(void); long CALLBACK SPUclose(void); -#endif +#endif \ No newline at end of file diff --git a/extras/modules/peops/prospu.c b/extras/modules/peops/prospu.c deleted file mode 100644 index b43870d52..000000000 --- a/extras/modules/peops/prospu.c +++ /dev/null @@ -1,597 +0,0 @@ -#include "spu/registers.h" - -// IRQ Disabler -void removeIRQ(unsigned int * irqdata) -{ - // List Root Element - unsigned int * root = (unsigned int *)(gp + 0x1B8); - - // Extract Pointer - unsigned int * next = (unsigned int *)irqdata[0]; - unsigned int * previous = (unsigned int *)irqdata[1]; - - // Unlink IRQ Data Item from List - { - // Next->Previous = Previous - next[1] = (unsigned int)previous; - - // Previous->Next = Next - previous[0] = (unsigned int)next; - } - - // Previous Element is IRQ List Root - if(previous == root) - { - // Some kind of counter maybe? - if(_lw(gp + 0x1B0) > 0) - { - // Fetch Delta Basedata - unsigned int fromnext = next[2]; - unsigned int fromglobal = _lw(gp + 0x1AC); - - // Override Global Clone - _sw(fromnext, gp + 0x1AC); - - // Calculate and store Delta - _sw(_lw(gp + 0x1B0) + fromnext - fromglobal, gp + 0x1B0); - } - } - - // Unlink Previous Item from current Item ? (why does it do that ?) - irqdata[1] = 0; -} - -// IRQ Enabler -void addIRQ(unsigned int * irqdata, unsigned int arg2) -{ - // List Root Element - unsigned int * root = (unsigned int *)(gp + 0x1B8); - - // Calculate Root Info - unsigned int rootinfo = _lw(gp + 0x1AC) - _lw(gp + 0x1B0) + arg2; - - // Start of IRQ Item List - unsigned int * irq = (unsigned int *)root[0]; - - // Last Item in List - unsigned int * lastitem = root; - - // Move to last Item in List - while(1) - { - // How could this ever happen? - if(irq == root) break; - - // Magic? No idea. - if((irq[2] - rootinfo) > 0) break; - - // Save Last Item - lastitem = irq; - - // Move to next Item - irq = (unsigned int *)irq[0]; - } - - // Set Last Element as Next Element - irqdata[0] = (unsigned int)irq; - - // Set Element before Last Element as Previous Element - irqdata[1] = (unsigned int)lastitem; - - // Set Element before Last Element's Next Element to new Item - lastitem[0] = (unsigned int)irqdata; - - // Set Last Elements Previous Element to new Item - irq[1] = (unsigned int)irqdata; - - // No idea... but hey its there in the original. - if(_lw(gp + 0x1B0) > 0 && lastitem == root) - { - // So lets clone it for now. - _sw(arg2, gp + 0x1B0); - _sw(rootinfo, gp + 0x1AC); - } - - // Nooo ideaaaa. - irqdata[2] = rootinfo; -} - -// SPU Register Memory Getter Callback -unsigned int spuReadCallback(int address, int type) -{ - // Reduce ??? Value by 10 - _sw(_lw(gp + 432) - 10, gp + 432); - - // 16bit Result - unsigned short result = 0; - - // Read Register from SPU Emulator - if(SPUreadRegister(address, &result)) - { - // 16bit Read - if((type & 0x3) == SIGNED_SHORT) return result; - - // 8bit Read - if(type == SIGNED_BYTE) return result & 0xFF; - - // 32bit Result Part #2 - unsigned short result2nd = 0; - - // Read Register from SPU Emulator - if(SPUreadRegister(address + 2, &result2nd)) - { - // Mix Results - return result | (result2nd << 16); - } - } - - // Relative Address - unsigned int reladdress = address & 0x3FF; - - // Full Address - unsigned int fulladdress = PSP_SPU_REGISTER + reladdress; - - // Special Handling for SPU status register - if(reladdress == 0x1AE && (type & 0x3) == SIGNED_SHORT) - { - // Load SPU Status Register Value - unsigned short psxstatus = _lh(fulladdress); - - // Load POPS Emulator-specific SPU Status Register Additions - unsigned char popsstatus = _lb(gp + 842); - - // Mix Values together - return ((((psxstatus & 0xF7F) & 0x20) >> 5) << 7) | (psxstatus & 0xF7F) | popsstatus; - } - - // Signed Byte Type - if(type == SIGNED_BYTE) return _lb(fulladdress); - - // Signed Short Type - if(type == SIGNED_SHORT) return _lh(fulladdress); - - // Signed Int Type - if(type == SIGNED_INT) - { - // Reduce ??? Value by 7 - _sw(_lw(gp + 432) - 7, gp + 432); - - // Return Signed Int Value - return _lw(fulladdress); - } - - // Unsigned Short Type - if(type == UNSIGNED_SHORT) return _lh(fulladdress); - - // Unsigned Byte Type - return _lb(fulladdress); -} - - -// SPU Register Memory Setter Callback -void spuWriteCallback(int address, int value, int type) -{ - // Relative Address (SPU registers range is only 0x200 bytes long) - unsigned int reladdress = address & 0x1FF; - - // 16bit Value Masking (PSX registers are 16bit wide) - unsigned short usvalue = value & 0xFFFF; - - // Special Non-16bit Write Handling - if(type != SIGNED_SHORT) - { - // 32bit Write - if(type != SIGNED_BYTE) - { - // Write first 16bit - spuWriteCallback(reladdress, usvalue, SIGNED_SHORT); - - // Move Pointer for next 16bit - reladdress += 2; - - // Use HI-16bit of Value - usvalue = value >> 16; - } - - // 8bit Write - else - { - // Mask Single Byte - usvalue = value & 0xFF; - - // Change Target (can this writer only write shorts? can't this glitch?) - reladdress--; - } - } - - // Write's reduce this global field... by 1...? - _sw(_lw(gp + 432) - 1, gp + 432); - - // SPU status register - if(reladdress == 0x1AE) - { - // Forward to SPU Emulator - SPUwriteRegister(address, usvalue); - - // SPU status register is read only in POPS - return; - } - - // Voice Data Area Range (8x2 Bytes per Voice) - if(reladdress < 0x180) - { - // Don't ask me... 0xE however is the loop address... could have to do with that. - if((((reladdress & 0xE) ^ 0x6) < 1) & (usvalue < 0x200)) - { - // 0x202 Override - usvalue = 0x202; - } - } - - // Write Value to Register - _sh(usvalue, PSP_SPU_REGISTER + reladdress); - - // Forward to SPU Emulator - SPUwriteRegister(address, usvalue); - - // After-Write Special Handling for Non-Voice Areas - if(reladdress >= 0x180) - { - // Special Treatment for Sound buffer IRQ address - if(reladdress == 0x1A4) - { - // Check if IRQ Enable Bit is set in SPU control register and value == IRQ target buffer - if(((_lh(PSP_SPU_REGISTER + 0x1AA) >> 6) & 1) == 1 && ((_lw(gp + 844) >> 2) ^ usvalue) < 1) - { - // Disable SPU Status Register Bit Overrides - _sb(0x40, gp + 842); - } - } - - // Non-IRQ addresses - else - { - // zeile 65 - if(reladdress >= 0x18C) - { - // zeile 67 - if(reladdress >= 0x190) - { - // SPU data register for non-DMA transfer - if(reladdress == 0x1A8) - { - // No Idea... - if(_lb(gp + 843) < 0x20) - { - // Fetch Pointer - unsigned short * pointer = (unsigned short *)(gp + (_lb(gp + 843) << 1)); - - // Copy Value in there too... - pointer[388] = usvalue; - - // Move Pointer forward by 2 Bytes for next Run - _sb(_lb(gp + 843) + 1, gp + 843); - } - } - - // 0x190 ~ 0x1A8 (not including) - // (not including) 0x1A8 ~ 0x1FF - else - { - if(reladdress >= 0x19C) - { - // SPU control bitflag register - if(reladdress == 0x1AA) - { - // Backup GP + 888 Value - unsigned int gp888 = _lw(gp + 888); - - // Store Copy of Bitflag Value - _sh(usvalue, gp + 840); - - // No idea... - _sw(_lw(gp + 428) - _lw(gp + 432), gp + 888); - - // Really no idea... - if(((_lw(gp + 428) - _lw(gp + 432)) - gp888) >= 0x300) - { - // For sample synchronization maybe... one sample playback time is 22? - if(_lw(PSP_SPU_REGISTER + 0x294) == _lw(gp + 892)) - { - // Wait a bit... - sceKernelDelayThread(22); - } - } - - // Override Timer Variable? - _sw(_lw(PSP_SPU_REGISTER + 0x294), gp + 892); - - // Enable SPU control bitflag isn't set (this means shut SPU down) - if(((usvalue >> 15) & 1) == 0) - { - // Remove bitflags a turned off SPU wouldn't need and update register - _sh(usvalue & 0x3F, PSP_SPU_REGISTER + 0x1AA); - } - - // Non-DMA Write (write through data register) - if(((usvalue >> 4) & 0x3) == 1) - { - // Get Copy Length - unsigned char length = _lb(gp + 843); - - // Get Target Memory Address - unsigned int target = _lw(gp + 844); - - // Get Source Memory Address - unsigned int source = gp + 776; - - // Copy Loop - while(length > 0) - { - // Reduce Length - length--; - - // Some Special PSX Memory Address? - if(target == (_lh(PSP_SPU_REGISTER + 0x1A4) << 2)) - { - // Force SPU Status Bit #6 to 1 (overrides PSX register bit in read callback) - _sb(0x40, gp + 842); - } - - // Move Target Address (should this really be BEFORE copying data?) - target = ((target + 1) & 0x3FFFF); - - // Copy 16bit of Data - _sh(_lh(source), PSP_SPU_REGISTER + 704 + (target << 1)); - - // Move Source Pointer - source += 2; - } - - // Copy Current Target Pointer Position back into Memory - _sw(target, gp + 844); - - // Erase Copy Length - _sb(0, gp + 843); - } - - // Disable IRQ (enable bit isn't set) - if(((usvalue >> 6) & 1) == 0) - { - // IRQ is currently enabled - if(_lw(gp + 852) != 0) - { - // IRQ disable callback - removeIRQ((unsigned int *)(gp + 848)); - } - - // And some more stuff I don't understand... - _sb(1, PSP_SPU_REGISTER + 0x292); - - // Remove SPU Register Status Bit Overrides - _sb(0, gp + 842); - } - - // Enable IRQ (enable bit is set) - else - { - // IRQ is currently disabled - if(_lw(gp + 852) == 0) - { - // IRQ enable callback - addIRQ((unsigned int *)(gp + 848), 0x869); - } - } - } - - else - { - // Sound buffer address setter - if(reladdress == 0x1A6) - { - // Fetch IRQ Sound Buffer Value (for comparison with normal sound buffer) - unsigned short irqsoundbuffer = _lh(PSP_SPU_REGISTER + 0x1A4); - - // Write Value - _sw(usvalue << 2, gp + 844); - - // IRQ enabled and buffer == irqsoundbuffer - if(((_lh(PSP_SPU_REGISTER + 0x1AA) >> 6) & 1) == 1 && (usvalue ^ irqsoundbuffer) < 1) - { - // Force SPU Status Bit #6 to 1 (overrides PSX register bit in read callback) - _sb(0x40, gp + 842); - } - } - - else - { - // Reverb work area start register - // It seems unknown registers are handled as reverb work start too... - if(reladdress == 0x1A2 || reladdress < 512) - { - // Don't ask me.. - _sb(1, PSP_SPU_REGISTER + 0x29D); - _sb(1, PSP_SPU_REGISTER + 0x29F); - - // Wait... - while(_lh(PSP_SPU_REGISTER + 0x29E) == 0x101) - { - // Do nothing... - } - - // I really don't know... - _sw(_lw(PSP_SPU_REGISTER + 0x288) | 0x80000000, PSP_SPU_REGISTER + 0x288); - _sb(0, PSP_SPU_REGISTER + 0x29D); - } - } - } - } - - else - { - // Backup GP + 888 Value - unsigned int gp888 = _lw(gp + 888); - - // Update GP + 888 Value - _sw(_lw(gp + 428) - _lw(gp + 432), gp + 888); - - // No clue~ - if((_lw(gp + 428) - _lw(gp + 432) - gp888) >= 0x300) - { - // Again this weird wait comparison... - if(_lw(PSP_SPU_REGISTER + 0x294) == _lw(gp + 892)) - { - // Alright we wait... - sceKernelDelayThread(22); - } - } - - // Overwrite Wait Timer - _sw(_lw(PSP_SPU_REGISTER + 0x294), gp + 892); - } - } - } - - else - { - // Valid Value - if(usvalue != 0) - { - // Backup GP + 888 Value - unsigned int gp888 = _lw(gp + 888); - - // Update GP + 888 Value - _sw(_lw(gp + 428) - _lw(gp + 432), gp + 888); - - // No clue~ - if((_lw(gp + 428) - _lw(gp + 432) - gp888) >= 0x300) - { - // Again this weird wait comparison... - if(_lw(PSP_SPU_REGISTER + 0x294) == _lw(gp + 892)) - { - // Alright we wait... - sceKernelDelayThread(22); - } - } - - // Overwrite Wait Timer - _sw(_lw(PSP_SPU_REGISTER + 0x294), gp + 892); - - // Don't ask me.. - _sb(1, PSP_SPU_REGISTER + 0x29D); - _sb(1, PSP_SPU_REGISTER + 0x29F); - - // Wait... - while(_lh(PSP_SPU_REGISTER + 0x29E) == 0x101) - { - // Do nothing... - } - - // I really don't know... - _sw(_lw(PSP_SPU_REGISTER + 0x284) | (usvalue << ((reladdress << 3) - 3168)), PSP_SPU_REGISTER + 0x284); - _sb(0, PSP_SPU_REGISTER + 0x29D); - } - } - } - - else - { - // Valid Value - if(usvalue != 0) - { - // Backup GP + 888 Value - unsigned int gp888 = _lw(gp + 888); - - // Update GP + 888 Value - _sw(_lw(gp + 428) - _lw(gp + 432), gp + 888); - - // No clue~ - if((_lw(gp + 428) - _lw(gp + 432) - gp888) >= 0x300) - { - // Again this weird wait comparison... - if(_lw(PSP_SPU_REGISTER + 0x294) == _lw(gp + 892)) - { - // Alright we wait... - sceKernelDelayThread(22); - } - } - - // Overwrite Wait Timer - _sw(_lw(PSP_SPU_REGISTER + 0x294), gp + 892); - - // Don't ask me.. - _sb(1, PSP_SPU_REGISTER + 0x29D); - _sb(1, PSP_SPU_REGISTER + 0x29F); - - // Wait... - while(_lh(PSP_SPU_REGISTER + 0x29E) == 0x101) - { - // Do nothing... - } - - // Temporary Variable - unsigned int temp = usvalue << ((reladdress << 3) - 3163); - - // Update Register (??) 0x280 - _sw(_lw(PSP_SPU_REGISTER + 0x280) | temp, PSP_SPU_REGISTER + 0x280); - - // Update Register (??) 0x284 - _sw(_lw(PSP_SPU_REGISTER + 0x284) & (!temp), PSP_SPU_REGISTER + 0x284); - - // And reset to zero again... could be a thread semaphore? - _sb(0, PSP_SPU_REGISTER + 0x29D); - } - } - } - } - - // After-Write Special Handling for Voice Data Addresses (< 0x180) - else - { - // Backup GP + 888 Value - unsigned int gp888 = _lw(gp + 888); - - // Update GP + 888 Value - _sw(_lw(gp + 428) - _lw(gp + 432), gp + 888); - - // No clue~ - if((_lw(gp + 428) - _lw(gp + 432) - gp888) >= 0x300) - { - // Again this weird wait comparison... - if(_lw(PSP_SPU_REGISTER + 0x294) == _lw(gp + 892)) - { - // Alright we wait... - sceKernelDelayThread(22); - } - } - - // Overwrite Wait Timer - _sw(_lw(PSP_SPU_REGISTER + 0x294), gp + 892); - - // Don't ask me.. - _sb(1, PSP_SPU_REGISTER + 0x29D); - _sb(1, PSP_SPU_REGISTER + 0x29F); - - // Wait... - while(_lh(PSP_SPU_REGISTER + 0x29E) == 0x101) - { - // Do nothing... - } - - // Temporary Variable - unsigned int temp = 1 << (reladdress >> 4); - - // Update Register (??) 0x288 - _sw(_lw(PSP_SPU_REGISTER + 0x288) | temp, PSP_SPU_REGISTER + 0x288); - - // Writing Voice Repeat Address - if((reladdress & 0xF) == 0xE) - { - // Update ... something related to repeat address? - _sw(_lw(PSP_SPU_REGISTER + 0x2A0) | temp, PSP_SPU_REGISTER + 0x2A0); - } - - // Okay, this has to be a "busy writing" thing! It happens too often! - _sb(0, PSP_SPU_REGISTER + 0x29D); - } -} diff --git a/extras/modules/peops/psp.c b/extras/modules/peops/psp.c index 168177cbd..c8168d277 100644 --- a/extras/modules/peops/psp.c +++ b/extras/modules/peops/psp.c @@ -1,19 +1,19 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or - (at your option) any later version. + 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 3 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. + 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, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include @@ -24,43 +24,35 @@ void *malloc(size_t size) { - SceUID uid = sceKernelAllocPartitionMemory(11, "", PSP_SMEM_Low, size + 8, NULL); - if(uid >= 0) - { - unsigned int *p = (unsigned int *)sceKernelGetBlockHeadAddr(uid); - *p = uid; - *(p + 4) = size; - return (void *)(p + 8); - } - - return NULL; + SceUID uid = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "", PSP_SMEM_Low, size + 8, NULL); + if(uid >= 0) + { + unsigned int *p = (unsigned int *)sceKernelGetBlockHeadAddr(uid); + *p = uid; + *(p + 4) = size; + return (void *)(p + 8); + } + + return NULL; } void free(void *ptr) { - if(ptr) - { - sceKernelFreePartitionMemory(*((SceUID *)ptr - 8)); - } -} - -int usleep(useconds_t __useconds) -{ - sceKernelDelayThread(__useconds); - return __useconds; + if(ptr) + { + sceKernelFreePartitionMemory(*((SceUID *)ptr - 8)); + } } unsigned long timeGetTime() { - return sceKernelLibcClock(); + return sceKernelLibcClock(); } void ReadConfig(void) { - iVolume = 4 - config.volume; - iUseXA = config.enablexaplaying; - iXAPitch = config.changexapitch; - iSPUIRQWait = config.spuirqwait; - iUseReverb = config.reverb; - iUseInterpolation = config.interpolation; + iVolume = 4 - config.volume; + iXAPitch = config.changexapitch; + iUseReverb = config.reverb; + iUseInterpolation = config.interpolation; } \ No newline at end of file diff --git a/extras/modules/peops/psp.h b/extras/modules/peops/psp.h index 3419449e9..9dd71d60e 100644 --- a/extras/modules/peops/psp.h +++ b/extras/modules/peops/psp.h @@ -1,25 +1,24 @@ /* - Custom Emulator Firmware - Copyright (C) 2012-2014, Total_Noob + Custom Emulator Firmware + Copyright (C) 2012-2014, Total_Noob - 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 3 of the License, or - (at your option) any later version. + 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 3 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. + 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, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifndef __PSP_H__ #define __PSP_H__ -int usleep(useconds_t __useconds); unsigned long timeGetTime(); void ReadConfig(void); diff --git a/extras/modules/peops/spu/adsr.c b/extras/modules/peops/spu/adsr.c index 88647f585..9a3ad0aaf 100644 --- a/extras/modules/peops/spu/adsr.c +++ b/extras/modules/peops/spu/adsr.c @@ -40,8 +40,6 @@ // will be included from spu.c #ifdef _IN_SPU -#include "adsr.h" - //////////////////////////////////////////////////////////////////////// // ADSR func //////////////////////////////////////////////////////////////////////// diff --git a/extras/modules/peops/spu/adsr.h b/extras/modules/peops/spu/adsr.h index 90cd65967..1e365c90b 100644 --- a/extras/modules/peops/spu/adsr.h +++ b/extras/modules/peops/spu/adsr.h @@ -1,10 +1,11 @@ /*************************************************************************** - adsr.c - description + adsr.h - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ + /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -15,650 +16,13 @@ * * ***************************************************************************/ -// #include "stdafx.h" - -#define _IN_ADSR - -#include - -// will be included from spu.c -#ifdef _IN_SPU - -extern void StartADSR(int ch); - -//////////////////////////////////////////////////////////////////////// -// ADSR func -//////////////////////////////////////////////////////////////////////// - -static int RateTableAdd[128]; -static int RateTableSub[128]; - -void InitADSR(void) // INIT ADSR -{ - int lcv, denom; - - // Optimize table - Dr. Hell ADSR math - for (lcv = 0; lcv < 48; lcv++) - { - RateTableAdd[lcv] = (7 - (lcv&3)) << (11 + 16 - (lcv >> 2)); - RateTableSub[lcv] = (-8 + (lcv&3)) << (11 + 16 - (lcv >> 2)); - } - - for (; lcv < 128; lcv++) - { - denom = 1 << ((lcv>>2) - 11); - - RateTableAdd[lcv] = ((7 - (lcv&3)) << 16) / denom; - RateTableSub[lcv] = ((-8 + (lcv&3)) << 16) / denom; - } -} - -//////////////////////////////////////////////////////////////////////// - -inline void StartADSR(int ch) // MIX ADSR -{ - s_chan[ch].ADSRX.State=0; // and init some adsr vars - s_chan[ch].ADSRX.EnvelopeVol=0; -} - -//////////////////////////////////////////////////////////////////////// - -static void MixADSR(int ch, int ns, int ns_to) // MIX ADSR -{ - int EnvelopeVol = s_chan[ch].ADSRX.EnvelopeVol; - int val, rto, level; - - if (s_chan[ch].bStop) // should be stopped: - { // do release - val = RateTableSub[s_chan[ch].ADSRX.ReleaseRate * 4]; - if (s_chan[ch].ADSRX.ReleaseModeExp) - { - for (; ns < ns_to; ns++) - { - EnvelopeVol += ((long long)val * EnvelopeVol) >> (15+16); - if (EnvelopeVol < 0) - break; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - } - else - { - for (; ns < ns_to; ns++) - { - EnvelopeVol += val; - if (EnvelopeVol < 0) - break; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - } - - if (EnvelopeVol < 0) - goto stop; - - goto done; - } - - switch (s_chan[ch].ADSRX.State) - { - case 0: // -> attack - rto = 0; - if (s_chan[ch].ADSRX.AttackModeExp && EnvelopeVol >= 0x60000000) - rto = 8; - val = RateTableAdd[s_chan[ch].ADSRX.AttackRate + rto]; - - for (; ns < ns_to; ns++) - { - EnvelopeVol += val; - if (EnvelopeVol < 0) - break; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - - if (EnvelopeVol < 0) // overflow - { - EnvelopeVol = 0x7fffffff; - s_chan[ch].ADSRX.State = 1; - ns++; // sample is good already - goto decay; - } - break; - - //--------------------------------------------------// - decay: - case 1: // -> decay - val = RateTableSub[s_chan[ch].ADSRX.DecayRate * 4]; - level = s_chan[ch].ADSRX.SustainLevel; - - for (; ns < ns_to; ) - { - EnvelopeVol += ((long long)val * EnvelopeVol) >> (15+16); - if (EnvelopeVol < 0) - EnvelopeVol = 0; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - ns++; - - if (((EnvelopeVol >> 27) & 0xf) <= level) - { - s_chan[ch].ADSRX.State = 2; - goto sustain; - } - } - break; - - //--------------------------------------------------// - sustain: - case 2: // -> sustain - if (s_chan[ch].ADSRX.SustainIncrease) - { - if (EnvelopeVol >= 0x7fff0000) - break; - - rto = 0; - if (s_chan[ch].ADSRX.SustainModeExp && EnvelopeVol >= 0x60000000) - rto = 8; - val = RateTableAdd[s_chan[ch].ADSRX.SustainRate + rto]; - - for (; ns < ns_to; ns++) - { - EnvelopeVol += val; - if ((unsigned int)EnvelopeVol >= 0x7fe00000) - { - EnvelopeVol = 0x7fffffff; - break; - } - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - } - else - { - val = RateTableSub[s_chan[ch].ADSRX.SustainRate]; - if (s_chan[ch].ADSRX.SustainModeExp) - { - for (; ns < ns_to; ns++) - { - EnvelopeVol += ((long long)val * EnvelopeVol) >> (15+16); - if (EnvelopeVol < 0) - goto stop; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - } - else - { - for (; ns < ns_to; ns++) - { - EnvelopeVol += val; - if (EnvelopeVol < 0) - goto stop; - - ChanBuf[ns] *= EnvelopeVol >> 21; - ChanBuf[ns] >>= 10; - } - } - } - break; - } - -done: - s_chan[ch].ADSRX.EnvelopeVol = EnvelopeVol; - return; - -stop: - memset(&ChanBuf[ns], 0, (ns_to - ns) * sizeof(ChanBuf[0])); - s_chan[ch].ADSRX.EnvelopeVol = 0; - dwChannelOn &= ~(1<time - -The overal volume can also be set to sweep up or down lineairly or -exponentially from it's current value. This can be done seperately -for left and right. - -Relevant SPU registers: -------------------------------------------------------------- -$1f801xx8 Attack/Decay/Sustain level -bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| -desc.|Am| Ar |Dr |Sl | - -Am 0 Attack mode Linear - 1 Exponential - -Ar 0-7f attack rate -Dr 0-f decay rate -Sl 0-f sustain level -------------------------------------------------------------- -$1f801xxa Sustain rate, Release Rate. -bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| -desc.|Sm|Sd| 0| Sr |Rm|Rr | - -Sm 0 sustain rate mode linear - 1 exponential -Sd 0 sustain rate mode increase - 1 decrease -Sr 0-7f Sustain Rate -Rm 0 Linear decrease - 1 Exponential decrease -Rr 0-1f Release Rate - -Note: decay mode is always Expontial decrease, and thus cannot -be set. -------------------------------------------------------------- -$1f801xxc Current ADSR volume -bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| -desc.|ADSRvol | - -ADSRvol Returns the current envelope volume when - read. --- James' Note: return range: 0 -> 32767 - -*** doomed doc extract end *** - -By using a small PSX proggie to visualise the envelope as it was played, -the following results for envelope timing were obtained: - -1. Attack rate value (linear mode) - - Attack value range: 0 -> 127 - - Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | - ----------------------------------------------------------------- - Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| - - Note: frames is no. of PAL frames to reach full volume (100% - amplitude) - - Hmm, noticing that the time taken to reach full volume doubles - every time we add 4 to our attack value, we know the equation is - of form: - frames = k * 2 ^ (value / 4) - - (You may ponder about envelope generator hardware at this point, - or maybe not... :) - - By substituting some stuff and running some checks, we get: - - k = 0.00257 (close enuf) - - therefore, - frames = 0.00257 * 2 ^ (value / 4) - If you just happen to be writing an emulator, then you can probably - use an equation like: - - %volume_increase_per_tick = 1 / frames - - - ------------------------------------ - Pete: - ms=((1<<(value>>2))*514)/10000 - ------------------------------------ - -2. Decay rate value (only has log mode) - - Decay value range: 0 -> 15 - - Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | - ------------------------------------------------ - frames | | | | | 6 | 12 | 24 | 47 | - - Note: frames here is no. of PAL frames to decay to 50% volume. - - formula: frames = k * 2 ^ (value) - - Substituting, we get: k = 0.00146 - - Further info on logarithmic nature: - frames to decay to sustain level 3 = 3 * frames to decay to - sustain level 9 - - Also no. of frames to 25% volume = roughly 1.85 * no. of frames to - 50% volume. - - Frag it - just use linear approx. - - ------------------------------------ - Pete: - ms=((1< 127 - - Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | - ------------------------------------------- - frames | 9 | 19 | 37 | 74 | 147| 293| 587| - - Here, frames = no. of PAL frames for volume amplitude to go from 100% - to 0% (or vice-versa). - - Same formula as for attack value, just a different value for k: - - k = 0.00225 - - ie: frames = 0.00225 * 2 ^ (value / 4) - - For emulation purposes: - - %volume_increase_or_decrease_per_tick = 1 / frames - - ------------------------------------ - Pete: - ms=((1<<(value>>2))*450)/10000 - ------------------------------------ - - -4. Release rate (linear mode) - - Release rate range: 0 -> 31 - - Value | 13 | 14 | 15 | 16 | 17 | - --------------------------------------------------------------- - frames | 18 | 36 | 73 | 146| 292| - - Here, frames = no. of PAL frames to decay from 100% vol to 0% vol - after "note-off" is triggered. - - Formula: frames = k * 2 ^ (value) - - And so: k = 0.00223 - - ------------------------------------ - Pete: - ms=((1< release phase - { - if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) - { - if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff - { - s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; - s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; - s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level - (s_chan[ch].ADSR.ReleaseTime* - s_chan[ch].ADSR.ReleaseVol)/1024; - } - // -> NO release exp mode used (yet) - v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume - lT=s_chan[ch].ADSR.lTime- // -> how much time is past? - s_chan[ch].ADSR.ReleaseStartTime; - l1=s_chan[ch].ADSR.ReleaseTime; - - if(lT we still have to release - { - v=v-((v*lT)/l1); // --> calc new volume - } - else // -> release is over: now really stop that sample - {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} - } - else // -> release IS 0: release at once - { - v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; - } - } - else - {//--------------------------------------------------// not in release phase: - v=1024; - lT=s_chan[ch].ADSR.lTime; - l1=s_chan[ch].ADSR.AttackTime; - - if(lT0) - { - if(l3!=0) v2+=((v-v2)*lT)/l3; - else v2=v; - } - else - { - if(l3!=0) v2-=(v2*lT)/l3; - else v2=v; - } - - if(v2>v) v2=v; - if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} - - v=v2; - } - } - } - - //----------------------------------------------------// - // ok, done for this channel, so increase time - - s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; - - if(v>1024) v=1024; // adjust volume - if(v<0) v=0; - s_chan[ch].ADSR.lVolume=v; // store act volume - - return v; // return the volume factor -*/ - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -/* ------------------------------------------------------------------------------ -Neill Corlett -Playstation SPU envelope timing notes ------------------------------------------------------------------------------ - -This is preliminary. This may be wrong. But the model described herein fits -all of my experimental data, and it's just simple enough to sound right. - -ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. -The value returned by channel reg 0xC is (envelope_level>>16). - -Each sample, an increment or decrement value will be added to or -subtracted from this envelope level. - -Create the rate log table. The values double every 4 entries. - entry #0 = 4 - - 4, 5, 6, 7, - 8,10,12,14, - 16,20,24,28, ... - - entry #40 = 4096... - entry #44 = 8192... - entry #48 = 16384... - entry #52 = 32768... - entry #56 = 65536... - -increments and decrements are in terms of ratelogtable[n] -n may exceed the table bounds (plan on n being between -32 and 127). -table values are all clipped between 0x00000000 and 0x3FFFFFFF - -when you "voice on", the envelope is always fully reset. -(yes, it may click. the real thing does this too.) - -envelope level begins at zero. - -each state happens for at least 1 cycle -(transitions are not instantaneous) -this may result in some oddness: if the decay rate is uberfast, it will cut -the envelope from full down to half in one sample, potentially skipping over -the sustain level - -ATTACK ------- -- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and - proceed to DECAY. - -Linear attack mode: -- line extends upward to 0x7FFFFFFF -- increment per sample is ratelogtable[(Ar^0x7F)-0x10] - -Logarithmic attack mode: -if envelope_level < 0x60000000: - - line extends upward to 0x60000000 - - increment per sample is ratelogtable[(Ar^0x7F)-0x10] -else: - - line extends upward to 0x7FFFFFFF - - increment per sample is ratelogtable[(Ar^0x7F)-0x18] - -DECAY ------ -- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. - Do not clip to the sustain level. -- current line ends at (envelope_level & 0x07FFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] - 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] - 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] - 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] - 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] - 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] - 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] - 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] - (note that this is the same as the release rate formula, except that - decay rates 10-1F aren't possible... those would be slower in theory) - -SUSTAIN -------- -- no terminating condition except for voice off -- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. -- Sd=1 (decrease) behavior: -Linear sustain decrease: -- line extends to 0x00000000 -- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] -Logarithmic sustain decrease: -- current line ends at (envelope_level & 0x07FFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(Sr^0x7F)-0x1B+0] - 1: ratelogtable[(Sr^0x7F)-0x1B+4] - 2: ratelogtable[(Sr^0x7F)-0x1B+6] - 3: ratelogtable[(Sr^0x7F)-0x1B+8] - 4: ratelogtable[(Sr^0x7F)-0x1B+9] - 5: ratelogtable[(Sr^0x7F)-0x1B+10] - 6: ratelogtable[(Sr^0x7F)-0x1B+11] - 7: ratelogtable[(Sr^0x7F)-0x1B+12] - -RELEASE -------- -- if the envelope level has overflowed to negative, clip to 0 and QUIT. - -Linear release mode: -- line extends to 0x00000000 -- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] - -Logarithmic release mode: -- line extends to (envelope_level & 0x0FFFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] - 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] - 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] - 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] - 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] - 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] - 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] - 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] - ------------------------------------------------------------------------------ -*/ +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// -// vim:shiftwidth=1:expandtab +INLINE void StartADSR(SPUCHAN * pChannel); +INLINE int MixADSR(SPUCHAN * pChannel); diff --git a/extras/modules/peops/spu/alsa.c b/extras/modules/peops/spu/alsa.c deleted file mode 100644 index ce514868f..000000000 --- a/extras/modules/peops/spu/alsa.c +++ /dev/null @@ -1,162 +0,0 @@ -/*************************************************************************** - alsa.c - description - ------------------- - begin : Sat Mar 01 2003 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -#include -#define ALSA_PCM_NEW_HW_PARAMS_API -#define ALSA_PCM_NEW_SW_PARAMS_API -#include -#include "out.h" - -static snd_pcm_t *handle = NULL; -static snd_pcm_uframes_t buffer_size; - -// SETUP SOUND -static int alsa_init(void) -{ - snd_pcm_hw_params_t *hwparams; - snd_pcm_status_t *status; - unsigned int pspeed; - int pchannels; - int format; - unsigned int buffer_time = 100000; - unsigned int period_time = buffer_time / 4; - int err; - - pchannels=2; - - pspeed = 44100; - format = SND_PCM_FORMAT_S16; - - if ((err = snd_pcm_open(&handle, "default", - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) - { - printf("Audio open error: %s\n", snd_strerror(err)); - return -1; - } - - if((err = snd_pcm_nonblock(handle, 0))<0) - { - printf("Can't set blocking moded: %s\n", snd_strerror(err)); - return -1; - } - - snd_pcm_hw_params_alloca(&hwparams); - - if((err=snd_pcm_hw_params_any(handle, hwparams))<0) - { - printf("Broken configuration for this PCM: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0) - { - printf("Access type not available: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0) - { - printf("Sample format not available: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0) - { - printf("Channels count not available: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0) - { - printf("Rate not available: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0) - { - printf("Buffer time error: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0) - { - printf("Period time error: %s\n", snd_strerror(err)); - return -1; - } - - if((err=snd_pcm_hw_params(handle, hwparams))<0) - { - printf("Unable to install hw params: %s\n", snd_strerror(err)); - return -1; - } - - snd_pcm_status_alloca(&status); - if((err=snd_pcm_status(handle, status))<0) - { - printf("Unable to get status: %s\n", snd_strerror(err)); - return -1; - } - - buffer_size = snd_pcm_status_get_avail(status); - return 0; -} - -// REMOVE SOUND -static void alsa_finish(void) -{ - if(handle != NULL) - { - snd_pcm_drop(handle); - snd_pcm_close(handle); - handle = NULL; - } -} - -// GET BYTES BUFFERED -static int alsa_busy(void) -{ - int l; - - if (handle == NULL) // failed to open? - return 1; - l = snd_pcm_avail(handle); - if (l < 0) return 0; - if (l < buffer_size / 2) // can we write in at least the half of fragments? - l = 1; // -> no? wait - else l = 0; // -> else go on - - return l; -} - -// FEED SOUND DATA -static void alsa_feed(void *pSound, int lBytes) -{ - if (handle == NULL) return; - - if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN) - snd_pcm_prepare(handle); - snd_pcm_writei(handle,pSound, lBytes / 4); -} - -void out_register_alsa(struct out_driver *drv) -{ - drv->name = "alsa"; - drv->init = alsa_init; - drv->finish = alsa_finish; - drv->busy = alsa_busy; - drv->feed = alsa_feed; -} diff --git a/extras/modules/peops/spu/arm_utils.S b/extras/modules/peops/spu/arm_utils.S deleted file mode 100644 index 22e584432..000000000 --- a/extras/modules/peops/spu/arm_utils.S +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) Gražvydas "notaz" Ignotas, 2011 - * - * This work is licensed under the terms of any of these licenses - * (at your option): - * - GNU GPL, version 2 or later. - * - GNU LGPL, version 2.1 or later. - * See the COPYING file in the top-level directory. - */ - - -.text -.align 2 - -.macro load_varadr reg var -#if defined(__ARM_ARCH_7A__) && !defined(__PIC__) - movw \reg, #:lower16:\var - movt \reg, #:upper16:\var -#else - ldr \reg, =\var -#endif -.endm - -#ifdef __ARM_NEON__ - -.global mix_chan @ (int start, int count, int lv, int rv) -mix_chan: - vmov.32 d14[0], r2 - vmov.32 d14[1], r3 @ multipliers - mov r12, r0 - load_varadr r0, ChanBuf - load_varadr r2, SSumLR - add r0, r12, lsl #2 - add r2, r12, lsl #3 -0: - vldmia r0!, {d0-d1} - vldmia r2, {d2-d5} - vmul.s32 d10, d14, d0[0] - vmul.s32 d11, d14, d0[1] - vmul.s32 d12, d14, d1[0] - vmul.s32 d13, d14, d1[1] - vsra.s32 q1, q5, #14 - vsra.s32 q2, q6, #14 - subs r1, #4 - blt mc_finish - vstmia r2!, {d2-d5} - bgt 0b - nop - bxeq lr - -mc_finish: - vstmia r2!, {d2} - cmp r1, #-2 - vstmiage r2!, {d3} - cmp r1, #-1 - vstmiage r2!, {d4} - bx lr - - -.global mix_chan_rvb @ (int start, int count, int lv, int rv) -mix_chan_rvb: - vmov.32 d14[0], r2 - vmov.32 d14[1], r3 @ multipliers - mov r12, r0 - load_varadr r0, ChanBuf - load_varadr r3, sRVBStart - load_varadr r2, SSumLR - ldr r3, [r3] - add r0, r12, lsl #2 - add r2, r12, lsl #3 - add r3, r12, lsl #3 -0: - vldmia r0!, {d0-d1} - vldmia r2, {d2-d5} - vldmia r3, {d6-d9} - vmul.s32 d10, d14, d0[0] - vmul.s32 d11, d14, d0[1] - vmul.s32 d12, d14, d1[0] - vmul.s32 d13, d14, d1[1] - vsra.s32 q1, q5, #14 - vsra.s32 q2, q6, #14 - vsra.s32 q3, q5, #14 - vsra.s32 q4, q6, #14 - subs r1, #4 - blt mcr_finish - vstmia r2!, {d2-d5} - vstmia r3!, {d6-d9} - bgt 0b - nop - bxeq lr - -mcr_finish: - vstmia r2!, {d2} - vstmia r3!, {d6} - cmp r1, #-2 - vstmiage r2!, {d3} - vstmiage r3!, {d7} - cmp r1, #-1 - vstmiage r2!, {d4} - vstmiage r3!, {d8} - bx lr - -#else - -.global mix_chan @ (int start, int count, int lv, int rv) -mix_chan: - stmfd sp!, {r4-r8,lr} - orr r3, r2, r3, lsl #16 - lsl r3, #1 @ packed multipliers << 1 - mov r12, r0 - load_varadr r0, ChanBuf - load_varadr r2, SSumLR - add r0, r12, lsl #2 - add r2, r12, lsl #3 -0: - ldmia r0!, {r4,r5} - ldmia r2, {r6-r8,lr} - lsl r4, #1 @ adjust for mul - lsl r5, #1 - smlawb r6, r4, r3, r6 - smlawt r7, r4, r3, r7 - smlawb r8, r5, r3, r8 - smlawt lr, r5, r3, lr - subs r1, #2 - blt mc_finish - stmia r2!, {r6-r8,lr} - bgt 0b - ldmeqfd sp!, {r4-r8,pc} - -mc_finish: - stmia r2!, {r6,r7} - ldmfd sp!, {r4-r8,pc} - - -.global mix_chan_rvb @ (int start, int count, int lv, int rv) -mix_chan_rvb: - stmfd sp!, {r4-r8,lr} - orr lr, r2, r3, lsl #16 - lsl lr, #1 - load_varadr r3, sRVBStart - load_varadr r2, SSumLR - load_varadr r4, ChanBuf - ldr r3, [r3] - add r2, r2, r0, lsl #3 - add r3, r3, r0, lsl #3 - add r0, r4, r0, lsl #2 -0: - ldr r4, [r0], #4 - ldmia r2, {r6,r7} - ldmia r3, {r8,r12} - lsl r4, #1 - smlawb r6, r4, lr, r6 @ supposedly takes single cycle? - smlawt r7, r4, lr, r7 - smlawb r8, r4, lr, r8 - smlawt r12,r4, lr, r12 - subs r1, #1 - stmia r2!, {r6,r7} - stmia r3!, {r8,r12} - bgt 0b - ldmfd sp!, {r4-r8,pc} - -#endif - -@ vim:filetype=armasm diff --git a/extras/modules/peops/spu/decode_xa.c b/extras/modules/peops/spu/decode_xa.c index 87a603249..ee1dd6f3e 100644 --- a/extras/modules/peops/spu/decode_xa.c +++ b/extras/modules/peops/spu/decode_xa.c @@ -25,11 +25,11 @@ #define FIXED -#define NOT(_X_) (!(_X_)) -#define XACLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} +#define NOT(_X_) (!(_X_)) +#define XACLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} -#define SH 4 -#define SHC 10 +#define SH 4 +#define SHC 10 //============================================ //=== ADPCM DECODING ROUTINES @@ -51,17 +51,17 @@ static double K1[4] = { }; #else static int K0[4] = { - 0.0 * (1<y0 = 0; - decp->y1 = 0; + decp->y0 = 0; + decp->y1 = 0; } //=========================================== #ifndef FIXED -#define IK0(fid) ((int)((-K0[fid]) * (1<> 4) & 0x0f; - range = (filter_range >> 0) & 0x0f; - - fy0 = decp->y0; - fy1 = decp->y1; - - for (i = BLKSIZ/4; i; --i) { - s32 y; - s32 x0, x1, x2, x3; - - y = *blockp++; - x3 = (short)( y & 0xf000) >> range; x3 <<= SH; - x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; - x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; - x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; - - x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; - x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; - x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; - x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; - - XACLAMP( x0, -32768<> SH; destp += inc; - XACLAMP( x1, -32768<> SH; destp += inc; - XACLAMP( x2, -32768<> SH; destp += inc; - XACLAMP( x3, -32768<> SH; destp += inc; - } - decp->y0 = fy0; - decp->y1 = fy1; + int i; + int range, filterid; + s32 fy0, fy1; + const u16 *blockp; + + blockp = (const unsigned short *)vblockp; + filterid = (filter_range >> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + s32 y; + s32 x0, x1, x2, x3; + + y = *blockp++; + x3 = (short)( y & 0xf000) >> range; x3 <<= SH; + x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; + x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; + x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; + + x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; + x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; + x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; + x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; + + XACLAMP( x0, -32768<> SH; destp += inc; + XACLAMP( x1, -32768<> SH; destp += inc; + XACLAMP( x2, -32768<> SH; destp += inc; + XACLAMP( x3, -32768<> SH; destp += inc; + } + decp->y0 = fy0; + decp->y1 = fy1; } static int headtable[4] = {0,2,8,10}; //=========================================== static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { - const u8 *sound_groupsp; - const u8 *sound_datap, *sound_datap2; - int i, j, k, nbits; - u16 data[4096], *datap; - short *destp; - - destp = xdp->pcm; - nbits = xdp->nbits == 4 ? 4 : 2; - - if (xdp->stereo) { // stereo - if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A - for (j=0; j < 18; j++) { - sound_groupsp = srcp + j * 128; // sound groups header - sound_datap = sound_groupsp + 16; // sound data just after the header - - for (i=0; i < nbits; i++) { - datap = data; - sound_datap2 = sound_datap + i; - - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (u16)sound_datap2[0] | - (u16)(sound_datap2[4] << 8); - } - - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, - destp+0, 2 ); - - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (u16)sound_datap2[0] | - (u16)(sound_datap2[4] << 8); - } - ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, - destp+1, 2 ); - - destp += 28*2; - } - } - } else { // level B/C - for (j=0; j < 18; j++) { - sound_groupsp = srcp + j * 128; // sound groups header - sound_datap = sound_groupsp + 16; // sound data just after the header - - for (i=0; i < nbits; i++) { - datap = data; - sound_datap2 = sound_datap + i; - - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | - ((u16)(sound_datap2[ 4] & 0x0f) << 4) | - ((u16)(sound_datap2[ 8] & 0x0f) << 8) | - ((u16)(sound_datap2[12] & 0x0f) << 12); - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, - destp+0, 2 ); - - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (u16)(sound_datap2[ 0] >> 4) | - ((u16)(sound_datap2[ 4] >> 4) << 4) | - ((u16)(sound_datap2[ 8] >> 4) << 8) | - ((u16)(sound_datap2[12] >> 4) << 12); - } - ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, - destp+1, 2 ); - - destp += 28*2; - } - } - } - } else { // mono - if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A - for (j=0; j < 18; j++) { - sound_groupsp = srcp + j * 128; // sound groups header - sound_datap = sound_groupsp + 16; // sound data just after the header - - for (i=0; i < nbits; i++) { - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (u16)sound_datap2[0] | - (u16)(sound_datap2[4] << 8); - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, - destp, 1 ); - - destp += 28; - - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 14; k++, sound_datap2 += 8) { - *(datap++) = (u16)sound_datap2[0] | - (u16)(sound_datap2[4] << 8); - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, - destp, 1 ); - - destp += 28; - } - } - } else { // level B/C - for (j=0; j < 18; j++) { - sound_groupsp = srcp + j * 128; // sound groups header - sound_datap = sound_groupsp + 16; // sound data just after the header - - for (i=0; i < nbits; i++) { - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | - ((u16)(sound_datap2[ 4] & 0x0f) << 4) | - ((u16)(sound_datap2[ 8] & 0x0f) << 8) | - ((u16)(sound_datap2[12] & 0x0f) << 12); - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, - destp, 1 ); - - destp += 28; - - datap = data; - sound_datap2 = sound_datap + i; - for (k=0; k < 7; k++, sound_datap2 += 16) { - *(datap++) = (u16)(sound_datap2[ 0] >> 4) | - ((u16)(sound_datap2[ 4] >> 4) << 4) | - ((u16)(sound_datap2[ 8] >> 4) << 8) | - ((u16)(sound_datap2[12] >> 4) << 12); - } - ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, - destp, 1 ); - - destp += 28; - } - } - } - } + const u8 *sound_groupsp; + const u8 *sound_datap, *sound_datap2; + int i, j, k, nbits; + u16 data[4096], *datap; + short *destp; + + destp = xdp->pcm; + nbits = xdp->nbits == 4 ? 4 : 2; + + if (xdp->stereo) { // stereo + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } else { // level B/C + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | + ((u16)(sound_datap2[ 4] & 0x0f) << 4) | + ((u16)(sound_datap2[ 8] & 0x0f) << 8) | + ((u16)(sound_datap2[12] & 0x0f) << 12); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (u16)(sound_datap2[ 0] >> 4) | + ((u16)(sound_datap2[ 4] >> 4) << 4) | + ((u16)(sound_datap2[ 8] >> 4) << 8) | + ((u16)(sound_datap2[12] >> 4) << 12); + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } + } else { // mono + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (u16)sound_datap2[0] | + (u16)(sound_datap2[4] << 8); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } else { // level B/C + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | + ((u16)(sound_datap2[ 4] & 0x0f) << 4) | + ((u16)(sound_datap2[ 8] & 0x0f) << 8) | + ((u16)(sound_datap2[12] & 0x0f) << 12); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (u16)(sound_datap2[ 0] >> 4) | + ((u16)(sound_datap2[ 4] >> 4) << 4) | + ((u16)(sound_datap2[ 8] >> 4) << 8) | + ((u16)(sound_datap2[12] >> 4) << 12); + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } + } } //============================================ @@ -297,38 +297,38 @@ u8 coding2; //============================================ static int parse_xa_audio_sector( xa_decode_t *xdp, - xa_subheader_t *subheadp, - unsigned char *sectorp, - int is_first_sector ) { + xa_subheader_t *subheadp, + unsigned char *sectorp, + int is_first_sector ) { if ( is_first_sector ) { - switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { - case 0: xdp->freq = 37800; break; - case 1: xdp->freq = 18900; break; - default: xdp->freq = 0; break; - } - switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { - case 0: xdp->nbits = 4; break; - case 1: xdp->nbits = 8; break; - default: xdp->nbits = 0; break; - } - switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { - case 0: xdp->stereo = 0; break; - case 1: xdp->stereo = 1; break; - default: xdp->stereo = 0; break; - } - - if ( xdp->freq == 0 ) - return -1; - - ADPCM_InitDecode( &xdp->left ); - ADPCM_InitDecode( &xdp->right ); - - xdp->nsamples = 18 * 28 * 8; - if (xdp->stereo == 1) xdp->nsamples /= 2; + switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { + case 0: xdp->freq = 37800; break; + case 1: xdp->freq = 18900; break; + default: xdp->freq = 0; break; + } + switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { + case 0: xdp->nbits = 4; break; + case 1: xdp->nbits = 8; break; + default: xdp->nbits = 0; break; + } + switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { + case 0: xdp->stereo = 0; break; + case 1: xdp->stereo = 1; break; + default: xdp->stereo = 0; break; + } + + if ( xdp->freq == 0 ) + return -1; + + ADPCM_InitDecode( &xdp->left ); + ADPCM_InitDecode( &xdp->right ); + + xdp->nsamples = 18 * 28 * 8; + if (xdp->stereo == 1) xdp->nsamples /= 2; } - xa_decode_data( xdp, sectorp ); + xa_decode_data( xdp, sectorp ); - return 0; + return 0; } //================================================================ @@ -341,27 +341,27 @@ static int parse_xa_audio_sector( xa_decode_t *xdp, //=== return -1 if error //================================================================ s32 xa_decode_sector( xa_decode_t *xdp, - unsigned char *sectorp, int is_first_sector ) { - if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) - return -1; + unsigned char *sectorp, int is_first_sector ) { + if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) + return -1; - return 0; + return 0; } /* EXAMPLE: "nsamples" is the number of 16 bit samples every sample is 2 bytes in mono and 4 bytes in stereo -xa_decode_t xa; +xa_decode_t xa; - sectorp = read_first_sector(); - xa_decode_sector( &xa, sectorp, 1 ); - play_wave( xa.pcm, xa.freq, xa.nsamples ); + sectorp = read_first_sector(); + xa_decode_sector( &xa, sectorp, 1 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); - while ( --n_sectors ) - { - sectorp = read_next_sector(); - xa_decode_sector( &xa, sectorp, 0 ); - play_wave( xa.pcm, xa.freq, xa.nsamples ); - } + while ( --n_sectors ) + { + sectorp = read_next_sector(); + xa_decode_sector( &xa, sectorp, 0 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + } */ diff --git a/extras/modules/peops/spu/decode_xa.h b/extras/modules/peops/spu/decode_xa.h index b7939957a..884e9797f 100644 --- a/extras/modules/peops/spu/decode_xa.h +++ b/extras/modules/peops/spu/decode_xa.h @@ -27,21 +27,21 @@ extern "C" { #include typedef struct { - s32 y0, y1; + s32 y0, y1; } ADPCM_Decode_t; typedef struct { - int freq; - int nbits; - int stereo; - int nsamples; - ADPCM_Decode_t left, right; - short pcm[16384]; + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; } xa_decode_t; s32 xa_decode_sector( xa_decode_t *xdp, - unsigned char *sectorp, - int is_first_sector ); + unsigned char *sectorp, + int is_first_sector ); #ifdef __cplusplus } diff --git a/extras/modules/peops/spu/dma.c b/extras/modules/peops/spu/dma.c deleted file mode 100644 index 80f7cb86b..000000000 --- a/extras/modules/peops/spu/dma.c +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************** - dma.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -// #include "stdafx.h" - -#define _IN_DMA - -#include "externals.h" -#include - -//////////////////////////////////////////////////////////////////////// -// READ DMA (one value) -//////////////////////////////////////////////////////////////////////// - -unsigned short SPUreadDMA(void) -{ - unsigned short s=spuMem[spuAddr>>1]; - spuAddr+=2; - if(spuAddr>0x7ffff) spuAddr=0; - - return s; -} - -//////////////////////////////////////////////////////////////////////// -// READ DMA (many values) -//////////////////////////////////////////////////////////////////////// - -void SPUreadDMAMem(unsigned short * pusPSXMem,int iSize) -{ - int i; - - for(i=0;i>1]; // spu addr got by writeregister - spuAddr+=2; // inc spu addr - if(spuAddr>0x7ffff) spuAddr=0; // wrap - } -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -// to investigate: do sound data updates by writedma affect spu -// irqs? Will an irq be triggered, if new data is written to -// the memory irq address? - -//////////////////////////////////////////////////////////////////////// -// WRITE DMA (one value) -//////////////////////////////////////////////////////////////////////// - -void SPUwriteDMA(unsigned short val) -{ - spuMem[spuAddr>>1] = val; // spu addr got by writeregister - - spuAddr+=2; // inc spu addr - if(spuAddr>0x7ffff) spuAddr=0; // wrap -} - -//////////////////////////////////////////////////////////////////////// -// WRITE DMA (many values) -//////////////////////////////////////////////////////////////////////// - -void SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize) -{ - int i; - - had_dma = 1; - - if(spuAddr + iSize*2 < 0x80000) - { - memcpy(&spuMem[spuAddr>>1], pusPSXMem, iSize*2); - spuAddr += iSize*2; - return; - } - - for(i=0;i>1] = *pusPSXMem++; // spu addr got by writeregister - spuAddr+=2; // inc spu addr - spuAddr&=0x7ffff; // wrap - } -} - -//////////////////////////////////////////////////////////////////////// diff --git a/extras/modules/peops/spu/dma.h b/extras/modules/peops/spu/dma.h deleted file mode 100644 index 440536feb..000000000 --- a/extras/modules/peops/spu/dma.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - dma.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ - -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -//*************************************************************************// -// History of changes: -// -// 2002/05/15 - Pete -// - generic cleanup for the Peops release -// -//*************************************************************************// - - -unsigned short CALLBACK SPUreadDMA(void); -void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize); -void CALLBACK SPUwriteDMA(unsigned short val); -void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); diff --git a/extras/modules/peops/spu/externals.h b/extras/modules/peops/spu/externals.h index df75c65d3..004de6c90 100644 --- a/extras/modules/peops/spu/externals.h +++ b/extras/modules/peops/spu/externals.h @@ -138,11 +138,9 @@ typedef struct int iLeftVolume; // left volume int iLeftVolRaw; // left psx volume value int bIgnoreLoop; // ignore loop bit, if an external loop address is used - int iMute; // mute mode int iRightVolume; // right volume int iRightVolRaw; // right psx volume value int iRawPitch; // raw pitch (0...3fff) - int iIrqDone; // debug irq done flag int s_1; // last decoding infos int s_2; int bRVBActive; // reverb active flag @@ -214,9 +212,7 @@ typedef struct // psx buffers / addresses -extern unsigned short * spuMem; extern unsigned char * spuMemC; -extern unsigned char * pSpuIrq; extern unsigned char * pSpuBuffer; // user settings @@ -224,12 +220,8 @@ extern unsigned char * pSpuBuffer; extern int iUseXA; extern int iVolume; extern int iXAPitch; -extern int iUseTimer; -extern int iSPUIRQWait; extern int iUseReverb; extern int iUseInterpolation; -extern int iDisStereo; -extern int iUseDBufIrq; // MISC @@ -238,9 +230,7 @@ extern REVERBInfo rvb; extern unsigned long dwNoiseVal; extern unsigned short spuCtrl; -extern unsigned short spuIrq; extern int bEndThread; -extern int bThreadEnded; extern int bSpuInit; extern unsigned long dwNewChannel; @@ -249,10 +239,6 @@ extern int SSumL[]; extern int iCycle; extern short * pS; -extern int iSpuAsyncWait; - -extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); - #endif /////////////////////////////////////////////////////////// @@ -263,13 +249,18 @@ extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); extern xa_decode_t * xapGlobal; -extern unsigned long * XAFeed; -extern unsigned long * XAPlay; -extern unsigned long * XAStart; -extern unsigned long * XAEnd; +extern uint32_t * XAFeed; +extern uint32_t * XAPlay; +extern uint32_t * XAStart; +extern uint32_t * XAEnd; + +extern uint32_t XARepeat; +extern uint32_t XALastVal; -extern unsigned long XARepeat; -extern unsigned long XALastVal; +extern uint32_t * CDDAFeed; +extern uint32_t * CDDAPlay; +extern uint32_t * CDDAStart; +extern uint32_t * CDDAEnd; extern int iLeftXAVol; extern int iRightXAVol; diff --git a/extras/modules/peops/spu/freeze.c b/extras/modules/peops/spu/freeze.c deleted file mode 100644 index ec097c5be..000000000 --- a/extras/modules/peops/spu/freeze.c +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************** - freeze.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -#include "stdafx.h" - -#define _IN_FREEZE - -#include "externals.h" -#include "registers.h" -#include "spu.h" - -//////////////////////////////////////////////////////////////////////// -// freeze structs -//////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int State; - int AttackModeExp; - int AttackRate; - int DecayRate; - int SustainLevel; - int SustainModeExp; - int SustainIncrease; - int SustainRate; - int ReleaseModeExp; - int ReleaseRate; - int EnvelopeVol; - long lVolume; - long lDummy1; - long lDummy2; -} ADSRInfoEx_orig; - -typedef struct -{ - // no mutexes used anymore... don't need them to sync access - //HANDLE hMutex; - - int bNew; // start flag - - int iSBPos; // mixing stuff - int spos; - int sinc; - int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) - int sval; - - unsigned char * pStart; // start ptr into sound mem - unsigned char * pCurr; // current pos in sound mem - unsigned char * pLoop; // loop ptr in sound mem - - int bOn; // is channel active (sample playing?) - int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) - int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active - int iActFreq; // current psx pitch - int iUsedFreq; // current pc pitch - int iLeftVolume; // left volume - int iLeftVolRaw; // left psx volume value - int bIgnoreLoop; // ignore loop bit, if an external loop address is used - int iMute; // mute mode - int iRightVolume; // right volume - int iRightVolRaw; // right psx volume value - int iRawPitch; // raw pitch (0...3fff) - int iIrqDone; // debug irq done flag - int s_1; // last decoding infos - int s_2; - int bRVBActive; // reverb active flag - int iRVBOffset; // reverb offset - int iRVBRepeat; // reverb repeat - int bNoise; // noise active flag - int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) - int iRVBNum; // another reverb helper - int iOldNoise; // old noise val for this channel - ADSRInfo ADSR; // active ADSR settings - ADSRInfoEx_orig ADSRX; // next ADSR settings (will be moved to active on sample start) -} SPUCHAN_orig; - -typedef struct -{ - char szSPUName[8]; - uint32_t ulFreezeVersion; - uint32_t ulFreezeSize; - unsigned char cSPUPort[0x200]; - unsigned char cSPURam[0x80000]; - xa_decode_t xaS; -} SPUFreeze_t; - -typedef struct -{ - unsigned short spuIrq; - uint32_t pSpuIrq; - uint32_t spuAddr; - uint32_t dummy1; - uint32_t dummy2; - uint32_t dummy3; - - SPUCHAN_orig s_chan[MAXCHAN]; - -} SPUOSSFreeze_t; - -//////////////////////////////////////////////////////////////////////// - -void LoadStateV5(SPUFreeze_t * pF); // newest version -void LoadStateUnknown(SPUFreeze_t * pF); // unknown format - -extern int lastch; - -// we want to retain compatibility between versions, -// so use original channel struct -static void save_channel(SPUCHAN_orig *d, const SPUCHAN *s, int ch) -{ - memset(d, 0, sizeof(*d)); - d->bNew = !!(dwNewChannel & (1<iSBPos = s->iSBPos; - d->spos = s->spos; - d->sinc = s->sinc; - memcpy(d->SB, s->SB, sizeof(d->SB)); - d->pStart = (unsigned char *)((regAreaGet(ch,6)&~1)<<3); - d->pCurr = s->pCurr; - d->pLoop = s->pLoop; - d->bOn = !!(dwChannelOn & (1<bStop = s->bStop; - d->bReverb = s->bReverb; - d->iActFreq = 1; - d->iUsedFreq = 2; - d->iLeftVolume = s->iLeftVolume; - // this one is nasty but safe, save compat is important - d->bIgnoreLoop = (s->prevflags ^ 2) << 1; - d->iRightVolume = s->iRightVolume; - d->iRawPitch = s->iRawPitch; - d->s_1 = s->SB[27]; // yes it's reversed - d->s_2 = s->SB[26]; - d->bRVBActive = s->bRVBActive; - d->bNoise = s->bNoise; - d->bFMod = s->bFMod; - d->ADSRX.State = s->ADSRX.State; - d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp; - d->ADSRX.AttackRate = s->ADSRX.AttackRate; - d->ADSRX.DecayRate = s->ADSRX.DecayRate; - d->ADSRX.SustainLevel = s->ADSRX.SustainLevel; - d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp; - d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease; - d->ADSRX.SustainRate = s->ADSRX.SustainRate; - d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp; - d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate; - d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol; - d->ADSRX.lVolume = d->bOn; // hmh -} - -static void load_channel(SPUCHAN *d, const SPUCHAN_orig *s, int ch) -{ - memset(d, 0, sizeof(*d)); - if (s->bNew) dwNewChannel |= 1<iSBPos = s->iSBPos; - d->spos = s->spos; - d->sinc = s->sinc; - memcpy(d->SB, s->SB, sizeof(d->SB)); - d->pCurr = (void *)((long)s->pCurr & 0x7fff0); - d->pLoop = (void *)((long)s->pLoop & 0x7fff0); - if (s->bOn) dwChannelOn |= 1<bStop = s->bStop; - d->bReverb = s->bReverb; - d->iLeftVolume = s->iLeftVolume; - d->iRightVolume = s->iRightVolume; - d->iRawPitch = s->iRawPitch; - d->bRVBActive = s->bRVBActive; - d->bNoise = s->bNoise; - d->bFMod = s->bFMod; - d->prevflags = (s->bIgnoreLoop >> 1) ^ 2; - d->ADSRX.State = s->ADSRX.State; - d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp; - d->ADSRX.AttackRate = s->ADSRX.AttackRate; - d->ADSRX.DecayRate = s->ADSRX.DecayRate; - d->ADSRX.SustainLevel = s->ADSRX.SustainLevel; - d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp; - d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease; - d->ADSRX.SustainRate = s->ADSRX.SustainRate; - d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp; - d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate; - d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol; -} - -//////////////////////////////////////////////////////////////////////// -// SPUFREEZE: called by main emu on savestate load/save -//////////////////////////////////////////////////////////////////////// - -long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF) -{ - int i;SPUOSSFreeze_t * pFO; - - if(!pF) return 0; // first check - - if(ulFreezeMode) // info or save? - {//--------------------------------------------------// - if(ulFreezeMode==1) - memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t)); - - strcpy(pF->szSPUName,"PBOSS"); - pF->ulFreezeVersion=5; - pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t); - - if(ulFreezeMode==2) return 1; // info mode? ok, bye - // save mode: - memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos - memcpy(pF->cSPUPort,regArea,0x200); - - if(xapGlobal && XAPlay!=XAFeed) // some xa - { - pF->xaS=*xapGlobal; - } - else - memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa - - pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff - - pFO->spuIrq=spuIrq; - if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC; - - pFO->spuAddr=spuAddr; - if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d; - - for(i=0;is_chan[i],&s_chan[i],i); - if(pFO->s_chan[i].pCurr) - pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; - if(pFO->s_chan[i].pLoop) - pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; - } - - return 1; - //--------------------------------------------------// - } - - if(ulFreezeMode!=0) return 0; // bad mode? bye - - memcpy(spuMem,pF->cSPURam,0x80000); // get ram - memcpy(regArea,pF->cSPUPort,0x200); - - if(pF->xaS.nsamples<=4032) // start xa again - SPUplayADPCMchannel(&pF->xaS); - - xapGlobal=0; - - if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5) - LoadStateV5(pF); - else LoadStateUnknown(pF); - - lastch = -1; - - // repair some globals - for(i=0;i<=62;i+=2) - SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]); - SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]); - SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]); - SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]); - - SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000)); - SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]); - SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]); - SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]); - - // fix to prevent new interpolations from crashing - for(i=0;ispuIrq; - if(pFO->pSpuIrq) pSpuIrq = spuMemC+((long)pFO->pSpuIrq&0x7fff0); else pSpuIrq=NULL; - - if(pFO->spuAddr) - { - spuAddr = pFO->spuAddr; - if (spuAddr == 0xbaadf00d) spuAddr = 0; - } - - dwNewChannel=0; - dwChannelOn=0; - dwChannelDead=0; - for(i=0;is_chan[i],i); - - s_chan[i].pCurr+=(unsigned long)spuMemC; - s_chan[i].pLoop+=(unsigned long)spuMemC; - } -} - -//////////////////////////////////////////////////////////////////////// - -void LoadStateUnknown(SPUFreeze_t * pF) -{ - int i; - - for(i=0;i -#include -#include - -// Sample Alignment -#define PSP_NUM_AUDIO_SAMPLES 1024 - -// Current Channel -int currentChannel = -1; - -// Alternate Channel -int alternateChannel = -1; - -// Last Feed Silence Sample Count -int silenceSamples = 0; - -// SETUP SOUND -static int none_init(void) -{ - // Reserve Main Channel - currentChannel = sceAudioChReserve(-1, PSP_NUM_AUDIO_SAMPLES, 0); - - #ifdef DEBUG - // Log Main Channel Creation - printk("sceAudioChReserve(MainChannel): %08X\n", currentChannel); - #endif - - // Main Channel Reservation Error - if(currentChannel < 0) return -1; - - // Reserve Alternate Channel - alternateChannel = sceAudioChReserve(-1, PSP_NUM_AUDIO_SAMPLES, 0); - - #ifdef DEBUG - // Log Alternate Channel Creation - printk("sceAudioChReserve(AlternateChannel): %08X\n", alternateChannel); - #endif - - // Alternate Channel Reservation Error - if(alternateChannel < 0) - { - // Release Main Channel - sceAudioChRelease(currentChannel); - - // Return Error to Emulator - return -1; - } - - // Initialization Success - return 0; -} - -// REMOVE SOUND -static void none_finish(void) -{ - // Release Main Channel - if(currentChannel >= 0) sceAudioChRelease(currentChannel); - - // Release Alternate Channel - if(alternateChannel >= 0) sceAudioChRelease(alternateChannel); - - // Erase References - currentChannel = -1; - alternateChannel = -1; -} - -// GET BYTES BUFFERED -static int none_busy(void) -{ - // Fetch remaining samples - int remainingSamples = sceAudioGetChannelRestLength(currentChannel); - - #ifdef DEBUG - // Log remaining Samples - printk("sceAudioGetChannelRestLength: %08X (%08X)\n", remainingSamples, currentChannel); - #endif - - // Time to switch channels! - if(remainingSamples >= 0 && remainingSamples <= silenceSamples) return 0; - - // Busy playing Audio - return 1; -} - -// FEED SOUND DATA -static void none_feed(void * buf, int bytes) -{ - // Calculate Number of Samples (1 Sample = 2 * 2 (Stereo) Bytes = 4 Bytes) - int samples = bytes >> 2; - - // Uh-oh... Channel can't fit whole Feed! - if(samples > PSP_NUM_AUDIO_SAMPLES) - { - #ifdef DEBUG - // Log Problem - printk("SPU Feed exceeds channel capacity! (%d > %d)\n", samples, PSP_NUM_AUDIO_SAMPLES); - #endif - - // Exit Feeder - return; - } - - // Sample Buffer - unsigned short * feedBuffer[PSP_NUM_AUDIO_SAMPLES * 2]; - - // Clear Buffer (fill with silence) - memset(feedBuffer, 0, sizeof(feedBuffer)); - - // Copy PSX Samples into Sample Buffer - memcpy(feedBuffer, buf, bytes); - - // Switch Audio Channels - int lastChannel = currentChannel; - currentChannel = alternateChannel; - alternateChannel = lastChannel; - - // Set Silence Sample Count - silenceSamples = PSP_NUM_AUDIO_SAMPLES - samples; - - // Output Audio Data - #ifdef DEBUG - int output = - #endif - sceAudioOutputPannedBlocking(currentChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, feedBuffer); - - // Debug Log - #ifdef DEBUG - printk("sceAudioOutputPannedBlocking: %08X (%08X)\n", output, currentChannel); - #endif -} - -void out_register_none(struct out_driver *drv) -{ - drv->name = "none"; - drv->init = none_init; - drv->finish = none_finish; - drv->busy = none_busy; - drv->feed = none_feed; -} - diff --git a/extras/modules/peops/spu/oss.c b/extras/modules/peops/spu/oss.c deleted file mode 100644 index 522584ea5..000000000 --- a/extras/modules/peops/spu/oss.c +++ /dev/null @@ -1,167 +0,0 @@ -/*************************************************************************** - oss.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include "out.h" - -//////////////////////////////////////////////////////////////////////// -// oss globals -//////////////////////////////////////////////////////////////////////// - -#define OSS_MODE_STEREO 1 -#define OSS_MODE_MONO 0 - -#define OSS_SPEED_44100 44100 - -static int oss_audio_fd = -1; -extern int errno; - -//////////////////////////////////////////////////////////////////////// -// SETUP SOUND -//////////////////////////////////////////////////////////////////////// - -static int oss_init(void) -{ - int pspeed=44100; - int pstereo; - int format; - int fragsize = 0; - int myfrag; - int oss_speed, oss_stereo; - - pstereo = OSS_MODE_STEREO; - oss_speed = pspeed; - oss_stereo = pstereo; - - if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) - { - printf("OSS device not available\n"); - return -1; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1) - { - printf("Sound reset failed\n"); - return -1; - } - - // we use 64 fragments with 1024 bytes each - // rearmed: now using 10*4096 for better latency - - fragsize=12; - myfrag=(10<<16)|fragsize; - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1) - { - printf("Sound set fragment failed!\n"); - return -1; - } - - format = AFMT_S16_NE; - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1) - { - printf("Sound format not supported!\n"); - return -1; - } - - if(format!=AFMT_S16_NE) - { - printf("Sound format not supported!\n"); - return -1; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1 || !oss_stereo) - { - printf("Stereo mode not supported!\n"); - return -1; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1) - { - printf("Sound frequency not supported\n"); - return -1; - } - - if(oss_speed!=pspeed) - { - printf("Sound frequency not supported\n"); - return -1; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// REMOVE SOUND -//////////////////////////////////////////////////////////////////////// - -static void oss_finish(void) -{ - if(oss_audio_fd != -1 ) - { - close(oss_audio_fd); - oss_audio_fd = -1; - } -} - -//////////////////////////////////////////////////////////////////////// -// GET BUFFERED STATUS -//////////////////////////////////////////////////////////////////////// - -static int oss_busy(void) -{ - audio_buf_info info; - unsigned long l; - - if(oss_audio_fd == -1) return 1; - if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1) - l=0; - else - { - if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments? - l=1; // -> no? wait - else l=0; // -> else go on - } - - return l; -} - -//////////////////////////////////////////////////////////////////////// -// FEED SOUND DATA -//////////////////////////////////////////////////////////////////////// - -static void oss_feed(void *buf, int bytes) -{ - if(oss_audio_fd == -1) return; - write(oss_audio_fd, buf, bytes); -} - -void out_register_oss(struct out_driver *drv) -{ - drv->name = "oss"; - drv->init = oss_init; - drv->finish = oss_finish; - drv->busy = oss_busy; - drv->feed = oss_feed; -} diff --git a/extras/modules/peops/spu/out.c b/extras/modules/peops/spu/out.c deleted file mode 100644 index da5716560..000000000 --- a/extras/modules/peops/spu/out.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include "out.h" - -#define MAX_OUT_DRIVERS 5 - -static struct out_driver out_drivers[MAX_OUT_DRIVERS]; -struct out_driver *out_current; -static int driver_count; - -#define REGISTER_DRIVER(d) { \ - extern void out_register_##d(struct out_driver *drv); \ - out_register_##d(&out_drivers[driver_count++]); \ -} - -void SetupSound(void) -{ - int i; - - if (driver_count == 0) { -#ifdef HAVE_OSS - REGISTER_DRIVER(oss); -#endif -#ifdef HAVE_ALSA - REGISTER_DRIVER(alsa); -#endif -#ifdef HAVE_SDL - REGISTER_DRIVER(sdl); -#endif -#ifdef HAVE_PULSE - REGISTER_DRIVER(pulse); -#endif -#ifdef HAVE_LIBRETRO - REGISTER_DRIVER(libretro); -#endif - REGISTER_DRIVER(none); - } - - for (i = 0; i < driver_count; i++) - if (out_drivers[i].init() == 0) - break; - - if (i < 0 || i >= driver_count) { - printf("the impossible happened\n"); - abort(); - } - - out_current = &out_drivers[i]; - printf("selected sound output driver: %s\n", out_current->name); -} - diff --git a/extras/modules/peops/spu/out.h b/extras/modules/peops/spu/out.h deleted file mode 100644 index 46e2b3395..000000000 --- a/extras/modules/peops/spu/out.h +++ /dev/null @@ -1,12 +0,0 @@ - -struct out_driver { - const char *name; - int (*init)(void); - void (*finish)(void); - int (*busy)(void); - void (*feed)(void *data, int bytes); -}; - -extern struct out_driver *out_current; - -void SetupSound(void); diff --git a/extras/modules/peops/spu/psemuxa.h b/extras/modules/peops/spu/psemuxa.h deleted file mode 100644 index 24ecc61d7..000000000 --- a/extras/modules/peops/spu/psemuxa.h +++ /dev/null @@ -1,28 +0,0 @@ -//============================================ -//=== Audio XA decoding -//=== Kazzuya -//============================================ - -#ifndef DECODEXA_H -#define DECODEXA_H - -typedef struct -{ - long y0, y1; -} ADPCM_Decode_t; - -typedef struct -{ - int freq; - int nbits; - int stereo; - int nsamples; - ADPCM_Decode_t left, right; - short pcm[16384]; -} xa_decode_t; - -long xa_decode_sector( xa_decode_t *xdp, - unsigned char *sectorp, - int is_first_sector ); - -#endif diff --git a/extras/modules/peops/spu/pulseaudio.c b/extras/modules/peops/spu/pulseaudio.c deleted file mode 100644 index 13630aa92..000000000 --- a/extras/modules/peops/spu/pulseaudio.c +++ /dev/null @@ -1,357 +0,0 @@ -/*************************************************************************** - pulseaudio.c - description - ------------------- -begin : Thu Feb 04 2010 -copyright : (C) 2010 by Tristin Celestin -email : cetris1@umbc.edu -comment : Much of this was taken from simple.c, in the pulseaudio - library -***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -#include "stdafx.h" - -#define _IN_OSS - -#include "externals.h" -#include - -//////////////////////////////////////////////////////////////////////// -// pulseaudio structs -//////////////////////////////////////////////////////////////////////// - -typedef struct { - pa_threaded_mainloop *mainloop; - pa_context *context; - pa_mainloop_api *api; - pa_stream *stream; - pa_sample_spec spec; - int first; -} Device; - -typedef struct { - unsigned int frequency; - unsigned int latency_in_msec; -} Settings; - -//////////////////////////////////////////////////////////////////////// -// pulseaudio globals -//////////////////////////////////////////////////////////////////////// - -static Device device = { - .mainloop = NULL, - .api = NULL, - .context = NULL, - .stream = NULL -}; - -static Settings settings = { - .frequency = 44100, - .latency_in_msec = 20, -}; - -// the number of bytes written in SoundFeedStreamData -const int mixlen = 3240; - -// used to calculate how much space is used in the buffer, for debugging purposes -//int maxlength = 0; - -//////////////////////////////////////////////////////////////////////// -// CALLBACKS FOR THREADED MAINLOOP -//////////////////////////////////////////////////////////////////////// -static void context_state_cb (pa_context *context, void *userdata) -{ - Device *dev = userdata; - - if ((context == NULL) || (dev == NULL)) - return; - - switch (pa_context_get_state (context)) - { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal (dev->mainloop, 0); - break; - - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - } -} - -static void stream_state_cb (pa_stream *stream, void * userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - - switch (pa_stream_get_state (stream)) - { - case PA_STREAM_READY: - case PA_STREAM_FAILED: - case PA_STREAM_TERMINATED: - pa_threaded_mainloop_signal (dev->mainloop, 0); - break; - - case PA_STREAM_UNCONNECTED: - case PA_STREAM_CREATING: - break; - } -} - -static void stream_latency_update_cb (pa_stream *stream, void *userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - - pa_threaded_mainloop_signal (dev->mainloop, 0); -} - -static void stream_request_cb (pa_stream *stream, size_t length, void *userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - pa_threaded_mainloop_signal (dev->mainloop, 0); -} - -//////////////////////////////////////////////////////////////////////// -// SETUP SOUND -//////////////////////////////////////////////////////////////////////// - -static void pulse_init(void) -{ - int error_number; - - // Acquire mainloop /////////////////////////////////////////////////////// - device.mainloop = pa_threaded_mainloop_new (); - if (device.mainloop == NULL) - { - fprintf (stderr, "Could not acquire PulseAudio main loop\n"); - return -1; - } - - // Acquire context //////////////////////////////////////////////////////// - device.api = pa_threaded_mainloop_get_api (device.mainloop); - device.context = pa_context_new (device.api, "PCSX"); - pa_context_set_state_callback (device.context, context_state_cb, &device); - - if (device.context == NULL) - { - fprintf (stderr, "Could not acquire PulseAudio device context\n"); - return -1; - } - - // Connect to PulseAudio server /////////////////////////////////////////// - if (pa_context_connect (device.context, NULL, 0, NULL) < 0) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Could not connect to PulseAudio server: %s\n", pa_strerror(error_number)); - return -1; - } - - // Run mainloop until sever context is ready ////////////////////////////// - pa_threaded_mainloop_lock (device.mainloop); - if (pa_threaded_mainloop_start (device.mainloop) < 0) - { - fprintf (stderr, "Could not start mainloop\n"); - return -1; - } - - pa_context_state_t context_state; - context_state = pa_context_get_state (device.context); - while (context_state != PA_CONTEXT_READY) - { - context_state = pa_context_get_state (device.context); - if (! PA_CONTEXT_IS_GOOD (context_state)) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Context state is not good: %s\n", pa_strerror (error_number)); - return -1; - } - else if (context_state == PA_CONTEXT_READY) - break; - else - fprintf (stderr, "PulseAudio context state is %d\n", context_state); - pa_threaded_mainloop_wait (device.mainloop); - } - - // Set sample spec //////////////////////////////////////////////////////// - device.spec.format = PA_SAMPLE_S16NE; - device.spec.channels = 2; - device.spec.rate = settings.frequency; - - pa_buffer_attr buffer_attributes; - buffer_attributes.tlength = pa_bytes_per_second (& device.spec) / 5; - buffer_attributes.maxlength = buffer_attributes.tlength * 3; - buffer_attributes.minreq = buffer_attributes.tlength / 3; - buffer_attributes.prebuf = buffer_attributes.tlength; - - //maxlength = buffer_attributes.maxlength; - //fprintf (stderr, "Total space: %u\n", buffer_attributes.maxlength); - //fprintf (stderr, "Minimum request size: %u\n", buffer_attributes.minreq); - //fprintf (stderr, "Bytes needed before playback: %u\n", buffer_attributes.prebuf); - //fprintf (stderr, "Target buffer size: %lu\n", buffer_attributes.tlength); - - // Acquire new stream using spec ////////////////////////////////////////// - device.stream = pa_stream_new (device.context, "PCSX", &device.spec, NULL); - if (device.stream == NULL) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Could not acquire new PulseAudio stream: %s\n", pa_strerror (error_number)); - return -1; - } - - // Set callbacks for server events //////////////////////////////////////// - pa_stream_set_state_callback (device.stream, stream_state_cb, &device); - pa_stream_set_write_callback (device.stream, stream_request_cb, &device); - pa_stream_set_latency_update_callback (device.stream, stream_latency_update_cb, &device); - - // Ready stream for playback ////////////////////////////////////////////// - pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); - //pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); - if (pa_stream_connect_playback (device.stream, NULL, &buffer_attributes, flags, NULL, NULL) < 0) - { - pa_context_errno (device.context); - fprintf (stderr, "Could not connect for playback: %s\n", pa_strerror (error_number)); - return -1; - } - - // Run mainloop until stream is ready ///////////////////////////////////// - pa_stream_state_t stream_state; - stream_state = pa_stream_get_state (device.stream); - while (stream_state != PA_STREAM_READY) - { - stream_state = pa_stream_get_state (device.stream); - - if (stream_state == PA_STREAM_READY) - break; - - else if (! PA_STREAM_IS_GOOD (stream_state)) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Stream state is not good: %s\n", pa_strerror (error_number)); - return -1; - } - else - fprintf (stderr, "PulseAudio stream state is %d\n", stream_state); - pa_threaded_mainloop_wait (device.mainloop); - } - - pa_threaded_mainloop_unlock (device.mainloop); - - fprintf (stderr, "PulseAudio should be connected\n"); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// REMOVE SOUND -//////////////////////////////////////////////////////////////////////// -static void pulse_finish(void) -{ - if (device.mainloop != NULL) - pa_threaded_mainloop_stop (device.mainloop); - - // Release in reverse order of acquisition - if (device.stream != NULL) - { - pa_stream_unref (device.stream); - device.stream = NULL; - - } - if (device.context != NULL) - { - pa_context_disconnect (device.context); - pa_context_unref (device.context); - device.context = NULL; - } - - if (device.mainloop != NULL) - { - pa_threaded_mainloop_free (device.mainloop); - device.mainloop = NULL; - } - -} - -//////////////////////////////////////////////////////////////////////// -// GET BYTES BUFFERED -//////////////////////////////////////////////////////////////////////// - -static int pulse_busy(void) -{ - int free_space; - int error_code; - long latency; - int playing = 0; - - if ((device.mainloop == NULL) || (device.api == NULL) || ( device.context == NULL) || (device.stream == NULL)) - return 1; - - pa_threaded_mainloop_lock (device.mainloop); - free_space = pa_stream_writable_size (device.stream); - pa_threaded_mainloop_unlock (device.mainloop); - - //fprintf (stderr, "Free space: %d\n", free_space); - //fprintf (stderr, "Used space: %d\n", maxlength - free_space); - if (free_space < mixlen * 3) - { - // Don't buffer anymore, just play - //fprintf (stderr, "Not buffering.\n"); - return 1; - } - else - { - // Buffer some sound - //fprintf (stderr, "Buffering.\n"); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -// FEED SOUND DATA -//////////////////////////////////////////////////////////////////////// - -static void pulse_feed(void *pSound, int lBytes) -{ - int error_code; - int size; - - if (device.mainloop != NULL) - { - pa_threaded_mainloop_lock (device.mainloop); - if (pa_stream_write (device.stream, pSound, lBytes, NULL, 0LL, PA_SEEK_RELATIVE) < 0) - { - fprintf (stderr, "Could not perform write\n"); - } - else - { - //fprintf (stderr, "Wrote %d bytes\n", lBytes); - pa_threaded_mainloop_unlock (device.mainloop); - } - } -} - -void out_register_pulse(struct out_driver *drv) -{ - drv->name = "pulseaudio"; - drv->init = pulse_init; - drv->finish = pulse_finish; - drv->busy = pulse_busy; - drv->feed = pulse_feed; -} diff --git a/extras/modules/peops/spu/registers.c b/extras/modules/peops/spu/registers.c index 2c4b148d9..962b4d4ed 100644 --- a/extras/modules/peops/spu/registers.c +++ b/extras/modules/peops/spu/registers.c @@ -1,512 +1,410 @@ -/*************************************************************************** - registers.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -// #include "stdafx.h" - -#define _IN_REGISTERS - -#include "externals.h" -#include "registers.h" - -static void SoundOn(int start,int end,unsigned short val); -static void SoundOff(int start,int end,unsigned short val); -static void FModOn(int start,int end,unsigned short val); -static void NoiseOn(int start,int end,unsigned short val); -static void SetVolumeL(unsigned char ch,short vol); -static void SetVolumeR(unsigned char ch,short vol); -static void SetPitch(int ch,unsigned short val); -static void ReverbOn(int start,int end,unsigned short val); - -//////////////////////////////////////////////////////////////////////// -// WRITE REGISTERS: called by main emu -//////////////////////////////////////////////////////////////////////// - -void SPUwriteRegister(unsigned long reg, unsigned short val) -{ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/09/18 - LDChen +// - pre-calculated ADSRX values +// +// 2003/02/09 - kode54 +// - removed &0x3fff from reverb volume registers, fixes a few games, +// hopefully won't be breaking anything +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "externals.h" +#include "registers.h" +#include "regs.h" +#include "reverb.h" + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val) +{ const unsigned long r=reg&0xfff; - // regArea[(r-0xc00)>>1] = val; - - if(r>=0x0c00 && r<0x0d80) // some channel info? - { - int ch=(r>>4)-0xc0; // calc channel - switch(r&0x0f) - { - //------------------------------------------------// r volume - case 0: - SetVolumeL((unsigned char)ch,val); - break; - //------------------------------------------------// l volume - case 2: - SetVolumeR((unsigned char)ch,val); - break; - //------------------------------------------------// pitch - case 4: - SetPitch(ch,val); - break; - //------------------------------------------------// start - case 6: - // taken from regArea later - break; - //------------------------------------------------// level with pre-calcs - case 8: - { - const unsigned long lval=val; - //---------------------------------------------// - s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; - s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f; - s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f; - s_chan[ch].ADSRX.SustainLevel=lval & 0x000f; - //---------------------------------------------// - } - break; - //------------------------------------------------// adsr times with pre-calcs - case 10: - { - const unsigned long lval=val; - - //----------------------------------------------// - s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; - s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; - s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f; - s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; - s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f; - //----------------------------------------------// - } - break; - //------------------------------------------------// adsr volume... mmm have to investigate this - case 12: - break; - //------------------------------------------------// - case 14: // loop? - s_chan[ch].pLoop=spuMemC+((val&~1)<<3); - break; - //------------------------------------------------// + + if(r>=0x0c00 && r<0x0d80) // some channel info? + { + int ch=(r>>4)-0xc0; // calc channel + switch(r&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeL((unsigned char)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeR((unsigned char)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(ch,val); + break; + //------------------------------------------------// start + case 6: + s_chan[ch].pStart=spuMemC+((unsigned long) val<<3); + break; + //------------------------------------------------// level with pre-calcs + case 8: + { + //---------------------------------------------// + s_chan[ch].ADSRX.AttackModeExp=(val&0x8000)?1:0; + s_chan[ch].ADSRX.AttackRate = ((val>>8) & 0x007f)^0x7f; + s_chan[ch].ADSRX.DecayRate = 4*(((val>>4) & 0x000f)^0x1f); + s_chan[ch].ADSRX.SustainLevel = (val & 0x000f) << 27; + //---------------------------------------------// + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 10: + { + //----------------------------------------------// + s_chan[ch].ADSRX.SustainModeExp = (val&0x8000)?1:0; + s_chan[ch].ADSRX.SustainIncrease= (val&0x4000)?0:1; + s_chan[ch].ADSRX.SustainRate = ((val>>6) & 0x007f)^0x7f; + s_chan[ch].ADSRX.ReleaseModeExp = (val&0x0020)?1:0; + s_chan[ch].ADSRX.ReleaseRate = 4*((val & 0x001f)^0x1f); + //----------------------------------------------// + } + break; + //------------------------------------------------// + case 14: // loop? + s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3); + s_chan[ch].bIgnoreLoop=1; + break; + //------------------------------------------------// } - return; - } - - switch(r) - { - //-------------------------------------------------// - case H_SPUaddr: - spuAddr = (unsigned long) val<<3; - break; - //-------------------------------------------------// - case H_SPUdata: - spuMem[spuAddr>>1] = val; - spuAddr+=2; - if(spuAddr>0x7ffff) spuAddr=0; - break; - //-------------------------------------------------// - case H_SPUctrl: - if(!(spuCtrl & CTRL_IRQ)) - spuStat&=~STAT_IRQ; - spuCtrl=val; - break; - //-------------------------------------------------// - case H_SPUstat: - spuStat=val & 0xf800; - break; - //-------------------------------------------------// - case H_SPUReverbAddr: - if(val==0xFFFF || val<=0x200) - {rvb.StartAddr=rvb.CurrAddr=0;} - else - { - const long iv=(unsigned long)val<<2; - if(rvb.StartAddr!=iv) - { - rvb.StartAddr=(unsigned long)val<<2; - rvb.CurrAddr=rvb.StartAddr; - // sync-with-decode-buffers hack.. - if(rvb.StartAddr==0x3ff00) - rvb.CurrAddr+=decode_pos/2; - } - } - rvb.dirty = 1; - break; - //-------------------------------------------------// - case H_SPUirqAddr: - spuIrq = val; - pSpuIrq=spuMemC+(((unsigned long) val<<3)&~0xf); - break; - //-------------------------------------------------// - case H_SPUrvolL: - rvb.VolLeft=val; - break; - //-------------------------------------------------// - case H_SPUrvolR: - rvb.VolRight=val; - break; - //-------------------------------------------------// -/* - case H_ExtLeft: - //auxprintf("EL %d\n",val); - break; - //-------------------------------------------------// - case H_ExtRight: - //auxprintf("ER %d\n",val); - break; - //-------------------------------------------------// - case H_SPUmvolL: - //auxprintf("ML %d\n",val); - break; - //-------------------------------------------------// - case H_SPUmvolR: - //auxprintf("MR %d\n",val); - break; - //-------------------------------------------------// - case H_SPUMute1: - //auxprintf("M0 %04x\n",val); - break; - //-------------------------------------------------// - case H_SPUMute2: - //auxprintf("M1 %04x\n",val); - break; -*/ - //-------------------------------------------------// - case H_SPUon1: - SoundOn(0,16,val); - break; - //-------------------------------------------------// - case H_SPUon2: - SoundOn(16,24,val); - break; - //-------------------------------------------------// - case H_SPUoff1: - SoundOff(0,16,val); - break; - //-------------------------------------------------// - case H_SPUoff2: - SoundOff(16,24,val); - break; - //-------------------------------------------------// - case H_CDLeft: - iLeftXAVol=val & 0x7fff; - if(cddavCallback) cddavCallback(0,val); - break; - case H_CDRight: - iRightXAVol=val & 0x7fff; - if(cddavCallback) cddavCallback(1,val); - break; - //-------------------------------------------------// - case H_FMod1: - FModOn(0,16,val); - break; - //-------------------------------------------------// - case H_FMod2: - FModOn(16,24,val); - break; - //-------------------------------------------------// - case H_Noise1: - NoiseOn(0,16,val); - break; - //-------------------------------------------------// - case H_Noise2: - NoiseOn(16,24,val); - break; - //-------------------------------------------------// - case H_RVBon1: - ReverbOn(0,16,val); - break; - //-------------------------------------------------// - case H_RVBon2: - ReverbOn(16,24,val); - break; - //-------------------------------------------------// - case H_Reverb+0 : rvb.FB_SRC_A=val*4; break; - case H_Reverb+2 : rvb.FB_SRC_B=val*4; break; - case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break; - case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break; - case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break; - case H_Reverb+10 : rvb.ACC_COEF_C=(short)val; break; - case H_Reverb+12 : rvb.ACC_COEF_D=(short)val; break; - case H_Reverb+14 : rvb.IIR_COEF=(short)val; break; - case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break; - case H_Reverb+18 : rvb.FB_X=(short)val; break; - case H_Reverb+20 : rvb.IIR_DEST_A0=val*4; break; - case H_Reverb+22 : rvb.IIR_DEST_A1=val*4; break; - case H_Reverb+24 : rvb.ACC_SRC_A0=val*4; break; - case H_Reverb+26 : rvb.ACC_SRC_A1=val*4; break; - case H_Reverb+28 : rvb.ACC_SRC_B0=val*4; break; - case H_Reverb+30 : rvb.ACC_SRC_B1=val*4; break; - case H_Reverb+32 : rvb.IIR_SRC_A0=val*4; break; - case H_Reverb+34 : rvb.IIR_SRC_A1=val*4; break; - case H_Reverb+36 : rvb.IIR_DEST_B0=val*4; break; - case H_Reverb+38 : rvb.IIR_DEST_B1=val*4; break; - case H_Reverb+40 : rvb.ACC_SRC_C0=val*4; break; - case H_Reverb+42 : rvb.ACC_SRC_C1=val*4; break; - case H_Reverb+44 : rvb.ACC_SRC_D0=val*4; break; - case H_Reverb+46 : rvb.ACC_SRC_D1=val*4; break; - case H_Reverb+48 : rvb.IIR_SRC_B1=val*4; break; - case H_Reverb+50 : rvb.IIR_SRC_B0=val*4; break; - case H_Reverb+52 : rvb.MIX_DEST_A0=val*4; break; - case H_Reverb+54 : rvb.MIX_DEST_A1=val*4; break; - case H_Reverb+56 : rvb.MIX_DEST_B0=val*4; break; - case H_Reverb+58 : rvb.MIX_DEST_B1=val*4; break; - case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break; - case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break; + return; + } + + switch(r) + { + //-------------------------------------------------// + case H_SPUctrl: + spuCtrl=val; + break; + //-------------------------------------------------// + case H_SPUReverbAddr: + if(val==0xFFFF || val<=0x200) + {rvb.StartAddr=rvb.CurrAddr=0;} + else + { + const long iv=(unsigned long)val<<2; + if(rvb.StartAddr!=iv) + { + rvb.StartAddr=(unsigned long)val<<2; + rvb.CurrAddr=rvb.StartAddr; + } + } + break; + //-------------------------------------------------// + case H_SPUrvolL: + rvb.VolLeft=val; + break; + //-------------------------------------------------// + case H_SPUrvolR: + rvb.VolRight=val; + break; + //-------------------------------------------------// + case H_SPUon1: + SoundOn(0,16,val); + break; + //-------------------------------------------------// + case H_SPUon2: + SoundOn(16,24,val); + break; + //-------------------------------------------------// + case H_SPUoff1: + SoundOff(0,16,val); + break; + //-------------------------------------------------// + case H_SPUoff2: + SoundOff(16,24,val); + break; + //-------------------------------------------------// + case H_CDLeft: + iLeftXAVol=val & 0x7fff; + break; + case H_CDRight: + iRightXAVol=val & 0x7fff; + break; + //-------------------------------------------------// + case H_FMod1: + FModOn(0,16,val); + break; + //-------------------------------------------------// + case H_FMod2: + FModOn(16,24,val); + break; + //-------------------------------------------------// + case H_Noise1: + NoiseOn(0,16,val); + break; + //-------------------------------------------------// + case H_Noise2: + NoiseOn(16,24,val); + break; + //-------------------------------------------------// + case H_RVBon1: + ReverbOn(0,16,val); + break; + //-------------------------------------------------// + case H_RVBon2: + ReverbOn(16,24,val); + break; + //-------------------------------------------------// + case H_Reverb+0: + + rvb.FB_SRC_A=val; + + // OK, here's the fake REVERB stuff... + // depending on effect we do more or less delay and repeats... bah + // still... better than nothing :) + + SetREVERB(val); + break; + + + case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break; + case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break; + case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break; + case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break; + case H_Reverb+10 : rvb.ACC_COEF_C=(short)val; break; + case H_Reverb+12 : rvb.ACC_COEF_D=(short)val; break; + case H_Reverb+14 : rvb.IIR_COEF=(short)val; break; + case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break; + case H_Reverb+18 : rvb.FB_X=(short)val; break; + case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break; + case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break; + case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break; + case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break; + case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break; + case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break; + case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break; + case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break; + case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break; + case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break; + case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break; + case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break; + case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break; + case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break; + case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break; + case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break; + case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break; + case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break; + case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break; + case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break; + case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break; + case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break; } - - if ((r & ~0x3f) == H_Reverb) - rvb.dirty = 1; // recalculate on next update -} - -//////////////////////////////////////////////////////////////////////// -// READ REGISTER: called by main emu -//////////////////////////////////////////////////////////////////////// - -int SPUreadRegister(unsigned long reg, unsigned short * result) -{ - const unsigned long r=reg&0xfff; - - if(r>=0x0c00 && r<0x0d80) - { - switch(r&0x0f) - { - case 12: // get adsr vol - { - const int ch=(r>>4)-0xc0; - if(dwNewChannel&(1<>16); - return 1; - } - - case 14: // get loop address - { - const int ch=(r>>4)-0xc0; - *result = (unsigned short)((s_chan[ch].pLoop-spuMemC)>>3); - return 1; - } - } - } - - switch(r) - { - case H_SPUctrl: - *result = spuCtrl; - return 1; - - case H_SPUstat: - *result = spuStat; - return 1; - - case H_SPUaddr: - *result = (unsigned short)(spuAddr>>3); - return 1; - - case H_SPUdata: - { - unsigned short s=spuMem[spuAddr>>1]; - spuAddr+=2; - if(spuAddr>0x7ffff) spuAddr=0; - *result = s; - return 1; - } - - case H_SPUirqAddr: - *result = spuIrq; - return 1; - - //case H_SPUIsOn1: - // return IsSoundOn(0,16); - - //case H_SPUIsOn2: - // return IsSoundOn(16,24); - - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// SOUND ON register write -//////////////////////////////////////////////////////////////////////// - -static void SoundOn(int start,int end,unsigned short val) -{ - int ch; - - for(ch=start;ch>=1) // loop channels - { - if((val&1) && regAreaGet(ch,6)) // mmm... start has to be set before key on !?! - { - // do this here, not in StartSound - // - fixes fussy timing issues - s_chan[ch].bStop=0; - s_chan[ch].pCurr=spuMemC+((regAreaGet(ch,6)&~1)<<3); // must be block aligned - s_chan[ch].pLoop=spuMemC+((regAreaGet(ch,14)&~1)<<3); - s_chan[ch].prevflags=2; - - dwNewChannel|=(1<>=1) // loop channels - { - if(val&1) // && s_chan[i].bOn) mmm... - { - s_chan[ch].bStop=1; - - // Jungle Book - Rhythm 'n Groove - // - turns off buzzing sound (loop hangs) - dwNewChannel &= ~(1<>=1) // loop channels - { - if(val&1) // -> fmod on/off - { - if(ch>0) - { - s_chan[ch].bFMod=1; // --> sound channel - s_chan[ch-1].bFMod=2; // --> freq channel - } - } - else - { - s_chan[ch].bFMod=0; // --> turn off fmod - if(ch>0&&s_chan[ch-1].bFMod==2) - s_chan[ch-1].bFMod=0; - } - } -} - -//////////////////////////////////////////////////////////////////////// -// NOISE register write -//////////////////////////////////////////////////////////////////////// - -static void NoiseOn(int start,int end,unsigned short val) -{ - int ch; - - for(ch=start;ch>=1) // loop channels - { - s_chan[ch].bNoise=val&1; // -> noise on/off - } -} - -//////////////////////////////////////////////////////////////////////// -// LEFT VOLUME register write -//////////////////////////////////////////////////////////////////////// - -// please note: sweep and phase invert are wrong... but I've never seen -// them used - -static void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME -{ - if(vol&0x8000) // sweep? - { - short sInc=1; // -> sweep up? - if(vol&0x2000) sInc=-1; // -> or down? - if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this - vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 - vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! - vol*=128; - } - else // no sweep: - { - if(vol&0x4000) // -> mmm... phase inverted? have to investigate this - //vol^=0xffff; - vol=0x3fff-(vol&0x3fff); - } - - vol&=0x3fff; - s_chan[ch].iLeftVolume=vol; // store volume -} - -//////////////////////////////////////////////////////////////////////// -// RIGHT VOLUME register write -//////////////////////////////////////////////////////////////////////// - -static void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME -{ - if(vol&0x8000) // comments... see above :) - { - short sInc=1; - if(vol&0x2000) sInc=-1; - if(vol&0x1000) vol^=0xffff; - vol=((vol&0x7f)+1)/2; - vol+=vol/(2*sInc); - vol*=128; - } - else - { - if(vol&0x4000) //vol=vol^=0xffff; - vol=0x3fff-(vol&0x3fff); - } - - vol&=0x3fff; - - s_chan[ch].iRightVolume=vol; -} - -//////////////////////////////////////////////////////////////////////// -// PITCH register write -//////////////////////////////////////////////////////////////////////// - -static void SetPitch(int ch,unsigned short val) // SET PITCH -{ - int NP; - if(val>0x3fff) NP=0x3fff; // get pitch val - else NP=val; - - s_chan[ch].iRawPitch=NP; - s_chan[ch].sinc=(NP<<4)|8; - if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simple interpolation mode: set flag -} - -//////////////////////////////////////////////////////////////////////// -// REVERB register write -//////////////////////////////////////////////////////////////////////// - -static void ReverbOn(int start,int end,unsigned short val) -{ - int ch; - - for(ch=start;ch>=1) // loop channels - { - s_chan[ch].bReverb=val&1; // -> reverb on/off - } -} +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + s_chan[ch].bIgnoreLoop=0; + s_chan[ch].bNew=1; + dwNewChannel|=(1<>=1) // loop channels + { + if(val&1) // && s_chan[i].bOn) mmm... + { + s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + s_chan[ch].bFMod=1; // --> sound channel + s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +void NoiseOn(int start,int end,unsigned short val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> noise on/off + { + s_chan[ch].bNoise=1; + } + else + { + s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep and phase invert are wrong... but I've never seen +// them used + +void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME +{ + s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME +{ + s_chan[ch].iRightVolRaw=vol; + + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + s_chan[ch].iRightVolume=vol; +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +void SetPitch(int ch,unsigned short val) // SET PITCH +{ + int NP; + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + s_chan[ch].iRawPitch=NP; + + NP=(44100L*NP)/4096L; // calc frequency + if(NP<1) NP=1; // some security + s_chan[ch].iActFreq=NP; // store frequency +} + +//////////////////////////////////////////////////////////////////////// +// REVERB register write +//////////////////////////////////////////////////////////////////////// + +void ReverbOn(int start,int end,unsigned short val) // REVERB ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + s_chan[ch].bReverb=1; + } + else + { + s_chan[ch].bReverb=0; + } + } +} diff --git a/extras/modules/peops/spu/registers.h b/extras/modules/peops/spu/registers.h index 927ffcbb6..dc453cfac 100644 --- a/extras/modules/peops/spu/registers.h +++ b/extras/modules/peops/spu/registers.h @@ -5,6 +5,7 @@ copyright : (C) 2002 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ + /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -15,13 +16,14 @@ * * ***************************************************************************/ -// POPS Global Pointer -#define gp 0x10000 - -// SPU Register PSP Start Address -#define PSP_SPU_REGISTER 0x49F40000 +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// -// SPU Register Names #define H_SPUReverbAddr 0x0da2 #define H_SPUirqAddr 0x0da4 #define H_SPUaddr 0x0da6 @@ -149,15 +151,3 @@ #define H_SPU_ADSRLevel22 0x0d68 #define H_SPU_ADSRLevel23 0x0d78 -#define CTRL_IRQ 0x40 -#define CTRL_REVERB 0x80 -#define CTRL_NOISE 0x3f00 -#define CTRL_MUTE 0x4000 -#define CTRL_ON 0x8000 - -#define STAT_IRQ 0x40 - -/////////////////////////////////////////////////////////// - -void SPUwriteRegister(unsigned long reg, unsigned short val); -int SPUreadRegister(unsigned long reg, unsigned short * result); diff --git a/extras/modules/peops/spu/reverb.c b/extras/modules/peops/spu/reverb.c index 4cf1b31ef..610c1f328 100644 --- a/extras/modules/peops/spu/reverb.c +++ b/extras/modules/peops/spu/reverb.c @@ -40,8 +40,6 @@ // will be included from spu.c #ifdef _IN_SPU -#include "reverb.h" - //////////////////////////////////////////////////////////////////////// // globals //////////////////////////////////////////////////////////////////////// @@ -150,9 +148,9 @@ INLINE void StoreREVERB(SPUCHAN * pChannel,int ns) //////////////////////////////////////////////////////////////////////// -static INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps +INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps { - short * p=(short *)spuMem; + short * p=(short *)spuMemC; iOff=(iOff*4)+rvb.CurrAddr; while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); while(iOff - -// will be included from spu.c -#ifdef _IN_SPU - -//////////////////////////////////////////////////////////////////////// -// globals -//////////////////////////////////////////////////////////////////////// - -// REVERB info and timing vars... - -int * sRVBPlay = 0; -int * sRVBEnd = 0; -int * sRVBStart = 0; - -//////////////////////////////////////////////////////////////////////// -// START REVERB -//////////////////////////////////////////////////////////////////////// - -static inline void StartREVERB(int ch) -{ - if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible? - { - s_chan[ch].bRVBActive=!!iUseReverb; - } - else s_chan[ch].bRVBActive=0; // else -> no reverb -} - -//////////////////////////////////////////////////////////////////////// -// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf -//////////////////////////////////////////////////////////////////////// - -static inline void InitREVERB(void) -{ - memset(sRVBStart,0,NSSIZE*2*4); -} - -//////////////////////////////////////////////////////////////////////// -// STORE REVERB -//////////////////////////////////////////////////////////////////////// - -inline void StoreREVERB(int ch,int ns,int l,int r) -{ - ns<<=1; - - sRVBStart[ns] +=l; // -> we mix all active reverb channels into an extra buffer - sRVBStart[ns+1]+=r; -} - -//////////////////////////////////////////////////////////////////////// - -inline int rvb2ram_offs(int curr, int space, int iOff) -{ - iOff += curr; - if (iOff >= 0x40000) iOff -= space; - return iOff; -} - -// get_buffer content helper: takes care about wraps -#define g_buffer(var) \ - ((int)(signed short)spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)]) - -// saturate iVal and store it as var -#define s_buffer(var, iVal) \ - ssat32_to_16(iVal); \ - spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)] = iVal - -#define s_buffer1(var, iVal) \ - ssat32_to_16(iVal); \ - spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var + 1)] = iVal - -//////////////////////////////////////////////////////////////////////// - -// portions based on spu2-x from PCSX2 -static void MixREVERB(void) -{ - int l_old = rvb.iRVBLeft; - int r_old = rvb.iRVBRight; - int curr_addr = rvb.CurrAddr; - int space = 0x40000 - rvb.StartAddr; - int l, r, ns; - - for (ns = 0; ns < NSSIZE*2; ) - { - int IIR_ALPHA = rvb.IIR_ALPHA; - int ACC0, ACC1, FB_A0, FB_A1, FB_B0, FB_B1; - int mix_dest_a0, mix_dest_a1, mix_dest_b0, mix_dest_b1; - - int input_L = sRVBStart[ns] * rvb.IN_COEF_L; - int input_R = sRVBStart[ns+1] * rvb.IN_COEF_R; - - int IIR_INPUT_A0 = ((g_buffer(IIR_SRC_A0) * rvb.IIR_COEF) + input_L) >> 15; - int IIR_INPUT_A1 = ((g_buffer(IIR_SRC_A1) * rvb.IIR_COEF) + input_R) >> 15; - int IIR_INPUT_B0 = ((g_buffer(IIR_SRC_B0) * rvb.IIR_COEF) + input_L) >> 15; - int IIR_INPUT_B1 = ((g_buffer(IIR_SRC_B1) * rvb.IIR_COEF) + input_R) >> 15; - - int iir_dest_a0 = g_buffer(IIR_DEST_A0); - int iir_dest_a1 = g_buffer(IIR_DEST_A1); - int iir_dest_b0 = g_buffer(IIR_DEST_B0); - int iir_dest_b1 = g_buffer(IIR_DEST_B1); - - int IIR_A0 = iir_dest_a0 + ((IIR_INPUT_A0 - iir_dest_a0) * IIR_ALPHA >> 15); - int IIR_A1 = iir_dest_a1 + ((IIR_INPUT_A1 - iir_dest_a1) * IIR_ALPHA >> 15); - int IIR_B0 = iir_dest_b0 + ((IIR_INPUT_B0 - iir_dest_b0) * IIR_ALPHA >> 15); - int IIR_B1 = iir_dest_b1 + ((IIR_INPUT_B1 - iir_dest_b1) * IIR_ALPHA >> 15); - - s_buffer1(IIR_DEST_A0, IIR_A0); - s_buffer1(IIR_DEST_A1, IIR_A1); - s_buffer1(IIR_DEST_B0, IIR_B0); - s_buffer1(IIR_DEST_B1, IIR_B1); - - ACC0 = (g_buffer(ACC_SRC_A0) * rvb.ACC_COEF_A + - g_buffer(ACC_SRC_B0) * rvb.ACC_COEF_B + - g_buffer(ACC_SRC_C0) * rvb.ACC_COEF_C + - g_buffer(ACC_SRC_D0) * rvb.ACC_COEF_D) >> 15; - ACC1 = (g_buffer(ACC_SRC_A1) * rvb.ACC_COEF_A + - g_buffer(ACC_SRC_B1) * rvb.ACC_COEF_B + - g_buffer(ACC_SRC_C1) * rvb.ACC_COEF_C + - g_buffer(ACC_SRC_D1) * rvb.ACC_COEF_D) >> 15; - - FB_A0 = g_buffer(FB_SRC_A0); - FB_A1 = g_buffer(FB_SRC_A1); - FB_B0 = g_buffer(FB_SRC_B0); - FB_B1 = g_buffer(FB_SRC_B1); - - mix_dest_a0 = ACC0 - ((FB_A0 * rvb.FB_ALPHA) >> 15); - mix_dest_a1 = ACC1 - ((FB_A1 * rvb.FB_ALPHA) >> 15); - - mix_dest_b0 = FB_A0 + (((ACC0 - FB_A0) * rvb.FB_ALPHA - FB_B0 * rvb.FB_X) >> 15); - mix_dest_b1 = FB_A1 + (((ACC1 - FB_A1) * rvb.FB_ALPHA - FB_B1 * rvb.FB_X) >> 15); - - s_buffer(MIX_DEST_A0, mix_dest_a0); - s_buffer(MIX_DEST_A1, mix_dest_a1); - s_buffer(MIX_DEST_B0, mix_dest_b0); - s_buffer(MIX_DEST_B1, mix_dest_b1); - - l = (mix_dest_a0 + mix_dest_b0) / 2; - r = (mix_dest_a1 + mix_dest_b1) / 2; - - l = (l * rvb.VolLeft) >> 15; // 15? - r = (r * rvb.VolRight) >> 15; - - SSumLR[ns++] += (l + l_old) / 2; - SSumLR[ns++] += (r + r_old) / 2; - SSumLR[ns++] += l; - SSumLR[ns++] += r; - - l_old = l; - r_old = r; - - curr_addr++; - if (curr_addr >= 0x40000) curr_addr = rvb.StartAddr; - } - - rvb.iRVBLeft = l; - rvb.iRVBRight = r; - rvb.CurrAddr = curr_addr; -} - -static void MixREVERB_off(void) -{ - int l_old = rvb.iRVBLeft; - int r_old = rvb.iRVBRight; - int curr_addr = rvb.CurrAddr; - int space = 0x40000 - rvb.StartAddr; - int l, r, ns; - - for (ns = 0; ns < NSSIZE*2; ) - { - l = (g_buffer(MIX_DEST_A0) + g_buffer(MIX_DEST_B0)) / 2; - r = (g_buffer(MIX_DEST_A1) + g_buffer(MIX_DEST_B1)) / 2; - - l = (l * rvb.VolLeft) >> 15; - r = (r * rvb.VolRight) >> 15; - - SSumLR[ns++] += (l + l_old) / 2; - SSumLR[ns++] += (r + r_old) / 2; - SSumLR[ns++] += l; - SSumLR[ns++] += r; - - l_old = l; - r_old = r; - - curr_addr++; - if (curr_addr >= 0x40000) curr_addr = rvb.StartAddr; - } - - rvb.iRVBLeft = l; - rvb.iRVBRight = r; - rvb.CurrAddr = curr_addr; -} - -static void prepare_offsets(void) -{ - int space = 0x40000 - rvb.StartAddr; - int t; - #define prep_offs(v) \ - t = rvb.v; \ - while (t >= space) \ - t -= space; \ - rvb.n##v = t - #define prep_offs2(d, v1, v2) \ - t = rvb.v1 - rvb.v2; \ - while (t >= space) \ - t -= space; \ - rvb.n##d = t - - prep_offs(IIR_SRC_A0); - prep_offs(IIR_SRC_A1); - prep_offs(IIR_SRC_B0); - prep_offs(IIR_SRC_B1); - prep_offs(IIR_DEST_A0); - prep_offs(IIR_DEST_A1); - prep_offs(IIR_DEST_B0); - prep_offs(IIR_DEST_B1); - prep_offs(ACC_SRC_A0); - prep_offs(ACC_SRC_A1); - prep_offs(ACC_SRC_B0); - prep_offs(ACC_SRC_B1); - prep_offs(ACC_SRC_C0); - prep_offs(ACC_SRC_C1); - prep_offs(ACC_SRC_D0); - prep_offs(ACC_SRC_D1); - prep_offs(MIX_DEST_A0); - prep_offs(MIX_DEST_A1); - prep_offs(MIX_DEST_B0); - prep_offs(MIX_DEST_B1); - prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A); - prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A); - prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B); - prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B); - -#undef prep_offs -#undef prep_offs2 - rvb.dirty = 0; -} - -static inline void REVERBDo(void) -{ - if (!rvb.StartAddr) // reverb is off - { - rvb.iRVBLeft = rvb.iRVBRight = 0; - return; - } - - if (spuCtrl & 0x80) // -> reverb on? oki - { - if (unlikely(rvb.dirty)) - prepare_offsets(); - - MixREVERB(); - } - else if (rvb.VolLeft || rvb.VolRight) - { - if (unlikely(rvb.dirty)) - prepare_offsets(); - - MixREVERB_off(); - } - else // -> reverb off - { - // reverb runs anyway - rvb.CurrAddr += NSSIZE/2; - while (rvb.CurrAddr >= 0x40000) - rvb.CurrAddr -= 0x40000 - rvb.StartAddr; - } -} - -//////////////////////////////////////////////////////////////////////// - -#endif - -/* ------------------------------------------------------------------------------ -PSX reverb hardware notes -by Neill Corlett ------------------------------------------------------------------------------ - -Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway -yadda yadda. - ------------------------------------------------------------------------------ - -Basics ------- - -- The reverb buffer is 22khz 16-bit mono PCM. -- It starts at the reverb address given by 1DA2, extends to - the end of sound RAM, and wraps back to the 1DA2 address. - -Setting the address at 1DA2 resets the current reverb work address. - -This work address ALWAYS increments every 1/22050 sec., regardless of -whether reverb is enabled (bit 7 of 1DAA set). - -And the contents of the reverb buffer ALWAYS play, scaled by the -"reverberation depth left/right" volumes (1D84/1D86). -(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) - ------------------------------------------------------------------------------ - -Register names --------------- - -These are probably not their real names. -These are probably not even correct names. -We will use them anyway, because we can. - -1DC0: FB_SRC_A (offset) -1DC2: FB_SRC_B (offset) -1DC4: IIR_ALPHA (coef.) -1DC6: ACC_COEF_A (coef.) -1DC8: ACC_COEF_B (coef.) -1DCA: ACC_COEF_C (coef.) -1DCC: ACC_COEF_D (coef.) -1DCE: IIR_COEF (coef.) -1DD0: FB_ALPHA (coef.) -1DD2: FB_X (coef.) -1DD4: IIR_DEST_A0 (offset) -1DD6: IIR_DEST_A1 (offset) -1DD8: ACC_SRC_A0 (offset) -1DDA: ACC_SRC_A1 (offset) -1DDC: ACC_SRC_B0 (offset) -1DDE: ACC_SRC_B1 (offset) -1DE0: IIR_SRC_A0 (offset) -1DE2: IIR_SRC_A1 (offset) -1DE4: IIR_DEST_B0 (offset) -1DE6: IIR_DEST_B1 (offset) -1DE8: ACC_SRC_C0 (offset) -1DEA: ACC_SRC_C1 (offset) -1DEC: ACC_SRC_D0 (offset) -1DEE: ACC_SRC_D1 (offset) -1DF0: IIR_SRC_B1 (offset) -1DF2: IIR_SRC_B0 (offset) -1DF4: MIX_DEST_A0 (offset) -1DF6: MIX_DEST_A1 (offset) -1DF8: MIX_DEST_B0 (offset) -1DFA: MIX_DEST_B1 (offset) -1DFC: IN_COEF_L (coef.) -1DFE: IN_COEF_R (coef.) - -The coefficients are signed fractional values. --32768 would be -1.0 - 32768 would be 1.0 (if it were possible... the highest is of course 32767) - -The offsets are (byte/8) offsets into the reverb buffer. -i.e. you multiply them by 8, you get byte offsets. -You can also think of them as (samples/4) offsets. -They appear to be signed. They can be negative. -None of the documented presets make them negative, though. - -Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. - ------------------------------------------------------------------------------ - -What it does ------------- - -We take all reverb sources: -- regular channels that have the reverb bit on -- cd and external sources, if their reverb bits are on -and mix them into one stereo 44100hz signal. - -Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting -algorithm here, but I haven't figured out the hysterically exact specifics. -I use an 8-tap filter with these coefficients, which are nice but probably -not the real ones: - -0.037828187894 -0.157538631280 -0.321159685278 -0.449322115345 -0.449322115345 -0.321159685278 -0.157538631280 -0.037828187894 - -So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. - -* IN MY EMULATION, I divide these by 2 to make it clip less. - (and of course the L/R output coefficients are adjusted to compensate) - The real thing appears to not do this. - -At every 22050hz tick: -- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb - steady-state algorithm described below -- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer - (This part may not be exactly right and I guessed at the coefs. TODO: check later.) - L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) - R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) -- Advance the current buffer position by 1 sample - -The wet out L and R are then upsampled to 44100hz and played at the -"reverberation depth left/right" (1D84/1D86) volume, independent of the main -volume. - ------------------------------------------------------------------------------ - -Reverb steady-state -------------------- - -The reverb steady-state algorithm is fairly clever, and of course by -"clever" I mean "batshit insane". - -buffer[x] is relative to the current buffer position, not the beginning of -the buffer. Note that all buffer offsets must wrap around so they're -contained within the reverb work area. - -Clipping is performed at the end... maybe also sooner, but definitely at -the end. - -IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; -IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; -IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; -IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; - -IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); -IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); -IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); -IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); - -buffer[IIR_DEST_A0 + 1sample] = IIR_A0; -buffer[IIR_DEST_A1 + 1sample] = IIR_A1; -buffer[IIR_DEST_B0 + 1sample] = IIR_B0; -buffer[IIR_DEST_B1 + 1sample] = IIR_B1; - -ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + - buffer[ACC_SRC_B0] * ACC_COEF_B + - buffer[ACC_SRC_C0] * ACC_COEF_C + - buffer[ACC_SRC_D0] * ACC_COEF_D; -ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + - buffer[ACC_SRC_B1] * ACC_COEF_B + - buffer[ACC_SRC_C1] * ACC_COEF_C + - buffer[ACC_SRC_D1] * ACC_COEF_D; - -FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; -FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; -FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; -FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; - -buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; -buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; -buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; -buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// ------------------------------------------------------------------------------ -*/ -// vim:shiftwidth=1:expandtab +void SetREVERB(unsigned short val); +INLINE void StartREVERB(SPUCHAN * pChannel); +INLINE void StoreREVERB(SPUCHAN * pChannel,int ns); \ No newline at end of file diff --git a/extras/modules/peops/spu/sdl.c b/extras/modules/peops/spu/sdl.c deleted file mode 100644 index 644df7a4e..000000000 --- a/extras/modules/peops/spu/sdl.c +++ /dev/null @@ -1,143 +0,0 @@ -/* SDL Driver for P.E.Op.S Sound Plugin - * Copyright (c) 2010, Wei Mingzhi . - * - * 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 02111-1307 USA - */ - -#include -#include -#include "out.h" - -#define BUFFER_SIZE 22050 - -short *pSndBuffer = NULL; -int iBufSize = 0; -volatile int iReadPos = 0, iWritePos = 0; - -static void SOUND_FillAudio(void *unused, Uint8 *stream, int len) { - short *p = (short *)stream; - - len /= sizeof(short); - - while (iReadPos != iWritePos && len > 0) { - *p++ = pSndBuffer[iReadPos++]; - if (iReadPos >= iBufSize) iReadPos = 0; - --len; - } - - // Fill remaining space with zero - while (len > 0) { - *p++ = 0; - --len; - } -} - -static void InitSDL() { - if (SDL_WasInit(SDL_INIT_EVERYTHING)) { - SDL_InitSubSystem(SDL_INIT_AUDIO); - } else { - SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); - } -} - -static void DestroySDL() { - if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO)) { - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } else { - SDL_Quit(); - } -} - -static int sdl_init(void) { - SDL_AudioSpec spec; - - if (pSndBuffer != NULL) return -1; - - InitSDL(); - - spec.freq = 44100; - spec.format = AUDIO_S16SYS; - spec.channels = 2; - spec.samples = 512; - spec.callback = SOUND_FillAudio; - - if (SDL_OpenAudio(&spec, NULL) < 0) { - DestroySDL(); - return -1; - } - - iBufSize = BUFFER_SIZE; - - pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); - if (pSndBuffer == NULL) { - SDL_CloseAudio(); - return -1; - } - - iReadPos = 0; - iWritePos = 0; - - SDL_PauseAudio(0); - return 0; -} - -static void sdl_finish(void) { - if (pSndBuffer == NULL) return; - - SDL_CloseAudio(); - DestroySDL(); - - free(pSndBuffer); - pSndBuffer = NULL; -} - -static int sdl_busy(void) { - int size; - - if (pSndBuffer == NULL) return 1; - - size = iReadPos - iWritePos; - if (size <= 0) size += iBufSize; - - if (size < iBufSize / 2) return 1; - - return 0; -} - -static void sdl_feed(void *pSound, int lBytes) { - short *p = (short *)pSound; - - if (pSndBuffer == NULL) return; - - while (lBytes > 0) { - if (((iWritePos + 1) % iBufSize) == iReadPos) break; - - pSndBuffer[iWritePos] = *p++; - - ++iWritePos; - if (iWritePos >= iBufSize) iWritePos = 0; - - lBytes -= sizeof(short); - } -} - -void out_register_sdl(struct out_driver *drv) -{ - drv->name = "sdl"; - drv->init = sdl_init; - drv->finish = sdl_finish; - drv->busy = sdl_busy; - drv->feed = sdl_feed; -} diff --git a/extras/modules/peops/spu/spu.c b/extras/modules/peops/spu/spu.c index f02b78fd2..61fb2a801 100644 --- a/extras/modules/peops/spu/spu.c +++ b/extras/modules/peops/spu/spu.c @@ -15,82 +15,6 @@ * additional informations. * * * ***************************************************************************/ - -//*************************************************************************// -// History of changes: -// -// 2004/09/19 - Pete -// - added option: IRQ handling in the decoded sound buffer areas (Crash Team Racing) -// -// 2004/09/18 - Pete -// - changed global channel var handling to local pointers (hopefully it will help LDChen's port) -// -// 2004/04/22 - Pete -// - finally fixed frequency modulation and made some cleanups -// -// 2003/04/07 - Eric -// - adjusted cubic interpolation algorithm -// -// 2003/03/16 - Eric -// - added cubic interpolation -// -// 2003/03/01 - linuzappz -// - libraryName changes using ALSA -// -// 2003/02/28 - Pete -// - added option for type of interpolation -// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile) -// - added MONO support for MSWindows DirectSound -// -// 2003/02/20 - kode54 -// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault -// -// 2003/02/19 - kode54 -// - moved SPU IRQ handler and changed sample flag processing -// -// 2003/02/18 - kode54 -// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that -// ADSR timing is relative to the frequency at which a sample is played... I guess -// this remains to be seen, and I don't know whether ADSR is applied to noise channels... -// -// 2003/02/09 - kode54 -// - one-shot samples now process the end block before stopping -// - in light of removing fmod hack, now processing ADSR on frequency channel as well -// -// 2003/02/08 - kode54 -// - replaced easy interpolation with gaussian -// - removed fmod averaging hack -// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :) -// -// 2003/02/08 - linuzappz -// - small bugfix for one usleep that was 1 instead of 1000 -// - added iDisStereo for no stereo (Linux) -// -// 2003/01/22 - Pete -// - added easy interpolation & small noise adjustments -// -// 2003/01/19 - Pete -// - added Neill's reverb -// -// 2003/01/12 - Pete -// - added recording window handlers -// -// 2003/01/06 - Pete -// - added Neill's ADSR timings -// -// 2002/12/28 - Pete -// - adjusted spu irq handling, fmod handling and loop handling -// -// 2002/08/14 - Pete -// - added extra reverb -// -// 2002/06/08 - linuzappz -// - SPUupdate changed for SPUasync -// -// 2002/05/15 - Pete -// - generic cleanup for the Peops release -// -//*************************************************************************// #include "stdafx.h" @@ -105,24 +29,16 @@ // psx buffer / addresses -unsigned short * spuMem; unsigned char * spuMemC; -unsigned char * pSpuIrq=0; unsigned char * pSpuBuffer; -unsigned char * pMixIrq=0; - + + +// user settings -// user settings - -int iUseXA=1; int iVolume=3; int iXAPitch=1; -int iUseTimer=2; -int iSPUIRQWait=1; int iUseReverb=2; int iUseInterpolation=2; -int iDisStereo=0; -int iUseDBufIrq=0; // MAIN infos struct for each channel @@ -132,18 +48,12 @@ REVERBInfo rvb; unsigned long dwNoiseVal=1; // global noise generator unsigned short spuCtrl=0; // some vars to store psx reg infos -unsigned short spuIrq=0; int bEndThread=0; // thread handlers -int bThreadEnded=0; int bSpuInit=0; int bSPUIsOpen=0; unsigned long dwNewChannel=0; // flags for faster testing, if new channel starts -void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq -void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; -void (CALLBACK *irqQSound)(unsigned char *,long *,long)=0; - // certain globals (were local before, but with the new timeproc I need em global) const int f[5][2] = { { 0, 0 }, @@ -170,55 +80,12 @@ static int iSecureStart=0; // secure start counter #include "reverb.c" #include "adsr.c" -//////////////////////////////////////////////////////////////////////// -// helpers for simple interpolation - -// -// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm -// -// instead of having n equal sample values in a row like: -// ____ -// |____ -// -// we compare the current delta change with the next delta change. -// -// if curr_delta is positive, -// -// - and next delta is smaller (or changing direction): -// \. -// -__ -// -// - and next delta significant (at least twice) bigger: -// --_ -// \. -// -// - and next delta is nearly same: -// \. -// \. -// -// -// if curr_delta is negative, -// -// - and next delta is smaller (or changing direction): -// _-- -// / -// -// - and next delta significant (at least twice) bigger: -// / -// __- -// -// - and next delta is nearly same: -// / -// / -// - - -static INLINE void InterpolateUp(SPUCHAN * pChannel) +INLINE void InterpolateUp(SPUCHAN * pChannel) { - if(pChannel->SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + if(pChannel->SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass { - const int id1=pChannel->SB[30]-pChannel->SB[29]; // curr delta to next val - const int id2=pChannel->SB[31]-pChannel->SB[30]; // and next delta to next-next val :) + const int id1=pChannel->SB[30]-pChannel->SB[29]; // curr delta to next val + const int id2=pChannel->SB[31]-pChannel->SB[30]; // and next delta to next-next val :) pChannel->SB[32]=0; @@ -244,7 +111,7 @@ static INLINE void InterpolateUp(SPUCHAN * pChannel) } } else - if(pChannel->SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + if(pChannel->SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass { pChannel->SB[32]=0; @@ -261,13 +128,13 @@ static INLINE void InterpolateUp(SPUCHAN * pChannel) // even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm // -static INLINE void InterpolateDown(SPUCHAN * pChannel) +INLINE void InterpolateDown(SPUCHAN * pChannel) { - if(pChannel->sinc>=0x20000L) // we would skip at least one val? + if(pChannel->sinc>=0x20000L) // we would skip at least one val? { - pChannel->SB[29]+=(pChannel->SB[30]-pChannel->SB[29])/2; // add easy weight - if(pChannel->sinc>=0x30000L) // we would skip even more vals? - pChannel->SB[29]+=(pChannel->SB[31]-pChannel->SB[30])/2; // add additional next weight + pChannel->SB[29]+=(pChannel->SB[30]-pChannel->SB[29])/2; // add easy weight + if(pChannel->sinc>=0x30000L) // we would skip even more vals? + pChannel->SB[29]+=(pChannel->SB[31]-pChannel->SB[30])/2; // add additional next weight } } @@ -287,44 +154,44 @@ static INLINE void InterpolateDown(SPUCHAN * pChannel) // START SOUND... called by main thread to setup a new sound on a channel //////////////////////////////////////////////////////////////////////// -static INLINE void StartSound(SPUCHAN * pChannel) +INLINE void StartSound(SPUCHAN * pChannel) { StartADSR(pChannel); StartREVERB(pChannel); - pChannel->pCurr=pChannel->pStart; // set sample start + pChannel->pCurr=pChannel->pStart; // set sample start - pChannel->s_1=0; // init mixing vars + pChannel->s_1=0; // init mixing vars pChannel->s_2=0; pChannel->iSBPos=28; - pChannel->bNew=0; // init channel flags + pChannel->bNew=0; // init channel flags pChannel->bStop=0; pChannel->bOn=1; - pChannel->SB[29]=0; // init our interpolation helpers + pChannel->SB[29]=0; // init our interpolation helpers pChannel->SB[30]=0; if(iUseInterpolation>=2) // gauss interpolation? - {pChannel->spos=0x30000L;pChannel->SB[28]=0;} // -> start with more decoding - else {pChannel->spos=0x10000L;pChannel->SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding + {pChannel->spos=0x30000L;pChannel->SB[28]=0;} // -> start with more decoding + else {pChannel->spos=0x10000L;pChannel->SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding } //////////////////////////////////////////////////////////////////////// // ALL KIND OF HELPERS //////////////////////////////////////////////////////////////////////// -static INLINE void VoiceChangeFrequency(SPUCHAN * pChannel) +INLINE void VoiceChangeFrequency(SPUCHAN * pChannel) { - pChannel->iUsedFreq=pChannel->iActFreq; // -> take it and calc steps + pChannel->iUsedFreq=pChannel->iActFreq; // -> take it and calc steps pChannel->sinc=pChannel->iRawPitch<<4; if(!pChannel->sinc) pChannel->sinc=1; - if(iUseInterpolation==1) pChannel->SB[32]=1; // -> freq change in simle imterpolation mode: set flag + if(iUseInterpolation==1) pChannel->SB[32]=1; // -> freq change in simle imterpolation mode: set flag } //////////////////////////////////////////////////////////////////////// -static INLINE void FModChangeFrequency(SPUCHAN * pChannel,int ns) +INLINE void FModChangeFrequency(SPUCHAN * pChannel,int ns) { int NP=pChannel->iRawPitch; @@ -339,7 +206,7 @@ static INLINE void FModChangeFrequency(SPUCHAN * pChannel,int ns) pChannel->iUsedFreq=NP; pChannel->sinc=(((NP/10)<<16)/4410); if(!pChannel->sinc) pChannel->sinc=1; - if(iUseInterpolation==1) pChannel->SB[32]=1; // freq change in simple interpolation mode + if(iUseInterpolation==1) pChannel->SB[32]=1; // freq change in simple interpolation mode iFMod[ns]=0; } @@ -350,7 +217,7 @@ static INLINE void FModChangeFrequency(SPUCHAN * pChannel,int ns) // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... // and sometimes the noise will be used as fmod modulation... pfff -static INLINE int iGetNoiseVal(SPUCHAN * pChannel) +INLINE int iGetNoiseVal(SPUCHAN * pChannel) { int fa; @@ -369,15 +236,15 @@ static INLINE int iGetNoiseVal(SPUCHAN * pChannel) pChannel->iOldNoise=fa; if(iUseInterpolation<2) // no gauss/cubic interpolation? - pChannel->SB[29] = fa; // -> store noise val in "current sample" slot + pChannel->SB[29] = fa; // -> store noise val in "current sample" slot return fa; } //////////////////////////////////////////////////////////////////////// -static INLINE void StoreInterpolationVal(SPUCHAN * pChannel,int fa) +INLINE void StoreInterpolationVal(SPUCHAN * pChannel,int fa) { - if(pChannel->bFMod==2) // fmod freq channel + if(pChannel->bFMod==2) // fmod freq channel pChannel->SB[29]=fa; else { @@ -399,18 +266,18 @@ static INLINE void StoreInterpolationVal(SPUCHAN * pChannel,int fa) if(iUseInterpolation==1) // simple interpolation { pChannel->SB[28] = 0; - pChannel->SB[29] = pChannel->SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + pChannel->SB[29] = pChannel->SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' pChannel->SB[30] = pChannel->SB[31]; pChannel->SB[31] = fa; - pChannel->SB[32] = 1; // -> flag: calc new interolation + pChannel->SB[32] = 1; // -> flag: calc new interolation } - else pChannel->SB[29]=fa; // no interpolation + else pChannel->SB[29]=fa; // no interpolation } } //////////////////////////////////////////////////////////////////////// -static INLINE int iGetInterpolationVal(SPUCHAN * pChannel) +INLINE int iGetInterpolationVal(SPUCHAN * pChannel) { int fa; @@ -452,9 +319,9 @@ static INLINE int iGetInterpolationVal(SPUCHAN * pChannel) //--------------------------------------------------// case 1: // simple interpolation { - if(pChannel->sinc<0x10000L) // -> upsampling? - InterpolateUp(pChannel); // --> interpolate up - else InterpolateDown(pChannel); // --> else down + if(pChannel->sinc<0x10000L) // -> upsampling? + InterpolateUp(pChannel); // --> interpolate up + else InterpolateDown(pChannel); // --> else down fa=pChannel->SB[29]; } break; //--------------------------------------------------// @@ -474,23 +341,12 @@ static INLINE int iGetInterpolationVal(SPUCHAN * pChannel) // basically the whole sound processing is done in this fat func! //////////////////////////////////////////////////////////////////////// -// 5 ms waiting phase, if buffer is full and no new sound has to get started -// .. can be made smaller (smallest val: 1 ms), but bigger waits give -// better performance - -#define PAUSE_W 5 -#define PAUSE_L 5000 - -//////////////////////////////////////////////////////////////////////// - -int iSpuAsyncWait=0; - static void *MAINThread(void *arg) { int s_1,s_2,fa,ns,voldiv=iVolume; unsigned char * start;unsigned int nSample; int ch,predict_nr,shift_factor,flags,d,s; - int bIRQReturn=0;SPUCHAN * pChannel; + SPUCHAN * pChannel; while(!bEndThread) // until we are shutting down @@ -515,17 +371,14 @@ static void *MAINThread(void *arg) { iSecureStart=0; // reset secure - if(iUseTimer) return 0; // linux no-thread mode? bye - usleep(PAUSE_L); // else sleep for x ms (linux) - - if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + return 0; // linux no-thread mode? bye } //--------------------------------------------------// continue from irq handling in timer mode? - + if(lastch>=0) // will be -1 if no continue is pending { - ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue pChannel=&s_chan[ch]; goto GOON; // -> directly jump to the continue point } @@ -533,36 +386,36 @@ static void *MAINThread(void *arg) //--------------------------------------------------// //- main channel loop -// //--------------------------------------------------// - { + { pChannel=s_chan; - for(ch=0;chbNew) - { - StartSound(pChannel); // start new sound - dwNewChannel&=~(1<bOn) continue; // channel not playing? next - - if(pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? + if(pChannel->bNew) + { + StartSound(pChannel); // start new sound + dwNewChannel&=~(1<bOn) continue; // channel not playing? next + + if(pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? VoiceChangeFrequency(pChannel); ns=0; while(nsbFMod==1 && iFMod[ns]) // fmod freq channel + if(pChannel->bFMod==1 && iFMod[ns]) // fmod freq channel FModChangeFrequency(pChannel,ns); while(pChannel->spos>=0x10000L) { - if(pChannel->iSBPos==28) // 28 reached? + if(pChannel->iSBPos==28) // 28 reached? { - start=pChannel->pCurr; // set up the current pos + start=pChannel->pCurr; // set up the current pos if (start == (unsigned char*)-1) // special "stop" sign { - pChannel->bOn=0; // -> turn everything off + pChannel->bOn=0; // -> turn everything off pChannel->ADSRX.lVolume=0; pChannel->ADSRX.EnvelopeVol=0; goto ENDX; // -> and done for this channel @@ -603,37 +456,16 @@ static void *MAINThread(void *arg) pChannel->SB[nSample++]=fa; } - //////////////////////////////////////////// irq check - - if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? - { - if((pSpuIrq > start-16 && // irq address reached? - pSpuIrq <= start) || - ((flags&1) && // special: irq on looping addr, when stop/loop flag is set - (pSpuIrq > pChannel->pLoop-16 && - pSpuIrq <= pChannel->pLoop))) - { - pChannel->iIrqDone=1; // -> debug flag - irqCallback(); // -> call main emu - - if(iSPUIRQWait) // -> option: wait after irq for main emu - { - iSpuAsyncWait=1; - bIRQReturn=1; - } - } - } - //////////////////////////////////////////// flag handler if((flags&4) && (!pChannel->bIgnoreLoop)) - pChannel->pLoop=start-16; // loop adress + pChannel->pLoop=start-16; // loop adress if(flags&1) // 1: stop/loop { // We play this block out first... //if(!(flags&2)) // 1+2: do loop... otherwise: stop - if(flags!=3 || pChannel->pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + if(flags!=3 || pChannel->pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) { // and checking if pLoop is set avoids crashes, yeah start = (unsigned char*)-1; } @@ -643,41 +475,17 @@ static void *MAINThread(void *arg) } } - pChannel->pCurr=start; // store values for next cycle + pChannel->pCurr=start; // store values for next cycle pChannel->s_1=s_1; pChannel->s_2=s_2; - //////////////////////////////////////////// - - if(bIRQReturn) // special return for "spu irq - wait for cpu action" - { - bIRQReturn=0; - if(iUseTimer!=2) - { - DWORD dwWatchTime=timeGetTime()+2500; - - while(iSpuAsyncWait && !bEndThread && - timeGetTime()SB[pChannel->iSBPos++]; // get sample data + fa=pChannel->SB[pChannel->iSBPos++]; // get sample data - StoreInterpolationVal(pChannel,fa); // store val for later interpolation + StoreInterpolationVal(pChannel,fa); // store val for later interpolation pChannel->spos -= 0x10000L; } @@ -685,25 +493,20 @@ GOON: ; //////////////////////////////////////////////// if(pChannel->bNoise) - fa=iGetNoiseVal(pChannel); // get noise val - else fa=iGetInterpolationVal(pChannel); // get sample val + fa=iGetNoiseVal(pChannel); // get noise val + else fa=iGetInterpolationVal(pChannel); // get sample val - pChannel->sval=(MixADSR(pChannel)*fa)/1023; // mix adsr + pChannel->sval=(MixADSR(pChannel)*fa)/1023; // mix adsr - if(pChannel->bFMod==2) // fmod freq channel - iFMod[ns]=pChannel->sval; // -> store 1T sample data, use that to do fmod on next channel + if(pChannel->bFMod==2) // fmod freq channel + iFMod[ns]=pChannel->sval; // -> store 1T sample data, use that to do fmod on next channel else // no fmod freq channel { ////////////////////////////////////////////// // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) - if(pChannel->iMute) - pChannel->sval=0; // debug mute - else - { SSumL[ns]+=(pChannel->sval*pChannel->iLeftVolume)/0x4000L; SSumR[ns]+=(pChannel->sval*pChannel->iRightVolume)/0x4000L; - } ////////////////////////////////////////////// // now let us store sound data for reverb @@ -721,35 +524,17 @@ GOON: ; ENDX: ; } } - + //---------------------------------------------------// //- here we have another 1 ms of sound data //---------------------------------------------------// // mix XA infos (if any) - if(XAPlay!=XAFeed || XARepeat) MixXA(); + MixXA(); /////////////////////////////////////////////////////// // mix all channels (including reverb) into one buffer - if(iDisStereo) // no stereo? - { - int dl,dr; - for(ns=0;ns32767) dl=32767; - - SSumR[ns]+=MixREVERBRight(); - - dr=SSumR[ns]/voldiv;SSumR[ns]=0; - if(dr<-32767) dr=-32767;if(dr>32767) dr=32767; - *pS++=(dl+dr)/2; - } - } - else // stereo: for(ns=0;ns=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; - } - } - InitREVERB(); ////////////////////////////////////////////////////// // feed the sound // wanna have around 1/60 sec (16.666 ms) updates - if(iCycle++>16) - { - //- zn qsound mixer callback ----------------------// - - if(irqQSound) - { - long * pl=(long *)XAPlay; - short * ps=(short *)pSpuBuffer; - int g,iBytes=((unsigned char *)pS)-((unsigned char *)pSpuBuffer); - iBytes/=2; - for(g=0;g16) + { SoundFeedStreamData((unsigned char*)pSpuBuffer, ((unsigned char *)pS)- ((unsigned char *)pSpuBuffer)); @@ -834,34 +568,9 @@ ENDX: ; // end of big main loop... - bThreadEnded=1; - return 0; } -//////////////////////////////////////////////////////////////////////// -// SPU ASYNC... even newer epsxe func -// 1 time every 'cycle' cycles... harhar -//////////////////////////////////////////////////////////////////////// - -void CALLBACK SPUasync(unsigned long cycle) -{ - - if(iSpuAsyncWait) - { - iSpuAsyncWait++; - if(iSpuAsyncWait<=64) return; - iSpuAsyncWait=0; - } - - if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) - { - if(!bSpuInit) return; // -> no init, no call - - MAINThread(0); // -> linux high-compat mode - } -} - //////////////////////////////////////////////////////////////////////// // SPU UPDATE... new epsxe func // 1 time every 32 hsync lines @@ -875,7 +584,7 @@ void CALLBACK SPUasync(unsigned long cycle) void CALLBACK SPUupdate(void) { - SPUasync(0); + MAINThread(0); // -> linux high-compat mode } //////////////////////////////////////////////////////////////////////// @@ -884,13 +593,20 @@ void CALLBACK SPUupdate(void) void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) { - if(!iUseXA) return; // no XA? bye if(!xap) return; if(!xap->freq) return; // no xa freq ? bye FeedXA(xap); // call main XA feeder } +void CALLBACK SPUplayCDDAchannel(unsigned char *pcm, int nbytes) +{ + if (!pcm) return; + if (nbytes<=0) return; + + FeedCDDA(pcm, nbytes); +} + //////////////////////////////////////////////////////////////////////// // INIT/EXIT STUFF //////////////////////////////////////////////////////////////////////// @@ -901,8 +617,7 @@ void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) long CALLBACK SPUinit(void) { - spuMem = (unsigned short *)0x49F402C0; - spuMemC=(unsigned char *)spuMem; // just small setup + spuMemC=(unsigned char *)0x49F402C0; // just small setup memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); memset((void *)&rvb,0,sizeof(REVERBInfo)); InitADSR(); @@ -922,7 +637,6 @@ void SetupTimer(void) pS=(short *)pSpuBuffer; // setup soundbuffer pointer bEndThread=0; // init thread vars - bThreadEnded=0; bSpuInit=1; // flag: we are inited } @@ -933,7 +647,6 @@ void SetupTimer(void) void RemoveTimer(void) { bEndThread=1; // raise flag to end thread - bThreadEnded=0; // no more spu is running bSpuInit=0; } @@ -956,25 +669,24 @@ void SetupStreams(void) sRVBPlay = sRVBStart; XAStart = // alloc xa buffer - (unsigned long *)malloc(44100*4); + (uint32_t *)malloc(44100 * sizeof(uint32_t)); + XAEnd = XAStart + 44100; XAPlay = XAStart; XAFeed = XAStart; - XAEnd = XAStart + 44100; + + CDDAStart = // alloc cdda buffer + (uint32_t *)malloc(16384 * sizeof(uint32_t)); + CDDAEnd = CDDAStart + 16384; + CDDAPlay = CDDAStart; + CDDAFeed = CDDAStart; for(i=0;i init sustain - s_chan[i].iMute=0; - s_chan[i].iIrqDone=0; + s_chan[i].ADSRX.SustainLevel = 0xf<<27; // -> init sustain s_chan[i].pLoop=spuMemC; s_chan[i].pStart=spuMemC; s_chan[i].pCurr=spuMemC; - } - - if(iUseDBufIrq) pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address + } } //////////////////////////////////////////////////////////////////////// @@ -984,22 +696,13 @@ void SetupStreams(void) void RemoveStreams(void) { free(pSpuBuffer); // free mixing buffer - pSpuBuffer=NULL; + pSpuBuffer = NULL; free(sRVBStart); // free reverb buffer - sRVBStart=0; + sRVBStart = NULL; free(XAStart); // free XA buffer - XAStart=0; - -/* - int i; - for(i=0;i>16)&0xffff)) * iRightXAVol)/32767; - } - - if(XAPlay==XAFeed && XARepeat) - { - XARepeat--; - for(;ns>16)&0xffff)) * iRightXAVol)/32767; - } - } -} - -//////////////////////////////////////////////////////////////////////// -// FEED XA -//////////////////////////////////////////////////////////////////////// - -INLINE void FeedXA(xa_decode_t *xap) -{ - int sinc,spos,i,iSize,iPlace,vl,vr; - - if(!bSPUIsOpen) return; - - xapGlobal = xap; // store info for save states - XARepeat = 100; // set up repeat - - iSize=((44100*xap->nsamples)/xap->freq); // get size - if(!iSize) return; // none? bye - - if(XAFeed=10) - { - if(!dwFPS) dwFPS=1; - dw1=1000000/dwFPS; - if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; - else dwL1=dw1; - dw2=(xap->freq*100/xap->nsamples); - if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; - else - { - iLastSize=iSize*dw2/dw1; - if(iLastSize>iPlace) iLastSize=iPlace; - iSize=iLastSize; - } - iFPSCnt=0;dwFPS=0; - } - else - { - if(iLastSize) iSize=iLastSize; - } - } - //----------------------------------------------------// - - spos=0x10000L; - sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size - - if(xap->stereo) - { - unsigned long * pS=(unsigned long *)xap->pcm; - unsigned long l=0; - - if(iXAPitch) - { - long l1,l2;short s; - for(i=0;i=0x10000L) - { - l = *pS++; - gauss_window[gauss_ptr] = (short)LOWORD(l); - gauss_window[4+gauss_ptr] = (short)HIWORD(l); - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l= (vr >> 11) & 0xffff; - vr=(gauss[vl]*gvalr0)&~2047; - vr+=(gauss[vl+1]*gvalr(1))&~2047; - vr+=(gauss[vl+2]*gvalr(2))&~2047; - vr+=(gauss[vl+3]*gvalr(3))&~2047; - l |= vr << 5; - } - else - { - while(spos>=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - } - - s=(short)LOWORD(l); - l1=s; - l1=(l1*iPlace)/iSize; - if(l1<-32767) l1=-32767; - if(l1> 32767) l1=32767; - s=(short)HIWORD(l); - l2=s; - l2=(l2*iPlace)/iSize; - if(l2<-32767) l2=-32767; - if(l2> 32767) l2=32767; - l=(l1&0xffff)|(l2<<16); - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - l = *pS++; - gauss_window[gauss_ptr] = (short)LOWORD(l); - gauss_window[4+gauss_ptr] = (short)HIWORD(l); - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l= (vr >> 11) & 0xffff; - vr=(gauss[vl]*gvalr0)&~2047; - vr+=(gauss[vl+1]*gvalr(1))&~2047; - vr+=(gauss[vl+2]*gvalr(2))&~2047; - vr+=(gauss[vl+3]*gvalr(3))&~2047; - l |= vr << 5; - } - else - { - while(spos>=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - } - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } - else - { - unsigned short * pS=(unsigned short *)xap->pcm; - unsigned long l;short s=0; - - if(iXAPitch) - { - long l1; - for(i=0;i=0x10000L) - { - gauss_window[gauss_ptr] = (short)*pS++; - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l1=s= vr >> 11; - l1 &= 0xffff; - } - else - { - while(spos>=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l1=s; - } - - l1=(l1*iPlace)/iSize; - if(l1<-32767) l1=-32767; - if(l1> 32767) l1=32767; - l=(l1&0xffff)|(l1<<16); - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - gauss_window[gauss_ptr] = (short)*pS++; - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l=s= vr >> 11; - l &= 0xffff; - } - else - { - while(spos>=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l=s; - } - - *XAFeed++=(l|(l<<16)); - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } -} - -#endif +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * 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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" +#define _IN_XA +#include + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +uint32_t * XAFeed = NULL; +uint32_t * XAPlay = NULL; +uint32_t * XAStart = NULL; +uint32_t * XAEnd = NULL; + +uint32_t XARepeat = 0; +uint32_t XALastVal = 0; + +uint32_t * CDDAFeed = NULL; +uint32_t * CDDAPlay = NULL; +uint32_t * CDDAStart = NULL; +uint32_t * CDDAEnd = NULL; + +int iLeftXAVol = 32767; +int iRightXAVol = 32767; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +//////////////////////////////////////////////////////////////////////// +// MIX XA & CDDA +//////////////////////////////////////////////////////////////////////// + +INLINE void MixXA(void) +{ + int ns; + uint32_t l; + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32767; + } + + if(XAPlay==XAFeed && XARepeat) + { + XARepeat--; + for(;ns>16)&0xffff)) * iRightXAVol)/32767; + } + } + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32767; + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + + iSize=((44100*xap->nsamples)/xap->freq); // get size + if(!iSize) return; // none? bye + + if(XAFeed=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) +{ + uint32_t * pS=(uint32_t *)xap->pcm; + uint32_t l=0; + + if(iXAPitch) + { + int32_t l1,l2;short s; + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + uint32_t l;short s=0; + + if(iXAPitch) + { + int32_t l1; + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l1=s= vr >> 11; + l1 &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + } + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l=s= vr >> 11; + l &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + } + + *XAFeed++=(l|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED CDDA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedCDDA(unsigned char *pcm, int nBytes) +{ + while(nBytes>0) + { + if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; + while(CDDAFeed==CDDAPlay-1|| + (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) + { + return; + } + *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); + nBytes-=4; + pcm+=4; + } +} + +#endif diff --git a/extras/modules/peops/spu/xa.h b/extras/modules/peops/spu/xa.h index dd5da9356..0928eba2a 100644 --- a/extras/modules/peops/spu/xa.h +++ b/extras/modules/peops/spu/xa.h @@ -1,426 +1,20 @@ -/*************************************************************************** - xa.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ -/*************************************************************************** - * * - * 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. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -// #include "stdafx.h" -#define _IN_XA -#include -#include -#include -#include -#include - -// will be included from spu.c -#ifdef _IN_SPU - -#define LOWORD(v) (v & 0xFFFF) -#define HIWORD(v) ((v >> 16) & 0xFFFF) - -//////////////////////////////////////////////////////////////////////// -// XA GLOBALS -//////////////////////////////////////////////////////////////////////// - -xa_decode_t * xapGlobal=0; - -uint32_t * XAFeed = NULL; -uint32_t * XAPlay = NULL; -uint32_t * XAStart = NULL; -uint32_t * XAEnd = NULL; - -uint32_t XARepeat = 0; -uint32_t XALastVal = 0; - -uint32_t * CDDAFeed = NULL; -uint32_t * CDDAPlay = NULL; -uint32_t * CDDAStart = NULL; -uint32_t * CDDAEnd = NULL; - -int iLeftXAVol = 32767; -int iRightXAVol = 32767; - -static int gauss_ptr = 0; -static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - -#define gvall0 gauss_window[gauss_ptr] -#define gvall(x) gauss_window[(gauss_ptr+x)&3] -#define gvalr0 gauss_window[4+gauss_ptr] -#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] - -//////////////////////////////////////////////////////////////////////// -// MIX XA & CDDA -//////////////////////////////////////////////////////////////////////// - -static inline void MixXA(void) -{ - int ns; - short l, r; - uint32_t v; - int cursor = decode_pos; - - if(XAPlay != XAFeed || XARepeat > 0) - { - if(XAPlay == XAFeed) - XARepeat--; - - v = XALastVal; - for(ns=0;ns> 15; - r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15; - SSumLR[ns++] += l; - SSumLR[ns++] += r; - spuMem[cursor] = l; - spuMem[cursor + 0x400/2] = r; - cursor = (cursor + 1) & 0x1ff; - } - XALastVal = v; - } - - for(ns=0;ns> 15; - r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15; - SSumLR[ns++] += l; - SSumLR[ns++] += r; - spuMem[cursor] = l; - spuMem[cursor + 0x400/2] = r; - cursor = (cursor + 1) & 0x1ff; - } -} - -//////////////////////////////////////////////////////////////////////// -// small linux time helper... only used for watchdog -//////////////////////////////////////////////////////////////////////// - -static unsigned long timeGetTime_spu() -{ - unsigned long long tick = 0; - sceRtcGetCurrentTick(&tick); - - // return runtime milliseconds - return (unsigned long)(tick / (sceRtcGetTickResolution() / 1000.0f)); -} - -//////////////////////////////////////////////////////////////////////// -// FEED XA -//////////////////////////////////////////////////////////////////////// - -static inline void FeedXA(xa_decode_t *xap) -{ - int sinc,spos,i,iSize,iPlace,vl,vr; - - if(!bSPUIsOpen) return; - - xapGlobal = xap; // store info for save states - XARepeat = 100; // set up repeat - -#if 0//def XA_HACK - iSize=((45500*xap->nsamples)/xap->freq); // get size -#else - iSize=((44100*xap->nsamples)/xap->freq); // get size -#endif - if(!iSize) return; // none? bye - - if(XAFeed=10) - { - if(!dwFPS) dwFPS=1; - dw1=1000000/dwFPS; - if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; - else dwL1=dw1; - dw2=(xap->freq*100/xap->nsamples); - if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; - else - { - iLastSize=iSize*dw2/dw1; - if(iLastSize>iPlace) iLastSize=iPlace; - iSize=iLastSize; - } - iFPSCnt=0;dwFPS=0; - } - else - { - if(iLastSize) iSize=iLastSize; - } - } - //----------------------------------------------------// - - spos=0x10000L; - sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size - - if(xap->stereo) -{ - uint32_t * pS=(uint32_t *)xap->pcm; - uint32_t l=0; - - if(iXAPitch) - { - int32_t l1,l2;short s; - for(i=0;i=0x10000L) - { - l = *pS++; - gauss_window[gauss_ptr] = (short)LOWORD(l); - gauss_window[4+gauss_ptr] = (short)HIWORD(l); - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l= (vr >> 11) & 0xffff; - vr=(gauss[vl]*gvalr0)&~2047; - vr+=(gauss[vl+1]*gvalr(1))&~2047; - vr+=(gauss[vl+2]*gvalr(2))&~2047; - vr+=(gauss[vl+3]*gvalr(3))&~2047; - l |= vr << 5; - } - else - { - while(spos>=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - } - - s=(short)LOWORD(l); - l1=s; - l1=(l1*iPlace)/iSize; - ssat32_to_16(l1); - s=(short)HIWORD(l); - l2=s; - l2=(l2*iPlace)/iSize; - ssat32_to_16(l2); - l=(l1&0xffff)|(l2<<16); - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - l = *pS++; - gauss_window[gauss_ptr] = (short)LOWORD(l); - gauss_window[4+gauss_ptr] = (short)HIWORD(l); - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l= (vr >> 11) & 0xffff; - vr=(gauss[vl]*gvalr0)&~2047; - vr+=(gauss[vl+1]*gvalr(1))&~2047; - vr+=(gauss[vl+2]*gvalr(2))&~2047; - vr+=(gauss[vl+3]*gvalr(3))&~2047; - l |= vr << 5; - } - else - { - while(spos>=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - } - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } - else - { - unsigned short * pS=(unsigned short *)xap->pcm; - uint32_t l;short s=0; - - if(iXAPitch) - { - int32_t l1; - for(i=0;i=0x10000L) - { - gauss_window[gauss_ptr] = (short)*pS++; - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l1=s= vr >> 11; - l1 &= 0xffff; - } - else - { - while(spos>=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l1=s; - } - - l1=(l1*iPlace)/iSize; - ssat32_to_16(l1); - l=(l1&0xffff)|(l1<<16); - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - gauss_window[gauss_ptr] = (short)*pS++; - gauss_ptr = (gauss_ptr+1) & 3; - spos -= 0x10000L; - } - vl = (spos >> 6) & ~3; - vr=(gauss[vl]*gvall0)&~2047; - vr+=(gauss[vl+1]*gvall(1))&~2047; - vr+=(gauss[vl+2]*gvall(2))&~2047; - vr+=(gauss[vl+3]*gvall(3))&~2047; - l=s= vr >> 11; - } - else - { - while(spos>=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l=s; - } - - l &= 0xffff; - *XAFeed++=(l|(l<<16)); - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -// FEED CDDA -//////////////////////////////////////////////////////////////////////// - -static inline int FeedCDDA(unsigned char *pcm, int nBytes) -{ - int space; - space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1); - if(space0) - { - if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; - space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1); - if(CDDAFeed+space/4>CDDAEnd) - space=(CDDAEnd-CDDAFeed)*4; - if(space>nBytes) - space=nBytes; - - memcpy(CDDAFeed,pcm,space); - CDDAFeed+=space/4; - nBytes-=space; - pcm+=space; - } - - return 0x676f; // rearmed_go -} - -#endif +/*************************************************************************** + xa.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * 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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +INLINE void MixXA(void); +INLINE void FeedXA(xa_decode_t *xap); +INLINE void FeedCDDA(unsigned char *pcm, int nBytes); diff --git a/loader/live/user/psxloader/main.c b/loader/live/user/psxloader/main.c index 9af5e24db..61d77cbf4 100644 --- a/loader/live/user/psxloader/main.c +++ b/loader/live/user/psxloader/main.c @@ -19,6 +19,7 @@ PSP_MODULE_INFO("ARK VitaPOPS Loader", 0, 1, 0); int psxloader_thread(int argc, void* argv){ + // trigger virtual exploit in ps1cfw_enabler int res = sceIoOpen("ms0:/__dokxploit__", 0, 0); if (res < 0){ @@ -26,6 +27,7 @@ int psxloader_thread(int argc, void* argv){ return 0; } + // open ARKX binloader SceUID fd = sceIoOpen("ms0:/PSP/SAVEDATA/ARK_01234/ARKX.BIN", PSP_O_RDONLY, 0); if (fd < 0){ @@ -33,6 +35,7 @@ int psxloader_thread(int argc, void* argv){ return 0; } + // read binloader into KRAM at 0x88380000 sceIoRead(fd, (void *)0x88380000, 0x80000); sceIoClose(fd); sceKernelDcacheWritebackAll(); @@ -47,6 +50,7 @@ int psxloader_thread(int argc, void* argv){ int module_start(SceSize args, void* argp) { + // loader needs to be in a thread int thid = sceKernelCreateThread("psxloader", &psxloader_thread, 0x10, 0x20000, PSP_THREAD_ATTR_USER|PSP_THREAD_ATTR_VFPU, NULL); sceKernelStartThread(thid, 0, NULL);