diff --git a/Makefile b/Makefile index 321106b..5f98c60 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ MIPS_BUILTIN_DEFS := -DMIPSEB -D_MIPS_FPSET=16 -D_MIPS_ISA=2 -D_ABIO32=1 -D_MIPS ifneq ($(RUN_CC_CHECK),0) # The -MMD flags additionaly creates a .d file with the same name as the .o file. CC_CHECK := $(CC_CHECK_COMP) - CC_CHECK_FLAGS := -MMD -MP -fno-builtin -fsyntax-only -funsigned-char -fdiagnostics-color -std=gnu89 -m32 -DNON_MATCHING -DAVOID_UB -DCC_CHECK=1 + CC_CHECK_FLAGS := -MMD -MP -fno-builtin -fsyntax-only -funsigned-char -fdiagnostics-color -std=gnu89 -m32 -DNON_MATCHING -DAVOID_UB -DCC_CHECK ifneq ($(WERROR), 0) CHECK_WARNINGS += -Werror endif diff --git a/linker_scripts/us/symbol_addrs_code.txt b/linker_scripts/us/symbol_addrs_code.txt index 1ee55da..d63f748 100644 --- a/linker_scripts/us/symbol_addrs_code.txt +++ b/linker_scripts/us/symbol_addrs_code.txt @@ -1470,11 +1470,11 @@ func_8004FF20 = 0x8004FF20; // type:func func_8004FF40 = 0x8004FF40; // type:func func_80050020 = 0x80050020; // type:func n_alFxPull = 0x800500C0; // type:func -func_800503A0 = 0x800503A0; // type:func -func_80050600 = 0x80050600; // type:func -func_80050818 = 0x80050818; // type:func -func_80050960 = 0x80050960; // type:func -func_80050A8C = 0x80050A8C; // type:func +n_alFxParamHdl = 0x800503A0; // type:func +_n_loadOutputBuffer = 0x80050600; // type:func +_n_loadBuffer = 0x80050818; // type:func +_n_saveBuffer = 0x80050960; // type:func +_n_filterBuffer = 0x80050A8C; // type:func func_80050B40 = 0x80050B40; // type:func func_80050BA0 = 0x80050BA0; // type:func n_alSavePull = 0x80050C50; // type:func diff --git a/src/50CC0.c b/src/50CC0.c deleted file mode 100644 index 8c9e736..0000000 --- a/src/50CC0.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "50CC0.h" - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/n_alFxPull.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_800503A0.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_80050600.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_80050818.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_80050960.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_80050A8C.s") - -#pragma GLOBAL_ASM("asm/us/nonmatchings/50CC0/func_80050B40.s") diff --git a/src/51740.c b/src/51740.c new file mode 100644 index 0000000..3b12cfb --- /dev/null +++ b/src/51740.c @@ -0,0 +1,4 @@ +#include "global.h" + + +#pragma GLOBAL_ASM("asm/us/nonmatchings/51740/func_80050B40.s") diff --git a/src/libnaudio/n_reverb.c b/src/libnaudio/n_reverb.c new file mode 100644 index 0000000..4484b4a --- /dev/null +++ b/src/libnaudio/n_reverb.c @@ -0,0 +1,401 @@ +/*==================================================================== + * + * Copyright 1993, Silicon Graphics, Inc. + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, + * Inc.; the contents of this file may not be disclosed to third + * parties, copied or duplicated in any form, in whole or in part, + * without the prior written permission of Silicon Graphics, Inc. + * + * RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to + * restrictions as set forth in subdivision (c)(1)(ii) of the Rights + * in Technical Data and Computer Software clause at DFARS + * 252.227-7013, and/or in similar or successor clauses in the FAR, + * DOD or NASA FAR Supplement. Unpublished - rights reserved under the + * Copyright Laws of the United States. + *====================================================================*/ + +#include "n_synthInternals.h" +#include + +#include +#include +#include +#define RANGE 2.0 + +#ifdef AUD_PROFILE +extern u32 cnt_index, reverb_num, reverb_cnt, reverb_max, reverb_min, lastCnt[]; +extern u32 load_num, load_cnt, load_max, load_min, save_num, save_cnt, save_max, save_min; +#endif + +/* + * macros + */ +#define SWAP(in, out) \ +{ \ + s16 t = out; \ + out = in; \ + in = t; \ + } + +Acmd *_n_loadOutputBuffer(ALFx *r, ALDelay *d, s32 buff, Acmd *p); +Acmd *_n_loadBuffer(ALFx *r, s16 *curr_ptr, s32 buff, s32 count, Acmd *p); +Acmd *_n_saveBuffer(ALFx *r, s16 *curr_ptr, s32 buff, Acmd *p); +Acmd *_n_filterBuffer(ALLowPass *lp, s32 buff, Acmd *p); + +extern f32 _doModFunc(ALDelay *d, s32 count); +extern s32 L_INC[]; + +/*********************************************************************** + * Reverb filter public interfaces + ***********************************************************************/ +Acmd *n_alFxPull(s32 sampleOffset, Acmd *p) +{ + Acmd *ptr = p; + ALFx *r = (ALFx *)n_syn->auxBus->fx; + s16 i, buff1, buff2, input, output; + s16 *in_ptr, *out_ptr, gain, *prev_out_ptr = 0; + ALDelay *d, *pd; + +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + + /* + * pull channels going into this effect first + */ + ptr = n_alAuxBusPull(sampleOffset, p); + +#ifndef N_MICRO + input = AL_AUX_L_OUT; + output = AL_AUX_R_OUT; + buff1 = AL_TEMP_0; + buff2 = AL_TEMP_1; +#else + input = N_AL_AUX_L_OUT; + output = N_AL_AUX_R_OUT; + buff1 = N_AL_TEMP_0; + buff2 = N_AL_TEMP_1; +#endif + +#ifndef N_MICRO + aSetBuffer(ptr++, 0, 0, 0, FIXED_SAMPLE<<1); /* set the buffer size */ + aMix(ptr++, 0, 0xda83, AL_AUX_L_OUT, input); /* .707L = L - .293L */ + aMix(ptr++, 0, 0x5a82, AL_AUX_R_OUT, input); /* mix the AuxL and AuxR into the AuxL */ +#else + aMix(ptr++, 0, 0xda83, N_AL_AUX_L_OUT, input); + aMix(ptr++, 0, 0x5a82, N_AL_AUX_R_OUT, input); +#endif + + /* and write the mixed value to the delay line at r->input */ + ptr = _n_saveBuffer(r, r->input, input, ptr); + + aClearBuffer(ptr++, output, FIXED_SAMPLE<<1); /* clear the AL_AUX_R_OUT */ + + for (i = 0; i < r->section_count; i++) { + d = &r->delay[i]; /* get the ALDelay structure */ + in_ptr = &r->input[-d->input]; + out_ptr = &r->input[-d->output]; + + if (in_ptr == prev_out_ptr) { + SWAP(buff1, buff2); + } else { /* load data at in_ptr into buff1 */ + ptr = _n_loadBuffer(r, in_ptr, buff1, FIXED_SAMPLE, ptr); + } + ptr = _n_loadOutputBuffer(r, d, buff2, ptr); + + if (d->ffcoef) { + aMix(ptr++, 0, (u16)d->ffcoef, buff1, buff2); + if (!d->rs && !d->lp) { + ptr = _n_saveBuffer(r, out_ptr, buff2, ptr); + } + } + + if (d->fbcoef) { + aMix(ptr++, 0, (u16)d->fbcoef, buff2, buff1); + ptr = _n_saveBuffer(r, in_ptr, buff1, ptr); + } + + if (d->lp) + ptr = _n_filterBuffer(d->lp, buff2, ptr); + + if (!d->rs) + ptr = _n_saveBuffer(r, out_ptr, buff2, ptr); + + if (d->gain) + aMix(ptr++, 0, (u16)d->gain, buff2, output); + + prev_out_ptr = &r->input[d->output]; + } + + /* + * bump the master delay line input pointer + * modulo the length + */ + r->input += FIXED_SAMPLE; + if (r->input > &r->base[r->length]) + r->input -= r->length; + + /* + * output already in AL_AUX_R_OUT + * just copy to AL_AUX_L_OUT + */ +#ifndef N_MICRO + aDMEMMove(ptr++, output, AL_AUX_L_OUT, FIXED_SAMPLE<<1); +#else + aDMEMMove(ptr++, output, N_AL_AUX_L_OUT, FIXED_SAMPLE<<1); +#endif + +#ifdef AUD_PROFILE + PROFILE_AUD(reverb_num, reverb_cnt, reverb_max, reverb_min); +#endif + return ptr; +} + +/* + * This routine gets called by alSynSetFXParam. No checking takes place to + * verify the validity of the paramID or the param value. input and output + * values must be 8 byte aligned, so round down any param passed. + */ +s32 n_alFxParamHdl(void *filter, s32 paramID, void *param) +{ + ALFx *f = (ALFx *) filter; + s32 p = (paramID - 2) % 8; + s32 s = (paramID - 2) / 8; + s32 val = *(s32*)param; + +#define INPUT_PARAM 0 +#define OUTPUT_PARAM 1 +#define FBCOEF_PARAM 2 +#define FFCOEF_PARAM 3 +#define GAIN_PARAM 4 +#define CHORUSRATE_PARAM 5 +#define CHORUSDEPTH_PARAM 6 +#define LPFILT_PARAM 7 + + switch(p) + { + case INPUT_PARAM: + f->delay[s].input = (u32)val & 0xFFFFFFF8; + break; + case OUTPUT_PARAM: + f->delay[s].output = (u32)val & 0xFFFFFFF8; + break; + case FFCOEF_PARAM: + f->delay[s].ffcoef = (s16)val; + break; + case FBCOEF_PARAM: + f->delay[s].fbcoef = (s16)val; + break; + case GAIN_PARAM: + f->delay[s].gain = (s16)val; + break; + case CHORUSRATE_PARAM: + /* f->delay[s].rsinc = ((f32)val)/0xffffff; */ + f->delay[s].rsinc + = ((((f32)val)/1000) * RANGE)/n_syn->outputRate; + break; + + /* + * the following constant is derived from: + * + * ratio = 2^(cents/1200) + * + * and therefore for hundredths of a cent + * x + * ln(ratio) = --------------- + * (120,000)/ln(2) + * where + * 120,000/ln(2) = 173123.40... + */ +#define CONVERT 173123.404906676 +#define LENGTH (f->delay[s].output - f->delay[s].input) + + case CHORUSDEPTH_PARAM: + /*f->delay[s].rsgain = (((f32)val) / CONVERT) * LENGTH; */ + f->delay[s].rsgain = (((f32)val) / CONVERT) * LENGTH; + break; + case LPFILT_PARAM: + if(f->delay[s].lp) + { + f->delay[s].lp->fc = (s16)val; +#ifdef _OLD_AUDIO_LIBRARY + init_lpfilter(f->delay[s].lp); +#else + _init_lpfilter(f->delay[s].lp); +#endif + } + break; + } + return 0; +} + +Acmd *_n_loadOutputBuffer(ALFx *r, ALDelay *d, s32 buff, Acmd *p) +{ + Acmd *ptr = p; +#ifndef N_MICRO + s32 ratio, count, rbuff = AL_TEMP_2; +#else + s32 ratio, count, rbuff = N_AL_TEMP_2; +#endif + s16 *out_ptr; + f32 fincount, fratio, delta; + s32 ramalign = 0, length; + static f32 val=0.0, lastval=-10.0; + static f32 blob=0; + s32 incount = FIXED_SAMPLE; + + if (d->rs) { + length = d->output - d->input; + delta = _doModFunc(d, incount); + delta /= length; + delta = (s32)(delta * UNITY_PITCH); + delta = delta / UNITY_PITCH; + fratio = 1.0 - delta; + fincount = d->rs->delta + (fratio * (f32)incount); + count = (s32) fincount; + d->rs->delta = fincount - (f32)count; + out_ptr = &r->input[-(d->output - d->rsdelta)]; + ramalign = ((s32)out_ptr & 0x7) >> 1; + ptr = _n_loadBuffer(r, out_ptr - ramalign, rbuff, count + ramalign, ptr); + + ratio = (s32)(fratio * UNITY_PITCH); +#ifndef N_MICRO + aSetBuffer(ptr++, 0, rbuff + (ramalign<<1), buff, incount<<1); + aResample(ptr++, d->rs->first, ratio, osVirtualToPhysical(d->rs->state)); +#else + { + s16 tmp; + + tmp = buff >> 8; + n_aResample(ptr++, osVirtualToPhysical(d->rs->state), d->rs->first, ratio, rbuff + (ramalign<<1), tmp); + } +#endif + d->rs->first = 0; + d->rsdelta += count - incount; + } else { + out_ptr = &r->input[-d->output]; + ptr = _n_loadBuffer(r, out_ptr, buff, FIXED_SAMPLE, ptr); + } + + return ptr; +} + +Acmd *_n_loadBuffer(ALFx *r, s16 *curr_ptr, s32 buff,s32 count, Acmd *p) +{ + Acmd *ptr = p; + s32 after_end, before_end; + s16 *updated_ptr, *delay_end; + +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + + delay_end = &r->base[r->length]; + +#ifdef _DEBUG + if(curr_ptr > delay_end) + __osError(ERR_ALMODDELAYOVERFLOW, 1, delay_end - curr_ptr); +#endif + + if (curr_ptr < r->base) + curr_ptr += r->length; + updated_ptr = curr_ptr + count; + + if (updated_ptr > delay_end) { + after_end = updated_ptr - delay_end; + before_end = delay_end - curr_ptr; + +#ifndef N_MICRO + aSetBuffer(ptr++, 0, buff, 0, before_end<<1); + aLoadBuffer(ptr++, osVirtualToPhysical(curr_ptr)); + aSetBuffer(ptr++, 0, buff+(before_end<<1), 0, after_end<<1); + aLoadBuffer(ptr++, osVirtualToPhysical(r->base)); + } else { + aSetBuffer(ptr++, 0, buff, 0, count<<1); + aLoadBuffer(ptr++, osVirtualToPhysical(curr_ptr)); + } + + aSetBuffer(ptr++, 0, 0, 0, count<<1); +#else + n_aLoadBuffer(ptr++, before_end<<1, buff, osVirtualToPhysical(curr_ptr)); + n_aLoadBuffer(ptr++, after_end<<1, buff+(before_end<<1), osVirtualToPhysical(r->base)); + } else { + n_aLoadBuffer(ptr++, count<<1, buff, osVirtualToPhysical(curr_ptr)); + } +#endif + +#ifdef AUD_PROFILE + PROFILE_AUD(load_num, load_cnt, load_max, load_min); +#endif + return ptr; +} + +Acmd *_n_saveBuffer(ALFx *r, s16 *curr_ptr, s32 buff, Acmd *p) +{ + Acmd *ptr = p; + s32 after_end, before_end; + s16 *updated_ptr, *delay_end; +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + + delay_end = &r->base[r->length]; + if (curr_ptr < r->base) /* probably just security */ + curr_ptr += r->length; /* shouldn't occur */ + updated_ptr = curr_ptr + FIXED_SAMPLE; + + if (updated_ptr > delay_end) { /* if the data wraps past end of r->base */ + after_end = updated_ptr - delay_end; + before_end = delay_end - curr_ptr; + +#ifndef N_MICRO + aSetBuffer(ptr++, 0, 0, buff, before_end<<1); + aSaveBuffer(ptr++, osVirtualToPhysical(curr_ptr)); + aSetBuffer(ptr++, 0, 0, buff+(before_end<<1), after_end<<1); + aSaveBuffer(ptr++, osVirtualToPhysical(r->base)); + aSetBuffer(ptr++, 0, 0, 0, FIXED_SAMPLE<<1); + } else { + aSetBuffer(ptr++, 0, 0, buff, FIXED_SAMPLE<<1); + aSaveBuffer(ptr++, osVirtualToPhysical(curr_ptr)); + } +#else + n_aSaveBuffer(ptr++, before_end<<1, buff, osVirtualToPhysical(curr_ptr)); + n_aSaveBuffer(ptr++, after_end<<1, buff+(before_end<<1), osVirtualToPhysical(r->base)); + } else { + n_aSaveBuffer(ptr++, FIXED_SAMPLE<<1, buff, osVirtualToPhysical(curr_ptr)); + } +#endif + +#ifdef AUD_PROFILE + PROFILE_AUD(save_num, save_cnt, save_max, save_min); +#endif + return ptr; + +} + +Acmd *_n_filterBuffer(ALLowPass *lp, s32 buff, Acmd *p) +{ + Acmd *ptr = p; +#ifndef N_MICRO + aSetBuffer(ptr++, 0, buff, buff, FIXED_SAMPLE<<1); + aLoadADPCM(ptr++, 32, osVirtualToPhysical(lp->fcvec.fccoef)); + aPoleFilter(ptr++, lp->first, lp->fgain, osVirtualToPhysical(lp->fstate)); +#else + { + s16 tmp; + + tmp = buff >> 8; + n_aLoadADPCM(ptr++, 32, osVirtualToPhysical(lp->fcvec.fccoef)); + n_aPoleFilter(ptr++, lp->first, lp->fgain, tmp, osVirtualToPhysical(lp->fstate)); + } +#endif + + lp->first = 0; + + return ptr; +} + + diff --git a/yamls/us/rom.yaml b/yamls/us/rom.yaml index 47fe08b..7da6278 100644 --- a/yamls/us/rom.yaml +++ b/yamls/us/rom.yaml @@ -114,7 +114,8 @@ - [0x509A0, c, libnaudio/n_synallocfx] - [0x50A00, c] - [0x50C20, c] - - [0x50CC0, c] + - [0x50CC0, c, libnaudio/n_reverb] + - [0x51740, c] - [0x517A0, c] # yay0 audio decoder - [0x51850, c] - [0x518A0, c] @@ -345,7 +346,8 @@ - [0x79AE0, .data, 4CBC0] - [0x79C70, data, rom_data_79C70] - [0x79F70, .data, libnaudio/n_drvrNew] - - [0x7A100, data, rom_data_7A100] + - [0x7A100, .data, libnaudio/n_reverb] + - [0x7A110, data, rom_data_7A110] # libleo - [0x7A180, .data, libleo/driverominit] @@ -420,7 +422,7 @@ - [0x7E560, rodata, rom_rodata_7E560] - [0x7E5D0, .rodata, libnaudio/n_drvrNew] - [0x7E5F0, rodata, rom_rodata_7E5F0] - - [0x7E600, rodata, rom_rodata_7E600] + - [0x7E600, .rodata, libnaudio/n_reverb] # libleo - [0x7E630, .rodata, libleo/leofunc]