diff --git a/.vscode/settings.json b/.vscode/settings.json index 8f78dba0..dcd6c9da 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -51,7 +51,9 @@ "dsp.h": "c", "ar.h": "c", "osrtcpriv.h": "c", - "osbootinfo.h": "c" + "osbootinfo.h": "c", + "assert.h": "c", + "math.h": "c" }, "files.autoSave": "onFocusChange", "files.insertFinalNewline": true, diff --git a/asm/musyx/reverb.s b/asm/musyx/reverb.s index 0111e89d..cc76339e 100644 --- a/asm/musyx/reverb.s +++ b/asm/musyx/reverb.s @@ -545,8 +545,7 @@ lbl_803B6164: /* 803B6254 003B31B4 38 21 00 30 */ addi r1, r1, 0x30 /* 803B6258 003B31B8 4E 80 00 20 */ blr -.global HandleReverb_0 -HandleReverb_0: +.fn HandleReverb, local /* 803B625C 003B31BC 94 21 FF 40 */ stwu r1, -0xc0(r1) /* 803B6260 003B31C0 BD C1 00 08 */ stmw r14, 8(r1) /* 803B6264 003B31C4 D9 C1 00 60 */ stfd f14, 0x60(r1) @@ -899,6 +898,7 @@ lbl_803B66C0: /* 803B675C 003B36BC B9 C1 00 08 */ lmw r14, 8(r1) /* 803B6760 003B36C0 38 21 00 C0 */ addi r1, r1, 0xc0 /* 803B6764 003B36C4 4E 80 00 20 */ blr +.endfn HandleReverb .global ReverbHICallback ReverbHICallback: @@ -941,19 +941,19 @@ lbl_803B67E8: /* 803B67E8 003B3748 7F 63 DB 78 */ mr r3, r27 /* 803B67EC 003B374C 7F C4 F3 78 */ mr r4, r30 /* 803B67F0 003B3750 38 A0 00 00 */ li r5, 0 -/* 803B67F4 003B3754 4B FF FA 69 */ bl HandleReverb_0 +/* 803B67F4 003B3754 4B FF FA 69 */ bl HandleReverb /* 803B67F8 003B3758 48 00 00 28 */ b lbl_803B6820 lbl_803B67FC: /* 803B67FC 003B375C 7F 83 E3 78 */ mr r3, r28 /* 803B6800 003B3760 7F C4 F3 78 */ mr r4, r30 /* 803B6804 003B3764 38 A0 00 01 */ li r5, 1 -/* 803B6808 003B3768 4B FF FA 55 */ bl HandleReverb_0 +/* 803B6808 003B3768 4B FF FA 55 */ bl HandleReverb /* 803B680C 003B376C 48 00 00 14 */ b lbl_803B6820 lbl_803B6810: /* 803B6810 003B3770 7F A3 EB 78 */ mr r3, r29 /* 803B6814 003B3774 7F C4 F3 78 */ mr r4, r30 /* 803B6818 003B3778 38 A0 00 02 */ li r5, 2 -/* 803B681C 003B377C 4B FF FA 41 */ bl HandleReverb_0 +/* 803B681C 003B377C 4B FF FA 41 */ bl HandleReverb lbl_803B6820: /* 803B6820 003B3780 3B FF 00 01 */ addi r31, r31, 1 lbl_803B6824: diff --git a/configure.py b/configure.py index 77147bfd..46c778d1 100755 --- a/configure.py +++ b/configure.py @@ -940,8 +940,8 @@ LIBS = [ "musyx/hw_volconv", ["musyx/snd3d", False], ["musyx/snd_init", True], - ["musyx/snd_math", False], - "musyx/snd_midictrl", + ["musyx/snd_math", True], + ["musyx/snd_midictrl", False], ["musyx/snd_service", True], ["musyx/hardware", False], "musyx/hw_aramdma", @@ -953,7 +953,7 @@ LIBS = [ ["musyx/reverb_fx", True], ["musyx/reverb", False], ["musyx/delay_fx", True], - "musyx/chorus_fx", + ["musyx/chorus_fx", True], ], }, { @@ -1133,7 +1133,10 @@ if __name__ == "__main__": n.variable("devkitppc", "/opt/devkitpro/devkitPPC") cflags_base = "-proc gekko -nodefaults -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -O4,p -maxerrors 1 -enum int -inline auto -str reuse -nosyspath -MMD -DPRIME1 -DVERSION=$version_num -DNONMATCHING=0 -i include/ -i libc/" if args.debug: - cflags_base += " -sym on" + cflags_base += " -sym on -D_DEBUG" + else: + cflags_base += " -DNDEBUG" + n.variable("cflags_base", cflags_base) n.variable( "cflags_retro", @@ -1143,7 +1146,7 @@ if __name__ == "__main__": "cflags_runtime", "$cflags_base -use_lmw_stmw on -str reuse,pool,readonly -gccinc -inline deferred,auto", ) - n.variable("cflags_musyx", "$cflags_base -str reuse,pool,readonly") + n.variable("cflags_musyx", "$cflags_base -str reuse,pool,readonly -fp_contract off") asflags = "-mgekko -I include/ --defsym version=$version_num -W --strip-local-absolute -gdwarf-2" n.variable("asflags", asflags) ldflags = "-fp fmadd -nodefaults -lcf ldscript.lcf" diff --git a/include/musyx/assert.h b/include/musyx/assert.h new file mode 100644 index 00000000..b6664204 --- /dev/null +++ b/include/musyx/assert.h @@ -0,0 +1,32 @@ +#ifndef _MUSYX_ASSERT +#define _MUSYX_ASSERT + +extern void OSPanic(const char* file, int line, const char* msg, ...); + +#ifndef ASSERT +#ifdef _DEBUG +#define ASSERT(cond) \ + do { \ + if (!cond) { \ + OSPanic(__FILE__, __LINE__, "Failed assertion " #cond); \ + } \ + } while(0) +#else +#define ASSERT(cond) +#endif +#endif + +#ifndef ASSERT_MSG +#ifdef _DEBUG +#define ASSERT_MSG(cond, msg) \ + do { \ + if (!cond) { \ + OSPanic(__FILE__, __LINE__, msg); \ + } \ + } while(0) +#else +#define ASSERT_MSG(cond, msg) +#endif +#endif + +#endif // _MUSYX_ASSERT diff --git a/include/musyx/musyx.h b/include/musyx/musyx.h index 810a448f..7981a76a 100644 --- a/include/musyx/musyx.h +++ b/include/musyx/musyx.h @@ -236,7 +236,49 @@ SND_VOICEID sndFXCheck(SND_VOICEID vid); bool sndFXKeyOff(SND_VOICEID vid); bool sndFXCtrl(SND_VOICEID vid, u8 ctrl, u8 value); bool sndFXCtrl14(SND_VOICEID vid, u8 ctrl, u16 value); +#define _SND_CHORUS_NUM_BLOCKS 3 +typedef struct _SND_CHORUS_SRCINFO { + s32* dest; + s32* smpBase; + s32* old; + u32 posLo; + u32 posHi; + u32 pitchLo; + u32 pitchHi; + u32 trigger; + u32 target; +} _SND_CHORUS_SRCINFO; +typedef struct _SND_CHORUS_WORK { + s32* lastLeft[_SND_CHORUS_NUM_BLOCKS]; + s32* lastRight[_SND_CHORUS_NUM_BLOCKS]; + s32* lastSur[_SND_CHORUS_NUM_BLOCKS]; + u8 currentLast; + s32 oldLeft[4]; + s32 oldRight[4]; + s32 oldSur[4]; + + u32 currentPosLo; + u32 currentPosHi; + + s32 pitchOffset; + u32 pitchOffsetPeriodCount; + u32 pitchOffsetPeriod; + + _SND_CHORUS_SRCINFO src; +} _SND_CHORUS_WORK; + +typedef struct SND_AUX_CHORUS { + _SND_CHORUS_WORK work; + u32 baseDelay; + u32 variation; + u32 period; +} SND_AUX_CHORUS; + +void sndAuxCallbackChorus(u8 reason, SND_AUX_INFO* info, void* user); +bool sndAuxCallbackPrepareChorus(SND_AUX_CHORUS* ch); +bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch); +bool sndAuxCallbackUpdateSettingsChorus(SND_AUX_CHORUS* ch); #ifdef __cplusplus } #endif diff --git a/libc/math.h b/libc/math.h index 5e9f359a..0ad14fe5 100644 --- a/libc/math.h +++ b/libc/math.h @@ -89,6 +89,7 @@ double copysign(double x, double y); double floor(double x); double fabs(double x); +double pow(double x, double y); #ifdef __MWERKS__ #pragma cplusplus on diff --git a/src/musyx/chorus_fx.c b/src/musyx/chorus_fx.c new file mode 100644 index 00000000..b1c0135a --- /dev/null +++ b/src/musyx/chorus_fx.c @@ -0,0 +1,540 @@ +#include "musyx/musyx_priv.h" +#include "musyx/assert.h" + +static float rsmpTab12khz[512] = { + 0.097503662109f, 0.802215576172f, 0.101593017578f, -0.000976562500f, 0.093505859375f, + 0.802032470703f, 0.105804443359f, -0.001037597656f, 0.089599609375f, 0.801696777344f, + 0.110107421875f, -0.001159667969f, 0.085784912109f, 0.801177978516f, 0.114471435547f, + -0.001281738281f, 0.082031250000f, 0.800476074219f, 0.118927001953f, -0.001403808594f, + 0.078369140625f, 0.799621582031f, 0.123474121094f, -0.001525878906f, 0.074798583984f, + 0.798614501953f, 0.128143310547f, -0.001647949219f, 0.071350097656f, 0.797424316406f, + 0.132873535156f, -0.001770019531f, 0.067962646484f, 0.796051025391f, 0.137695312500f, + -0.001922607422f, 0.064697265625f, 0.794525146484f, 0.142608642578f, -0.002044677734f, + 0.061492919922f, 0.792846679688f, 0.147613525391f, -0.002197265625f, 0.058349609375f, + 0.790985107422f, 0.152709960938f, -0.002319335938f, 0.055328369141f, 0.788940429688f, + 0.157897949219f, -0.002471923828f, 0.052368164062f, 0.786743164062f, 0.163177490234f, + -0.002655029297f, 0.049499511719f, 0.784423828125f, 0.168518066406f, -0.002807617188f, + 0.046722412109f, 0.781890869141f, 0.173980712891f, -0.002990722656f, 0.044006347656f, + 0.779205322266f, 0.179504394531f, -0.003143310547f, 0.041412353516f, 0.776367187500f, + 0.185119628906f, -0.003326416016f, 0.038879394531f, 0.773376464844f, 0.190826416016f, + -0.003509521484f, 0.036407470703f, 0.770233154297f, 0.196594238281f, -0.003692626953f, + 0.034027099609f, 0.766937255859f, 0.202484130859f, -0.003875732422f, 0.031738281250f, + 0.763488769531f, 0.208435058594f, -0.004058837891f, 0.029510498047f, 0.759857177734f, + 0.214447021484f, -0.004272460938f, 0.027374267578f, 0.756103515625f, 0.220550537109f, + -0.004455566406f, 0.025299072266f, 0.752197265625f, 0.226745605469f, -0.004669189453f, + 0.023315429688f, 0.748168945312f, 0.233001708984f, -0.004852294922f, 0.021392822266f, + 0.743988037109f, 0.239318847656f, -0.005065917969f, 0.019561767578f, 0.739654541016f, + 0.245727539062f, -0.005310058594f, 0.017791748047f, 0.735198974609f, 0.252197265625f, + -0.005523681641f, 0.016052246094f, 0.730590820312f, 0.258728027344f, -0.005706787109f, + 0.014404296875f, 0.725860595703f, 0.265350341797f, -0.005920410156f, 0.012817382812f, + 0.721008300781f, 0.272033691406f, -0.006164550781f, 0.011322021484f, 0.716003417969f, + 0.278778076172f, -0.006378173828f, 0.009887695312f, 0.710906982422f, 0.285583496094f, + -0.006561279297f, 0.008514404297f, 0.705657958984f, 0.292449951172f, -0.006774902344f, + 0.007202148438f, 0.700317382812f, 0.299346923828f, -0.007019042969f, 0.005920410156f, + 0.694854736328f, 0.306335449219f, -0.007232666016f, 0.004699707031f, 0.689270019531f, + 0.313385009766f, -0.007415771484f, 0.003570556641f, 0.683563232422f, 0.320465087891f, + -0.007629394531f, 0.002471923828f, 0.677734375000f, 0.327606201172f, -0.007873535156f, + 0.001434326172f, 0.671844482422f, 0.334777832031f, -0.008087158203f, 0.000457763672f, + 0.665832519531f, 0.341979980469f, -0.008270263672f, -0.000488281250f, 0.659729003906f, + 0.349243164062f, -0.008453369141f, -0.001342773438f, 0.653533935547f, 0.356567382812f, + -0.008636474609f, -0.002166748047f, 0.647216796875f, 0.363891601562f, -0.008850097656f, + -0.002960205078f, 0.640838623047f, 0.371276855469f, -0.009033203125f, -0.003692626953f, + 0.634338378906f, 0.378692626953f, -0.009216308594f, -0.004364013672f, 0.627777099609f, + 0.386138916016f, -0.009338378906f, -0.004974365234f, 0.621154785156f, 0.393615722656f, + -0.009490966797f, -0.005584716797f, 0.614440917969f, 0.401092529297f, -0.009643554688f, + -0.006134033203f, 0.607635498047f, 0.408599853516f, -0.009796142578f, -0.006652832031f, + 0.600769042969f, 0.416107177734f, -0.009918212891f, -0.007141113281f, 0.593841552734f, + 0.423645019531f, -0.010009765625f, -0.007568359375f, 0.586853027344f, 0.431213378906f, + -0.010131835938f, -0.007965087891f, 0.579772949219f, 0.438751220703f, -0.010223388672f, + -0.008331298828f, 0.572662353516f, 0.446319580078f, -0.010284423828f, -0.008666992188f, + 0.565521240234f, 0.453887939453f, -0.010345458984f, -0.008972167969f, 0.558319091797f, + 0.461456298828f, -0.010406494141f, -0.009216308594f, 0.551055908203f, 0.469024658203f, + -0.010406494141f, -0.009460449219f, 0.543731689453f, 0.476593017578f, -0.010406494141f, + -0.009674072266f, 0.536407470703f, 0.484130859375f, -0.010375976562f, -0.009857177734f, + 0.529022216797f, 0.491668701172f, -0.010375976562f, -0.010009765625f, 0.521606445312f, + 0.499176025391f, -0.010314941406f, -0.010131835938f, 0.514160156250f, 0.506683349609f, + -0.010253906250f, -0.010253906250f, 0.506683349609f, 0.514160156250f, -0.010131835938f, + -0.010314941406f, 0.499176025391f, 0.521606445312f, -0.010009765625f, -0.010375976562f, + 0.491668701172f, 0.529022216797f, -0.009857177734f, -0.010375976562f, 0.484130859375f, + 0.536407470703f, -0.009674072266f, -0.010406494141f, 0.476593017578f, 0.543731689453f, + -0.009460449219f, -0.010406494141f, 0.469024658203f, 0.551055908203f, -0.009216308594f, + -0.010406494141f, 0.461456298828f, 0.558319091797f, -0.008972167969f, -0.010345458984f, + 0.453887939453f, 0.565521240234f, -0.008666992188f, -0.010284423828f, 0.446319580078f, + 0.572662353516f, -0.008331298828f, -0.010223388672f, 0.438751220703f, 0.579772949219f, + -0.007965087891f, -0.010131835938f, 0.431213378906f, 0.586853027344f, -0.007568359375f, + -0.010009765625f, 0.423645019531f, 0.593841552734f, -0.007141113281f, -0.009918212891f, + 0.416107177734f, 0.600769042969f, -0.006652832031f, -0.009796142578f, 0.408599853516f, + 0.607635498047f, -0.006134033203f, -0.009643554688f, 0.401092529297f, 0.614440917969f, + -0.005584716797f, -0.009490966797f, 0.393615722656f, 0.621154785156f, -0.004974365234f, + -0.009338378906f, 0.386138916016f, 0.627777099609f, -0.004364013672f, -0.009216308594f, + 0.378692626953f, 0.634338378906f, -0.003692626953f, -0.009033203125f, 0.371276855469f, + 0.640838623047f, -0.002960205078f, -0.008850097656f, 0.363891601562f, 0.647216796875f, + -0.002166748047f, -0.008636474609f, 0.356567382812f, 0.653533935547f, -0.001342773438f, + -0.008453369141f, 0.349243164062f, 0.659729003906f, -0.000488281250f, -0.008270263672f, + 0.341979980469f, 0.665832519531f, 0.000457763672f, -0.008087158203f, 0.334777832031f, + 0.671844482422f, 0.001434326172f, -0.007873535156f, 0.327606201172f, 0.677734375000f, + 0.002471923828f, -0.007629394531f, 0.320465087891f, 0.683563232422f, 0.003570556641f, + -0.007415771484f, 0.313385009766f, 0.689270019531f, 0.004699707031f, -0.007232666016f, + 0.306335449219f, 0.694854736328f, 0.005920410156f, -0.007019042969f, 0.299346923828f, + 0.700317382812f, 0.007202148438f, -0.006774902344f, 0.292449951172f, 0.705657958984f, + 0.008514404297f, -0.006561279297f, 0.285583496094f, 0.710906982422f, 0.009887695312f, + -0.006378173828f, 0.278778076172f, 0.716003417969f, 0.011322021484f, -0.006164550781f, + 0.272033691406f, 0.721008300781f, 0.012817382812f, -0.005920410156f, 0.265350341797f, + 0.725860595703f, 0.014404296875f, -0.005706787109f, 0.258728027344f, 0.730590820312f, + 0.016052246094f, -0.005523681641f, 0.252197265625f, 0.735198974609f, 0.017791748047f, + -0.005310058594f, 0.245727539062f, 0.739654541016f, 0.019561767578f, -0.005065917969f, + 0.239318847656f, 0.743988037109f, 0.021392822266f, -0.004852294922f, 0.233001708984f, + 0.748168945312f, 0.023315429688f, -0.004669189453f, 0.226745605469f, 0.752197265625f, + 0.025299072266f, -0.004455566406f, 0.220550537109f, 0.756103515625f, 0.027374267578f, + -0.004272460938f, 0.214447021484f, 0.759857177734f, 0.029510498047f, -0.004058837891f, + 0.208435058594f, 0.763488769531f, 0.031738281250f, -0.003875732422f, 0.202484130859f, + 0.766937255859f, 0.034027099609f, -0.003692626953f, 0.196594238281f, 0.770233154297f, + 0.036407470703f, -0.003509521484f, 0.190826416016f, 0.773376464844f, 0.038879394531f, + -0.003326416016f, 0.185119628906f, 0.776367187500f, 0.041412353516f, -0.003143310547f, + 0.179504394531f, 0.779205322266f, 0.044006347656f, -0.002990722656f, 0.173980712891f, + 0.781890869141f, 0.046722412109f, -0.002807617188f, 0.168518066406f, 0.784423828125f, + 0.049499511719f, -0.002655029297f, 0.163177490234f, 0.786743164062f, 0.052368164062f, + -0.002471923828f, 0.157897949219f, 0.788940429688f, 0.055328369141f, -0.002319335938f, + 0.152709960938f, 0.790985107422f, 0.058349609375f, -0.002197265625f, 0.147613525391f, + 0.792846679688f, 0.061492919922f, -0.002044677734f, 0.142608642578f, 0.794525146484f, + 0.064697265625f, -0.001922607422f, 0.137695312500f, 0.796051025391f, 0.067962646484f, + -0.001770019531f, 0.132873535156f, 0.797424316406f, 0.071350097656f, -0.001647949219f, + 0.128143310547f, 0.798614501953f, 0.074798583984f, -0.001525878906f, 0.123474121094f, + 0.799621582031f, 0.078369140625f, -0.001403808594f, 0.118927001953f, 0.800476074219f, + 0.082031250000f, -0.001281738281f, 0.114471435547f, 0.801177978516f, 0.085784912109f, + -0.001159667969f, 0.110107421875f, 0.801696777344f, 0.089599609375f, -0.001037597656f, + 0.105804443359f, 0.802032470703f, 0.093505859375f, -0.000976562500f, 0.101593017578f, + 0.802215576172f, 0.097503662109f, +}; + +const double i2fMagic = 4.503601774854144E15; + +#if NONMATCHING +void do_src1(_SND_CHORUS_SRCINFO* src) { + // TODO: Match this +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +asm void do_src1(_SND_CHORUS_SRCINFO* src) { + nofralloc + stwu r1, -0x40(r1) + stmw r26, 0x28(r1) + lwz r4, 0xc(r3) + lwz r5, 0x10(r3) + lwz r6, 0x14(r3) + lwz r8, 0x1c(r3) + lwz r7, 0x20(r3) + lwz r31, 4(r3) + lwz r30, 0(r3) + lwz r9, 8(r3) + lis r10, 0x4330 + stw r10, 8(r1) + stw r10, 0x10(r1) + stw r10, 0x18(r1) + stw r10, 0x20(r1) + lis r10, i2fMagic@ha + lfd f9, i2fMagic@l(r10) + slwi r10, r5, 2 + lwz r11, 0(r9) + lwz r29, 4(r9) + lwz r28, 8(r9) + lwzx r27, r31, r10 + xoris r11, r11, 0x8000 + xoris r29, r29, 0x8000 + stw r11, 0xc(r1) + xoris r28, r28, 0x8000 + stw r29, 0x14(r1) + xoris r27, r27, 0x8000 + stw r28, 0x1c(r1) + lfd f1, 8(r1) + stw r27, 0x24(r1) + lfd f2, 0x10(r1) + fsubs f1, f1, f9 + lfd f3, 0x18(r1) + fsubs f2, f2, f9 + lfd f4, 0x20(r1) + fsubs f3, f3, f9 + fsubs f4, f4, f9 + li r26, -4 + lis r12, rsmpTab12khz@ha + addi r12, r12, rsmpTab12khz@l + li r9, 0xa0 + mtctr r9 +lbl_803B6D5C: + rlwinm r10, r4, 7, 0x15, 0x1b + addc r4, r4, r6 + add r10, r10, r12 + mcrxr cr0 + lfs f5, 0(r10) + beq lbl_803B6DA4 + lfs f6, 4(r10) + fmuls f10, f1, f5 + lfs f7, 8(r10) + fmadds f10, f2, f6, f10 + lfs f8, 0xc(r10) + fmadds f10, f3, f7, f10 + addi r30, r30, 4 + fmadds f10, f4, f8, f10 + fctiwz f10, f10 + stfiwx f10, r26, r30 + bdnz lbl_803B6D5C + b lbl_803B6E10 +lbl_803B6DA4: + addi r5, r5, 1 + lfs f6, 4(r10) + fmuls f10, f1, f5 + cmpw r5, r8 + fmr f1, f2 + lfs f7, 8(r10) + fmadds f10, f2, f6, f10 + fmr f2, f3 + lfs f8, 0xc(r10) + fmadds f10, f3, f7, f10 + addi r30, r30, 4 + fmr f3, f4 + bne+ lbl_803B6DDC + mr r5, r7 +lbl_803B6DDC: + fmadds f10, f4, f8, f10 + slwi r9, r5, 2 + bdz lbl_803B6E08 + lwzx r10, r9, r31 + fctiwz f10, f10 + xoris r10, r10, 0x8000 + stw r10, 0xc(r1) + stfiwx f10, r26, r30 + lfd f4, 8(r1) + fsubs f4, f4, f9 + b lbl_803B6D5C +lbl_803B6E08: + fctiwz f10, f10 + stfiwx f10, r26, r30 +lbl_803B6E10: + lwz r9, 8(r3) + fctiwz f1, f1 + fctiwz f2, f2 + fctiwz f3, f3 + stfiwx f1, r0, r9 + addi r10, r9, 4 + stfiwx f2, r0, r10 + addi r10, r9, 8 + stfiwx f3, r0, r10 + stw r4, 0xc(r3) + stw r5, 0x10(r3) + lmw r26, 0x28(r1) + addi r1, r1, 0x40 + blr +} +#pragma pop +/* clang-format on */ +#endif + +#if NONMATCHING +void do_src2(_SND_CHORUS_SRCINFO* src) { + // TODO: Match this +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +asm void do_src2(_SND_CHORUS_SRCINFO* src) { + nofralloc + stwu r1, -0x40(r1) + stmw r26, 0x28(r1) + lwz r4, 0xc(r3) + lwz r5, 0x10(r3) + lwz r6, 0x14(r3) + lwz r8, 0x1c(r3) + lwz r7, 0x20(r3) + lwz r31, 4(r3) + lwz r30, 0(r3) + lwz r9, 8(r3) + lis r10, 0x4330 + stw r10, 8(r1) + stw r10, 0x10(r1) + stw r10, 0x18(r1) + stw r10, 0x20(r1) + lis r10, i2fMagic@ha + lfd f9, i2fMagic@l(r10) + slwi r10, r5, 2 + lwz r11, 0(r9) + lwz r29, 4(r9) + lwz r28, 8(r9) + lwzx r27, r31, r10 + xoris r11, r11, 0x8000 + xoris r29, r29, 0x8000 + stw r11, 0xc(r1) + xoris r28, r28, 0x8000 + stw r29, 0x14(r1) + xoris r27, r27, 0x8000 + stw r28, 0x1c(r1) + lfd f1, 8(r1) + stw r27, 0x24(r1) + lfd f2, 0x10(r1) + fsubs f1, f1, f9 + lfd f3, 0x18(r1) + fsubs f2, f2, f9 + lfd f4, 0x20(r1) + fsubs f3, f3, f9 + fsubs f4, f4, f9 + li r26, -4 + lis r12, rsmpTab12khz@ha + addi r12, r12, rsmpTab12khz@l + li r9, 0xa0 + mtctr r9 +lbl_803B6EF4: + rlwinm r10, r4, 7, 0x15, 0x1b + addc r4, r4, r6 + add r10, r10, r12 + mcrxr cr0 + addi r5, r5, 1 + lfs f5, 0(r10) + beq lbl_803B6F70 + lfs f6, 4(r10) + fmuls f10, f1, f5 + cmpw r5, r8 + fmr f1, f2 + lfs f7, 8(r10) + fmadds f10, f2, f6, f10 + fmr f2, f3 + lfs f8, 0xc(r10) + fmadds f10, f3, f7, f10 + addi r30, r30, 4 + fmr f3, f4 + bne+ lbl_803B6F44 + mr r5, r7 +lbl_803B6F44: + fmadds f10, f4, f8, f10 + slwi r9, r5, 2 + bdz lbl_803B6FF4 + lwzx r10, r9, r31 + fctiwz f10, f10 + xoris r10, r10, 0x8000 + stw r10, 0xc(r1) + stfiwx f10, r26, r30 + lfd f4, 8(r1) + fsubs f4, f4, f9 + b lbl_803B6EF4 +lbl_803B6F70: + cmpw r5, r8 + lfs f6, 4(r10) + bne+ lbl_803B6F80 + mr r5, r7 +lbl_803B6F80: + slwi r11, r5, 2 + addi r5, r5, 1 + lwzx r29, r11, r31 + fmuls f10, f1, f5 + cmpw r5, r8 + xoris r29, r29, 0x8000 + fmr f1, f3 + lfs f7, 8(r10) + stw r29, 0xc(r1) + fmadds f10, f2, f6, f10 + lfs f8, 0xc(r10) + fmadds f10, f3, f7, f10 + lfd f3, 8(r1) + fmr f2, f4 + addi r30, r30, 4 + fsubs f3, f3, f9 + bne+ lbl_803B6FC8 + mr r5, r7 +lbl_803B6FC8: + fmadds f10, f4, f8, f10 + slwi r9, r5, 2 + bdz lbl_803B6FF4 + lwzx r10, r9, r31 + fctiwz f10, f10 + xoris r10, r10, 0x8000 + stw r10, 0xc(r1) + stfiwx f10, r26, r30 + lfd f4, 8(r1) + fsubs f4, f4, f9 + b lbl_803B6EF4 +lbl_803B6FF4: + fctiwz f10, f10 + stfiwx f10, r26, r30 + lwz r9, 8(r3) + fctiwz f1, f1 + fctiwz f2, f2 + fctiwz f3, f3 + stfiwx f1, r0, r9 + addi r10, r9, 4 + stfiwx f2, r0, r10 + addi r10, r9, 8 + stfiwx f3, r0, r10 + stw r4, 0xc(r3) + stw r5, 0x10(r3) + lmw r26, 0x28(r1) + addi r1, r1, 0x40 + blr +} +#pragma pop +/* clang-format on */ +#endif + +void sndAuxCallbackChorus(u8 reason, SND_AUX_INFO* info, void* user) { + SND_AUX_CHORUS* chorus; + u8 currLast; + s32* lastLeft; + s32* lastRight; + s32* lastSur; + s32* left; + s32* right; + s32* sur; + u32 i; + s32 tmp; + + switch (reason) { + case SND_AUX_REASON_BUFFERUPDATE: + chorus = (SND_AUX_CHORUS*)user; + currLast = (chorus->work.currentLast + 1) % 3; + lastLeft = chorus->work.lastLeft[currLast]; + lastRight = chorus->work.lastRight[currLast]; + lastSur = chorus->work.lastSur[currLast]; + left = info->data.bufferUpdate.left; + right = info->data.bufferUpdate.right; + sur = info->data.bufferUpdate.surround; + + for (i = 0; i < 160; ++i) { + int tmp = *left; + ++left; + *lastLeft = tmp; + ++lastLeft; + + tmp = *right; + ++right; + *lastRight = tmp; + ++lastRight; + + tmp = *sur; + ++sur; + *lastSur = tmp; + ++lastSur; + } + + chorus->work.src.pitchHi = (chorus->work.pitchOffset >> 0x10) + 1; + chorus->work.src.pitchLo = (chorus->work.pitchOffset << 0x10); + + tmp = chorus->work.pitchOffsetPeriodCount - 1; + chorus->work.pitchOffsetPeriodCount = tmp; + if (tmp == 0) { + chorus->work.pitchOffsetPeriodCount = chorus->work.pitchOffsetPeriod; + chorus->work.pitchOffset = -chorus->work.pitchOffset; + } + + for (i = 0; i < 3; ++i) { + chorus->work.src.posHi = chorus->work.currentPosHi; + chorus->work.src.posLo = chorus->work.currentPosLo; + switch (i) { + case 0: + chorus->work.src.smpBase = chorus->work.lastLeft[0]; + chorus->work.src.dest = info->data.bufferUpdate.left; + chorus->work.src.old = chorus->work.oldLeft; + break; + case 1: + chorus->work.src.smpBase = chorus->work.lastRight[0]; + chorus->work.src.dest = info->data.bufferUpdate.right; + chorus->work.src.old = chorus->work.oldRight; + break; + case 2: + chorus->work.src.smpBase = chorus->work.lastSur[0]; + chorus->work.src.dest = info->data.bufferUpdate.surround; + chorus->work.src.old = chorus->work.oldSur; + break; + } + + switch (chorus->work.src.pitchHi) { + case 0: + do_src1(&chorus->work.src); + break; + case 1: + do_src2(&chorus->work.src); + break; + } + } + + chorus->work.currentPosHi = chorus->work.src.posHi % 480; + chorus->work.currentPosLo = chorus->work.src.posLo; + chorus->work.currentLast = currLast; + break; + case SND_AUX_REASON_PARAMETERUPDATE: + break; + default: + ASSERT(FALSE); + break; + } +} + +bool sndAuxCallbackUpdateSettingsChorus(SND_AUX_CHORUS* ch) { + ch->work.currentPosHi = 0x140 - ((ch->baseDelay - 5) << 5); + ch->work.currentPosLo = 0; + ch->work.currentPosHi = (ch->work.currentPosHi + (ch->work.currentLast - 1) * 0xa0) % 0x1e0; + ch->work.pitchOffsetPeriod = (ch->period / 5) + 1 & ~1; + ch->work.pitchOffsetPeriodCount = (u32)ch->work.pitchOffsetPeriod >> 1; + ch->work.pitchOffset = (ch->variation << 16) / (ch->work.pitchOffsetPeriod * 5); + return TRUE; +} + +bool sndAuxCallbackPrepareChorus(SND_AUX_CHORUS* chorus) { + u32 i; + bool ret; + s32* lastLeft; + s32* lastRight; + s32* lastSur; + + chorus->work.lastLeft[0] = (s32*)salMalloc(0x1680); + + if (chorus->work.lastLeft[0] != NULL) { + chorus->work.lastRight[0] = chorus->work.lastLeft[0] + 0x1e0; + chorus->work.lastSur[0] = chorus->work.lastRight[0] + 0x1e0; + + for (i = 0; i < 3; ++i) { + chorus->work.lastLeft[i] = chorus->work.lastLeft[0] + i * 0xa0; + chorus->work.lastRight[i] = chorus->work.lastRight[0] + i * 0xa0; + chorus->work.lastSur[i] = chorus->work.lastSur[0] + i * 0xa0; + } + + lastLeft = chorus->work.lastLeft[0]; + lastRight = chorus->work.lastRight[0]; + lastSur = chorus->work.lastSur[0]; + for (i = 0; i < 0x140; i += 1) { + *lastLeft = 0; + ++lastLeft; + *lastRight = 0; + ++lastRight; + *lastSur = 0; + ++lastSur; + } + + chorus->work.currentLast = 1; + chorus->work.oldLeft[3] = 0; + chorus->work.oldLeft[2] = 0; + chorus->work.oldLeft[1] = 0; + chorus->work.oldLeft[0] = 0; + chorus->work.oldRight[3] = 0; + chorus->work.oldRight[2] = 0; + chorus->work.oldRight[1] = 0; + chorus->work.oldRight[0] = 0; + chorus->work.oldSur[3] = 0; + chorus->work.oldSur[2] = 0; + chorus->work.oldSur[1] = 0; + chorus->work.oldSur[0] = 0; + + chorus->work.src.trigger = 480; + chorus->work.src.target = 0; + ret = sndAuxCallbackUpdateSettingsChorus(chorus); + } else { + ret = FALSE; + } + return ret; +} + +bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch) { + salFree(ch->work.lastLeft[0]); + return TRUE; +} diff --git a/src/musyx/reverb.c b/src/musyx/reverb.c index 96dc57f4..4bdfd29b 100644 --- a/src/musyx/reverb.c +++ b/src/musyx/reverb.c @@ -34,17 +34,17 @@ bool ReverbHICreate(_SND_REVHI_WORK* rev, f32 coloration, f32 time, f32 mix, f32 for (i = 0; i < 3; ++i) { for (j = 0; j < 3; ++j) { - DLcreate(&rev->C[i], lens[j] + 2); - DLsetdelay(&rev->C[i], lens[j]); + DLcreate(&rev->C[j + i], lens[j] + 2); + DLsetdelay(&rev->C[j + i], lens[j]); rev->combCoef[j + i * 3] = pow(10.f, (lens[j] * -3) / (32000.f * time)); } for (j = 0; j < 2; ++j) { - DLcreate(&rev->AP[i], lens[j + 3] + 2); - DLsetdelay(&rev->AP[i], lens[j + 3]); + DLcreate(&rev->AP[j + i], lens[j + 3] + 2); + DLsetdelay(&rev->AP[j + i], lens[j + 3]); } - DLcreate(&rev->AP[i], lens[i + 5] + 2); - DLsetdelay(&rev->AP[i], lens[i + 5]); + DLcreate(&rev->AP[i + 2], lens[i + 5] + 2); + DLsetdelay(&rev->AP[i + 2], lens[i + 5]); rev->lpLastout[i] = 0.f; } @@ -74,11 +74,32 @@ bool ReverbHICreate(_SND_REVHI_WORK* rev, f32 coloration, f32 time, f32 mix, f32 return TRUE; } -void DoCrossTalk() {} -void HandleReverb_0() {} +static void DoCrossTalk(s32* a, s32* b, f32 start, f32 end) {} -void ReverbHICallback() {} +static void HandleReverb(s32*, SND_AUX_REVERBHI* rev, s32) {} + +#pragma dont_inline on +void ReverbHICallback(s32* left, s32* right, s32* surround, SND_AUX_REVERBHI* rev) { + u8 i; + for (i = 0; i < 3; ++i) { + switch (i) { + case 0: + if (rev->rv.crosstalk != 0.f) { + DoCrossTalk(left, right, 0.5f * rev->rv.crosstalk, 1.f - (0.5f * rev->rv.crosstalk)); + } + HandleReverb(left, rev, 0); + break; + case 1: + HandleReverb(right, rev, 1); + break; + case 2: + HandleReverb(surround, rev, 2); + break; + } + } +} +#pragma dont_inline reset void ReverbHIFree(_SND_REVHI_WORK* rv) { u8 i; diff --git a/src/musyx/reverb_fx.c b/src/musyx/reverb_fx.c index 118d93b9..2e8eaac7 100644 --- a/src/musyx/reverb_fx.c +++ b/src/musyx/reverb_fx.c @@ -15,13 +15,16 @@ extern bool ReverbHICreate(_SND_REVHI_WORK* rev, f32 coloration, f32 time, f32 mix, f32 damping, f32 preDelay, f32 crosstalk); extern void ReverbHIFree(_SND_REVHI_WORK* rev); +extern void ReverbHIModify(_SND_REVHI_WORK* rev, f32 coloration, f32 time, f32 mix, f32 damping, + f32 preDelay, f32 crosstalk); +extern void ReverbHICallback(s32* left, s32* right, s32* surround, SND_AUX_REVERBHI* rev); void sndAuxCallbackReverbHI(u8 reason, SND_AUX_INFO* info, void* user) { switch (reason) { case SND_AUX_REASON_BUFFERUPDATE: if (((SND_AUX_REVERBHI*)user)->tempDisableFX == 0) { ReverbHICallback(info->data.bufferUpdate.left, info->data.bufferUpdate.right, - info->data.bufferUpdate.surround, user); + info->data.bufferUpdate.surround, (SND_AUX_REVERBHI*)user); } case SND_AUX_REASON_PARAMETERUPDATE: break; @@ -31,8 +34,16 @@ void sndAuxCallbackReverbHI(u8 reason, SND_AUX_INFO* info, void* user) { } } +bool sndAuxCallbackUpdateSettingsReverbHI(SND_AUX_REVERBHI* rev) { + rev->tempDisableFX = TRUE; + ReverbHIModify(&rev->rv, rev->coloration, rev->time, rev->mix, rev->damping, rev->preDelay, + rev->crosstalk); + rev->tempDisableFX = FALSE; + return TRUE; +} + bool sndAuxCallbackPrepareReverbHI(SND_AUX_REVERBHI* rev) { - rev->tempDisableFX = 0; + rev->tempDisableFX = FALSE; return ReverbHICreate(&rev->rv, rev->coloration, rev->time, rev->mix, rev->damping, rev->preDelay, rev->crosstalk); } @@ -41,8 +52,3 @@ bool sndAuxCallbackShutdownReverbHI(SND_AUX_REVERBHI* rev) { ReverbHIFree(&rev->rv); return TRUE; } - -bool sndAuxCallbackUpdateSettingsReverbHI(SND_AUX_REVERBHI* rev) { - /* not in MP */ - return FALSE; -} diff --git a/src/musyx/snd_init.c b/src/musyx/snd_init.c index 76a67a8d..9f83801c 100644 --- a/src/musyx/snd_init.c +++ b/src/musyx/snd_init.c @@ -1,11 +1,6 @@ #include "musyx/musyx_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* TODO: Move these to a more approprate location */ - +//#define _DEBUG +#include "musyx/assert.h" s32 DoInit(u32 rate, u32 aramSize, u8 voices, u32 flags) { dataInitStack(); @@ -54,6 +49,9 @@ void sndQuit() { sndActive = 0; } -#ifdef __cplusplus +void sndSetMaxVoices(u8 music, u8 sfx) { + ASSERT_MSG(music > synthInfo.voices, "Music voices are above maximum voice number."); + ASSERT_MSG(sfx > synthInfo.voices, "Sfx voices are above maximum voice number."); + synthInfo.music = music; + synthInfo.sfx = sfx; } -#endif diff --git a/src/musyx/snd_math.c b/src/musyx/snd_math.c index f31c94d3..7ac63567 100644 --- a/src/musyx/snd_math.c +++ b/src/musyx/snd_math.c @@ -21,4 +21,166 @@ void salCrossProduct(SND_FVECTOR* out, const SND_FVECTOR* a, const SND_FVECTOR* out->z = (a->x * b->y) - (a->y * b->x); } -void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in) { out->t[0] = 1.f; } +#if NONMATCHING +void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in) { + float fVar1; + float fVar2; + float fVar3; + float fVar4; + + fVar1 = in->m[1][1] * in->m[2][2] - in->m[2][1] * in->m[1][2]; + fVar4 = -(in->m[1][0] * in->m[2][2] - in->m[2][0] * in->m[1][2]); + fVar2 = in->m[1][0] * in->m[2][1] - in->m[2][0] * in->m[1][1]; + fVar3 = 1.f / (in->m[0][2] * fVar2 + in->m[0][0] * fVar1 + in->m[0][1] * fVar4); + out->m[0][0] = fVar3 * fVar1; + out->m[1][0] = fVar3 * fVar4; + out->m[2][0] = fVar3 * fVar2; + out->m[0][1] = -fVar3 * (in->m[0][1] * in->m[2][2] - in->m[2][1] * in->m[0][2]); + out->m[1][1] = fVar3 * (in->m[0][0] * in->m[2][2] - in->m[2][0] * in->m[0][2]); + out->m[2][1] = -fVar3 * (in->m[0][0] * in->m[2][1] - in->m[2][0] * in->m[0][1]); + out->m[0][2] = fVar3 * (in->m[0][1] * in->m[1][2] - in->m[1][1] * in->m[0][2]); + out->m[1][2] = -fVar3 * (in->m[0][0] * in->m[1][2] - in->m[1][0] * in->m[0][2]); + out->m[2][2] = fVar3 * (in->m[0][0] * in->m[1][1] - in->m[1][0] * in->m[0][1]); + out->t[0] = (-in->t[0] * out->m[0][0] - in->t[1] * out->m[0][1]) - in->t[2] * out->m[0][2]; + out->t[1] = (-in->t[0] * out->m[1][0] - in->t[1] * out->m[1][1]) - in->t[2] * out->m[1][2]; + out->t[2] = (-in->t[0] * out->m[2][0] - in->t[1] * out->m[2][1]) - in->t[2] * out->m[2][2]; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +const float one = 1.f; +asm void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in) { + nofralloc + lfs f5, 0x20(r4) + lfs f10, 0xc(r4) + lfs f0, 0x14(r4) + lfs f6, 0x1c(r4) + fmuls f3, f10, f5 + lfs f9, 0x18(r4) + lfs f8, 0x10(r4) + fmuls f4, f6, f0 + fmuls f2, f9, f0 + lfs f1, 0(r4) + fmuls f7, f8, f5 + lfs f0, 4(r4) + fmuls f5, f10, f6 + fsubs f6, f3, f2 + fsubs f7, f7, f4 + lfs f2, 8(r4) + fmuls f4, f9, f8 + lfs f3, one + fneg f6, f6 + fmuls f1, f1, f7 + fsubs f4, f5, f4 + fmuls f0, f0, f6 + fmuls f2, f2, f4 + fadds f0, f1, f0 + fadds f0, f2, f0 + fdivs f1, f3, f0 + fmuls f0, f1, f7 + fmuls f3, f1, f6 + fmuls f2, f1, f4 + stfs f0, 0(r3) + fneg f0, f1 + stfs f3, 0xc(r3) + stfs f2, 0x18(r3) + lfs f5, 4(r4) + lfs f4, 0x20(r4) + lfs f3, 0x1c(r4) + lfs f2, 8(r4) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fsubs f2, f4, f2 + fmuls f2, f0, f2 + stfs f2, 4(r3) + lfs f5, 0(r4) + lfs f4, 0x20(r4) + lfs f3, 0x18(r4) + lfs f2, 8(r4) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fsubs f2, f4, f2 + fmuls f2, f1, f2 + stfs f2, 0x10(r3) + lfs f5, 0(r4) + lfs f4, 0x1c(r4) + lfs f3, 0x18(r4) + lfs f2, 4(r4) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fsubs f2, f4, f2 + fmuls f2, f0, f2 + stfs f2, 0x1c(r3) + lfs f5, 4(r4) + lfs f4, 0x14(r4) + lfs f3, 0x10(r4) + lfs f2, 8(r4) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fsubs f2, f4, f2 + fmuls f2, f1, f2 + stfs f2, 8(r3) + lfs f5, 0(r4) + lfs f4, 0x14(r4) + lfs f3, 0xc(r4) + lfs f2, 8(r4) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fsubs f2, f4, f2 + fmuls f0, f0, f2 + stfs f0, 0x14(r3) + lfs f4, 0(r4) + lfs f3, 0x10(r4) + lfs f2, 0xc(r4) + lfs f0, 4(r4) + fmuls f3, f4, f3 + fmuls f0, f2, f0 + fsubs f0, f3, f0 + fmuls f0, f1, f0 + stfs f0, 0x20(r3) + lfs f0, 0x24(r4) + lfs f4, 0(r3) + fneg f5, f0 + lfs f3, 0x28(r4) + lfs f2, 4(r3) + lfs f1, 0x2c(r4) + lfs f0, 8(r3) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fmuls f0, f1, f0 + fsubs f1, f4, f2 + fsubs f0, f1, f0 + stfs f0, 0x24(r3) + lfs f0, 0x24(r4) + lfs f4, 0xc(r3) + fneg f5, f0 + lfs f3, 0x28(r4) + lfs f2, 0x10(r3) + lfs f1, 0x2c(r4) + lfs f0, 0x14(r3) + fmuls f4, f5, f4 + fmuls f2, f3, f2 + fmuls f0, f1, f0 + fsubs f1, f4, f2 + fsubs f0, f1, f0 + stfs f0, 0x28(r3) + lfs f1, 0x24(r4) + lfs f0, 0x18(r3) + fneg f4, f1 + lfs f3, 0x28(r4) + lfs f2, 0x1c(r3) + lfs f1, 0x2c(r4) + fmuls f4, f4, f0 + lfs f0, 0x20(r3) + fmuls f2, f3, f2 + fmuls f0, f1, f0 + fsubs f1, f4, f2 + fsubs f0, f1, f0 + stfs f0, 0x2c(r3) + blr +} +#pragma pop +/* clang-format on */ +#endif diff --git a/src/musyx/snd_midictrl.c b/src/musyx/snd_midictrl.c new file mode 100644 index 00000000..fdc904a3 --- /dev/null +++ b/src/musyx/snd_midictrl.c @@ -0,0 +1,50 @@ +#include "musyx/assert.h" +#include "musyx/musyx_priv.h" +#define SYNTH_FX_MIDISET 0xFF + +u32 inpGlobalMIDIDirtyFlags[8][16]; +s32 midi_ctrl; + +inline bool GetGlobalFlagSet(u8 chan, u8 midiSet, s32 flag) { + return (flag & inpGlobalMIDIDirtyFlags[midiSet][chan]) != 0; +} + +void inpResetGlobalMIDIDirtyFlags() { + u32 i, j; + for (i = 0; i < 8; ++i) { + for (j = 0; j < 16; ++j) { + inpGlobalMIDIDirtyFlags[i][j] = 0xFF; + } + } +} + +bool inpResetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag) { + // ASSERT(midiSet!=SYNTH_FX_MIDISET); + bool ret = GetGlobalFlagSet(chan, midiSet, flag); + if (ret) { + inpGlobalMIDIDirtyFlags[midiSet][chan] &= ~flag; + } + return ret; +} + +void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag) { + // ASSERT(midiSet!=SYNTH_FX_MIDISET); + inpGlobalMIDIDirtyFlags[midiSet][chan] |= flag; +} + +void inpSetRPNHi(u8 a, u8 b, u8 c) { + +} + +void inpSetRPNLo(u8 a, u8 b, u8 c) { + +} + +void inpSetRPNDec(u8 a, u8 b) { + +} + + +void inpSetRPNInc(u8 a, u8 b) { + +}