diff --git a/.vscode/settings.json b/.vscode/settings.json index 087d9bfc..77f718f9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -66,7 +66,20 @@ "i5.h": "c", "ast_warp_zone.h": "c", "sf64audio_provisional.h": "c", - "fox_enmy_assets.h": "c" + "fox_enmy_assets.h": "c", + "audiothread_cmd.h": "c", + "span": "c", + "string_span": "c", + "array": "c", + "bitset": "c", + "string_view": "c", + "initializer_list": "c", + "regex": "c", + "utility": "c", + "valarray": "c", + "util": "c", + "variant": "c", + "chrono": "c" }, "C_Cpp_Runner.msvcBatchPath": "" } \ No newline at end of file diff --git a/Makefile b/Makefile index 7c5a893a..23c3a888 100644 --- a/Makefile +++ b/Makefile @@ -262,7 +262,7 @@ build/src/main/audio_playback.o: OPTFLAGS := -O2 -g0 build/src/main/audio_load.o: OPTFLAGS := -O2 -g0 build/src/main/audio_general.o: OPTFLAGS := -O2 -g0 build/src/main/audio_heap.o: OPTFLAGS := -O2 -g0 -build/src/main/audio_thread.o: OPTFLAGS := -O1 -g0 +build/src/main/audio_thread.o: OPTFLAGS := -O2 -g0 build/src/main/sys_sprintf.o: OPTFLAGS := -O2 -g0 build/src/main/sys_math64.o: OPTFLAGS := -O2 -g0 diff --git a/include/PR/abi.h b/include/PR/abi.h index 2102bc87..f218a347 100644 --- a/include/PR/abi.h +++ b/include/PR/abi.h @@ -1,247 +1,223 @@ -#ifndef _ABI_H_ -#define _ABI_H_ - -/************************************************************************** - * * - * Copyright (C) 1994, Silicon Graphics, Inc. * - * * - * These coded instructions, statements, and computer programs contain * - * unpublished proprietary information of Silicon Graphics, Inc., and * - * are protected by Federal copyright law. They may not be disclosed * - * to third parties or copied or duplicated in any form, in whole or * - * in part, without the prior written consent of Silicon Graphics, Inc. * - * * - **************************************************************************/ - -/************************************************************************** - * - * $Revision: 1.32 $ - * $Date: 1997/02/11 08:16:37 $ - * $Source: /disk6/Master/cvsmdev2/PR/include/abi.h,v $ - * - **************************************************************************/ - -/* - * Header file for the Audio Binary Interface. - * This is included in the Media Binary Interface file - * mbi.h. - * - * This file follows the framework used for graphics. - * - */ +#ifndef ULTRA64_ABI_H +#define ULTRA64_ABI_H /* Audio commands: */ -#define A_SPNOOP 0 -#define A_ADPCM 1 -#define A_CLEARBUFF 2 -#define A_ENVMIXER 3 -#define A_LOADBUFF 4 -#define A_RESAMPLE 5 -#define A_SAVEBUFF 6 -#define A_SEGMENT 7 -#define A_SETBUFF 8 -#define A_SETVOL 9 -#define A_DMEMMOVE 10 -#define A_LOADADPCM 11 -#define A_MIXER 12 -#define A_INTERLEAVE 13 -#define A_POLEF 14 -#define A_SETLOOP 15 +#define A_SPNOOP 0 +#define A_ADPCM 1 +#define A_CLEARBUFF 2 +#define A_UNK3 3 +#define A_ADDMIXER 4 +#define A_RESAMPLE 5 +#define A_RESAMPLE_ZOH 6 +#define A_FILTER 7 +#define A_SETBUFF 8 +// #define A_DUPLICATE 9 +#define A_DMEMMOVE 10 +#define A_LOADADPCM 11 +#define A_MIXER 12 +#define A_INTERLEAVE 13 +// #define A_HILOGAIN 14 +#define A_SETLOOP 15 +#define A_INTERL 17 +#define A_ENVSETUP1 18 +#define A_ENVMIXER 19 +#define A_LOADBUFF 20 +#define A_SAVEBUFF 21 +#define A_ENVSETUP2 22 +#define A_S8DEC 23 +#define A_HILOGAIN 24 +#define A_UNK19 25 +#define A_DUPLICATE 26 + +#define ACMD_SIZE 32 -#define ACMD_SIZE 32 /* * Audio flags */ - -#define A_INIT 0x01 -#define A_CONTINUE 0x00 -#define A_LOOP 0x02 -#define A_OUT 0x02 -#define A_LEFT 0x02 -#define A_RIGHT 0x00 -#define A_VOL 0x04 -#define A_RATE 0x00 -#define A_AUX 0x08 -#define A_NOAUX 0x00 -#define A_MAIN 0x00 -#define A_MIX 0x10 - -/* - * BEGIN C-specific section: (typedef's) - */ -#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) +#define A_INIT 0x01 +#define A_CONTINUE 0x00 +#define A_LOOP 0x02 +#define A_OUT 0x02 +#define A_LEFT 0x02 +#define A_RIGHT 0x00 +#define A_VOL 0x04 +#define A_RATE 0x00 +#define A_AUX 0x08 +#define A_NOAUX 0x00 +#define A_MAIN 0x00 +#define A_MIX 0x10 /* * Data Structures. */ typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int gain:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 gain : 16; + u32 addr; } Aadpcm; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int gain:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 gain : 16; + u32 addr; } Apolef; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int pad1:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 pad1 : 16; + u32 addr; } Aenvelope; typedef struct { - unsigned int cmd:8; - unsigned int pad1:8; - unsigned int dmem:16; - unsigned int pad2:16; - unsigned int count:16; + u32 cmd : 8; + u32 pad1 : 8; + u32 dmem : 16; + u32 pad2 : 16; + u32 count : 16; } Aclearbuff; typedef struct { - unsigned int cmd:8; - unsigned int pad1:8; - unsigned int pad2:16; - unsigned int inL:16; - unsigned int inR:16; + u32 cmd : 8; + u32 pad1 : 8; + u32 pad2 : 16; + u32 inL : 16; + u32 inR : 16; } Ainterleave; typedef struct { - unsigned int cmd:8; - unsigned int pad1:24; - unsigned int addr; + u32 cmd : 8; + u32 pad1 : 24; + u32 addr; } Aloadbuff; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int pad1:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 pad1 : 16; + u32 addr; } Aenvmixer; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int gain:16; - unsigned int dmemi:16; - unsigned int dmemo:16; + u32 cmd : 8; + u32 flags : 8; + u32 gain : 16; + u32 dmemi : 16; + u32 dmemo : 16; } Amixer; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int dmem2:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 dmem2 : 16; + u32 addr; } Apan; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int pitch:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 pitch : 16; + u32 addr; } Aresample; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int pad1:16; - unsigned int addr; + u32 cmd : 8; + u32 flags : 8; + u32 pad1 : 16; + u32 addr; } Areverb; typedef struct { - unsigned int cmd:8; - unsigned int pad1:24; - unsigned int addr; + u32 cmd : 8; + u32 pad1 : 24; + u32 addr; } Asavebuff; typedef struct { - unsigned int cmd:8; - unsigned int pad1:24; - unsigned int pad2:2; - unsigned int number:4; - unsigned int base:24; + u32 cmd : 8; + u32 pad1 : 24; + u32 pad2 : 2; + u32 number : 4; + u32 base : 24; } Asegment; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int dmemin:16; - unsigned int dmemout:16; - unsigned int count:16; + u32 cmd : 8; + u32 flags : 8; + u32 dmemin : 16; + u32 dmemout : 16; + u32 count : 16; } Asetbuff; typedef struct { - unsigned int cmd:8; - unsigned int flags:8; - unsigned int vol:16; - unsigned int voltgt:16; - unsigned int volrate:16; + u32 cmd : 8; + u32 flags : 8; + u32 vol : 16; + u32 voltgt : 16; + u32 volrate : 16; } Asetvol; typedef struct { - unsigned int cmd:8; - unsigned int pad1:8; - unsigned int dmemin:16; - unsigned int dmemout:16; - unsigned int count:16; + u32 cmd : 8; + u32 pad1 : 8; + u32 dmemin : 16; + u32 dmemout : 16; + u32 count : 16; } Admemmove; typedef struct { - unsigned int cmd:8; - unsigned int pad1:8; - unsigned int count:16; - unsigned int addr; + u32 cmd : 8; + u32 pad1 : 8; + u32 count : 16; + u32 addr; } Aloadadpcm; typedef struct { - unsigned int cmd:8; - unsigned int pad1:8; - unsigned int pad2:16; - unsigned int addr; + u32 cmd : 8; + u32 pad1 : 8; + u32 pad2 : 16; + u32 addr; } Asetloop; - + /* * Generic Acmd Packet */ typedef struct { - unsigned int w0; - unsigned int w1; + u32 w0; + u32 w1; } Awords; typedef union { - Awords words; - Aadpcm adpcm; - Apolef polef; - Aclearbuff clearbuff; - Aenvelope envelope; - Ainterleave interleave; - Aloadbuff loadbuff; - Aenvmixer envmixer; - Aresample resample; - Areverb reverb; - Asavebuff savebuff; - Asegment segment; - Asetbuff setbuff; - Asetvol setvol; - Admemmove dmemmove; - Aloadadpcm loadadpcm; - Amixer mixer; - Asetloop setloop; - long long int force_union_align; /* dummy, force alignment */ + Awords words; + Aadpcm adpcm; + Apolef polef; + Aclearbuff clearbuff; + Aenvelope envelope; + Ainterleave interleave; + Aloadbuff loadbuff; + Aenvmixer envmixer; + Aresample resample; + Areverb reverb; + Asavebuff savebuff; + Asegment segment; + Asetbuff setbuff; + Asetvol setvol; + Admemmove dmemmove; + Aloadadpcm loadadpcm; + Amixer mixer; + Asetloop setloop; + long long int force_union_align; /* dummy, force alignment */ } Acmd; /* * ADPCM State */ -#define ADPCMVSIZE 8 -#define ADPCMFSIZE 16 +#define ADPCMVSIZE 8 +#define ADPCMFSIZE 16 typedef short ADPCM_STATE[ADPCMFSIZE]; /* @@ -258,7 +234,7 @@ typedef short RESAMPLE_STATE[16]; * Resampler constants */ #define UNITY_PITCH 0x8000 -#define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */ +#define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */ /* * Enveloper/Mixer state @@ -269,142 +245,277 @@ typedef short ENVMIX_STATE[40]; * Macros to assemble the audio command list */ -#define aADPCMdec(pkt, f, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \ - _a->words.w1 = (unsigned int)(s); \ +#define aADPCMdec(pkt, f, s) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \ + _a->words.w1 = (u32)(s); \ } -#define aPoleFilter(pkt, f, g, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \ - _SHIFTL(g, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ +#define aPoleFilter(pkt, f, g, s) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(g, 0, 16)); \ + _a->words.w1 = (u32)(s); \ } -#define aClearBuffer(pkt, d, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \ - _a->words.w1 = (unsigned int)(c); \ +#define aHiLoGain(pkt, gain, count, dmem, a4) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_HILOGAIN, 24, 8) | \ + _SHIFTL(gain, 16, 8) | _SHIFTL(count, 0, 16)); \ + _a->words.w1 = _SHIFTL(dmem, 16, 16) | _SHIFTL(a4, 0, 16); \ } -#define aEnvMixer(pkt, f, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \ - _a->words.w1 = (unsigned int)(s); \ +#define aUnkCmd3(pkt, a1, a2, a3) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_UNK3, 24, 8) | _SHIFTL(a3, 0, 16); \ + _a->words.w1 = _SHIFTL(a1, 16, 16) | _SHIFTL(a2, 0, 16); \ } -#define aInterleave(pkt, l, r) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8); \ - _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \ +#define aUnkCmd19(pkt, a1, a2, a3, a4) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_UNK19, 24, 8) | _SHIFTL(a1, 16, 8) | \ + _SHIFTL(a2, 0, 16)); \ + _a->words.w1 = _SHIFTL(a3, 16, 16) | _SHIFTL(a4, 0, 16); \ } -#define aLoadBuffer(pkt, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \ - _a->words.w1 = (unsigned int)(s); \ +#define aS8Dec(pkt, a1, a2) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_S8DEC, 24, 8) | _SHIFTL(a1, 16, 8); \ + _a->words.w1 = (u32)(a2); \ } -#define aMix(pkt, f, g, i, o) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \ - _SHIFTL(g, 0, 16)); \ - _a->words.w1 = _SHIFTL(i,16, 16) | _SHIFTL(o, 0, 16); \ +/* + * Clears DMEM by writing zeros. + * + * @param pkt pointer to an Acmd buffer + * @param dmem DMEM address to clear + * @param size number of bytes to clear (rounded up to the next multiple of 16) + */ +#define aClearBuffer(pkt, dmem, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(dmem, 0, 24); \ + _a->words.w1 = (uintptr_t)(size); \ + } + +#define aEnvMixer(pkt, dmemi, count, swapLR, x0, x1, x2, x3, m) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(dmemi >> 4, 16, 8) | \ + _SHIFTL(count, 8, 8) | _SHIFTL(swapLR, 4, 1) | \ + _SHIFTL(x0, 3, 1) | _SHIFTL(x1, 2, 1) | \ + _SHIFTL(x2, 1, 1) | _SHIFTL(x3, 0, 1)); \ + _a->words.w1 = (u32)(m); \ } -#define aPan(pkt, f, d, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \ - _SHIFTL(d, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ +#define aInterleave(pkt, o, l, r, c) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_INTERLEAVE, 24, 8) | \ + _SHIFTL(c >> 4, 16, 8) | _SHIFTL(o, 0, 16)); \ + _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \ } -#define aResample(pkt, f, p, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) |\ - _SHIFTL(p, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ +#define aInterl(pkt, dmemi, dmemo, count) \ +{ \ + Acmd *_a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_INTERL, 24, 8) | _SHIFTL(count, 0, 16)); \ + _a->words.w1 = _SHIFTL(dmemi, 16, 16) | _SHIFTL(dmemo, 0, 16); \ } -#define aSaveBuffer(pkt, s) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \ - _a->words.w1 = (unsigned int)(s); \ +/* + * Loads a buffer to DMEM from any physical source address, KSEG0, or KSEG1 + * + * @param pkt pointer to an Acmd buffer + * @param addrSrc Any physical source address, KSEG0, or KSEG1 + * @param dmemDest DMEM destination address + * @param size number of bytes to copy (rounded down to the next multiple of 16) + */ +#define aLoadBuffer(pkt, addrSrc, dmemDest, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_LOADBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemDest, 0, 16)); \ + _a->words.w1 = (uintptr_t)(addrSrc); \ + } + +#define aMix(pkt, f, g, i, o) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(g, 0, 16)); \ + _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \ } -#define aSegment(pkt, s, b) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \ - _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \ +#define aPan(pkt, f, d, s) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(d, 0, 16)); \ + _a->words.w1 = (u32)(s); \ } -#define aSetBuffer(pkt, f, i, o, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \ - _SHIFTL(i, 0, 16)); \ - _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ +#define aResample(pkt, f, p, s) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | \ + _SHIFTL(f, 16, 8) | _SHIFTL(p, 0, 16)); \ + _a->words.w1 = (u32)(s); \ } -#define aSetVolume(pkt, f, v, t, r) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \ - _SHIFTL(v, 0, 16)); \ - _a->words.w1 = _SHIFTL(t, 16, 16) | _SHIFTL(r, 0, 16); \ +/* + * Stores a buffer from DMEM to any physical source address, KSEG0, or KSEG1 + * + * @param pkt pointer to an Acmd buffer + * @param dmemSrc DMEM source address + * @param addrDest Any physical source address, KSEG0, or KSEG1 + * @param size number of bytes to copy (rounded down to the next multiple of 16) + */ +#define aSaveBuffer(pkt, dmemSrc, addrDest, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SAVEBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \ + _a->words.w1 = (uintptr_t)(addrDest); \ + } + +#define aSegment(pkt, s, b) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \ + _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \ } -#define aSetLoop(pkt, a) \ +#define aSetBuffer(pkt, f, i, o, c) \ { \ Acmd *_a = (Acmd *)pkt; \ - _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \ - _a->words.w1 = (unsigned int)(a); \ -} - -#define aDMEMMove(pkt, i, o, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \ - _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ + \ + _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(i, 0, 16)); \ + _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ } -#define aLoadADPCM(pkt, c, d) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \ - _a->words.w1 = (unsigned int) d; \ +#define aSetVolume(pkt, f, v, t, r) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \ + _SHIFTL(v, 0, 16)); \ + _a->words.w1 = _SHIFTL(r, 0, 16) | _SHIFTL(t, 16, 16); \ } -#endif /* _LANGUAGE_C */ +#define aSetVolume32(pkt, f, v, tr) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \ + _SHIFTL(v, 0, 16)); \ + _a->words.w1 = (u32)(tr); \ +} -#endif /* !_ABI_H_ */ +#define aSetLoop(pkt, a) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \ + _a->words.w1 = (u32)(a); \ +} +#define aDMEMMove(pkt, i, o, c) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \ + _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ +} +#define aLoadADPCM(pkt, c, d) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \ + _a->words.w1 = (u32)d; \ +} +#define aEnvSetup1(pkt, a, b, c, d) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_ENVSETUP1, 24, 8) | \ + _SHIFTL(a, 16, 8) | _SHIFTL(b, 0, 16)); \ + _a->words.w1 = _SHIFTL(c, 16, 16) | _SHIFTL(d, 0, 16); \ +} + +#define aEnvSetup2(pkt, volLeft, volRight) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); \ + _a->words.w1 = (_SHIFTL(volLeft, 16, 16) | \ + _SHIFTL(volRight, 0, 16)); \ +} + +#define aFilter(pkt, f, countOrBuf, addr) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_FILTER, 24, 8) | _SHIFTL(f, 16, 8) | \ + _SHIFTL(countOrBuf, 0, 16)); \ + _a->words.w1 = (u32)(addr); \ +} + +/* + * Duplicates 128 bytes of data a specified number of times. + * + * @param pkt pointer to an Acmd buffer + * @param numCopies number of times to duplicate 128 bytes from src + * @param dmemSrc DMEM source address + * @param dmemDest DMEM destination address for the duplicates, size 128 * numCopies + */ +#define aDuplicate(pkt, numCopies, dmemSrc, dmemDest) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | _SHIFTL(numCopies, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \ + _a->words.w1 = _SHIFTL(dmemDest, 16, 16) | _SHIFTL(0x80, 0, 16); \ + } + +#define aAddMixer(pkt, count, dmemi, dmemo, a4) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_ADDMIXER, 24, 8) | \ + _SHIFTL(count >> 4, 16, 8) | _SHIFTL(a4, 0, 16)); \ + _a->words.w1 = _SHIFTL(dmemi, 16, 16) | _SHIFTL(dmemo, 0, 16); \ +} + +#define aResampleZoh(pkt, pitch, pitchAccu) \ +{ \ + Acmd *_a = (Acmd *)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_RESAMPLE_ZOH, 24, 8) | \ + _SHIFTL(pitch, 0, 16)); \ + _a->words.w1 = _SHIFTL(pitchAccu, 0, 16); \ +} + +#endif /* ULTRA64_ABI_H */ diff --git a/include/audiothread_cmd.h b/include/audiothread_cmd.h index 123af3aa..2a9a013c 100644 --- a/include/audiothread_cmd.h +++ b/include/audiothread_cmd.h @@ -1,11 +1,9 @@ #ifndef AUDIOTHREAD_CMD_H #define AUDIOTHREAD_CMD_H - -void AudioThread_QueueCmd(u32, void**); -void AudioThread_QueueCmdF32(u32, f32); -void AudioThread_QueueCmdS32(u32, u32); -void AudioThread_QueueCmdS8(u32, s8); +void AudioThread_QueueCmdF32(u32 opArgs, f32 val); +void AudioThread_QueueCmdS32(u32 opArgs, u32 val); +void AudioThread_QueueCmdS8(u32 opArgs, s8 val); /** * Audio thread commands to safely transfer information/requests/data @@ -247,8 +245,8 @@ typedef enum { * @param ioPort the index of the array to store the input-output value * @param ioData (s8) the value that's written to the input-output array */ -#define AUDIOCMD_SEQPLAYER_SET_IO(seqPlayerIndex, unk, ioPort, ioData) \ - AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_IO, seqPlayerIndex, unk, ioPort), ioData) +#define AUDIOCMD_SEQPLAYER_SET_IO(seqPlayerIndex, unk, ioData) \ + AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_IO, seqPlayerIndex, unk, 0), ioData) /** * Set the tempo (bpm) of a sequence on a given seqPlayer @@ -344,8 +342,8 @@ typedef enum { * @param seqId the id of the sequence to play, see `SeqId` * @param fadeInTimer (s32) number of ticks to fade in the sequence to the requested volume */ -#define AUDIOCMD_GLOBAL_INIT_SEQPLAYER(seqPlayerIndex, seqId, fadeInTimer) \ - AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER, seqPlayerIndex, seqId, 0), fadeInTimer) +#define AUDIOCMD_GLOBAL_INIT_SEQPLAYER(seqPlayerIndex, seqId, arg2, fadeInTimer) \ + AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER, seqPlayerIndex, seqId, arg2), fadeInTimer) /** * Disable a sequence player @@ -456,8 +454,8 @@ typedef enum { * @param sampleBankId the id of the samplebank to load * @param retData return data from `externalLoadQueue` */ -#define AUDIOCMD_GLOBAL_ASYNC_LOAD_SAMPLE_BANK(sampleBankId, retData) \ - AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK, sampleBankId, 0, retData), 0) +#define AUDIOCMD_GLOBAL_ASYNC_LOAD_SAMPLE_BANK(sampleBankId, nChunks, retData) \ + AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK, sampleBankId, nChunks, retData), 0) /** * Asynchronously load a font @@ -465,8 +463,8 @@ typedef enum { * @param fontId the id of the soundfont to load * @param retData return data from `externalLoadQueue` */ -#define AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(fontId, unk, retData) \ - AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT, fontId, unk, retData), 0) +#define AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(fontId, nChunks, retData) \ + AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT, fontId, nChunks, retData), 0) /** * Discard sequence fonts diff --git a/include/sf64audio_external.h b/include/sf64audio_external.h index d6e675ee..5b4f134c 100644 --- a/include/sf64audio_external.h +++ b/include/sf64audio_external.h @@ -134,8 +134,8 @@ void AudioLoad_Init(void); void func_80016A50(void); void Audio_InitSounds(void); void Audio_Update(void); -SPTask* func_8001DF50(void); -void func_8001EE00(void); +SPTask* AudioThread_CreateTask(void); +void AudioThread_PreNMIReset(void); #endif diff --git a/include/sf64audio_provisional.h b/include/sf64audio_provisional.h index 9613fe18..482fbf76 100644 --- a/include/sf64audio_provisional.h +++ b/include/sf64audio_provisional.h @@ -262,7 +262,7 @@ typedef struct { /* 0x005 */ s8 unk_05; /* 0x006 */ u16 windowSize; /* 0x008 */ u16 unk_08; - /* 0x00A */ s16 unk_0A; + /* 0x00A */ u16 unk_0A; /* 0x00C */ u16 decayRatio; // determines how much reverb persists /* 0x00E */ u16 unk_0E; /* 0x010 */ s32 nextRingBufPos; @@ -302,7 +302,7 @@ typedef struct { /* 0x004 */ u8 seqId; /* 0x005 */ u8 defaultFont; /* 0x006 */ u8 unk_06[1]; - /* 0x007 */ s8 playerIdx; + /* 0x007 */ s8 unk_07[1]; // indexed like an array, but that can't be /* 0x008 */ u16 tempo; // seqTicks per minute /* 0x00A */ u16 tempoAcc; // tempo accumulation, used in a discretized algorithm to apply tempo. /* 0x00C */ u16 tempoChange; // Used to adjust the tempo without altering the base tempo. @@ -318,14 +318,14 @@ typedef struct { /* 0x02C */ f32 fadeVolumeMod; /* 0x030 */ f32 appliedFadeVolume; // /* 0x034 */ f32 bend; - /* 0x038 */ struct SequenceChannel* channels[16]; - /* 0x078 */ SeqScriptState scriptState; - /* 0x094 */ u8* shortNoteVelocityTable; - /* 0x098 */ u8* shortNoteGateTimeTable; - /* 0x09C */ NotePool notePool; - /* 0x0DC */ s32 skipTicks; - /* 0x0E0 */ u32 scriptCounter; - /* 0x0E4 */ char + /* 0x034 */ struct SequenceChannel* channels[16]; + /* 0x074 */ SeqScriptState scriptState; + /* 0x090 */ u8* shortNoteVelocityTable; + /* 0x094 */ u8* shortNoteGateTimeTable; + /* 0x098 */ NotePool notePool; + /* 0x0D8 */ s32 skipTicks; + /* 0x0DC */ u32 scriptCounter; + /* 0x0E0 */ char padE4[0x6C]; // unused struct members for sequence/sound font dma management, according to sm64 decomp } SequencePlayer; // size = 0x14C @@ -476,14 +476,28 @@ typedef struct SequenceLayer { /* 0x7C */ char pad7C[4]; } SequenceLayer; //size = 0x80 +typedef struct UnkStruct_800097A8 { + /* 0x00 */ s16* unk_0; + /* 0x04 */ s32 unk_4; + /* 0x08 */ s32 unk_8; + /* 0x0C */ s16* unk_C; + /* 0x10 */ char pad10[4]; + /* 0x14 */ struct SampleDma* unk_14; + /* 0x18 */ s16 unk18; + /* 0x1A */ char pad1A[6]; +} UnkStruct_800097A8; /* size = 0x20 */ + typedef struct { /* 0x000 */ s16 adpcmdecState[16]; /* 0x020 */ s16 finalResampleState[16]; - /* 0x040 */ s16 mixEnvelopeState[32]; - /* 0x080 */ s16 unusedState[16]; - /* 0x0A0 */ s16 haasEffectDelayState[32]; - /* 0x0E0 */ s16 combFilterState[128]; -} NoteSynthesisBuffers; // size = 0x1E0 + /* 0x040 */ UnkStruct_800097A8 unk_40; + /* 0x060 */ char pad[0x20]; + /* 0x080 */ s16 panSamplesBuffer[0x20]; + // /* 0x040 */ s16 mixEnvelopeState[32]; + // /* 0x080 */ s16 unusedState[16]; + // /* 0x0A0 */ s16 haasEffectDelayState[32]; + // /* 0x0E0 */ s16 combFilterState[128]; +} NoteSynthesisBuffers; // size = 0xC0 typedef struct { /* 0x00 */ u8 restart; @@ -547,13 +561,19 @@ typedef struct { } bitField0; struct { /* 0x01 */ u8 reverbIndex : 3; - /* 0x01 */ u8 bookOffset : 2; + /* 0x01 */ u8 bookOffset : 3; + // /* 0x01 */ u8 isSyntheticWave : 1; /* 0x01 */ u8 isSyntheticWave : 1; /* 0x01 */ u8 hasTwoParts : 1; - /* 0x01 */ u8 useHaasEffect : 1; } bitField1; - /* 0x02 */ u8 pad2[0xA]; - /* 0x0C*/ s16* waveSampleAddr; + /* 0x02 */ u8 unk_02; + /* 0x03 */ u8 unk_03; + /* 0x04 */ u8 unk_04; + /* 0x05 */ u8 unk_05; + /* 0x06 */ u16 unk_06; + /* 0x08 */ u16 unk_08; + /* 0x0A */ u16 unk_0A; + /* 0x0C */ s16* waveSampleAddr; } NoteSubEu; // size = 0x10 typedef struct Note { @@ -781,7 +801,7 @@ typedef struct { /* 0x10 */ AudioTableEntry entries[1]; // (dynamic size) } AudioTable; // size >= 0x20 -typedef struct { +typedef struct SampleDma { /* 0x00 */ u8* ramAddr; /* 0x04 */ u32 devAddr; /* 0x08 */ u16 sizeUnused; @@ -998,6 +1018,19 @@ typedef struct { ((bit10)<<21)|((bit11)<<20)|((bit12)<<19)|((bit13)<<18)) void func_80008780(f32 *, s32, f32 *); +void func_80009A2C(s32 updateIndex, s32 noteIndex); +void func_80009AAC(s32 updateIndex); +Acmd* func_8000A700(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); +Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); +Acmd* func_800098DC(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); +Acmd* func_80009984(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); +Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen); +Acmd* func_80009D78(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex); +Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex); +Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad); +Acmd* func_8000B480(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, u32 resampleFlags); +Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, s32 delaySide, s32 flags); +Acmd* func_8000B98C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, s32 delaySide); void AudioHeap_ResetLoadStatus(void); void AudioHeap_DiscardFont(s32 fontId); @@ -1039,12 +1072,12 @@ void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, u32 arg2, u8* dmaIndexRef, void AudioLoad_InitSampleDmaBuffers(s32 numNotes); void AudioLoad_InitTable(AudioTable* table, u8* romAddr, u16 unkMediumParam); void* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outFontId); -void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1); +void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 flags); s32 AudioLoad_SyncLoadSample(Sample* sample, s32 fontId); s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId); -void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue); -void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue); -void* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts); +void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 nChunks, s32 retData, OSMesgQueue* retQueue); +void AudioLoad_AsyncLoadSeq(s32 seqId, s32 nChunks, s32 retData, OSMesgQueue* retQueue); +u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts); void AudioLoad_DiscardSeqFonts(s32 seqId); s32 AudioLoad_DiscardFont(s32 fontId); void AudioLoad_SyncInitSeqPlayer(s32 playerIdx, s32 seqId, s32 arg2); @@ -1116,19 +1149,20 @@ void func_800132E8(void); void func_800144E4(SequencePlayer*); void func_800145BC(AudioListItem*, AudioListItem*); +void func_8001678C(s32); void func_80016804(s32); void func_800168BC(void); -SPTask* func_8001DF50(void); -void func_8001E920(void); -OSMesg func_8001ECAC(s32 *); -void* func_8001ED14(s32 seqId, u32* outNumFonts); +SPTask* AudioThread_CreateTask(void); +void AudioThread_ScheduleProcessCmds(void); +u32 AudioThread_GetAsyncLoadStatus(u32 *); +u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts); s32 func_8001ED34(void); -void func_8001ED8C(OSMesg); -void func_8001EE00(void); -void func_8001EE3C(void); +void AudioThread_ResetAudioHeap(s32); +void AudioThread_PreNMIReset(void); +void AudioThread_Init(void); @@ -1197,14 +1231,14 @@ extern u16 gSampleBankMedium; -extern s8 gThreadCmdWritePos; -extern s8 gThreadCmdReadPos; +// extern u8 gThreadCmdWritePos; +// extern u8 gThreadCmdReadPos; extern OSMesgQueue* gAudioTaskStartQueue; extern OSMesgQueue* gThreadCmdProcQueue; extern OSMesgQueue* gAudioUnkQueue; extern OSMesgQueue* gAudioResetQueue; extern s32 gMaxAbiCmdCnt; -extern AudioTask* gWaitingAudioTask; +extern SPTask* gWaitingAudioTask; extern s32 D_800C7C70; extern u8 gCurCmdReadPos; extern u8 gThreadCmdQueueFinished; @@ -1344,14 +1378,14 @@ extern volatile s32 gAudioTaskCountQ; extern s32 gCurAudioFrameDmaCount; extern s32 gAudioTaskIndexQ; extern s32 gCurAiBuffIndex; -extern void* gAbiCmdBuffs[2]; -extern Acmd* gCurAiCmdBuffer; -extern AudioTask* gAudioCurTask; -extern AudioTask gAudioRspTasks[2]; +extern Acmd* gAbiCmdBuffs[2]; +extern Acmd* gCurAbiCmdBuffer; +extern SPTask* gAudioCurTask; +extern SPTask gAudioRspTasks[2]; extern f32 gMaxTempoTvTypeFactors; extern s32 gRefreshRate; -extern u16* gAiBuffers[3]; -extern u16 gAiBuffLengths[3]; +extern s16* gAiBuffers[3]; +extern s16 gAiBuffLengths[3]; extern u32 gAudioRandom; extern UNK_TYPE D_80155D88; extern volatile u32 gResetTimer; diff --git a/linker_scripts/us/symbol_addrs_audio.txt b/linker_scripts/us/symbol_addrs_audio.txt index 96d42f8f..55b4a144 100644 --- a/linker_scripts/us/symbol_addrs_audio.txt +++ b/linker_scripts/us/symbol_addrs_audio.txt @@ -198,7 +198,7 @@ gCurAudioFrameDmaCount = 0x80155CAC; gAudioTaskIndexQ = 0x80155CB0; gCurAiBuffIndex = 0x80155CB4; gAbiCmdBuffs = 0x80155CB8;//size:0x8 -gCurAiCmdBuffer = 0x80155CC0; +gCurAbiCmdBuffer = 0x80155CC0; gAudioCurTask = 0x80155CC4; gAudioRspTasks = 0x80155CC8;//size:0xA0 gMaxTempoTvTypeFactors = 0x80155D68; @@ -505,21 +505,21 @@ Audio_Update = 0x8001DECC; -func_8001DF50 = 0x8001DF50; -func_8001E444 = 0x8001E444; -func_8001E720 = 0x8001E720; -func_8001E778 = 0x8001E778; -func_8001E7C8 = 0x8001E7C8; +AudioThread_CreateTask = 0x8001DF50; +AudioThread_ProcessGlobalCmd = 0x8001E444; +AudioThread_SetFadeOutTimer = 0x8001E720; +AudioThread_SetFadeInTimer = 0x8001E778; +AudioThread_InitQueues = 0x8001E7C8; AudioThread_QueueCmd = 0x8001E850; AudioThread_QueueCmdF32 = 0x8001E8A8; AudioThread_QueueCmdS32 = 0x8001E8CC; AudioThread_QueueCmdS8 = 0x8001E8F0; -func_8001E920 = 0x8001E920; -func_8001E998 = 0x8001E998; -func_8001E9AC = 0x8001E9AC; -func_8001ECAC = 0x8001ECAC; -func_8001ED14 = 0x8001ED14; +AudioThread_ScheduleProcessCmds = 0x8001E920; +AudioThread_ResetCmdQueue = 0x8001E998; +AudioThread_ProcessCmds = 0x8001E9AC; +AudioThread_GetAsyncLoadStatus = 0x8001ECAC; +AudioThread_GetFontsForSequence = 0x8001ED14; func_8001ED34 = 0x8001ED34; -func_8001ED8C = 0x8001ED8C; -func_8001EE00 = 0x8001EE00; -func_8001EE3C = 0x8001EE3C; +AudioThread_ResetAudioHeap = 0x8001ED8C; +AudioThread_PreNMIReset = 0x8001EE00; +AudioThread_Init = 0x8001EE3C; diff --git a/src/main/audio_context.c b/src/main/audio_context.c index f1e30182..41a9590f 100644 --- a/src/main/audio_context.c +++ b/src/main/audio_context.c @@ -90,14 +90,14 @@ volatile s32 gAudioTaskCountQ; s32 gCurAudioFrameDmaCount; s32 gAudioTaskIndexQ; s32 gCurAiBuffIndex; -void* gAbiCmdBuffs[2]; -Acmd* gCurAiCmdBuffer; -AudioTask* gAudioCurTask; -AudioTask gAudioRspTasks[2]; +Acmd* gAbiCmdBuffs[2]; +Acmd* gCurAbiCmdBuffer; +SPTask* gAudioCurTask; +SPTask gAudioRspTasks[2]; f32 gMaxTempoTvTypeFactors; s32 gRefreshRate; -u16* gAiBuffers[3]; -u16 gAiBuffLengths[3]; +s16* gAiBuffers[3]; +s16 gAiBuffLengths[3]; u32 gAudioRandom; UNK_TYPE D_80155D88; volatile u32 gResetTimer; diff --git a/src/main/audio_general.c b/src/main/audio_general.c index 311bcfad..55a074fd 100644 --- a/src/main/audio_general.c +++ b/src/main/audio_general.c @@ -870,7 +870,7 @@ void Audio_StartSequence(u8 seqPlayId, u8 seqId, u8 seqArgs, u16 fadeInTime) { s32 pad; if (!gStartSeqDisabled || (seqPlayId == SEQ_PLAYER_SFX)) { - AUDIOCMD_GLOBAL_INIT_SEQPLAYER((u32) seqPlayId, (u32) seqId, fadeInTime); + AUDIOCMD_GLOBAL_INIT_SEQPLAYER((u32) seqPlayId, (u32) seqId, 0, fadeInTime); gActiveSequences[seqPlayId].prevSeqId = gActiveSequences[seqPlayId].seqId = seqId | ((seqArgs) << 8); if (gActiveSequences[seqPlayId].mainVolume.mod != 1.0f) { AUDIOCMD_SEQPLAYER_FADE_VOLUME_SCALE((u32) seqPlayId, gActiveSequences[seqPlayId].mainVolume.mod); @@ -930,8 +930,8 @@ void Audio_ProcessSeqCmd(u32 seqCmd) { gActiveSequences[seqPlayId].isWaitingForFonts = 1; Audio_StopSequence(seqPlayId, 1); if (gActiveSequences[seqPlayId].prevSeqId != 0xFFFF) { - tempptr = func_8001ED14(seqNumber, &sp4C); - tempPtr2 = func_8001ED14(gActiveSequences[seqPlayId].prevSeqId & 0xFF, &sp4C); + tempptr = AudioThread_GetFontsForSequence(seqNumber, &sp4C); + tempPtr2 = AudioThread_GetFontsForSequence(gActiveSequences[seqPlayId].prevSeqId & 0xFF, &sp4C); if (tempptr[0] != tempPtr2[0]) { AUDIOCMD_GLOBAL_DISCARD_SEQ_FONTS(seqNumber); } @@ -1061,8 +1061,8 @@ void Audio_ProcessSeqCmd(u32 seqCmd) { break; case 7: val = seqCmd & 0xFF; - ioPort = ((seqCmd & 0xFF0000) >> 0x10); - AUDIOCMD_SEQPLAYER_SET_IO(seqPlayId, ioPort, 0, val); + ioPort = ((seqCmd & 0xFF0000) >> 0x10); // may be misnamed + AUDIOCMD_SEQPLAYER_SET_IO(seqPlayId, ioPort, val); // AudioThread_QueueCmdS8(((seqPlayId & 0xFF) << 0x10) | 0x46000000 | (temp3 << 8), temp4); break; case 8: @@ -1127,7 +1127,7 @@ void Audio_ProcessSeqCmd(u32 seqCmd) { sp61 = sNewAudioSpecId; sNewAudioSpecId = specId; if (sp61 != sNewAudioSpecId) { - func_8001ED8C((OSMesg) (u32) sNewAudioSpecId); + AudioThread_ResetAudioHeap(sNewAudioSpecId); func_8001DE1C(sp61); AUDIOCMD_GLOBAL_STOP_AUDIOCMDS(); } else { @@ -1224,17 +1224,17 @@ void Audio_UpdateActiveSequences(void) { s32 temp; u32 cmd; f32 fadeMod; - s32 sp70; + u32 sp70; s32 pad1; s32 pad2; for (seqPlayId = 0; seqPlayId < 4; seqPlayId++) { if ((gActiveSequences[seqPlayId].isWaitingForFonts != 0)) { - switch ((s32) func_8001ECAC(&sp70)) { - case 1: - case 2: - case 3: - case 4: + switch ((s32) AudioThread_GetAsyncLoadStatus(&sp70)) { + case SEQ_PLAYER_BGM + 1: + case SEQ_PLAYER_FANFARE + 1: + case SEQ_PLAYER_SFX + 1: + case SEQ_PLAYER_VOICE + 1: gActiveSequences[seqPlayId].isWaitingForFonts = 0; Audio_ProcessSeqCmd(gActiveSequences[seqPlayId].startSeqCmd); break; @@ -1433,7 +1433,7 @@ u8 func_80018FA4(void) { if (D_800C5D58 == 1) { if (func_8001ED34() == 1) { D_800C5D58 = 0; - AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_SFX, 0, 0, gSfxChannelLayout); + AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_SFX, 0, gSfxChannelLayout); func_8001DD40(); } } else if (D_800C5D58 == 2) { @@ -1441,7 +1441,7 @@ u8 func_80018FA4(void) { ; } D_800C5D58 = 0; - AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_SFX, 0, 0, gSfxChannelLayout); + AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_SFX, 0, gSfxChannelLayout); func_8001DD40(); } } @@ -2953,7 +2953,7 @@ void func_8001DD40(void) { func_80017550(); SEQCMD_SET_SEQPLAYER_VOLUME(SEQ_PLAYER_SFX, 0, 127); SEQCMD_SET_SEQPLAYER_VOLUME(SEQ_PLAYER_VOICE, 0, 127); - func_8001E920(); + AudioThread_ScheduleProcessCmds(); AUDIOCMD_GLOBAL_STOP_AUDIOCMDS(); AUDIOCMD_GLOBAL_STOP_AUDIOCMDS(); AUDIOCMD_GLOBAL_STOP_AUDIOCMDS(); @@ -2989,7 +2989,7 @@ void Audio_Update(void) { func_8001AF50(); Audio_UpdateActiveSequences(); Audio_UpdateDelayedSeqCmds(); - func_8001E920(); + AudioThread_ScheduleProcessCmds(); } gAudioFrameCounter++; } diff --git a/src/main/audio_heap.c b/src/main/audio_heap.c index 42a485f8..4dcfc8e5 100644 --- a/src/main/audio_heap.c +++ b/src/main/audio_heap.c @@ -590,7 +590,7 @@ s32 AudioHeap_ResetStep(void) { } } - gResetFadeoutFramesLeft = 0x10 / sp24; + gResetFadeoutFramesLeft = 16 / sp24; gResetStatus--; } break; diff --git a/src/main/audio_load.c b/src/main/audio_load.c index 9e21c972..31c3f586 100644 --- a/src/main/audio_load.c +++ b/src/main/audio_load.c @@ -252,15 +252,15 @@ void* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outFontId) { return soundFontData; } -void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) { +void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 flags) { s32 pad; u32 fontId; seqId = AudioLoad_GetLoadTableIndex(0, seqId); - if (arg1 & 2) { + if (flags & 2) { AudioLoad_SyncLoadSeqFonts(seqId, &fontId); } - if (arg1 & 1) { + if (flags & 1) { AudioLoad_SyncLoadSeq(seqId); } } @@ -309,22 +309,22 @@ s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId) { } } -void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue) { - if (AudioLoad_AsyncLoadInner(2, AudioLoad_GetLoadTableIndex(2, sampleBankId), arg1, retData, retQueue) == NULL) { +void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 nChunks, s32 retData, OSMesgQueue* retQueue) { + if (AudioLoad_AsyncLoadInner(2, AudioLoad_GetLoadTableIndex(2, sampleBankId), nChunks, retData, retQueue) == NULL) { osSendMesg(retQueue, NULL, 0); } } -void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue) { +void AudioLoad_AsyncLoadSeq(s32 seqId, s32 nChunks, s32 retData, OSMesgQueue* retQueue) { s32 index = ((u16*) gSeqFontTable)[AudioLoad_GetLoadTableIndex(0, seqId)]; s32 fontsLeft = gSeqFontTable[index++]; for (fontsLeft; fontsLeft > 0; fontsLeft--) { - AudioLoad_AsyncLoadInner(1, AudioLoad_GetLoadTableIndex(1, gSeqFontTable[index++]), arg1, retData, retQueue); + AudioLoad_AsyncLoadInner(1, AudioLoad_GetLoadTableIndex(1, gSeqFontTable[index++]), nChunks, retData, retQueue); } } -void* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { +u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { s32 index = ((u16*) gSeqFontTable)[AudioLoad_GetLoadTableIndex(0, seqId)]; *outNumFonts = gSeqFontTable[index++]; @@ -838,21 +838,21 @@ void AudioLoad_Init(void) { *clearContext++ = 0; } switch (osTvType) { - case 0: + case OS_TV_PAL: gMaxTempoTvTypeFactors = 20.03042f; - gRefreshRate = 0x32; + gRefreshRate = 50; break; - case 2: + case OS_TV_MPAL: gMaxTempoTvTypeFactors = 16.546f; - gRefreshRate = 0x3C; + gRefreshRate = 60; break; default: - case 1: + case OS_TV_NTSC: gMaxTempoTvTypeFactors = 16.713f; - gRefreshRate = 0x3C; + gRefreshRate = 60; break; } - func_8001EE3C(); + AudioThread_Init(); for (i = 0; i < 3; i++) { gAiBuffLengths[i] = 0xA0; } diff --git a/src/main/audio_synthesis.c b/src/main/audio_synthesis.c index 2d588d41..9ece431e 100644 --- a/src/main/audio_synthesis.c +++ b/src/main/audio_synthesis.c @@ -1,6 +1,8 @@ #include "sys.h" #include "sf64audio_provisional.h" +extern s16 D_800DD200[]; + s32 D_80145D40; f32 D_80145D48[256]; f32 D_80146148[256]; @@ -25,42 +27,1254 @@ static char devstr7[] = "S->W\n"; static char devstr8[] = "W->S\n"; static char devstr9[] = "S-Resample Pitch %x (old %d -> delay %d)\n"; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_800080C0.s") +void func_800080C0(s32 sampleCount, s32 itemIndex, s32 reverbIndex) { + ReverbRingBufferItem* ringItem; + SynthesisReverb* reverb = &gSynthReverbs[reverbIndex]; + s32 temp_lo; + s32 temp_v1_3; + s32 i; + s32 j; + s32 pad1; + s32 pad2; + s32 pad3; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80008364.s") + if ((reverb->downsampleRate != 1) && (reverb->framesToIgnore == 0)) { + ringItem = &reverb->items[reverb->curFrame][itemIndex]; + osInvalDCache(ringItem->toDownsampleLeft, 0x300); + j = 0; + for (i = 0; i < ringItem->lengthA / 2; i++, j += reverb->downsampleRate) { + reverb->leftRingBuf[ringItem->startPos + i] = ringItem->toDownsampleLeft[j]; + reverb->rightRingBuf[ringItem->startPos + i] = ringItem->toDownsampleRight[j]; + } + for (i = 0; i < ringItem->lengthB / 2; i++, j += reverb->downsampleRate) { + reverb->leftRingBuf[i] = ringItem->toDownsampleLeft[j]; + reverb->rightRingBuf[i] = ringItem->toDownsampleRight[j]; + } + } + ringItem = &reverb->items[reverb->curFrame][itemIndex]; + temp_lo = sampleCount / reverb->downsampleRate; + temp_v1_3 = reverb->nextRingBufPos + temp_lo - reverb->bufSizePerChan; + if (temp_v1_3 < 0) { + ringItem->lengthA = temp_lo * 2; + ringItem->lengthB = 0; + ringItem->startPos = reverb->nextRingBufPos; + reverb->nextRingBufPos += temp_lo; + } else { + ringItem->lengthA = (temp_lo - temp_v1_3) * 2; + ringItem->lengthB = temp_v1_3 * 2; + ringItem->startPos = reverb->nextRingBufPos; + reverb->nextRingBufPos = temp_v1_3; + } + ringItem->numSamplesAfterDownsampling = temp_lo; + ringItem->chunkLen = sampleCount; +} + +void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) { + f32 temp_ft0; + f32 var_fs0; + f32* buff0fromStart; + f32* buf2half2; + f32* buf2half3; + f32* buff1half1; + f32* buff0FromEnd; + f32* buff1half2; + s32 half; + s32 i; + s32 size; + + size = 1 << length; + half = size >> 1; + + // Initialize buffer 2 if it is the wrong size for this calculation + if (size != (s32) buffer2[0]) { + buf2half2 = &buffer2[half]; + buf2half3 = &buf2half2[half]; + var_fs0 = 0.0f; + temp_ft0 = D_PI / (f32) (2 * size); + for (i = 0; i < half; i++) { + *buf2half2++ = (__cosf(var_fs0) - __sinf(var_fs0)) * 0.707107f; + *buf2half3++ = (__cosf(var_fs0) + __sinf(var_fs0)) * 0.707107f; + var_fs0 += temp_ft0; + } + } + + // reset the buffer pointers + buf2half2 = &buffer2[half]; + buf2half3 = &buf2half2[half]; + buff1half1 = buffer1; + buff0fromStart = buffer0; + + // handle i = 0 case + buffer1[0] = buffer0[0]; + buffer1[half] = buffer0[half]; + + // advance buffer pointers + buf2half2++; + buf2half3++; + buff0fromStart++; + buff0FromEnd = &buffer0[size - 1]; + buff1half1++; + buff1half2 = &buffer1[size - 1]; + + // convert to real amplitudes + for (i = 1; i < half; i++) { + *buff1half1++ = (*buf2half2 * *buff0fromStart) + (*buf2half3 * *buff0FromEnd); + *buff1half2-- = (*buf2half3 * *buff0fromStart) - (*buf2half2 * *buff0FromEnd); + buff0fromStart++; + buf2half3++; + buf2half2++; + buff0FromEnd--; + } + + // FFT buffer 1 using buffer 2 + func_80008780(buffer1, length, buffer2); + + buff0fromStart = buffer0; + buff0FromEnd = &buffer0[size - 1]; + buff1half1 = buffer1; + buff1half2 = &buffer1[half]; + + // Copy even entries of buffer 0 into the first half of buffer 1. Copy odd entries into the second half in reverse + // order + for (i = 0; i < half; i++) { + *buff0fromStart = *buff1half1++; + *buff0FromEnd = *buff1half2++; + buff0fromStart += 2; + buff0FromEnd -= 2; + } +} + +#ifdef NON_MATCHING +void func_80008780(f32* arg0, s32 arg1, f32* arg2) { + s32 length; + s32 spD0; + s32 spCC; + s32 spC8; + s32 var_a0; + s32 spC0; + s32 spBC; + s32 pad; + s32 spB4; + s32 sp58; + s32 sp50; + s32 spA8; + f32 var_fs0; + f32 temp_fa0; + f32 temp_fv1; + f32* temp_a0; + f32* temp_a1; + f32* temp_a2; + f32* temp_a3; + f32* temp_b0; + f32* temp_b1; + f32* temp_b2; + f32* temp_b3; + f32* var_s0; + f32* var_s1; + f32* var_s2; + f32* var_s3; + + length = 1 << arg1; + spBC = length * 2; + sp58 = (length / 8) - 1; + switch (length) { + case 1: + break; + case 2: + temp_fa0 = arg0[1]; + temp_fv1 = arg0[0]; + + arg0[0] = (temp_fa0 + temp_fv1) * 0.707107f; + arg0[1] = (temp_fv1 - temp_fa0) * 0.707107f; + break; + case 4: + temp_fv1 = arg0[0]; + arg0[0] = (arg0[2] + temp_fv1) / 2.0f; + arg0[2] = (temp_fv1 - arg0[2]) / 2.0f; + + temp_fa0 = arg0[1]; + arg0[1] = (arg0[3] + temp_fa0) / 2.0f; + arg0[3] = (temp_fa0 - arg0[3]) / 2.0f; + + temp_fv1 = arg0[0]; + temp_fa0 = arg0[1]; + arg0[0] = arg0[1] + temp_fv1; + arg0[1] = arg0[3] + arg0[2]; + arg0[3] = arg0[2] - arg0[3]; + arg0[2] = temp_fv1 - temp_fa0; + break; + default: + if (length != (s32) *arg2) { + *arg2 = length; + + var_s0 = &arg2[1]; + var_s1 = &var_s0[sp58]; + var_s2 = &var_s1[sp58]; + var_s3 = &var_s2[sp58]; + + var_fs0 = 6.283186f / length; + for (spCC = 0; spCC < sp58; spCC++) { + *var_s0++ = __cosf(var_fs0); + *var_s1++ = __sinf(var_fs0); + *var_s2++ = __cosf(3.0f * var_fs0); + *var_s3++ = __sinf(3.0f * var_fs0); + var_fs0 += 6.283186f / length; + } + } + spC0 = 1; + for (spD0 = 0; spD0 < arg1 - 1; spD0++) { + spA8 = spBC; + spBC >>= 1; + spB4 = spBC >> 3; + sp50 = spBC >> 2; + var_a0 = 1; + do { + for (spCC = var_a0 - 1; spCC < length; spCC += spA8) { + // if (0) { } + temp_a0 = arg0 + spCC; + temp_a1 = temp_a0 + sp50; + temp_a2 = temp_a1 + sp50; + temp_a3 = temp_a2 + sp50; + + D_80146D54 = *temp_a0; + *temp_a0 = *temp_a2 + D_80146D54; + D_80146D58 = *temp_a1; + *temp_a1 = *temp_a1 + *temp_a3; + D_80146D5C = *temp_a2; + *temp_a2 = D_80146D54 - D_80146D5C + D_80146D58 - *temp_a3; + *temp_a3 = D_80146D54 - D_80146D5C - D_80146D58 + *temp_a3; + if (sp50 > 1) { + temp_a0 = arg0 + spCC + spB4; + temp_a1 = temp_a0 + sp50; + temp_a2 = temp_a1 + sp50; + temp_a3 = temp_a2 + sp50; + + D_80146D54 = *temp_a0; + *temp_a0 = *temp_a2 + D_80146D54; + D_80146D58 = *temp_a1; + *temp_a1 = *temp_a3 + D_80146D58; + *temp_a2 = (D_80146D54 - *temp_a2) * 1.414214f; + *temp_a3 = (D_80146D58 - *temp_a3) * 1.414214f; + + var_s0 = &arg2[spC0]; + var_s1 = &var_s0[sp58]; + var_s2 = &var_s1[sp58]; + var_s3 = &var_s2[sp58]; + for (spC8 = 1; spC8 < spB4; spC8++) { + temp_a0 = arg0 + spCC + spC8; + temp_a1 = temp_a0 + sp50; + temp_a2 = temp_a1 + sp50; + temp_a3 = temp_a2 + sp50; + + temp_b0 = arg0 + spCC + sp50 - spC8; + temp_b1 = temp_b0 + sp50; + temp_b2 = temp_b1 + sp50; + temp_b3 = temp_b2 + sp50; + + D_80146D54 = *temp_a0; + D_80146D58 = *temp_a1; + D_80146D5C = *temp_a2; + D_80146D60 = *temp_a3; + + D_80146D64 = *temp_b0; + D_80146D68 = *temp_b1; + D_80146D6C = *temp_b2; + D_80146D70 = *temp_b3; + + *temp_a0 = D_80146D54 + D_80146D5C; + *temp_a1 = D_80146D58 + D_80146D60; + *temp_a2 = ((D_80146D54 - D_80146D5C + D_80146D64 - D_80146D6C) * *var_s0) + + ((D_80146D60 - D_80146D58 + D_80146D68 - D_80146D70) * *var_s1); + *temp_a3 = ((D_80146D54 - D_80146D5C - D_80146D64 + D_80146D6C) * *var_s2) - + ((D_80146D60 - D_80146D58 - D_80146D68 + D_80146D70) * *var_s3); + *temp_b0 = D_80146D64 + D_80146D6C; + *temp_b1 = D_80146D68 + D_80146D70; + *temp_b2 = ((D_80146D54 - D_80146D5C + D_80146D64 - D_80146D6C) * *var_s1) - + ((D_80146D60 - D_80146D58 + D_80146D68 - D_80146D70) * *var_s0); + *temp_b3 = ((D_80146D54 - D_80146D5C - D_80146D64 + D_80146D6C) * *var_s3) + + ((D_80146D60 - D_80146D58 - D_80146D68 + D_80146D70) * *var_s2); + var_s0 += spC0; + var_s1 += spC0; + var_s2 += spC0; + var_s3 += spC0; + } + } + } + var_a0 = ((spA8 * 2) - spBC) + 1; + spA8 *= 4; + } while (var_a0 < length); + spC0 = spC0 * 2; + temp_a0 = arg0; + for (spC8 = 0; spC8 < length; spC8++, temp_a0++) { + *temp_a0 /= 1.414214f; + } + } + var_a0 = 1; + spA8 = 4; + + do { + for (spCC = var_a0 - 1; spCC < length; spCC += spA8) { + D_80146D54 = arg0[spCC]; + arg0[spCC] = arg0[spCC + 1] + D_80146D54; + arg0[spCC + 1] = D_80146D54 - arg0[spCC + 1]; + } + var_a0 = (spA8 * 2) - 1; + spA8 *= 4; + } while (var_a0 < length); + temp_a0 = arg0; + for (spC8 = 0; spC8 < length; spC8++) { + *temp_a0++ /= 1.414214f; + } + spB4 = 1; + temp_a0 = arg0; + + for (spC8 = 1; spC8 < length; spC8++) { + if (spC8 < spB4) { + D_80146D54 = arg0[spB4 - 1]; + arg0[spB4 - 1] = *temp_a0; + *temp_a0 = D_80146D54; + } + temp_a0++; + spC0 = length >> 1; + while (spC0 < spB4) { + spB4 -= spC0; + spC0 >>= 1; + } + spB4 += spC0; + } + break; + } +} +#else #pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80008780.s") +#endif +#ifdef NON_MATCHING +void func_80009124(s16** arg0) { + s16* var_a1; + s32 temp_a0; + u8 temp_s0; + u8 temp_s1; + s32 temp_t5_4; + s32 temp_v0; + u8 temp_v1; + s32 var_s1; + s32 var_t2; + s32 var_v1; + u16 var_s0; + u32 var_t3; + s32 i; + s32 j; + + var_a1 = *arg0; + + for (i = 255; i >= 0; i--) { + D_80145D48[i] = 0.0f; + } + var_t3 = *var_a1++ << 0x10; + var_t3 |= *var_a1++; + + for (var_t2 = 0; var_t2 != 0x100; var_t2 += 0x40) { + temp_s0 = var_t3 >> 0x18; + var_v1 = var_t2; + var_t3 <<= 8; + + temp_v0 = ((temp_s0 >> 4) & 0xF); + temp_a0 = temp_s0 & 0xF; + if (((temp_s0 >> 4) & 0xF) == 0) { + continue; + } + switch (temp_v0) { + case 1: + while (true) { + var_s0 = *var_a1++; + for (var_s1 = 0; var_s1 < 4; var_s1++) { + temp_s1 = (var_s0 >> 0xC) & 0xF; + var_s0 <<= 4; + D_80145D48[var_v1++] = ((temp_s1 & 7) - 4) << temp_a0; + + if (temp_s1 >= 8) { + goto case_1_break; + } + } + } + case_1_break: + break; + case 2: + var_s1 = -1; + while (++var_s1 < 16) { + var_s0 = *var_a1++; + for (i = 0; i < 4; i++) { + temp_s1 = (var_s0 >> 0xC) & 0xF; + var_s0 <<= 4; + D_80145D48[var_v1++] = (temp_s1 - 8) << temp_a0; + } + } + break; + case 6: + while (true) { + var_s0 = *var_a1++; + temp_s1 = (var_s0 >> 8) & 0xFF; + + D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; + if (temp_s1 >> 6 == 0) { + + break; + } + var_v1 += temp_s1 >> 6; + temp_s1 = var_s0 & 0xFF; + D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; + if (temp_s1 >> 6 == 0) { + + break; + } + var_v1 += temp_s1 >> 6; + } + break; + case 3: + while (true) { + var_s0 = *var_a1++; + + temp_s1 = (var_s0 >> 8) & 0xFF; + + D_80145D48[var_v1++] = ((temp_s1 & 0x7F) - 0x40) << temp_a0; + if (temp_s1 >= 0x80) { + break; + } + temp_s1 = var_s0 & 0xFF; + D_80145D48[var_v1++] = ((temp_s1 & 0x7F) - 0x40) << temp_a0; + if (temp_s1 >= 0x80) { + break; + } + } + break; + case 4: + while (true) { + var_s0 = *var_a1++; + temp_t5_4 = var_s0 >> 0xC; + D_80145D48[var_v1] = ((var_s0 & 0xFFF) - 0x800) << temp_a0; + if (temp_t5_4 == 0) { + break; + } + var_v1 += temp_t5_4; + } + break; + case 5: + while (true) { + var_s0 = *var_a1++; + D_80145D48[var_v1] = ((var_s0 & 0x7FFF) - 0x4000) << temp_a0; + if ((var_s0 >> 0xF) == 1) { + break; + } + var_v1++; + } + break; + } + } + *arg0 = var_a1; +} +#else +void func_80009124(s16** arg0); #pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009124.s") +#endif -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009504.s") +void func_80009504(s16* arg0, UnkStruct_800097A8* arg1) { + s32 i; + f32 temp_ft0; + f32* var_v0; + f32* var_v0_2; + s32 temp_v0; + void* var_s0; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000967C.s") + var_s0 = arg0; + if (arg1->unk_0 != NULL) { + arg1->unk_C = arg1->unk_0; + arg1->unk_0 = 0; + } + arg1->unk18 += D_8014C1B4; + while (arg1->unk18 > 0x1000) { + func_80009124(&arg1->unk_C); + arg1->unk18 -= 0x1000; + } + func_80008364(D_80145D48, D_80146148, 8, D_80146548); + for (i = 0; i < 0x100; i++) { + if (D_80145D48[i] > 32767.0f) { + D_80145D48[i] = 32767.0f; + } + if (D_80145D48[i] < -32767.0f) { + D_80145D48[i] = -32767.0f; + } + } + for (i = 0; i < 0x100; i++, arg0++) { + *arg0 = D_80145D48[i]; + } +} +s32 func_8000967C(s32 length, s16* ramAddr, UnkStruct_800097A8* arg2) { + s32 pad; + s32 temp_t0; + s32 i; + s32 var_s1; + s16* temp_t7 = (s16*) arg2->unk_14->ramAddr; + + for (i = 0; i < arg2->unk_4; i++) { + ramAddr[i] = temp_t7[i]; + } + var_s1 = arg2->unk_4; + temp_t0 = (length - arg2->unk_4 + 0xFF) / 256; + arg2->unk_4 = (temp_t0 * 256) + arg2->unk_4 - length; + + for (i = 0; i < temp_t0; i++) { + func_80009504(&ramAddr[var_s1], arg2); + var_s1 += 0x100; + } + for (i = 0; i < arg2->unk_4; i++) { + temp_t7[i] = ramAddr[length + i]; + } + return temp_t0; +} + +#ifdef NON_MATCHING +u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg3) { + s32 pad1; + SampleDma* pad2; + SampleDma* sp1C; + + if (flags == 1) { + arg3->unk_0 = (s16*) sample->sampleAddr; + arg3->unk_4 = 0; + arg3->unk_8 = 0; + arg3->unk18 = 0; + + if (gSampleDmaReuseQueue1RdPos != gSampleDmaReuseQueue1WrPos) { + arg3->unk_14 = &gSampleDmas[gSampleDmaReuseQueue1[gSampleDmaReuseQueue1RdPos++]]; + arg3->unk_14->devAddr = -1; + arg3->unk_14->sizeUnused = 0; + } + } + if (gSampleDmaReuseQueue1RdPos != gSampleDmaReuseQueue1WrPos) { + sp1C = &gSampleDmas[gSampleDmaReuseQueue1[gSampleDmaReuseQueue1RdPos++]]; + } + sp1C->ttl = 2; + sp1C->devAddr = sample->sampleAddr; + sp1C->sizeUnused = length * 2; + pad2 = arg3->unk_14; + pad2->ttl = 2; + arg3->unk_8 += func_8000967C(length, (s16*) sp1C->ramAddr, arg3); + return sp1C->ramAddr; +} +#else +u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg3); #pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_800097A8.s") +#endif -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_800098DC.s") +Acmd* func_800098DC(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].leftRingBuf[startPos]), dmem, size); + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), dmem + 0x180, size); + return aList; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009984.s") +Acmd* func_80009984(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { + aSaveBuffer(aList++, dmem, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].leftRingBuf[startPos]), size); + aSaveBuffer(aList++, dmem + 0x180, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), size); + return aList; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009A2C.s") +void func_80009A2C(s32 updateIndex, s32 noteIndex) { + NoteSubEu* noteSubEu; + s32 i; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009AAC.s") + for (i = updateIndex + 1; i < gAudioBufferParams.ticksPerUpdate; i++) { + if (!gNoteSubsEu[(gNumNotes * i) + noteIndex].bitField0.needsInit) { + gNoteSubsEu[(gNumNotes * i) + noteIndex].bitField0.enabled = false; + } else { + break; + } + } +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009B64.s") +void func_80009AAC(s32 updateIndex) { + NoteSubEu* subEu; + NoteSubEu* subEu2; + s32 i; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_80009D78.s") + for (i = 0; i < gNumNotes; i++) { + subEu = &gNotes[i].noteSubEu; + subEu2 = &gNoteSubsEu[gNumNotes * updateIndex + i]; + if (subEu->bitField0.enabled) { + *subEu2 = *subEu; + subEu->bitField0.needsInit = false; + } else { + subEu2->bitField0.enabled = false; + } + } +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000A128.s") +Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { + Acmd* aCmdPtr; + s32* aiBufPtr; + s32 chunkLen; + s32 i; + s32 j; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000A25C.s") + aCmdPtr = aList; + for (i = gAudioBufferParams.ticksPerUpdate; i > 0; i--) { + func_8001678C(i - 1); + func_80009AAC(gAudioBufferParams.ticksPerUpdate - i); + } + aiBufPtr = (s32*) aiBufStart; + for (i = gAudioBufferParams.ticksPerUpdate; i > 0; i--) { + if (i == 1) { + chunkLen = aiBufLen; + } else if ((aiBufLen / i) >= gAudioBufferParams.samplesPerTickMax) { + chunkLen = gAudioBufferParams.samplesPerTickMax; + } else if (gAudioBufferParams.samplesPerTickMin >= (aiBufLen / i)) { + chunkLen = gAudioBufferParams.samplesPerTickMin; + } else { + chunkLen = gAudioBufferParams.samplesPerTick; + } + for (j = 0; j < gNumSynthReverbs; j++) { + if (gSynthReverbs[j].useReverb) { + func_800080C0(chunkLen, gAudioBufferParams.ticksPerUpdate - i, j); + } + } + aCmdPtr = func_8000A25C(aiBufPtr, chunkLen, aCmdPtr, gAudioBufferParams.ticksPerUpdate - i); + aiBufLen -= chunkLen; + aiBufPtr += chunkLen; + } + for (j = 0; j < gNumSynthReverbs; j++) { + if (gSynthReverbs[j].framesToIgnore != 0) { + gSynthReverbs[j].framesToIgnore--; + } + gSynthReverbs[j].curFrame ^= 1; + } + *cmdCount = aCmdPtr - aList; + return aCmdPtr; +} +Acmd* func_80009D78(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex) { + ReverbRingBufferItem* sp64 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex]; + s16 sp62; + s16 sp60; + + aClearBuffer(aList++, 0xC90, 0x300); + + if (gSynthReverbs[reverbIndex].downsampleRate == 1) { + aList = func_800098DC(aList, 0xC90, sp64->startPos, sp64->lengthA, reverbIndex); + if (sp64->lengthB != 0) { + aList = func_800098DC(aList, sp64->lengthA + 0xC90, 0, sp64->lengthB, reverbIndex); + } + aAddMixer(aList++, 0x300, 0xC90, 0x990, 0x7FFF); + aMix(aList++, 0x30, gSynthReverbs[reverbIndex].unk_08 + 0x8000, 0xC90, 0xC90); + } else { + sp62 = (sp64->startPos & 7) * 2; + sp60 = ALIGN16(sp62 + sp64->lengthA); + aList = func_800098DC(aList, 0x470, sp64->startPos - (sp62 / 2), 0x180, reverbIndex); + if (sp64->lengthB != 0) { + aList = func_800098DC(aList, sp60 + 0x470, 0, 0x180 - sp60, reverbIndex); + } + aSetBuffer(aList++, 0, sp62 + 0x470, 0xC90, aiBufLen * 2); + aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A, + OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_30)); + aSetBuffer(aList++, 0, sp62 + 0x5F0, 0xE10, aiBufLen * 2); + aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A, + OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_34)); + aAddMixer(aList++, 0x300, 0xC90, 0x990, 0x7FFF); + aMix(aList++, 0x30, gSynthReverbs[reverbIndex].unk_08 + 0x8000, 0xC90, 0xC90); + } + + if ((gSynthReverbs[reverbIndex].decayRatio != 0) || (gSynthReverbs[reverbIndex].unk_0E != 0)) { + aDMEMMove(aList++, 0xC90, 0x470, 0x180); + aMix(aList++, 0x18, gSynthReverbs[reverbIndex].decayRatio, 0xE10, 0xC90); + aMix(aList++, 0x18, gSynthReverbs[reverbIndex].unk_0E, 0x470, 0xE10); + } + return aList; +} + +Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex) { + ReverbRingBufferItem* sp24; + + sp24 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex]; + switch (gSynthReverbs[reverbIndex].downsampleRate) { + case 1: + aList = func_80009984(aList, 0xC90, sp24->startPos, sp24->lengthA, reverbIndex); + if (sp24->lengthB != 0) { + aList = func_80009984(aList, sp24->lengthA + 0xC90, 0, sp24->lengthB, reverbIndex); + } + break; + default: + aSaveBuffer(aList++, 0xC90, + OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex] + .items[gSynthReverbs[reverbIndex].curFrame][updateIndex] + .toDownsampleLeft), + 0x300); + gSynthReverbs[reverbIndex].resampleFlags = 0; + break; + } + return aList; +} + +Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex) { + u8 sp84[0x3C]; + NoteSubEu* temp_v0; + s16 var_s2; + s16 var_s3; + s32 var_s1; + + var_s2 = 0; + if (gNumSynthReverbs == 0) { + if (gSynthReverbs[var_s3].useReverb) {} // fake? + for (var_s1 = 0; var_s1 < gNumNotes; var_s1++) { + if (gNoteSubsEu[gNumNotes * updateIndex + var_s1].bitField0.enabled) { + sp84[var_s2++] = var_s1; + } + } + } else { + for (var_s3 = 0; var_s3 < gNumSynthReverbs; var_s3++) { + for (var_s1 = 0; var_s1 < gNumNotes; var_s1++) { + temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + var_s1]; + if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex == var_s3)) { + sp84[var_s2++] = var_s1; + } + } + } + for (var_s1 = 0; var_s1 < gNumNotes; var_s1++) { + temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + var_s1]; + if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex >= gNumSynthReverbs)) { + sp84[var_s2++] = var_s1; + } + } + } + aClearBuffer(aList++, 0x990, 0x300); + var_s1 = 0; + for (var_s3 = 0; var_s3 < gNumSynthReverbs; var_s3++) { + D_8014C1B2 = gSynthReverbs[var_s3].useReverb; + if (D_8014C1B2) { + aList = func_80009D78(aList, aiBufLen, var_s3, updateIndex); + } + while (var_s1 < var_s2) { + if (var_s3 != gNoteSubsEu[updateIndex * gNumNotes + sp84[var_s1]].bitField1.reverbIndex) { + break; + } + aList = func_8000A700(sp84[var_s1], &gNoteSubsEu[updateIndex * gNumNotes + sp84[var_s1]], + &gNotes[sp84[var_s1]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); + var_s1++; + } + if (gSynthReverbs[var_s3].useReverb != 0) { + aList = func_8000A128(aList, var_s3, updateIndex); + } + } + while (var_s1 < var_s2) { + aList = func_8000A700(sp84[var_s1], &gNoteSubsEu[updateIndex * gNumNotes + sp84[var_s1]], + &gNotes[sp84[var_s1]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); + var_s1++; + } + var_s1 = aiBufLen * 2; + aSetBuffer(aList++, 0, 0, 0x450, var_s1); + aInterleave(aList++, 0, 0x990, 0xB10, 0); + aSaveBuffer(aList++, 0x450, OS_K0_TO_PHYSICAL(aiBuf), var_s1 * 2); + return aList; +} + +#ifdef NON_MATCHING +Acmd* func_8000A700(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, + Acmd* aList, s32 updateIndex) { + s32 pad11C; + s32 pad118; + s32 pad114; + Sample* bookSample; // sp110 + AdpcmLoop* loopInfo; // sp10C + s16* currentBook; // sp108 + s32 pad104; + s32 pad100; + s32 noteFinished; // spFC + u32 restart; // spF8 + s32 flags; // spF4 + u16 resampleRateFixedPoint; // spF2 + s32 nSamplesToLoad; // spEC + s32 padE8; + s32 padE4; + s32 padE0; + s32 skipBytes; // spDC + s32 padD8; + s32 padD4; + s32 padD0; + u32 sampleAddr; // spCC + s32 padC8; + s32 samplesLenAdjusted; // spC4 + s32 nAdpcmSamplesProcessed; // spC0 + u32 endPos; // spBC + s32 nSamplesToProcess; // spB8 + s32 padB4; + s32 padB0; + s32 padAC; + s32 padA8; + s32 padA4; + s32 nTrailingSamplesToIgnore; // spA0 + s32 pad9C; + s32 pad98; + s32 pad94; + s32 frameSize; // sp90 + s32 pad8C; + s32 skipInitialSamples; // sp88 + s32 sampleDmaStart; // sp84 + s32 pad80; + s32 nParts; // sp7C + s32 curPart; // sp78 + s32 nSamplesInThisIteration; + s32 sampleDataStartPad; + s32 resampledTempLen; // sp6C + u16 noteSamplesDmemAddrBeforeResampling; // sp6A + s32 samplesRemaining; + s32 frameIndex; + s32 sampleDataOffset; + Note* note; // sp58 + u16 sp56; // sp56 + + s32 nSamplesInFirstFrame; + s32 delaySide; + s32 nSamplesToDecode; + s32 nFramesToDecode; + s32 nFirstFrameSamplesToIgnore; + s32 s5; + u32 sampleslenFixedPoint; + u8* sampleData; + s32 temp; + s32 temp2; + u32 nEntries; + s32 aligned; + s32 align2; + u16 addr; + + currentBook = NULL; + note = &gNotes[noteIndex]; + flags = 0; + if (noteSub->bitField0.needsInit == 1) { + flags = 1; + synthState->restart = 0; + synthState->samplePosInt = 0; + synthState->samplePosFrac = 0; + synthState->curVolLeft = 0; + synthState->curVolRight = 0; + synthState->prevHaasEffectLeftDelaySize = 0; + synthState->prevHaasEffectRightDelaySize = 0; + synthState->numParts = 0; + note->noteSubEu.bitField0.finished = 0; + } + resampleRateFixedPoint = noteSub->unk_0A; + nParts = noteSub->bitField1.hasTwoParts + 1; + sampleslenFixedPoint = (resampleRateFixedPoint * aiBufLen * 2) + synthState->samplePosFrac; + nSamplesToLoad = (sampleslenFixedPoint) >> 0x10; + synthState->samplePosFrac = sampleslenFixedPoint & 0xFFFF; + if ((synthState->numParts == 1) && (nParts == 2)) { + nSamplesToLoad += 2; + sp56 = 2; + } else if ((synthState->numParts == 2) && (nParts == 1)) { + nSamplesToLoad -= 4; + sp56 = 4; + } else { + sp56 = 0; + } + synthState->numParts = nParts; + if (noteSub->bitField1.isSyntheticWave) { + aList = func_8000B3F0(aList, noteSub, synthState, nSamplesToLoad); + noteSamplesDmemAddrBeforeResampling = (synthState->samplePosInt * 2) + 0x5F0; + synthState->samplePosInt += nSamplesToLoad; + } else { + bookSample = *(Sample**) noteSub->waveSampleAddr; + loopInfo = bookSample->loop; + endPos = loopInfo->end; + sampleAddr = bookSample->sampleAddr; + resampledTempLen = 0; + + for (curPart = 0; curPart < nParts; curPart++) { + nAdpcmSamplesProcessed = 0; + s5 = 0; + if (nParts == 1) { + samplesLenAdjusted = nSamplesToLoad; + } else if (nSamplesToLoad & 1) { + samplesLenAdjusted = (nSamplesToLoad & ~1) + (curPart * 2); + } else { + samplesLenAdjusted = nSamplesToLoad; + } + if ((bookSample->codec == 0) && (currentBook != bookSample->book->book)) { + switch (noteSub->bitField1.bookOffset) { + case 1: + currentBook = &D_800DD200[1]; + break; + case 2: + currentBook = &D_800DD200[2]; + break; + default: + case 3: + currentBook = bookSample->book->book; + break; + } + + nEntries = 16 * bookSample->book->order * bookSample->book->numPredictors; + aLoadADPCM(aList++, nEntries, OS_K0_TO_PHYSICAL(currentBook)); + } + while (nAdpcmSamplesProcessed != samplesLenAdjusted) { + restart = 0; + noteFinished = 0; + samplesRemaining = endPos - synthState->samplePosInt; + nSamplesToProcess = samplesLenAdjusted - nAdpcmSamplesProcessed; + + nFirstFrameSamplesToIgnore = synthState->samplePosInt & 0xF; + + if ((nFirstFrameSamplesToIgnore == 0) && !synthState->restart) { + nFirstFrameSamplesToIgnore = 0x10; + } + + nSamplesInFirstFrame = 0x10 - nFirstFrameSamplesToIgnore; + if (nSamplesToProcess < samplesRemaining) { + nFramesToDecode = (nSamplesToProcess - nSamplesInFirstFrame + 0xF) / 16; + nSamplesToDecode = nFramesToDecode * 0x10; + // if(1) {} + nTrailingSamplesToIgnore = (nSamplesInFirstFrame + nSamplesToDecode) - nSamplesToProcess; + } else { + nSamplesToDecode = samplesRemaining - nSamplesInFirstFrame; + nTrailingSamplesToIgnore = 0; + if (nSamplesToDecode <= 0) { + nSamplesToDecode = 0; + nSamplesInFirstFrame = samplesRemaining; + } + nFramesToDecode = (nSamplesToDecode + 0xF) / 16; + if (loopInfo->count != 0) { + restart = 1; + } else { + noteFinished = 1; + } + } + switch (bookSample->codec) { + case 0: + frameSize = 9; + skipInitialSamples = 0x10; + sampleDmaStart = 0; + break; + case 1: + frameSize = 0x10; + skipInitialSamples = 0x10; + sampleDmaStart = 0; + break; + case 2: + temp = + func_800097A8(bookSample, samplesLenAdjusted, flags, &synthState->synthesisBuffers->unk_40); + aLoadBuffer(aList++, temp - 0x80000000, 0x5F0, (samplesLenAdjusted + 0x10) * 2); + s5 = samplesLenAdjusted; + nAdpcmSamplesProcessed = samplesLenAdjusted; + skipBytes = 0; + goto skip; + } + aligned = ALIGN16(nFramesToDecode * frameSize + 0x10); + addr = 0x990 - aligned; + if (nFramesToDecode != 0) { + frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16; + sampleDataOffset = frameIndex * frameSize; + if (bookSample->medium == 0) { + sampleData = sampleDmaStart + sampleDataOffset + sampleAddr; + } else { + sampleData = AudioLoad_DmaSampleData(sampleDmaStart + sampleDataOffset + sampleAddr, aligned, + flags, &synthState->sampleDmaIndex, bookSample->medium); + } + // if (1){} + sampleDataStartPad = (u32) sampleData & 0xF; + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(sampleData - sampleDataStartPad), addr, aligned); + } else { + nSamplesToDecode = 0; + sampleDataStartPad = 0; + } + if (synthState->restart) { + aSetLoop(aList++, OS_K0_TO_PHYSICAL(bookSample->loop->predictorState)); + flags = 2; + synthState->restart = 0; + } + nSamplesInThisIteration = nSamplesToDecode + nSamplesInFirstFrame - nTrailingSamplesToIgnore; + + if (nAdpcmSamplesProcessed == 0) { + switch (bookSample->codec) { + case 0: + aSetBuffer(aList++, 0, addr + sampleDataStartPad, 0x5F0, nSamplesToDecode * 2); + aADPCMdec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); + break; + case 1: + aSetBuffer(aList++, 0, addr + sampleDataStartPad, 0x5F0, nSamplesToDecode * 2); + aS8Dec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); + break; + } + + skipBytes = nFirstFrameSamplesToIgnore * 2; + } else { + // if (1) {} + align2 = ALIGN16(s5 + 0x10); + switch (bookSample->codec) { + case 0: + aSetBuffer(aList++, 0, addr + sampleDataStartPad, align2 + 0x5F0, nSamplesToDecode * 2); + aADPCMdec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); + break; + case 1: + aSetBuffer(aList++, 0, addr + sampleDataStartPad, align2 + 0x5F0, nSamplesToDecode * 2); + aS8Dec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); + break; + } + aDMEMMove(aList++, (align2 + (nFirstFrameSamplesToIgnore * 2) + 0x5F0), s5 + 0x5F0, + nSamplesInThisIteration * 2); + } + nAdpcmSamplesProcessed += nSamplesInThisIteration; + switch (flags) { + case 1: + skipBytes = 0x20; + s5 = (nSamplesToDecode + 0x10) * 2; + break; + case 2: + // if(1) {} + s5 = nSamplesInThisIteration * 2 + s5; + break; + default: + if (s5 != 0) { + s5 = nSamplesInThisIteration * 2 + s5; + } else { + // if (1) { } + s5 = (nFirstFrameSamplesToIgnore + nSamplesInThisIteration) * 2; + } + break; + } + skip: + flags = 0; + // goto dummy_label_147574; dummy_label_147574: ; + if (noteFinished) { + aClearBuffer(aList++, s5 + 0x5F0, (samplesLenAdjusted - nAdpcmSamplesProcessed) * 2); + noteSub->bitField0.finished = 1; + note->noteSubEu.bitField0.finished = 1; + func_80009A2C(updateIndex, noteIndex); + break; + } + if (restart) { + synthState->restart = 1; + synthState->samplePosInt = loopInfo->start; + } else { + synthState->samplePosInt += nSamplesToProcess; + } + } + switch (nParts) { + case 1: + noteSamplesDmemAddrBeforeResampling = skipBytes + 0x5F0; + break; + case 2: + switch (curPart) { + case 0: + aInterl(aList++, skipBytes + 0x5F0, 0x470, ALIGN8(samplesLenAdjusted / 2)); + resampledTempLen = samplesLenAdjusted; + noteSamplesDmemAddrBeforeResampling = 0x470; + if (noteSub->bitField0.finished) { + aClearBuffer(aList++, resampledTempLen + noteSamplesDmemAddrBeforeResampling, + samplesLenAdjusted + 0x10); + } + break; + case 1: + aInterl(aList++, skipBytes + 0x5F0, resampledTempLen + 0x470, + ALIGN8(samplesLenAdjusted / 2)); + break; + } + break; + } + + if (noteSub->bitField0.finished) { + break; + } + } + } + + flags = 0; + if (noteSub->bitField0.needsInit == 1) { + flags = 1; + noteSub->bitField0.needsInit = 0; + } + flags = sp56 | flags; + aList = func_8000B480(aList, synthState, aiBufLen * 2, resampleRateFixedPoint, noteSamplesDmemAddrBeforeResampling, + flags); + if (flags & 1) { + flags = 1; + } + if (noteSub->bitField1.bookOffset == 3) { + aUnkCmd19(aList++, 0, aiBufLen * 2, 0x450, 0x450); + } + + temp2 = noteSub->unk_02; + if (temp2 != 0) { + if (temp2 < 0x10) { + temp2 = 0x10; + } + aHiLoGain(aList++, temp2, (aiBufLen + 0x10) * 2, 0x450, 0); + } + if ((noteSub->unk_03 != 0) || (synthState->prevHaasEffectLeftDelaySize != 0)) { + delaySide = 1; + } else if ((noteSub->unk_04 != 0) || (synthState->prevHaasEffectRightDelaySize != 0)) { + delaySide = 2; + } else { + delaySide = 0; + } + + aList = func_8000B51C(aList, noteSub, synthState, aiBufLen, 0x450, delaySide, flags); + // if(restart) {} + if (noteSub->bitField0.usesHeadsetPanEffects) { + if (!(flags & 1)) { + flags = 0; + } + aList = func_8000B98C(aList, noteSub, synthState, aiBufLen * 2, flags, delaySide); + } + + return aList; +} +#else #pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000A700.s") +#endif -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000B3F0.s") +Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad) { + s32 temp_v1; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000B480.s") + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(noteSub->waveSampleAddr), 0x5F0, 0x80); + synthState->samplePosInt &= 0x3F; + temp_v1 = 0x40 - synthState->samplePosInt; + if (temp_v1 < numSamplesToLoad) { + if ((((numSamplesToLoad - temp_v1) + 0x3F) / 64) != 0) { + aDuplicate(aList++, ((numSamplesToLoad - temp_v1) + 0x3F) / 64, 0x5F0, 0x670); + } + } + return aList; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000B51C.s") +Acmd* func_8000B480(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, u32 resampleFlags) { + if (pitch == 0) { + aClearBuffer(aList++, 0x450, size); + } else { + aSetBuffer(aList++, 0, inpDmem, 0x450, size); + aResample(aList++, resampleFlags, pitch, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->finalResampleState)); + } + return aList; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_synthesis/func_8000B98C.s") +Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, + s32 delaySide, s32 flags) { + s16 var_a2; + s16 var_a3; + s16 var_t0; + u16 temp_t7; + u16 temp_t9; + u16 temp_t1; + u16 temp_t2; + s32 temp_a1; + s32 temp = 0; + + temp_t1 = synthState->curVolLeft; + temp_t2 = synthState->curVolRight; + temp_t7 = noteSub->unk_06; + + temp_t9 = noteSub->unk_08; + temp_t7 <<= 4; + temp_t9 <<= 4; + + if (temp_t7 != temp_t1) { + var_t0 = (temp_t7 - temp_t1) / (aiBufLen >> 3); + } else { + var_t0 = 0; + } + if (temp_t9 != temp_t2) { + var_a3 = (temp_t9 - temp_t2) / (aiBufLen >> 3); + } else { + var_a3 = 0; + } + + temp_a1 = synthState->reverbVol; + + if (noteSub->unk_05 != temp_a1) { + temp = (((noteSub->unk_05 & 0x7F) - (temp_a1 & 0x7F)) << 8); + var_a2 = temp / (aiBufLen >> 3); + synthState->reverbVol = noteSub->unk_05; + } else { + var_a2 = 0; + } + synthState->curVolLeft = temp_t1 + (var_t0 * (aiBufLen >> 3)); + synthState->curVolRight = temp_t2 + (var_a3 * (aiBufLen >> 3)); + if (noteSub->bitField0.usesHeadsetPanEffects) { + aClearBuffer(aList++, 0x650, 0x180); + aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); + aEnvSetup2(aList++, temp_t1, temp_t2); + + switch (delaySide) { + case 1: + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x65B1C9E1); + break; + case 2: + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x9965C9E1); + break; + default: + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1); + break; + } + } else { + aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); + aEnvSetup2(aList++, temp_t1, temp_t2); + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, + noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1); + } + + return aList; +} + +Acmd* func_8000B98C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, + s32 delaySide) { + u16 var_t0; + u8 var_a1; + u8 var_v1; + u16 temp; + + switch (delaySide) { /* irregular */ + case 1: + var_t0 = 0x990; + var_a1 = noteSub->unk_03; + synthState->prevHaasEffectRightDelaySize = 0; + var_v1 = synthState->prevHaasEffectLeftDelaySize; + synthState->prevHaasEffectLeftDelaySize = var_a1; + break; + case 2: + var_t0 = 0xB10; + var_a1 = noteSub->unk_04; + synthState->prevHaasEffectLeftDelaySize = 0; + var_v1 = synthState->prevHaasEffectRightDelaySize; + synthState->prevHaasEffectRightDelaySize = var_a1; + break; + default: + return aList; + } + if (flags != 1) { + if (var_a1 != var_v1) { + temp = (((size << 0xF) / 2) - 1) / ((size + var_a1 - var_v1 - 2) / 2); + aSetBuffer(aList++, 0, 0x650, 0x450, size + var_a1 - var_v1); + aResampleZoh(aList++, temp, 0); + } else { + aDMEMMove(aList++, 0x650, 0x450, size); + } + if (var_v1 != 0) { + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), 0x650, + ALIGN16(var_v1)); + aDMEMMove(aList++, 0x450, var_v1 + 0x650, size + var_a1 - var_v1); + } else { + aDMEMMove(aList++, 0x450, 0x650, size + var_a1); + } + } else { + aDMEMMove(aList++, 0x650, 0x450, size); + aClearBuffer(aList++, 0x650, var_a1); + aDMEMMove(aList++, 0x450, var_a1 + 0x650, size); + } + if (var_a1) { + aSaveBuffer(aList++, size + 0x650, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), + ALIGN16(var_a1)); + } + aAddMixer(aList++, ALIGN64(size), 0x650, var_t0, 0x7FFF); + return aList; +} diff --git a/src/main/audio_thread.c b/src/main/audio_thread.c index 75af8927..776971bd 100644 --- a/src/main/audio_thread.c +++ b/src/main/audio_thread.c @@ -1,5 +1,12 @@ #include "sys.h" #include "sf64audio_provisional.h" +#include "audiothread_cmd.h" + +void AudioThread_ProcessCmds(u32 msg); +void AudioThread_SetFadeOutTimer(s32 seqPlayId, s32 fadeTime); +void AudioThread_SetFadeInTimer(s32 seqPlayId, s32 fadeTime); + +extern AudioTable gSampleBankTableInit; OSMesgQueue sAudioTaskStartQueue; OSMesgQueue sThreadCmdProcQueue; @@ -11,27 +18,230 @@ OSMesg sThreadCmdProcMsg[4]; OSMesg sAudioUnkMsg[1]; OSMesg sAudioResetMsg[1]; -s8 gThreadCmdWritePos = 0; -s8 gThreadCmdReadPos = 0; +u8 gThreadCmdWritePos = 0; +u8 gThreadCmdReadPos = 0; OSMesgQueue* gAudioTaskStartQueue = &sAudioTaskStartQueue; OSMesgQueue* gThreadCmdProcQueue = &sThreadCmdProcQueue; OSMesgQueue* gAudioUnkQueue = &sAudioUnkQueue; OSMesgQueue* gAudioResetQueue = &sAudioResetQueue; -s32 gMaxAbiCmdCnt = 128; -AudioTask* gWaitingAudioTask = NULL; -s32 D_800C7C70 = 0; -u8 gCurCmdReadPos = 0; -u8 gThreadCmdQueueFinished = 0; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001DF50.s") +static const char devstr0[] = "DAC:Lost 1 Frame.\n"; +static const char devstr1[] = "DMA: Request queue over.( %d )\n"; +static const char devstr2[] = "Spec Change Override. %d -> %d\n"; +static const char devstr3[] = "Audio:now-max tasklen is %d / %d\n"; +static const char devstr4[] = "Audio:Warning:ABI Tasklist length over (%d)\n"; +static const char devstr5[] = "BGLOAD Start %d\n"; +static const char devstr6[] = "Error: OverFlow Your Request\n"; +static const char devstr7[] = "---AudioSending (%d->%d) \n"; +static const char devstr8[] = "AudioSend: %d -> %d (%d)\n"; +static const char devstr9[] = "Continue Port\n"; +static const char devstr10[] = "%d -> %d\n"; +static const char devstr11[] = "Sync-Frame Break. (Remain %d)\n"; +static const char devstr12[] = "Undefined Port Command %d\n"; +static const char devstr13[] = "specchg conjunction error (Msg:%d Cur:%d)\n"; +static const char devstr14[] = "Error : Queue is not empty ( %x ) \n"; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E444.s") +SPTask* AudioThread_CreateTask(void) { + static s32 gMaxAbiCmdCnt = 128; + static SPTask* gWaitingAudioTask = NULL; + u32 sp54; + s32 sp50; + s32 sp4C; + s32 pad48; + OSTask_t* task; + u16* sp40; + s32 pad3C; + u32 sp38; + u32 sp34; + s32 pad30; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E720.s") + gAudioTaskCountQ++; + if ((gAudioTaskCountQ % gAudioBufferParams.specUnk4) != 0) { + return gWaitingAudioTask; + } + osSendMesg(gAudioTaskStartQueue, (OSMesg) gAudioTaskCountQ, 0); + gAudioTaskIndexQ ^= 1; + gCurAiBuffIndex++; + gCurAiBuffIndex %= 3; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E778.s") + sp4C = (gCurAiBuffIndex + 1) % 3; + sp54 = osAiGetLength() >> 2; + if ((gResetTimer < 16) && (gAiBuffLengths[sp4C] != 0)) { + osAiSetNextBuffer(gAiBuffers[sp4C], gAiBuffLengths[sp4C] * 4); + } + if (gCurAudioFrameDmaCount && gCurAudioFrameDmaCount) {} + gCurAudioFrameDmaCount = 0; + AudioLoad_DecreaseSampleDmaTtls(); + AudioLoad_ProcessLoads(gResetStatus); + if (osRecvMesg(gAudioUnkQueue, (OSMesg) &sp38, 0) != -1) { + if (gResetStatus == 0) { + gResetStatus = 5; + } + gAudioSpecId = sp38; + } + if ((gResetStatus != 0) && (AudioHeap_ResetStep() == 0)) { + if (gResetStatus == 0) { + osSendMesg(gAudioResetQueue, (OSMesg) (s32) gAudioSpecId, 0); + } + gWaitingAudioTask = NULL; + return NULL; + } + if (gResetTimer > 16) { + return NULL; + } + if (gResetTimer != 0) { + gResetTimer++; + } + gAudioCurTask = &gAudioRspTasks[gAudioTaskIndexQ]; + gCurAbiCmdBuffer = gAbiCmdBuffs[gAudioTaskIndexQ]; + sp4C = gCurAiBuffIndex; + sp40 = gAiBuffers[sp4C]; + gAiBuffLengths[sp4C] = ((gAudioBufferParams.samplesPerFrameTarget - sp54 + 0x80) & ~0xF) + 0x10; -void func_8001E7C8(void) { + if (gAiBuffLengths[sp4C] < gAudioBufferParams.minAiBufferLength) { + gAiBuffLengths[sp4C] = gAudioBufferParams.minAiBufferLength; + } + if (gAiBuffLengths[sp4C] > gAudioBufferParams.maxAiBufferLength) { + gAiBuffLengths[sp4C] = gAudioBufferParams.maxAiBufferLength; + } + while (osRecvMesg(gThreadCmdProcQueue, (OSMesg) &sp34, 0) != -1) { + AudioThread_ProcessCmds(sp34); + } + gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &sp50, sp40, gAiBuffLengths[sp4C]); + gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ); + gAudioRandom = gAiBuffers[sp4C][gAudioTaskCountQ & 0xFF] + gAudioRandom; + + sp4C = gAudioTaskIndexQ; + + gAudioCurTask->msgQueue = NULL; + gAudioCurTask->msg = NULL; + + task = &gAudioCurTask->task.t; + + task->type = 2; + task->flags = 0; + task->ucode_boot = rspbootTextStart; + task->ucode_boot_size = (uintptr_t) rspbootTextEnd - (uintptr_t) rspbootTextStart; + + task->ucode = aspMainTextStart; + task->ucode_data = aspMainDataStart; + task->ucode_size = SP_UCODE_SIZE; + task->ucode_data_size = (aspMainDataEnd - aspMainDataStart) * 8; + + task->dram_stack = NULL; + task->dram_stack_size = 0; + + task->output_buff = NULL; + task->output_buff_size = NULL; + if (1) {} + task->data_ptr = (u64*) gAbiCmdBuffs[sp4C]; + task->data_size = sp50 * sizeof(Acmd); + + task->yield_data_ptr = NULL; + task->yield_data_size = 0; + + if (gMaxAbiCmdCnt < sp50) { + gMaxAbiCmdCnt = sp50; + } + + if (gAudioBufferParams.specUnk4 == 1) { + return gAudioCurTask; + } else { + gWaitingAudioTask = gAudioCurTask; + return NULL; + } +} + +void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) { + s32 i; + + switch (cmd->op) { + case AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS: + AudioLoad_SyncLoadSeqParts(cmd->arg1, 3); + break; + case AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER: + case 0x88: + AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2); + AudioThread_SetFadeInTimer(cmd->arg0, cmd->data); + break; + case AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER: + if (gSeqPlayers[cmd->arg0].enabled) { + if (cmd->asInt == 0) { + func_800144E4(&gSeqPlayers[cmd->arg0]); + } else { + AudioThread_SetFadeOutTimer(cmd->arg0, cmd->asInt); + } + } + break; + case 0x84: + break; + case AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE: + gAudioSoundMode = cmd->asUInt; + break; + case AUDIOCMD_OP_GLOBAL_MUTE: + for (i = 0; i < 4; i++) { + SequencePlayer* seqplayer = &gSeqPlayers[i]; + + seqplayer->muted = true; + seqplayer->recalculateVolume = true; + } + break; + case AUDIOCMD_OP_GLOBAL_UNMUTE: + if (cmd->asUInt == 1) { + for (i = 0; i < gNumNotes; i++) { + Note* note = &gNotes[i]; + NoteSubEu* noteSub = ¬e->noteSubEu; + + if ((noteSub->bitField0.enabled) && (note->playbackState.unk_04 == 0) && + (note->playbackState.parentLayer != NO_LAYER) && + (note->playbackState.parentLayer->channel->muteBehavior & 8)) { + noteSub->bitField0.finished = true; + } + } + } + for (i = 0; i < 4; i++) { + SequencePlayer* seqplayer = &gSeqPlayers[i]; + + seqplayer->muted = false; + seqplayer->recalculateVolume = true; + } + break; + case AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT: + AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2); + break; + case AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK: + AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gExternalLoadQueue); + break; + case AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT: + AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gExternalLoadQueue); + break; + case AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS: + AudioLoad_DiscardSeqFonts(cmd->arg1); + break; + } +} + +void AudioThread_SetFadeOutTimer(s32 seqPlayId, s32 fadeTime) { + if (fadeTime == 0) { + fadeTime = 1; + } + + gSeqPlayers[seqPlayId].state = 2; + gSeqPlayers[seqPlayId].fadeTimer = fadeTime; + gSeqPlayers[seqPlayId].fadeVelocity = -(gSeqPlayers[seqPlayId].fadeVolume / fadeTime); +} + +void AudioThread_SetFadeInTimer(s32 seqPlayId, s32 fadeTime) { + if (fadeTime != 0) { + gSeqPlayers[seqPlayId].state = 1; + gSeqPlayers[seqPlayId].fadeTimerUnkEu = fadeTime; + gSeqPlayers[seqPlayId].fadeTimer = fadeTime; + gSeqPlayers[seqPlayId].fadeVolume = 0.0f; + gSeqPlayers[seqPlayId].fadeVelocity = 0.0f; + } +} + +void AudioThread_InitQueues(void) { gThreadCmdWritePos = 0; gThreadCmdReadPos = 0; osCreateMesgQueue(gAudioTaskStartQueue, sAudioTaskStartMsg, 1); @@ -40,30 +250,187 @@ void func_8001E7C8(void) { osCreateMesgQueue(gAudioResetQueue, sAudioResetMsg, 1); } -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/AudioThread_QueueCmd.s") +void AudioThread_QueueCmd(u32 opArgs, void** data) { + AudioCmd* audioCmd = &gThreadCmdBuffer[gThreadCmdWritePos & 0xFF]; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/AudioThread_QueueCmdF32.s") + audioCmd->opArgs = opArgs; + audioCmd->data = *data; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/AudioThread_QueueCmdS32.s") + gThreadCmdWritePos++; + if (gThreadCmdWritePos == gThreadCmdReadPos) { + gThreadCmdWritePos--; + } +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/AudioThread_QueueCmdS8.s") +void AudioThread_QueueCmdF32(u32 opArgs, f32 val) { + AudioThread_QueueCmd(opArgs, (void**) &val); +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E920.s") +void AudioThread_QueueCmdS32(u32 opArgs, u32 val) { + AudioThread_QueueCmd(opArgs, (void**) &val); +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E998.s") +void AudioThread_QueueCmdS8(u32 opArgs, s8 val) { + s32 data = val << 0x18; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001E9AC.s") + AudioThread_QueueCmd(opArgs, (void**) &data); +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001ECAC.s") +void AudioThread_ScheduleProcessCmds(void) { + static s32 D_800C7C70 = 0; + s32 msg; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001ED14.s") + if (D_800C7C70 < (u8) (gThreadCmdWritePos - gThreadCmdReadPos + 0x100)) { + D_800C7C70 = (u8) (gThreadCmdWritePos - gThreadCmdReadPos + 0x100); + } + msg = (((gThreadCmdReadPos & 0xFF) << 8) | (gThreadCmdWritePos & 0xFF)); + osSendMesg(gThreadCmdProcQueue, (OSMesg) msg, 0); + gThreadCmdReadPos = gThreadCmdWritePos; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001ED34.s") +void AudioThread_ResetCmdQueue(void) { + gThreadCmdReadPos = gThreadCmdWritePos; +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001ED8C.s") +void AudioThread_ProcessCmds(u32 msg) { + static u8 gCurCmdReadPos = 0; + static u8 gThreadCmdQueueFinished = false; + AudioCmd* cmd; + SequenceChannel* channel; + SequencePlayer* player; + u8 writePos; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001EE00.s") + if (!gThreadCmdQueueFinished) { + gCurCmdReadPos = (msg >> 8) & 0xFF; + } + writePos = msg & 0xFF; + while (true) { + if (gCurCmdReadPos == writePos) { + gThreadCmdQueueFinished = 0; + break; + } + cmd = &gThreadCmdBuffer[gCurCmdReadPos & 0xFF]; + gCurCmdReadPos++; + if (cmd->op == AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS) { + gThreadCmdQueueFinished = true; + break; + } + if ((cmd->op & 0xF0) == 0xF0) { + AudioThread_ProcessGlobalCmd(cmd); + } else if (cmd->arg0 < 4) { + player = &gSeqPlayers[cmd->arg0]; + if (cmd->op & 0x80) { + AudioThread_ProcessGlobalCmd(cmd); + } else if (cmd->op & 0x40) { + switch (cmd->op) { + case AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE: + if (player->fadeVolumeMod != cmd->asFloat) { + player->fadeVolumeMod = cmd->asFloat; + player->recalculateVolume = true; + } + break; + case AUDIOCMD_OP_SEQPLAYER_SET_TEMPO: /* switch 1 */ + player->tempo = cmd->asInt * 48; + break; + case AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION: /* switch 1 */ + player->transposition = cmd->asSbyte; + break; + case 0x46: // AUDIOCMD_OP_SEQPLAYER_SET_IO? + player->unk_07[cmd->arg2] = cmd->asSbyte; + break; + } + } else if ((player->enabled) && (cmd->arg1 < 16)) { + channel = player->channels[cmd->arg1]; + if (channel != &gSeqChannelNone) { + switch (cmd->op) { + case AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE: + if (channel->volumeMod != cmd->asFloat) { + channel->volumeMod = cmd->asFloat; + channel->changes.s.volume = true; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_VOL: + if (channel->volume != cmd->asFloat) { + channel->volume = cmd->asFloat; + channel->changes.s.volume = true; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_PAN: + if (channel->newPan != cmd->asSbyte) { + channel->newPan = cmd->asSbyte; + channel->changes.s.pan = true; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE: + if (channel->freqMod != cmd->asFloat) { + channel->freqMod = cmd->asFloat; + channel->changes.s.freqMod = true; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME: + if (channel->targetReverbVol != cmd->asSbyte) { + channel->targetReverbVol = cmd->asSbyte; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_IO: + if (cmd->arg2 < 8) { + channel->seqScriptIO[cmd->arg2] = cmd->asSbyte; + } + break; + case AUDIOCMD_OP_CHANNEL_SET_MUTE: + channel->muted = cmd->asSbyte; + break; + } + } + } + } + cmd->op = 0; + } +} -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/func_8001EE3C.s") +u32 AudioThread_GetAsyncLoadStatus(u32* outData) { + u32 sp1C; -#pragma GLOBAL_ASM("asm/us/nonmatchings/main/audio_thread/D_800C90F0.s") + if (osRecvMesg(&gExternalLoadQueue, (OSMesg*) &sp1C, 0) == -1) { + *outData = 0; + return 0; + } + *outData = sp1C & 0xFFFFFF; + return sp1C >> 0x18; +} + +u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts) { + return AudioLoad_GetFontsForSequence(seqId, outNumFonts); +} + +s32 func_8001ED34(void) { + s32 pad; + s32 sp18; + + if (osRecvMesg(gAudioResetQueue, (OSMesg*) &sp18, 0) == -1) { + return 0; + } + if (sp18 != gAudioSpecId) { + return 0; + } + return 1; +} + +void AudioThread_ResetAudioHeap(s32 specId) { + // clang-format off + s32 m1 = -1;OSMesg sp28;do {} while (osRecvMesg(gAudioResetQueue, &sp28, 0) != m1); + // clang-format on + + AudioThread_ResetCmdQueue(); + osSendMesg(gAudioUnkQueue, (OSMesg) specId, 0); +} + +void AudioThread_PreNMIReset(void) { + gResetTimer = 1; + AudioThread_ResetAudioHeap(0); + gResetStatus = 0; +} + +void AudioThread_Init(void) { + AudioThread_InitQueues(); +} diff --git a/src/main/fox_reset.c b/src/main/fox_reset.c index 57b0c6a2..b7224c5d 100644 --- a/src/main/fox_reset.c +++ b/src/main/fox_reset.c @@ -23,7 +23,7 @@ void Graphics_NMIWipe(void) { Graphics_FillRectangle(&gMasterDisp, SCREEN_WIDTH - 8 - MIN(304, D_800D4A80), 176, SCREEN_WIDTH - 8, 232, 0, 0, 0, 255); if (D_800D4A80 == 0) { - func_8001EE00(); + AudioThread_PreNMIReset(); } D_800D4A80 += 45; if (D_800D4A80 >= 485) { diff --git a/src/main/sys_main.c b/src/main/sys_main.c index 61ad33c1..17ff9b28 100644 --- a/src/main/sys_main.c +++ b/src/main/sys_main.c @@ -1,7 +1,7 @@ #include "sys.h" void AudioLoad_Init(void); -SPTask* func_8001DF50(void); +SPTask* AudioThread_CreateTask(void); void Audio_InitSounds(void); void Audio_Update(void); @@ -109,7 +109,7 @@ void Audio_ThreadEntry(void* arg0) { AudioLoad_Init(); Audio_InitSounds(); - task = func_8001DF50(); + task = AudioThread_CreateTask(); if (task != NULL) { task->msgQueue = &gAudioTaskMsgQueue; task->msg = (OSMesg) TASK_MESG_1; @@ -117,7 +117,7 @@ void Audio_ThreadEntry(void* arg0) { osSendMesg(&gTaskMsgQueue, task, OS_MESG_PRI_NORMAL); } while (1) { - task = func_8001DF50(); + task = AudioThread_CreateTask(); if (task != NULL) { task->msgQueue = &gAudioTaskMsgQueue; task->msg = (OSMesg) TASK_MESG_1; diff --git a/tools/Torch b/tools/Torch index 0fd8f658..cfd2ec35 160000 --- a/tools/Torch +++ b/tools/Torch @@ -1 +1 @@ -Subproject commit 0fd8f658566f6269c1fbca297760e60e8e64cf0e +Subproject commit cfd2ec35ce03a36c10b005b952f765f035c8b836 diff --git a/tools/permuter_settings.toml b/tools/permuter_settings.toml index 4d8ef261..7eed343e 100644 --- a/tools/permuter_settings.toml +++ b/tools/permuter_settings.toml @@ -26,6 +26,10 @@ compiler_type = "ido" "false" = "int" "DMG_.*" = "int" "AUDIOCMD_.*" = "void" +"SEQCMD_.*" = "void" +"a[A-Z].*" = "void" +"ALIGN.*" = "int" +"OS_K0_TO_PHYSICAL" = "int" [decompme.compilers] "tools/ido-recomp/linux/cc" = "ido5.3" \ No newline at end of file