diff options
author | ShinyDragonHunter <32826900+ShinyDragonHunter@users.noreply.github.com> | 2018-11-05 21:44:00 +0000 |
---|---|---|
committer | ShinyDragonHunter <32826900+ShinyDragonHunter@users.noreply.github.com> | 2018-11-05 21:44:00 +0000 |
commit | d3a263f09c9e304a8bf1b3bbb4c51fc0668c55f6 (patch) | |
tree | 5259e3f99899b6374b401c685da5b1a7499cf196 | |
parent | 7c7221465456927d2f853a045d1ea0bb945e799f (diff) |
Updated Reduce noise and improve sound quality of music (markdown)
-rw-r--r-- | Reduce-noise-and-improve-sound-quality-of-music.md | 2553 |
1 files changed, 2 insertions, 2551 deletions
diff --git a/Reduce-noise-and-improve-sound-quality-of-music.md b/Reduce-noise-and-improve-sound-quality-of-music.md index 02da334..c0273d8 100644 --- a/Reduce-noise-and-improve-sound-quality-of-music.md +++ b/Reduce-noise-and-improve-sound-quality-of-music.md @@ -2,2558 +2,9 @@ Many thanks to ipatix and Kurausukun. Without them, none of this would be possib Anyway, these changes will allow the game to have reduced noise and output sound at a higher base frequency. -In asm/m4a_1.s, replace everything in that file with: +In asm/m4a_1.s, replace everything in that file with the code in the link below: -```asm - .include "asm/macros.inc" - .include "constants/gba_constants.inc" - .include "constants/m4a_constants.inc" - - .syntax unified - - .text - - thumb_func_start umul3232H32 -umul3232H32: - adr r2, __umul3232H32 - bx r2 - .arm -__umul3232H32: - umull r2, r3, r0, r1 - add r0, r3, 0 - bx lr - thumb_func_end umul3232H32 - - thumb_func_start SoundMain -SoundMain: - ldr r0, lt_SOUND_INFO_PTR - ldr r0, [r0] - ldr r2, lt_ID_NUMBER - ldr r3, [r0, o_SoundInfo_ident] - cmp r2, r3 - beq SoundMain_1 - bx lr @ Exit the function if ident doesn't match ID_NUMBER. -SoundMain_1: - adds r3, 1 - str r3, [r0, o_SoundInfo_ident] - push {r4-r7,lr} - mov r1, r8 - mov r2, r9 - mov r3, r10 - mov r4, r11 - push {r0-r4} - sub sp, 0x18 - ldrb r1, [r0, o_SoundInfo_maxLines] - cmp r1, 0 @ if maxLines is 0, there is no maximum - beq SoundMain_3 - ldr r2, lt_REG_VCOUNT - ldrb r2, [r2] - cmp r2, VCOUNT_VBLANK - bhs SoundMain_2 - adds r2, TOTAL_SCANLINES -SoundMain_2: - adds r1, r2 -SoundMain_3: - str r1, [sp, 0x14] - ldr r3, [r0, o_SoundInfo_func] - cmp r3, 0 - beq SoundMain_4 - ldr r0, [r0, o_SoundInfo_intp] - bl call_r3 - ldr r0, [sp, 0x18] -SoundMain_4: - ldr r3, [r0, o_SoundInfo_CgbSound] - bl call_r3 - ldr r0, [sp, 0x18] - ldr r3, [r0, o_SoundInfo_pcmSamplesPerVBlank] - mov r8, r3 - ldr r5, lt_o_SoundInfo_pcmBuffer - adds r5, r0 - ldrb r4, [r0, o_SoundInfo_pcmDmaCounter] - subs r7, r4, 1 - bls SoundMain_5 - ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] - subs r1, r7 - mov r2, r8 - muls r2, r1 - adds r5, r2 -SoundMain_5: - str r5, [sp, 0x8] - ldr r6, lt_PCM_DMA_BUF_SIZE - ldr r3, lt_SoundMainRAM_Buffer - bx r3 - - .align 2, 0 -lt_SOUND_INFO_PTR: .word SOUND_INFO_PTR -lt_ID_NUMBER: .word ID_NUMBER -lt_SoundMainRAM_Buffer: .word SoundMainRAM_Buffer + 1 -lt_REG_VCOUNT: .word REG_VCOUNT -lt_o_SoundInfo_pcmBuffer: .word o_SoundInfo_pcmBuffer -lt_PCM_DMA_BUF_SIZE: .word PCM_DMA_BUF_SIZE - thumb_func_end SoundMain - - .equ POKE_INIT, 1 - .equ DMA_FIX, 0 - .equ ENABLE_DECOMPRESSION, 1 - - /* stack variables */ - .equ ARG_FRAME_LENGTH, 0x0 @ TODO actually use this variable - .equ ARG_REMAIN_CHN, 0x4 @ This is the channel count variable - .equ ARG_BUFFER_POS, 0x8 @ stores the current output buffer pointer - .equ ARG_LOOP_START_POS, 0xC @ stores wave loop start position in channel loop - .equ ARG_LOOP_LENGTH, 0x10 @ '' '' '' end position - .equ ARG_BUFFER_POS_INDEX_HINT, 0x14 - .equ ARG_PCM_STRUCT, 0x18 @ pointer to engine the main work area - - /* channel struct */ - .equ CHN_STATUS, 0x0 @ [byte] channel status bitfield - .equ CHN_MODE, 0x1 @ [byte] channel mode bitfield - .equ CHN_VOL_1, 0x2 @ [byte] volume right - .equ CHN_VOL_2, 0x3 @ [byte] volume left - .equ CHN_ATTACK, 0x4 @ [byte] wave attack summand - .equ CHN_DECAY, 0x5 @ [byte] wave decay factor - .equ CHN_SUSTAIN, 0x6 @ [byte] wave sustain level - .equ CHN_RELEASE, 0x7 @ [byte] wave release factor - .equ CHN_ADSR_LEVEL, 0x9 @ [byte] current envelope level - .equ CHN_FINAL_VOL_1, 0xA @ [byte] not used anymore! - .equ CHN_FINAL_VOL_2, 0xB @ [byte] not used anymore! - .equ CHN_ECHO_VOL, 0xC @ [byte] pseudo echo volume - .equ CHN_ECHO_REMAIN, 0xD @ [byte] pseudo echo length - .equ CHN_SAMPLE_COUNTDOWN, 0x18 @ [word] sample countdown in mixing loop - .equ CHN_FINE_POSITION, 0x1C @ [word] inter sample position (23 bits) - .equ CHN_FREQUENCY, 0x20 @ [word] sample rate (in Hz) - .equ CHN_WAVE_OFFSET, 0x24 @ [word] wave header pointer - .equ CHN_POSITION_ABS, 0x28 @ [word] points to the current position in the wave data (relative offset for compressed samples) - .equ CHN_BLOCK_COUNT, 0x3C @ [word] only used for compressed samples: contains the value of the block that is currently decoded - - /* wave header struct */ - .equ WAVE_LOOP_FLAG, 0x3 @ [byte] 0x0 = oneshot; 0x40 = looped - .equ WAVE_FREQ, 0x4 @ [word] pitch adjustment value = mid-C samplerate * 1024 - .equ WAVE_LOOP_START, 0x8 @ [word] loop start position - .equ WAVE_LENGTH, 0xC @ [word] loop end / wave end position - .equ WAVE_DATA, 0x10 @ [byte array] actual wave data - - /* pulse wave synth configuration offset */ - .equ SYNTH_BASE_WAVE_DUTY, 0x1 @ [byte] - .equ SYNTH_WIDTH_CHANGE_1, 0x2 @ [byte] - .equ SYNTH_MOD_AMOUNT, 0x3 @ [byte] - .equ SYNTH_WIDTH_CHANGE_2, 0x4 @ [byte] - - /* CHN_STATUS flags - 0x0 = OFF */ - .equ FLAG_CHN_INIT, 0x80 @ [bit] write this value to init a channel - .equ FLAG_CHN_RELEASE, 0x40 @ [bit] write this value to release (fade out) the channel - .equ FLAG_CHN_COMP, 0x20 @ [bit] is wave being played compressed (yes/no) - .equ FLAG_CHN_LOOP, 0x10 @ [bit] loop (yes/no) - .equ FLAG_CHN_ECHO, 0x4 @ [bit] echo phase - .equ FLAG_CHN_ATTACK, 0x3 @ [bit] attack phase - .equ FLAG_CHN_DECAY, 0x2 @ [bit] decay phase - .equ FLAG_CHN_SUSTAIN, 0x1 @ [bit] sustain phase - - /* CHN_MODE flags */ - .equ MODE_FIXED_FREQ, 0x8 @ [bit] set to disable resampling (i.e. playback with output rate) - .equ MODE_REVERSE, 0x10 @ [bit] set to reverse sample playback - .equ MODE_COMP, 0x30 @ [bit] is wave being played compressed or reversed (TODO: rename flag) - .equ MODE_SYNTH, 0x40 @ [bit] READ ONLY, indicates synthzied output - - /* variables of the engine work area */ - .equ VAR_REVERB, 0x5 @ [byte] 0-127 = reverb level - .equ VAR_MAX_CHN, 0x6 @ [byte] maximum channels to process - .equ VAR_MASTER_VOL, 0x7 @ [byte] PCM master volume - .equ VAR_DEF_PITCH_FAC, 0x18 @ [word] this value gets multiplied with the sample rate for the inter sample distance - .equ VAR_FIRST_CHN, 0x50 @ [CHN struct] relative offset to channel array - - /* just some more defines */ - .equ REG_DMA3_SRC, 0x040000D4 - .equ ARM_OP_LEN, 0x4 - .syntax divided - - thumb_func_start SoundMainRAM -SoundMainRAM: -main_mixer: - /* load Reverb level and check if we need to apply it */ - STR R4, [SP, #ARG_BUFFER_POS_INDEX_HINT] - ADR R2, is_buffer_init - LDRB R0, [R2] - CMP R0, #0 - BNE C_setup_channel_state_loop - /* if buffer not initialized, clear first */ - LDR R3, hq_buffer - MOV R1, R8 - MOV R4, #0 - MOV R5, #0 - MOV R6, #0 - MOV R7, #0 - - LSR R1, #3 - BCC C_clear_buffer_align_8 - STMIA R3!, {R4, R5, R6, R7} - -C_clear_buffer_align_8: - LSR R1, #1 - BCC C_clear_buffer_align_16 - - STMIA R3!, {R4, R5, R6, R7} - STMIA R3!, {R4, R5, R6, R7} - -C_clear_buffer_align_16: - STMIA R3!, {R4, R5, R6, R7} - STMIA R3!, {R4, R5, R6, R7} - STMIA R3!, {R4, R5, R6, R7} - STMIA R3!, {R4, R5, R6, R7} - - SUB R1, #1 - BGT C_clear_buffer_align_16 - MOV R1, #1 - STRB R1, [R2] - B C_setup_channel_state_loop - - .align 2 -is_buffer_init: - .byte 0x0 - - .align 1 - -C_setup_channel_state_loop: - /* - * okay, before the actual mixing starts - * the volume and envelope calculation takes place - */ - MOV R4, R8 @ R4 = buffer length - /* - * this stroes the buffer length to a backup location - */ - STR R4, [SP, #ARG_FRAME_LENGTH] - /* init channel loop */ - LDR R4, [SP, #ARG_PCM_STRUCT] @ R4 = main work area pointer - LDR R0, [R4, #VAR_DEF_PITCH_FAC] @ R0 = samplingrate pitch factor - MOV R12, R0 - LDRB R0, [R4, #VAR_MAX_CHN] - ADD R4, #VAR_FIRST_CHN @ R4 = Base channel Offset (Channel #0) - -C_channel_state_loop: - /* this is the main channel processing loop */ - STR R0, [SP, #ARG_REMAIN_CHN] - LDR R3, [R4, #CHN_WAVE_OFFSET] - LDRB R6, [R4, #CHN_STATUS] @ R6 will hold the channel status - MOVS R0, #0xC7 @ check if any of the channel status flags is set - TST R0, R6 @ check if none of the flags is set - BEQ C_skip_channel - /* check channel flags */ - LSL R0, R6, #25 @ shift over the FLAG_CHN_INIT to CARRY - BCC C_adsr_echo_check @ continue with normal channel procedure - /* check leftmost bit */ - BMI C_stop_channel @ FLAG_CHN_INIT | FLAG_CHN_RELEASE -> stop directly - /* channel init procedure */ - MOVS R6, #FLAG_CHN_ATTACK - MOVS R0, R3 @ R0 = CHN_WAVE_OFFSET - ADD R0, #WAVE_DATA @ R0 = wave data offset - - /* Pokemon games seem to init channels differently than other m4a games */ - .if POKE_INIT==0 - STR R0, [R4, #CHN_POSITION_ABS] - LDR R0, [R3, #WAVE_LENGTH] - STR R0, [R4, #CHN_SAMPLE_COUNTDOWN] - .else - LDR R1, [R4, #CHN_SAMPLE_COUNTDOWN] - ADD R0, R0, R1 - STR R0, [R4, #CHN_POSITION_ABS] - LDR R0, [R3, #WAVE_LENGTH] - SUB R0, R0, R1 - STR R0, [R4, #CHN_SAMPLE_COUNTDOWN] - .endif - - MOVS R5, #0 @ initial envelope = #0 - STRB R5, [R4, #CHN_ADSR_LEVEL] - STR R5, [R4, #CHN_FINE_POSITION] - LDRB R2, [R3, #WAVE_LOOP_FLAG] - LSR R0, R2, #6 - BEQ C_adsr_attack - /* loop enabled here */ - MOVS R0, #FLAG_CHN_LOOP - ORR R6, R0 - B C_adsr_attack - -C_adsr_echo_check: - /* this is the normal ADSR procedure without init */ - LDRB R5, [R4, #CHN_ADSR_LEVEL] - LSL R0, R6, #29 @ FLAG_CHN_ECHO --> bit 31 (sign bit) - BPL C_adsr_release_check - /* pseudo echo handler */ - LDRB R0, [R4, #CHN_ECHO_REMAIN] - SUB R0, #1 - STRB R0, [R4, #CHN_ECHO_REMAIN] - BHI C_channel_vol_calc @ continue normal if channel is still on - -C_stop_channel: - MOVS R0, #0 - STRB R0, [R4, #CHN_STATUS] - -C_skip_channel: - /* go to end of the channel loop */ - B C_end_channel_state_loop - -C_adsr_release_check: - LSL R0, R6, #25 @ FLAG_CHN_RELEASE --> bit 31 (sign bit) - BPL C_adsr_decay_check - /* release handler */ - LDRB R0, [R4, #CHN_RELEASE] - @SUB R0, #0xFF @ linear decay; TODO make option for triggering it - @SUB R0, #1 - @ADD R5, R5, R0 - MUL R5, R5, R0 - LSR R5, #8 - BLE C_adsr_released - /* pseudo echo init handler */ - LDRB R0, [R4, #CHN_ECHO_VOL] - CMP R5, R0 - BHI C_channel_vol_calc - -C_adsr_released: - /* if volume released to #0 */ - LDRB R5, [R4, #CHN_ECHO_VOL] - CMP R5, #0 - BEQ C_stop_channel - /* pseudo echo volume handler */ - MOVS R0, #FLAG_CHN_ECHO - ORR R6, R0 @ set the echo flag - B C_adsr_save_and_finalize - -C_adsr_decay_check: - /* check if decay is active */ - MOVS R2, #(FLAG_CHN_DECAY+FLAG_CHN_SUSTAIN) - AND R2, R6 - CMP R2, #FLAG_CHN_DECAY - BNE C_adsr_attack_check @ decay not active yet - /* decay handler */ - LDRB R0, [R4, #CHN_DECAY] - MUL R5, R5, R0 - LSR R5, R5, #8 - LDRB R0, [R4, #CHN_SUSTAIN] - CMP R5, R0 - BHI C_channel_vol_calc @ sample didn't decay yet - /* sustain handler */ - MOVS R5, R0 @ current level = sustain level - BEQ C_adsr_released @ sustain level #0 --> branch - /* step to next phase otherweise */ - B C_adsr_next_state - -C_adsr_attack_check: - /* attack handler */ - CMP R2, #FLAG_CHN_ATTACK - BNE C_channel_vol_calc @ if it isn't in attack attack phase, it has to be in sustain (keep vol) --> branch - -C_adsr_attack: - /* apply attack summand */ - LDRB R0, [R4, #CHN_ATTACK] - ADD R5, R0 - CMP R5, #0xFF - BLO C_adsr_save_and_finalize - /* cap attack at 0xFF */ - MOVS R5, #0xFF - -C_adsr_next_state: - /* switch to next adsr phase */ - SUB R6, #1 - -C_adsr_save_and_finalize: - /* store channel status */ - STRB R6, [R4, #CHN_STATUS] - -C_channel_vol_calc: - /* store the calculated ADSR level */ - STRB R5, [R4, #CHN_ADSR_LEVEL] - /* apply master volume */ - LDR R0, [SP, #ARG_PCM_STRUCT] - LDRB R0, [R0, #VAR_MASTER_VOL] - ADD R0, #1 - MUL R5, R0 - /* left side volume */ - LDRB R0, [R4, #CHN_VOL_2] - MUL R0, R5 - LSR R0, #13 - MOV R10, R0 @ R10 = left volume - /* right side volume */ - LDRB R0, [R4, #CHN_VOL_1] - MUL R0, R5 - LSR R0, #13 - MOV R11, R0 @ R11 = right volume - /* - * Now we get closer to actual mixing: - * For looped samples some additional operations are required - */ - MOVS R0, #FLAG_CHN_LOOP - AND R0, R6 - BEQ C_skip_sample_loop_setup - /* loop setup handler */ - ADD R3, #WAVE_LOOP_START - LDMIA R3!, {R0, R1} @ R0 = loop start, R1 = loop end - ADD R3, R0 @ R3 = loop start position (absolute) - STR R3, [SP, #ARG_LOOP_START_POS] - SUB R0, R1, R0 - -C_skip_sample_loop_setup: - /* do the rest of the setup */ - STR R0, [SP, #ARG_LOOP_LENGTH] @ if loop is off --> R0 = 0x0 - LDR R5, hq_buffer - LDR R2, [R4, #CHN_SAMPLE_COUNTDOWN] - LDR R3, [R4, #CHN_POSITION_ABS] - LDRB R0, [R4, #CHN_MODE] - ADR R1, C_mixing_setup - BX R1 - - .align 2 -hq_buffer: - .word hq_buffer_ptr - - .arm - .align 2 - -C_mixing_setup: - /* frequency and mixing loading routine */ - LDR R8, [SP, #ARG_FRAME_LENGTH] - ORRS R11, R11, R10, LSL#16 @ R11 = 00LL00RR - BEQ C_mixing_epilogue @ volume #0 --> branch and skip channel processing - /* normal processing otherwise */ - TST R0, #MODE_FIXED_FREQ - BNE C_setup_fixed_freq_mixing - TST R0, #MODE_COMP - BNE C_setup_special_mixing @ compressed? --> branch - - STMFD SP!, {R4, R9, R12} - /* - * This mixer supports 4 different kind of synthesized sounds - * They are triggered if there is no samples to play - * This get's checked below - */ - MOVS R2, R2 - ORREQ R0, R0, #MODE_SYNTH - STREQB R0, [R4, #CHN_MODE] - ADD R4, R4, #CHN_FINE_POSITION - LDMIA R4, {R7, LR} @ R7 = Fine Position, LR = Frequency - MUL R4, LR, R12 @ R4 = inter sample steps = output rate factor * samplerate - /* now the first samples get loaded */ - LDRSB R6, [R3], #1 - LDRSB R12, [R3] - TST R0, #MODE_SYNTH - BNE C_setup_synth - /* incase no synth mode should be used, code contiues here */ - SUB R12, R12, R6 @ R12 = DELTA - /* - * Mixing goes with volume ranges 0-127 - * They come in 0-255 --> divide by 2 - */ - MOVS R11, R11, LSR#1 - ADC R11, R11, #0x8000 - BIC R11, R11, #0xFF00 - MOV R1, R7 @ R1 = inter sample position - /* - * There is 2 different mixing codepaths for uncompressed data - * path 1: fast mixing, but doesn't supports loop or stop - * path 2: not so fast but supports sample loops / stop - * This checks if there is enough samples aviable for path 1. - * important: R0 is expected to be #0 - */ - UMLAL R1, R0, R4, R8 - MOV R1, R1, LSR#23 - ORR R0, R1, R0, LSL#9 - CMP R2, R0 @ actual comparison - BLE C_setup_unbuffered_mixing @ if not enough samples are available for path 1 --> branch - /* - * This is the mixer path 1. - * The interesting thing here is that the code will - * buffer enough samples on stack if enough space - * on stack is available (or goes over the limit of 0x400 bytes) - */ - SUB R2, R2, R0 - LDR R10, upper_stack_bounds - ADD R10, R10, R0 - CMP R10, SP - ADD R10, R3, R0 - /* - * R2 = remaining samples after processing - * R10 = final sample position - * SP = original stack location - * These values will get reloaded after channel processing - * due to the lack of registers. - */ - STMFD SP!, {R2, R10} - CMPCC R0, #0x400 @ > 0x400 bytes --> read directly from ROM rather than buffered - MOV R10, SP - BCS C_select_highspeed_codepath - /* - * The code below inits the DMA to read word aligned - * samples from ROM to stack - */ - BIC R1, R3, #3 - MOV R9, #0x04000000 - ADD R9, R9, #0xD4 - ADD R0, R0, #7 - MOV R0, R0, LSR#2 - SUB SP, SP, R0, LSL#2 - AND R3, R3, #3 - ADD R3, R3, SP - ORR LR, R0, #0x84000000 - STMIA R9, {R1, SP, LR} @ actually starts the DMA - - /* Somehow is neccesary for some games not to break */ - .if DMA_FIX==1 - MOV R0, #0 - MOV R1, #0 - MOV R2, #0 - STMIA R9, {R0, R1, R2} - .endif - -C_select_highspeed_codepath: - STMFD SP!, {R10} @ save original SP for VLA - /* - * This code decides which piece of code to load - * depending on playback-rate / default-rate ratio. - * Modes > 1.0 run with different volume levels. - * R4 = inter sample step - */ - ADR R0, high_speed_code_resource @ loads the base pointer of the code - SUBS R4, R4, #0x800000 - MOVPL R11, R11, LSL#1 @ if >= 1.0* 0-127 --> 0-254 volume level - ADDPL R0, R0, #(ARM_OP_LEN*6) @ 6 instructions further - SUBPLS R4, R4, #0x800000 @ if >= 2.0* - ADDPL R0, R0, #(ARM_OP_LEN*6) - ADDPL R4, R4, #0x800000 - LDR R2, previous_fast_code - CMP R0, R2 @ code doesn't need to be reloaded if it's already in place - BEQ C_skip_fast_mixing_creation - /* This loads the needed code to RAM */ - STR R0, previous_fast_code - LDMIA R0, {R0-R2, R8-R10} @ load 6 opcodes - ADR LR, fast_mixing_instructions - -C_fast_mixing_creation_loop: - /* paste code to destination, see below for patterns */ - STMIA LR, {R0, R1} - ADD LR, LR, #(ARM_OP_LEN*38) - STMIA LR, {R0, R1} - SUB LR, LR, #(ARM_OP_LEN*35) - STMIA LR, {R2, R8-R10} - ADD LR, LR, #(ARM_OP_LEN*38) - STMIA LR, {R2, R8-R10} - SUB LR, LR, #(ARM_OP_LEN*32) - ADDS R5, R5, #0x40000000 @ do that for 4 blocks - BCC C_fast_mixing_creation_loop - - LDR R8, [SP] @ restore R8 with the frame length - LDR R8, [R8, #(ARG_FRAME_LENGTH + 0x8 + 0xC)] - -C_skip_fast_mixing_creation: - MOV R2, #0xFF000000 @ load the fine position overflow bitmask -C_fast_mixing_loop: - /* This is the actual processing and interpolation code loop; NOPs will be replaced by the code above */ - LDMIA R5, {R0, R1, R10, LR} @ load 4 stereo samples to Registers - MUL R9, R7, R12 -fast_mixing_instructions: - NOP @ Block #1 - NOP - MLANE R0, R11, R9, R0 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #2 - NOP - MLANE R1, R11, R9, R1 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #3 - NOP - MLANE R10, R11, R9, R10 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #4 - NOP - MLANE LR, R11, R9, LR - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples - - LDMIA R5, {R0, R1, R10, LR} @ load the next 4 stereo samples - MULNE R9, R7, R12 - NOP @ Block #1 - NOP - MLANE R0, R11, R9, R0 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #2 - NOP - MLANE R1, R11, R9, R1 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #3 - NOP - MLANE R10, R11, R9, R10 - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - MULNE R9, R7, R12 - NOP @ Block #4 - NOP - MLANE LR, R11, R9, LR - NOP - NOP - NOP - NOP - BIC R7, R7, R2, ASR#1 - STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples - SUBS R8, R8, #8 - BGT C_fast_mixing_loop - /* restore previously saved values */ - LDMFD SP, {SP} @ reload original stack pointer from VLA - LDMFD SP!, {R2, R3} - B C_end_mixing - -/* Various variables for the cached mixer */ - - .align 2 -upper_stack_bounds: - .word 0x03007910 -previous_fast_code: - .word 0x0 /* mark as invalid initially */ - -/* Those instructions below are used by the high speed loop self modifying code */ -high_speed_code_resource: - /* Block for Mix Freq < 1.0 * Output Frequency */ - MOV R9, R9, ASR#22 - ADDS R9, R9, R6, LSL#1 - ADDS R7, R7, R4 - ADDPL R6, R12, R6 - LDRPLSB R12, [R3, #1]! - SUBPLS R12, R12, R6 - - /* Block for Mix Freq > 1.0 AND < 2.0 * Output Frequency */ - ADDS R9, R6, R9, ASR#23 - ADD R6, R12, R6 - ADDS R7, R7, R4 - LDRPLSB R6, [R3, #1]! - LDRSB R12, [R3, #1]! - SUBS R12, R12, R6 - - /* Block for Mix Freq > 2.0 * Output Frequency */ - ADDS R9, R6, R9, ASR#23 - ADD R7, R7, R4 - ADD R3, R3, R7, LSR#23 - LDRSB R6, [R3] - LDRSB R12, [R3, #1]! - SUBS R12, R12, R6 - -/* incase a loop or end occurs during mixing, this code is used */ -C_setup_unbuffered_mixing: - ADD R5, R5, R8, LSL#2 @ R5 = End of HQ buffer - -/* This below is the unbuffered mixing loop. R6 = base sample, R12 diff to next */ -C_unbuffered_mixing_loop: - - MUL R9, R7, R12 - MOV R9, R9, ASR#22 - ADDS R9, R9, R6, LSL#1 - LDRNE R0, [R5, -R8, LSL#2] - MLANE R0, R11, R9, R0 - STRNE R0, [R5, -R8, LSL#2] - ADD R7, R7, R4 - MOVS R9, R7, LSR#23 - BEQ C_unbuffered_mixing_skip_load @ skip the mixing load if it isn't required - - SUBS R2, R2, R7, LSR#23 - BLLE C_mixing_loop_or_end - SUBS R9, R9, #1 - ADDEQ R6, R12, R6 - @RETURN LOCATION FROM LOOP HANDLER - LDRNESB R6, [R3, R9]! - LDRSB R12, [R3, #1]! - SUB R12, R12, R6 - BIC R7, R7, #0x3F800000 - -C_unbuffered_mixing_skip_load: - SUBS R8, R8, #1 @ reduce the sample count for the buffer by #1 - BGT C_unbuffered_mixing_loop - -C_end_mixing: - SUB R3, R3, #1 @ because the mixer always needs 1 byte lookahead, this reverts it - LDMFD SP!, {R4, R9, R12} - STR R7, [R4, #CHN_FINE_POSITION] - B C_mixing_end_store - -C_mixing_loop_or_end: - /* This loads the loop information end loops incase it should */ - ADD R3, SP, #ARG_LOOP_START_POS+0xC - LDMIA R3, {R3, R6} @ R3 = Loop Start; R6 = Loop Length - CMP R6, #0 @ check if loop is enabled; if Loop is enabled R6 is != 0 - RSBNE R9, R2, #0 @ loop wraparound logic - ADDNE R2, R6, R2 - ADDNE PC, LR, #(ARM_OP_LEN*2) - LDMFD SP!, {R4, R9, R12} - B C_mixing_end_and_stop_channel @ R6 == 0 (always) - -C_fixed_mixing_loop_or_end: - LDR R2, [SP, #ARG_LOOP_LENGTH+0x8] - MOVS R6, R2 @ copy it to R6 and check whether loop is disabled - LDRNE R3, [SP, #ARG_LOOP_START_POS+0x8] - BXNE LR @ if it loops return to mixing function, if it doesn't go on end mixing - - LDMFD SP!, {R4, R9} - -C_mixing_end_and_stop_channel: - STRB R6, [R4] @ update channel flag with chn halt - B C_mixing_epilogue - -/* These are used for the fixed freq mixer */ -fixed_mixing_code_resource: - MOVS R6, R10, LSL#24 - MOVS R6, R6, ASR#24 - MOVS R6, R10, LSL#16 - MOVS R6, R6, ASR#24 - MOVS R6, R10, LSL#8 - MOVS R6, R6, ASR#24 - MOVS R6, R10, ASR#24 - LDMIA R3!, {R10} @ load chunk of samples - MOVS R6, R10, LSL#24 - MOVS R6, R6, ASR#24 - MOVS R6, R10, LSL#16 - MOVS R6, R6, ASR#24 - MOVS R6, R10, LSL#8 - MOVS R6, R6, ASR#24 - LDMFD SP!, {R4, R9, R12} - -C_setup_fixed_freq_mixing: - STMFD SP!, {R4, R9} - -C_fixed_mixing_length_check: - MOV LR, R2 @ sample countdown - CMP R2, R8 - MOVGT LR, R8 @ min(buffer_size, sample_countdown) - SUB LR, LR, #1 - MOVS LR, LR, LSR#2 - BEQ C_fixed_mixing_process_rest @ <= 3 samples to process - - SUB R8, R8, LR, LSL#2 @ subtract the amount of samples we need to process from the buffer length - SUB R2, R2, LR, LSL#2 @ subtract the amount of samples we need to process from the remaining samples - ADR R1, fixed_mixing_instructions - ADR R0, fixed_mixing_code_resource - MOV R9, R3, LSL#30 - ADD R0, R0, R9, LSR#27 @ alignment * 8 + resource offset = new resource offset - LDMIA R0!, {R6, R7, R9, R10} @ load and write instructions - STMIA R1, {R6, R7} - ADD R1, R1, #0xC - STMIA R1, {R9, R10} - ADD R1, R1, #0xC - LDMIA R0, {R6, R7, R9, R10} - STMIA R1, {R6, R7} - ADD R1, R1, #0xC - STMIA R1, {R9, R10} - LDMIA R3!, {R10} @ load 4 samples from ROM - -C_fixed_mixing_loop: - LDMIA R5, {R0, R1, R7, R9} @ load 4 samples from hq buffer - -fixed_mixing_instructions: - NOP - NOP - MLANE R0, R11, R6, R0 @ add new sample if neccessary - NOP - NOP - MLANE R1, R11, R6, R1 - NOP - NOP - MLANE R7, R11, R6, R7 - NOP - NOP - MLANE R9, R11, R6, R9 - STMIA R5!, {R0, R1, R7, R9} @ write samples to the mixing buffer - SUBS LR, LR, #1 - BNE C_fixed_mixing_loop - - SUB R3, R3, #4 @ we'll need to load this block again, so rewind a bit - -C_fixed_mixing_process_rest: - MOV R1, #4 @ repeat the loop #4 times to completley get rid of alignment errors - -C_fixed_mixing_unaligned_loop: - LDR R0, [R5] - LDRSB R6, [R3], #1 - MLA R0, R11, R6, R0 - STR R0, [R5], #4 - SUBS R2, R2, #1 - BLEQ C_fixed_mixing_loop_or_end - SUBS R1, R1, #1 - BGT C_fixed_mixing_unaligned_loop - - SUBS R8, R8, #4 - BGT C_fixed_mixing_length_check @ repeat the mixing procedure until the buffer is filled - - LDMFD SP!, {R4, R9} - -C_mixing_end_store: - STR R2, [R4, #CHN_SAMPLE_COUNTDOWN] - STR R3, [R4, #CHN_POSITION_ABS] - -C_mixing_epilogue: - ADR R0, (C_end_channel_state_loop+1) - BX R0 - - .thumb - -C_end_channel_state_loop: - LDR R0, [SP, #ARG_REMAIN_CHN] - SUB R0, #1 - BLE C_main_mixer_return - - ADD R4, #0x40 - B C_channel_state_loop - -C_main_mixer_return: - ADR R5, V_noise_shape - LDRB R4, [R5, #0] @ left noise shape - LSL R4, R4, #16 - LDRB R5, [R5, #1] @ right noise shape - LSL R5, R5, #16 - ADR R0, C_downsampler - BX R0 - - -V_noise_shape: - .byte 0, 0 - - .arm - .align 2 - -C_downsampler: - LDR R8, [SP, #ARG_FRAME_LENGTH] - LDR R9, [SP, #ARG_BUFFER_POS] - LDR R10, hq_buffer - MOV R11, #0xFF000000 - MOV LR, #0xC0000000 - -C_downsampler_loop: - LDMIA R10, {R0, R1, R2, R3} - ADD R12, R4, R0 @ left sample #1 - ADDS R4, R12, R12 - EORVS R12, LR, R4, ASR#31 - AND R4, R12, #0x007F0000 - AND R6, R11, R12, LSL#1 - - ADD R0, R5, R0, LSL#16 @ right - ADDS R5, R0, R0 - EORVS R0, LR, R5, ASR#31 - AND R5, R0, #0x007F0000 - AND R7, R11, R0, LSL#1 - - ADD R12, R4, R1 @ left sample #2 - ADDS R4, R12, R12 - EORVS R12, LR, R4, ASR#31 - AND R4, R12, #0x007F0000 - AND R12, R11, R12, LSL#1 - ORR R6, R12, R6, LSR#8 - - ADD R1, R5, R1, LSL#16 @ right - ADDS R5, R1, R1 - EORVS R1, LR, R5, ASR#31 - AND R5, R1, #0x007F0000 - AND R1, R11, R1, LSL#1 - ORR R7, R1, R7, LSR#8 - - ADD R12, R4, R2 @ left sample #3 - ADDS R4, R12, R12 - EORVS R12, LR, R4, ASR#31 - AND R4, R12, #0x007F0000 - AND R12, R11, R12, LSL#1 - ORR R6, R12, R6, LSR#8 - - ADD R2, R5, R2, LSL#16 @ right - ADDS R5, R2, R2 - EORVS R2, LR, R5, ASR#31 - AND R5, R2, #0x007F0000 - AND R2, R11, R2, LSL#1 - ORR R7, R2, R7, LSR#8 - - ADD R12, R4, R3 @ left sample #4 - ADDS R4, R12, R12 - EORVS R12, LR, R4, ASR#31 - AND R4, R12, #0x007F0000 - AND R12, R11, R12, LSL#1 - ORR R6, R12, R6, LSR#8 - - ADD R3, R5, R3, LSL#16 @ right - ADDS R5, R3, R3 - EORVS R3, LR, R5, ASR#31 - AND R5, R3, #0x007F0000 - AND R3, R11, R3, LSL#1 - ORR R7, R3, R7, LSR#8 - - STR R6, [R9, #0x630] - STR R7, [R9], #4 - MOV R0, #0 - MOV R1, #0 - MOV R2, #0 - MOV R3, #0 - - STMIA R10!, {R0, R1, R2, R3} - - SUBS R8, #4 - BGT C_downsampler_loop - - ADR R1, V_noise_shape - ADR R0, (C_downsampler_return+1) - BX R0 - - .pool - - .align 1 - .thumb - -C_downsampler_return: - LSR R4, #16 - STRB R4, [R1, #0] - LSR R5, #16 - STRB R5, [R1, #1] - LDR R0, [SP, #ARG_PCM_STRUCT] - LDR R3, mixer_finished_status @ this is used to indicate the interrupt handler the rendering was finished properly - STR R3, [R0] - ADD SP, SP, #0x1C - POP {R0-R7} - MOV R8, R0 - MOV R9, R1 - MOV R10, R2 - MOV R11, R3 - POP {R3} - BX R3 - - .align 2 - -mixer_finished_status: - .word 0x68736D53 - - .arm - .align 2 - -C_setup_synth: - CMP R12, #0 - BNE C_check_synth_saw - - /* modulating pulse wave */ - LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_1] - ADD R2, R2, R6, LSL#24 - LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_2] - ADDS R6, R2, R6, LSL#24 - MVNMI R6, R6 - MOV R10, R6, LSR#8 - LDRB R1, [R3, #SYNTH_MOD_AMOUNT] - LDRB R0, [R3, #SYNTH_BASE_WAVE_DUTY] - MOV R0, R0, LSL#24 - MLA R6, R10, R1, R0 @ calculate the final duty cycle with the offset, and intensity * rotating duty cycle amount - STMFD SP!, {R2, R3, R9, R12} - -C_synth_pulse_loop: - LDMIA R5, {R0-R3, R9, R10, R12, LR} @ load 8 samples - CMP R7, R6 @ Block #1 - ADDLO R0, R0, R11, LSL#6 - SUBHS R0, R0, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #2 - ADDLO R1, R1, R11, LSL#6 - SUBHS R1, R1, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #3 - ADDLO R2, R2, R11, LSL#6 - SUBHS R2, R2, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #4 - ADDLO R3, R3, R11, LSL#6 - SUBHS R3, R3, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #5 - ADDLO R9, R9, R11, LSL#6 - SUBHS R9, R9, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #6 - ADDLO R10, R10, R11, LSL#6 - SUBHS R10, R10, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #7 - ADDLO R12, R12, R11, LSL#6 - SUBHS R12, R12, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - CMP R7, R6 @ Block #8 - ADDLO LR, LR, R11, LSL#6 - SUBHS LR, LR, R11, LSL#6 - ADDS R7, R7, R4, LSL#3 - - STMIA R5!, {R0-R3, R9, R10, R12, LR} @ write 8 samples - SUBS R8, R8, #8 - BGT C_synth_pulse_loop - - LDMFD SP!, {R2, R3, R9, R12} - B C_end_mixing - -C_check_synth_saw: - /* - * This is actually not a true saw wave - * but looks pretty similar - * (has a jump in the middle of the wave) - */ - SUBS R12, R12, #1 - BNE C_synth_triangle - - MOV R6, #0x300 - MOV R11, R11, LSR#1 - BIC R11, R11, #0xFF00 - MOV R12, #0x70 - -C_synth_saw_loop: - - LDMIA R5, {R0, R1, R10, LR} @ load 4 samples from memory - ADDS R7, R7, R4, LSL#3 @ Block #1 (some oscillator type code) - RSB R9, R12, R7, LSR#24 - MOV R6, R7, LSL#1 - SUB R9, R9, R6, LSR#27 - ADDS R2, R9, R2, ASR#1 - MLANE R0, R11, R2, R0 - - ADDS R7, R7, R4, LSL#3 @ Block #2 - RSB R9, R12, R7, LSR#24 - MOV R6, R7, LSL#1 - SUB R9, R9, R6, LSR#27 - ADDS R2, R9, R2, ASR#1 - MLANE R1, R11, R2, R1 - - ADDS R7, R7, R4, LSL#3 @ Block #3 - RSB R9, R12, R7, LSR#24 - MOV R6, R7, LSL#1 - SUB R9, R9, R6, LSR#27 - ADDS R2, R9, R2, ASR#1 - MLANE R10, R11, R2, R10 - - ADDS R7, R7, R4, LSL#3 @ Block #4 - RSB R9, R12, R7, LSR#24 - MOV R6, R7, LSL#1 - SUB R9, R9, R6, LSR#27 - ADDS R2, R9, R2, ASR#1 - MLANE LR, R11, R2, LR - - STMIA R5!, {R0, R1, R10, LR} - SUBS R8, R8, #4 - BGT C_synth_saw_loop - - B C_end_mixing - -C_synth_triangle: - MOV R6, #0x80 - MOV R12, #0x180 - -C_synth_triangle_loop: - LDMIA R5, {R0, R1, R10, LR} @ load samples from work buffer - ADDS R7, R7, R4, LSL#3 @ Block #1 - RSBPL R9, R6, R7, ASR#23 - SUBMI R9, R12, R7, LSR#23 - MLA R0, R11, R9, R0 - - ADDS R7, R7, R4, LSL#3 @ Block #2 - RSBPL R9, R6, R7, ASR#23 - SUBMI R9, R12, R7, LSR#23 - MLA R1, R11, R9, R1 - - ADDS R7, R7, R4, LSL#3 @ Block #3 - RSBPL R9, R6, R7, ASR#23 - SUBMI R9, R12, R7, LSR#23 - MLA R10, R11, R9, R10 - - ADDS R7, R7, R4, LSL#3 @ Block #4 - RSBPL R9, R6, R7, ASR#23 - SUBMI R9, R12, R7, LSR#23 - MLA LR, R11, R9, LR - - STMIA R5!, {R0, R1, R10, LR} - SUBS R8, R8, #4 @ subtract #4 from the remainging samples - BGT C_synth_triangle_loop - - B C_end_mixing - - .if ENABLE_DECOMPRESSION==1 -C_setup_special_mixing: - LDR R6, [R4, #CHN_WAVE_OFFSET] - LDRB R0, [R4] - TST R0, #FLAG_CHN_COMP - BNE C_setup_special_mixing_freq @ skip the setup procedure if it's running in compressed mode already - - ORR R0, #FLAG_CHN_COMP - STRB R0, [R4] - LDRB R0, [R4, #CHN_MODE] - TST R0, #MODE_REVERSE - BEQ C_check_compression @ reversed mode not enabled? - - LDR R1, [R6, #WAVE_LENGTH] @ calculate seek position for reverse playback - ADD R1, R1, R6, LSL#1 @ sorry, I don't actually understand that piece of code myself - ADD R1, R1, #0x20 - SUB R3, R1, R3 - STR R3, [R4, #CHN_POSITION_ABS] - -C_check_compression: - LDRH R0, [R6] - CMP R0, #0 - BEQ C_setup_special_mixing_freq - - SUB R3, R3, R6 - SUB R3, R3, #0x10 - STR R3, [R4, #CHN_POSITION_ABS] - -C_setup_special_mixing_freq: - LDR R0, [R6, #WAVE_LOOP_START] - STR R0, [SP, #ARG_LOOP_START_POS] - - STMFD SP!, {R4, R9, R12} - - MOVS R11, R11, LSR#1 - ADC R11, R11, #0x8000 - BIC R11, R11, #0xFF00 - - LDR R7, [R4, #CHN_FINE_POSITION] - LDR R1, [R4, #CHN_FREQUENCY] - LDRB R0, [R4, #CHN_MODE] - TST R0, #MODE_FIXED_FREQ - MOVNE R1, #0x800000 - MULEQ R1, R12, R1 @ default rate factor * frequency = sample steps - - ADD R5, R5, R8, LSL#2 @ set the buffer pointer to the end of the channel, same as slow mixing mode - - LDRH R0, [R6] - CMP R0, #0 - BEQ C_uncompressed_reverse_mixing_check - - MOV R0, #0xFF000000 @ --> invalid channel mod - STR R0, [R4, #CHN_BLOCK_COUNT] - LDRB R0, [R4, #CHN_MODE] - TST R0, #MODE_REVERSE - BNE C_setup_compressed_reverse_mixing @ check again of reverse mixing is enabled - - /* forward compressed mixing */ - BL F_bdpcm_decoder - MOV R6, R12 - ADD R3, R3, #1 - BL F_bdpcm_decoder - SUB R12, R12, R6 - - @***** MIXING LOOP REGISTER USAGE ***********@ - @ R0: Sample to modify from buffer - @ R1: sample steps (MOVED FROM R4) - @ R2: remaining samples before loop/end - @ R3: sample position - @ R4: channel pointer - @ R5: pointer to the end of buffer - @ R6: Base sample - @ R7: fine position - @ R8: remaining samples for current buffer - @ R9: interpolated sample - @ R10: not used - @ R11: volume - @ R12: Delta Sample - @ LR: not used - @********************************************@ - -C_compressed_mixing_loop: - MUL R9, R7, R12 @ check slow mixing for details, same procedure here - MOV R9, R9, ASR#22 - ADDS R9, R9, R6, LSL#1 - LDRNE R0, [R5, -R8, LSL#2] - MLANE R0, R11, R9, R0 - STRNE R0, [R5, -R8, LSL#2] - ADD R7, R7, R1 @ ### changed from R4 to R1 - MOVS R9, R7, LSR#23 - BEQ C_compressed_mixing_skip_load - - SUBS R2, R2, R7, LSR#23 - BLLE C_mixing_loop_or_end - SUBS R9, R9, #1 - ADDEQ R6, R12, R6 - BEQ C_compressed_mixing_skip_base_load - - ADD R3, R3, R9 @ equivalent to LDRNESB R6, [R3, R9]! - BL F_bdpcm_decoder - MOV R6, R12 - -C_compressed_mixing_skip_base_load: - ADD R3, R3, #1 @ equivalent to LDRSB R12, [R3, #1]! - BL F_bdpcm_decoder - SUB R12, R12, R6 - BIC R7, R7, #0x3F800000 - -C_compressed_mixing_skip_load: - SUBS R8, R8, #1 - BGT C_compressed_mixing_loop - - B C_end_mixing - -C_setup_compressed_reverse_mixing: - SUB R3, R3, #1 - BL F_bdpcm_decoder - MOV R6, R12 - SUB R3, R3, #1 - BL F_bdpcm_decoder - SUB R12, R12, R6 - -C_compressed_reverse_mixing_loop: - MUL R9, R7, R12 - MOV R9, R9, ASR#22 - ADDS R9, R9, R6, LSL#1 - LDRNE R0, [R5, -R8, LSL#2] - MLANE R0, R11, R9, R0 - STRNE R0, [R5, -R8, LSL#2] - ADD R7, R7, R1 @ ### changed from R4 to R1 - MOVS R9, R7, LSR#23 - BEQ C_compressed_reverse_mixing_skip_load - - SUBS R2, R2, R7, LSR#23 - BLLE C_mixing_loop_or_end - SUBS R9, R9, #1 - ADDEQ R6, R12, R6 - BEQ C_compressed_reverse_mixing_skip_base_load - - SUB R3, R3, R9 - BL F_bdpcm_decoder - MOV R6, R12 - -C_compressed_reverse_mixing_skip_base_load: - SUB R3, R3, #1 - BL F_bdpcm_decoder - SUB R12, R12, R6 - BIC R7, R7, #0x3F800000 - -C_compressed_reverse_mixing_skip_load: - SUBS R8, R8, #1 - BGT C_compressed_reverse_mixing_loop - - ADD R3, R3, #3 - B C_end_mixing - -C_uncompressed_reverse_mixing_check: - LDRB R0, [R4, #1] - TST R0, #MODE_REVERSE @ check if reverse mode is even enabled (consistency) - BEQ C_end_mixing - - LDRSB R6, [R3, #-1]! - LDRSB R12, [R3, #-1] - SUB R12, R12, R6 - -C_uncompressed_reverse_mixing_loop: - MUL R9, R7, R12 - MOV R9, R9, ASR#22 - ADDS R9, R9, R6, LSL#1 - LDRNE R0, [R5, -R8, LSL#2] - MLANE R0, R11, R9, R0 - STRNE R0, [R5, -R8, LSL#2] - ADD R7, R7, R1 @ ### changed from R4 to R1 - MOVS R9, R7, LSR#23 - BEQ C_uncompressed_reverse_mixing_load_skip - - SUBS R2, R2, R7, LSR#23 - BLLE C_mixing_loop_or_end - - MOVS R9, R9 - ADDEQ R6, R12, R6 - LDRNESB R6, [R3, -R9]! - LDRSB R12, [R3, #-1] - SUB R12, R12, R6 - BIC R7, R7, #0x3F800000 - -C_uncompressed_reverse_mixing_load_skip: - SUBS R8, R8, #1 - BGT C_uncompressed_reverse_mixing_loop - - ADD R3, R3, #2 - B C_end_mixing - -/* - * This is the main BDPCM Decoder - * It decodes and caches a block of PCM data - * and returns them in R12 - */ -F_bdpcm_decoder: - - STMFD SP!, {R0, LR} - MOV R0, R3, LSR#6 @ clip off everything but the block offset, each block is 0x40 samples long - LDR R12, [R4, #CHN_BLOCK_COUNT] - CMP R0, R12 - BEQ C_bdpcm_decoder_return @ block already decoded -> skip - - STMFD SP!, {R2, R5-R7} - STR R0, [R4, #CHN_BLOCK_COUNT] - MOV R12, #0x21 @ 1 Block = 0x21 Bytes, 0x40 decoded samples - MUL R2, R12, R0 - LDR R12, [R4, #CHN_WAVE_OFFSET] - ADD R2, R2, R12 @ calc block ROM position - ADD R2, R2, #0x10 - LDR R5, decoder_buffer - ADR R6, delta_lookup_table - MOV R7, #0x40 @ 1 block = 0x40 samples - LDRB LR, [R2], #1 - STRB LR, [R5], #1 - LDRB R12, [R2], #1 - B C_bdpcm_decoder_lsb - -C_bdpcm_decoder_msb: - LDRB R12, [R2], #1 - MOV R0, R12, LSR#4 - LDRSB R0, [R6, R0] - ADD LR, LR, R0 - STRB LR, [R5], #1 - -C_bdpcm_decoder_lsb: - AND R0, R12, #0xF - LDRSB R0, [R6, R0] - ADD LR, LR, R0 - STRB LR, [R5], #1 - SUBS R7, R7, #2 - BGT C_bdpcm_decoder_msb - - LDMFD SP!, {R2, R5-R7} -C_bdpcm_decoder_return: - LDR R12, decoder_buffer - AND R0, R3, #0x3F - LDRSB R12, [R12, R0] - LDMFD SP!, {R0, PC} - - .align 2 - -decoder_buffer: - .word gUnknown_03001300 - -delta_lookup_table: - .byte 0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF - -.endif /* ENABLE_DECOMPRESSION*/ - -main_mixer_end: - .syntax unified - - thumb_func_start SoundMainBTM -SoundMainBTM: - mov r12, r4 - movs r1, 0 - movs r2, 0 - movs r3, 0 - movs r4, 0 - stm r0!, {r1-r4} - stm r0!, {r1-r4} - stm r0!, {r1-r4} - stm r0!, {r1-r4} - mov r4, r12 - bx lr - thumb_func_end SoundMainBTM - - thumb_func_start RealClearChain -RealClearChain: - ldr r3, [r0, 0x2C] - cmp r3, 0 - beq _081DD5E2 - ldr r1, [r0, 0x34] - ldr r2, [r0, 0x30] - cmp r2, 0 - beq _081DD5D6 - str r1, [r2, 0x34] - b _081DD5D8 -_081DD5D6: - str r1, [r3, 0x20] -_081DD5D8: - cmp r1, 0 - beq _081DD5DE - str r2, [r1, 0x30] -_081DD5DE: - movs r1, 0 - str r1, [r0, 0x2C] -_081DD5E2: - bx lr - thumb_func_end RealClearChain - - thumb_func_start ply_fine -ply_fine: - push {r4,r5,lr} - adds r5, r1, 0 - ldr r4, [r5, o_MusicPlayerTrack_chan] - cmp r4, 0 - beq ply_fine_done -ply_fine_loop: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq ply_fine_ok - movs r0, 0x40 - orrs r1, r0 - strb r1, [r4] -ply_fine_ok: - adds r0, r4, 0 - bl RealClearChain - ldr r4, [r4, 0x34] - cmp r4, 0 - bne ply_fine_loop -ply_fine_done: - movs r0, 0 - strb r0, [r5] - pop {r4,r5} - pop {r0} - bx r0 - thumb_func_end ply_fine - - thumb_func_start MPlayJumpTableCopy -MPlayJumpTableCopy: - mov r12, lr - movs r1, 0x24 - ldr r2, lt_MPlayJumpTableTemplate -MPlayJumpTableCopy_Loop: - ldr r3, [r2] - bl chk_adr_r2 - stm r0!, {r3} - adds r2, 0x4 - subs r1, 0x1 - bgt MPlayJumpTableCopy_Loop - bx r12 - thumb_func_end MPlayJumpTableCopy - - .align 2, 0 - .thumb_func -ldrb_r3_r2: - ldrb r3, [r2] - -@ This attempts to protect against reading anything from the BIOS ROM -@ besides the jump table template. -@ It assumes that the jump table template is located at the end of the ROM. - .thumb_func -chk_adr_r2: - push {r0} - lsrs r0, r2, 25 - bne chk_adr_r2_done @ if adr >= 0x2000000 (i.e. not in BIOS ROM), accept it - ldr r0, lt_MPlayJumpTableTemplate - cmp r2, r0 - blo chk_adr_r2_reject @ if adr < gMPlayJumpTableTemplate, reject it - lsrs r0, r2, 14 - beq chk_adr_r2_done @ if adr < 0x40000 (i.e. in BIOS ROM), accept it -chk_adr_r2_reject: - movs r3, 0 -chk_adr_r2_done: - pop {r0} - bx lr - - .align 2, 0 -lt_MPlayJumpTableTemplate: .word gMPlayJumpTableTemplate - - thumb_func_start ld_r3_tp_adr_i -ld_r3_tp_adr_i: - ldr r2, [r1, 0x40] -_081DD64A: - adds r3, r2, 0x1 - str r3, [r1, 0x40] - ldrb r3, [r2] - b chk_adr_r2 - thumb_func_end ld_r3_tp_adr_i - - thumb_func_start ply_goto -ply_goto: - push {lr} -ply_goto_1: - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r0, [r2, 0x3] - lsls r0, 8 - ldrb r3, [r2, 0x2] - orrs r0, r3 - lsls r0, 8 - ldrb r3, [r2, 0x1] - orrs r0, r3 - lsls r0, 8 - bl ldrb_r3_r2 - orrs r0, r3 - str r0, [r1, o_MusicPlayerTrack_cmdPtr] - pop {r0} - bx r0 - thumb_func_end ply_goto - - thumb_func_start ply_patt -ply_patt: - ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] - cmp r2, 3 - bhs ply_patt_done - lsls r2, 2 - adds r3, r1, r2 - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - adds r2, 0x4 - str r2, [r3, o_MusicPlayerTrack_patternStack] - ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] - adds r2, 1 - strb r2, [r1, o_MusicPlayerTrack_patternLevel] - b ply_goto -ply_patt_done: - b ply_fine - thumb_func_end ply_patt - - thumb_func_start ply_pend -ply_pend: - ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] - cmp r2, 0 - beq ply_pend_done - subs r2, 1 - strb r2, [r1, o_MusicPlayerTrack_patternLevel] - lsls r2, 2 - adds r3, r1, r2 - ldr r2, [r3, o_MusicPlayerTrack_patternStack] - str r2, [r1, o_MusicPlayerTrack_cmdPtr] -ply_pend_done: - bx lr - thumb_func_end ply_pend - - thumb_func_start ply_rept -ply_rept: - push {lr} - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r3, [r2] - cmp r3, 0 - bne ply_rept_1 - adds r2, 1 - str r2, [r1, o_MusicPlayerTrack_cmdPtr] - b ply_goto_1 -ply_rept_1: - ldrb r3, [r1, o_MusicPlayerTrack_repN] - adds r3, 1 - strb r3, [r1, o_MusicPlayerTrack_repN] - mov r12, r3 - bl ld_r3_tp_adr_i - cmp r12, r3 - bhs ply_rept_2 - b ply_goto_1 -ply_rept_2: - movs r3, 0 - strb r3, [r1, o_MusicPlayerTrack_repN] - adds r2, 5 - str r2, [r1, o_MusicPlayerTrack_cmdPtr] - pop {r0} - bx r0 - thumb_func_end ply_rept - - thumb_func_start ply_prio -ply_prio: - mov r12, lr - bl ld_r3_tp_adr_i - strb r3, [r1, o_MusicPlayerTrack_priority] - bx r12 - thumb_func_end ply_prio - - thumb_func_start ply_tempo -ply_tempo: - mov r12, lr - bl ld_r3_tp_adr_i - lsls r3, 1 - strh r3, [r0, o_MusicPlayerInfo_tempoD] - ldrh r2, [r0, o_MusicPlayerInfo_tempoU] - muls r3, r2 - lsrs r3, 8 - strh r3, [r0, o_MusicPlayerInfo_tempoI] - bx r12 - thumb_func_end ply_tempo - - thumb_func_start ply_keysh -ply_keysh: - mov r12, lr - bl ld_r3_tp_adr_i - strb r3, [r1, o_MusicPlayerTrack_keyShift] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_keysh - - thumb_func_start ply_voice -ply_voice: - mov r12, lr - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r3, [r2] - adds r2, 1 - str r2, [r1, o_MusicPlayerTrack_cmdPtr] - lsls r2, r3, 1 - adds r2, r3 - lsls r2, 2 - ldr r3, [r0, o_MusicPlayerInfo_tone] - adds r2, r3 - ldr r3, [r2] - bl chk_adr_r2 - str r3, [r1, o_MusicPlayerTrack_ToneData_type] - ldr r3, [r2, 0x4] - bl chk_adr_r2 - str r3, [r1, o_MusicPlayerTrack_ToneData_wav] - ldr r3, [r2, 0x8] - bl chk_adr_r2 - str r3, [r1, o_MusicPlayerTrack_ToneData_attack] - bx r12 - thumb_func_end ply_voice - - thumb_func_start ply_vol -ply_vol: - mov r12, lr - bl ld_r3_tp_adr_i - strb r3, [r1, o_MusicPlayerTrack_vol] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0x3 - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_vol - - thumb_func_start ply_pan -ply_pan: - mov r12, lr - bl ld_r3_tp_adr_i - subs r3, 0x40 - strb r3, [r1, o_MusicPlayerTrack_pan] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0x3 - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_pan - - thumb_func_start ply_bend -ply_bend: - mov r12, lr - bl ld_r3_tp_adr_i - subs r3, 0x40 - strb r3, [r1, o_MusicPlayerTrack_bend] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_bend - - thumb_func_start ply_bendr -ply_bendr: - mov r12, lr - bl ld_r3_tp_adr_i - strb r3, [r1, o_MusicPlayerTrack_bendRange] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_bendr - - thumb_func_start ply_lfodl -ply_lfodl: - mov r12, lr - bl ld_r3_tp_adr_i - strb r3, [r1, o_MusicPlayerTrack_lfoDelay] - bx r12 - thumb_func_end ply_lfodl - - thumb_func_start ply_modt -ply_modt: - mov r12, lr - bl ld_r3_tp_adr_i - ldrb r0, [r1, o_MusicPlayerTrack_modT] - cmp r0, r3 - beq _081DD7AA - strb r3, [r1, o_MusicPlayerTrack_modT] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0xF - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] -_081DD7AA: - bx r12 - thumb_func_end ply_modt - - thumb_func_start ply_tune -ply_tune: - mov r12, lr - bl ld_r3_tp_adr_i - subs r3, 0x40 - strb r3, [r1, o_MusicPlayerTrack_tune] - ldrb r3, [r1, o_MusicPlayerTrack_flags] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx r12 - thumb_func_end ply_tune - - thumb_func_start ply_port -ply_port: - mov r12, lr - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r3, [r2] - adds r2, 1 - ldr r0, =REG_SOUND1CNT_L @ sound register base address - adds r0, r3 - bl _081DD64A - strb r3, [r0] - bx r12 - .pool - thumb_func_end ply_port - - thumb_func_start m4aSoundVSync -m4aSoundVSync: - ldr r0, lt2_SOUND_INFO_PTR - ldr r0, [r0] - - @ Exit the function if ident is not ID_NUMBER or ID_NUMBER+1. - ldr r2, lt2_ID_NUMBER - ldr r3, [r0, o_SoundInfo_ident] - subs r3, r2 - cmp r3, 1 - bhi m4aSoundVSync_Done - - @ Decrement the PCM DMA counter. If it reaches 0, we need to do a DMA. - ldrb r1, [r0, o_SoundInfo_pcmDmaCounter] - subs r1, 1 - strb r1, [r0, o_SoundInfo_pcmDmaCounter] - bgt m4aSoundVSync_Done - - @ Reload the PCM DMA counter. - ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] - strb r1, [r0, o_SoundInfo_pcmDmaCounter] - - ldr r2, =REG_DMA1 - - ldr r1, [r2, 0x8] @ DMA1CNT - lsls r1, 7 - bcc m4aSoundVSync_SkipDMA1 @ branch if repeat bit isn't set - - ldr r1, =((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4 - str r1, [r2, 0x8] @ DMA1CNT - -m4aSoundVSync_SkipDMA1: - ldr r1, [r2, 0xC + 0x8] @ DMA2CNT - lsls r1, 7 - bcc m4aSoundVSync_SkipDMA2 @ branch if repeat bit isn't set - - ldr r1, =((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4 - str r1, [r2, 0xC + 0x8] @ DMA2CNT - -m4aSoundVSync_SkipDMA2: - - @ turn off DMA1/DMA2 - movs r1, DMA_32BIT >> 8 - lsls r1, 8 - strh r1, [r2, 0xA] @ DMA1CNT_H - strh r1, [r2, 0xC + 0xA] @ DMA2CNT_H - - @ turn on DMA1/DMA2 direct-sound FIFO mode - movs r1, (DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT) >> 8 - lsls r1, 8 @ LSB is 0, so DMA_SRC_INC is used (destination is always fixed in FIFO mode) - strh r1, [r2, 0xA] @ DMA1CNT_H - strh r1, [r2, 0xC + 0xA] @ DMA2CNT_H - -m4aSoundVSync_Done: - bx lr - - .pool - thumb_func_end m4aSoundVSync - - thumb_func_start MPlayMain -MPlayMain: - ldr r2, lt2_ID_NUMBER - ldr r3, [r0, o_MusicPlayerInfo_ident] - cmp r2, r3 - beq _081DD82E - bx lr -_081DD82E: - adds r3, 0x1 - str r3, [r0, o_MusicPlayerInfo_ident] - push {r0,lr} - ldr r3, [r0, o_MusicPlayerInfo_func] - cmp r3, 0 - beq _081DD840 - ldr r0, [r0, o_MusicPlayerInfo_intp] - bl call_r3 -_081DD840: - pop {r0} - push {r4-r7} - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4-r7} - adds r7, r0, 0 - ldr r0, [r7, o_MusicPlayerInfo_status] - cmp r0, 0 - bge _081DD858 - b _081DDA6C -_081DD858: - ldr r0, lt2_SOUND_INFO_PTR - ldr r0, [r0] - mov r8, r0 - adds r0, r7, 0 - bl FadeOutBody - ldr r0, [r7, o_MusicPlayerInfo_status] - cmp r0, 0 - bge _081DD86C - b _081DDA6C -_081DD86C: - ldrh r0, [r7, o_MusicPlayerInfo_tempoC] - ldrh r1, [r7, o_MusicPlayerInfo_tempoI] - adds r0, r1 - b _081DD9BC -_081DD874: - ldrb r6, [r7, o_MusicPlayerInfo_trackCount] - ldr r5, [r7, o_MusicPlayerInfo_tracks] - movs r3, 0x1 - movs r4, 0 -_081DD87C: - ldrb r0, [r5] - movs r1, 0x80 - tst r1, r0 - bne _081DD886 - b _081DD998 -_081DD886: - mov r10, r3 - orrs r4, r3 - mov r11, r4 - ldr r4, [r5, o_MusicPlayerTrack_chan] - cmp r4, 0 - beq _081DD8BA -_081DD892: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _081DD8AE - ldrb r0, [r4, 0x10] - cmp r0, 0 - beq _081DD8B4 - subs r0, 0x1 - strb r0, [r4, 0x10] - bne _081DD8B4 - movs r0, 0x40 - orrs r1, r0 - strb r1, [r4] - b _081DD8B4 -_081DD8AE: - adds r0, r4, 0 - bl ClearChain -_081DD8B4: - ldr r4, [r4, 0x34] - cmp r4, 0 - bne _081DD892 -_081DD8BA: - ldrb r3, [r5, o_MusicPlayerTrack_flags] - movs r0, 0x40 - tst r0, r3 - beq _081DD938 - adds r0, r5, 0 - bl Clear64byte - movs r0, 0x80 - strb r0, [r5] - movs r0, 0x2 - strb r0, [r5, o_MusicPlayerTrack_bendRange] - movs r0, 0x40 - strb r0, [r5, o_MusicPlayerTrack_volX] - movs r0, 0x16 - strb r0, [r5, o_MusicPlayerTrack_lfoSpeed] - movs r0, 0x1 - adds r1, r5, 0x6 - strb r0, [r1, o_MusicPlayerTrack_ToneData_type - 0x6] - b _081DD938 -_081DD8E0: - ldr r2, [r5, o_MusicPlayerTrack_cmdPtr] - ldrb r1, [r2] - cmp r1, 0x80 - bhs _081DD8EC - ldrb r1, [r5, o_MusicPlayerTrack_runningStatus] - b _081DD8F6 -_081DD8EC: - adds r2, 0x1 - str r2, [r5, o_MusicPlayerTrack_cmdPtr] - cmp r1, 0xBD - bcc _081DD8F6 - strb r1, [r5, o_MusicPlayerTrack_runningStatus] -_081DD8F6: - cmp r1, 0xCF - bcc _081DD90C - mov r0, r8 - ldr r3, [r0, o_SoundInfo_plynote] - adds r0, r1, 0 - subs r0, 0xCF - adds r1, r7, 0 - adds r2, r5, 0 - bl call_r3 - b _081DD938 -_081DD90C: - cmp r1, 0xB0 - bls _081DD92E - adds r0, r1, 0 - subs r0, 0xB1 - strb r0, [r7, o_MusicPlayerInfo_cmd] - mov r3, r8 - ldr r3, [r3, o_SoundInfo_MPlayJumpTable] - lsls r0, 2 - ldr r3, [r3, r0] - adds r0, r7, 0 - adds r1, r5, 0 - bl call_r3 - ldrb r0, [r5, o_MusicPlayerTrack_flags] - cmp r0, 0 - beq _081DD994 - b _081DD938 -_081DD92E: - ldr r0, lt_gClockTable - subs r1, 0x80 - adds r1, r0 - ldrb r0, [r1] - strb r0, [r5, o_MusicPlayerTrack_wait] -_081DD938: - ldrb r0, [r5, o_MusicPlayerTrack_wait] - cmp r0, 0 - beq _081DD8E0 - subs r0, 0x1 - strb r0, [r5, o_MusicPlayerTrack_wait] - ldrb r1, [r5, o_MusicPlayerTrack_lfoSpeed] - cmp r1, 0 - beq _081DD994 - ldrb r0, [r5, o_MusicPlayerTrack_mod] - cmp r0, 0 - beq _081DD994 - ldrb r0, [r5, o_MusicPlayerTrack_lfoDelayC] - cmp r0, 0 - beq _081DD95A - subs r0, 0x1 - strb r0, [r5, o_MusicPlayerTrack_lfoDelayC] - b _081DD994 -_081DD95A: - ldrb r0, [r5, o_MusicPlayerTrack_lfoSpeedC] - adds r0, r1 - strb r0, [r5, o_MusicPlayerTrack_lfoSpeedC] - adds r1, r0, 0 - subs r0, 0x40 - lsls r0, 24 - bpl _081DD96E - lsls r2, r1, 24 - asrs r2, 24 - b _081DD972 -_081DD96E: - movs r0, 0x80 - subs r2, r0, r1 -_081DD972: - ldrb r0, [r5, o_MusicPlayerTrack_mod] - muls r0, r2 - asrs r2, r0, 6 - ldrb r0, [r5, o_MusicPlayerTrack_modM] - eors r0, r2 - lsls r0, 24 - beq _081DD994 - strb r2, [r5, o_MusicPlayerTrack_modM] - ldrb r0, [r5] - ldrb r1, [r5, o_MusicPlayerTrack_modT] - cmp r1, 0 - bne _081DD98E - movs r1, 0xC - b _081DD990 -_081DD98E: - movs r1, 0x3 -_081DD990: - orrs r0, r1 - strb r0, [r5, o_MusicPlayerTrack_flags] -_081DD994: - mov r3, r10 - mov r4, r11 -_081DD998: - subs r6, 0x1 - ble _081DD9A4 - movs r0, 0x50 - adds r5, r0 - lsls r3, 1 - b _081DD87C -_081DD9A4: - ldr r0, [r7, o_MusicPlayerInfo_clock] - adds r0, 0x1 - str r0, [r7, o_MusicPlayerInfo_clock] - cmp r4, 0 - bne _081DD9B6 - movs r0, 0x80 - lsls r0, 24 - str r0, [r7, o_MusicPlayerInfo_status] - b _081DDA6C -_081DD9B6: - str r4, [r7, o_MusicPlayerInfo_status] - ldrh r0, [r7, o_MusicPlayerInfo_tempoC] - subs r0, 0x96 -_081DD9BC: - strh r0, [r7, o_MusicPlayerInfo_tempoC] - cmp r0, 0x96 - bcc _081DD9C4 - b _081DD874 -_081DD9C4: - ldrb r2, [r7, o_MusicPlayerInfo_trackCount] - ldr r5, [r7, o_MusicPlayerInfo_tracks] -_081DD9C8: - ldrb r0, [r5, o_MusicPlayerTrack_flags] - movs r1, 0x80 - tst r1, r0 - beq _081DDA62 - movs r1, 0xF - tst r1, r0 - beq _081DDA62 - mov r9, r2 - adds r0, r7, 0 - adds r1, r5, 0 - bl TrkVolPitSet - ldr r4, [r5, o_MusicPlayerTrack_chan] - cmp r4, 0 - beq _081DDA58 -_081DD9E6: - ldrb r1, [r4, o_SoundChannel_status] - movs r0, 0xC7 - tst r0, r1 - bne _081DD9F6 - adds r0, r4, 0 - bl ClearChain - b _081DDA52 -_081DD9F6: - ldrb r0, [r4, o_SoundChannel_type] - movs r6, 0x7 - ands r6, r0 - ldrb r3, [r5, o_MusicPlayerTrack_flags] - movs r0, 0x3 - tst r0, r3 - beq _081DDA14 - bl ChnVolSetAsm - cmp r6, 0 - beq _081DDA14 - ldrb r0, [r4, o_CgbChannel_mo] - movs r1, 0x1 - orrs r0, r1 - strb r0, [r4, o_CgbChannel_mo] -_081DDA14: - ldrb r3, [r5, o_MusicPlayerTrack_flags] - movs r0, 0xC - tst r0, r3 - beq _081DDA52 - ldrb r1, [r4, o_SoundChannel_ky] - movs r0, 0x8 - ldrsb r0, [r5, r0] - adds r2, r1, r0 - bpl _081DDA28 - movs r2, 0 -_081DDA28: - cmp r6, 0 - beq _081DDA46 - mov r0, r8 - ldr r3, [r0, o_SoundInfo_MidiKeyToCgbFreq] - adds r1, r2, 0 - ldrb r2, [r5, o_MusicPlayerTrack_pitM] - adds r0, r6, 0 - bl call_r3 - str r0, [r4, o_CgbChannel_fr] - ldrb r0, [r4, o_CgbChannel_mo] - movs r1, 0x2 - orrs r0, r1 - strb r0, [r4, o_CgbChannel_mo] - b _081DDA52 -_081DDA46: - adds r1, r2, 0 - ldrb r2, [r5, o_MusicPlayerTrack_pitM] - ldr r0, [r4, o_SoundChannel_wav] - bl MidiKeyToFreq - str r0, [r4, o_SoundChannel_freq] -_081DDA52: - ldr r4, [r4, o_SoundChannel_np] - cmp r4, 0 - bne _081DD9E6 -_081DDA58: - ldrb r0, [r5, o_MusicPlayerTrack_flags] - movs r1, 0xF0 - ands r0, r1 - strb r0, [r5, o_MusicPlayerTrack_flags] - mov r2, r9 -_081DDA62: - subs r2, 0x1 - ble _081DDA6C - movs r0, 0x50 - adds r5, r0 - bgt _081DD9C8 -_081DDA6C: - ldr r0, lt2_ID_NUMBER - str r0, [r7, o_MusicPlayerInfo_ident] - pop {r0-r7} - mov r8, r0 - mov r9, r1 - mov r10, r2 - mov r11, r3 - pop {r3} - -call_r3: - bx r3 - - .align 2, 0 -lt_gClockTable: .word gClockTable -lt2_SOUND_INFO_PTR: .word SOUND_INFO_PTR -lt2_ID_NUMBER: .word ID_NUMBER - thumb_func_end MPlayMain - - thumb_func_start TrackStop -TrackStop: - push {r4-r6,lr} - adds r5, r1, 0 - ldrb r1, [r5, o_MusicPlayerTrack_flags] - movs r0, 0x80 - tst r0, r1 - beq TrackStop_Done - ldr r4, [r5, o_MusicPlayerTrack_chan] - cmp r4, 0 - beq TrackStop_3 - movs r6, 0 -TrackStop_Loop: - ldrb r0, [r4, o_SoundChannel_status] - cmp r0, 0 - beq TrackStop_2 - ldrb r0, [r4, o_SoundChannel_type] - movs r3, 0x7 - ands r0, r3 - beq TrackStop_1 - ldr r3, =SOUND_INFO_PTR - ldr r3, [r3] - ldr r3, [r3, o_SoundInfo_CgbOscOff] - bl call_r3 -TrackStop_1: - strb r6, [r4, o_SoundChannel_status] -TrackStop_2: - str r6, [r4, o_SoundChannel_track] - ldr r4, [r4, o_SoundChannel_np] - cmp r4, 0 - bne TrackStop_Loop -TrackStop_3: - str r4, [r5, o_MusicPlayerTrack_chan] -TrackStop_Done: - pop {r4-r6} - pop {r0} - bx r0 - .pool - thumb_func_end TrackStop - - thumb_func_start ChnVolSetAsm -ChnVolSetAsm: - ldrb r1, [r4, 0x12] - movs r0, 0x14 - ldrsb r2, [r4, r0] - movs r3, 0x80 - adds r3, r2 - muls r3, r1 - ldrb r0, [r5, 0x10] - muls r0, r3 - asrs r0, 14 - cmp r0, 0xFF - bls _081DDAE8 - movs r0, 0xFF -_081DDAE8: - strb r0, [r4, 0x2] - movs r3, 0x7F - subs r3, r2 - muls r3, r1 - ldrb r0, [r5, 0x11] - muls r0, r3 - asrs r0, 14 - cmp r0, 0xFF - bls _081DDAFC - movs r0, 0xFF -_081DDAFC: - strb r0, [r4, 0x3] - bx lr - thumb_func_end ChnVolSetAsm - - thumb_func_start ply_note -ply_note: - push {r4-r7,lr} - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4-r7} - sub sp, 0x18 - str r1, [sp] - adds r5, r2, 0 - ldr r1, =SOUND_INFO_PTR - ldr r1, [r1] - str r1, [sp, 0x4] - ldr r1, =gClockTable - adds r0, r1 - ldrb r0, [r0] - strb r0, [r5, o_MusicPlayerTrack_gateTime] - ldr r3, [r5, o_MusicPlayerTrack_cmdPtr] - ldrb r0, [r3] - cmp r0, 0x80 - bhs _081DDB46 - strb r0, [r5, o_MusicPlayerTrack_key] - adds r3, 0x1 - ldrb r0, [r3] - cmp r0, 0x80 - bhs _081DDB44 - strb r0, [r5, o_MusicPlayerTrack_velocity] - adds r3, 0x1 - ldrb r0, [r3] - cmp r0, 0x80 - bhs _081DDB44 - ldrb r1, [r5, o_MusicPlayerTrack_gateTime] - adds r1, r0 - strb r1, [r5, o_MusicPlayerTrack_gateTime] - adds r3, 0x1 -_081DDB44: - str r3, [r5, o_MusicPlayerTrack_cmdPtr] -_081DDB46: - movs r0, 0 - str r0, [sp, 0x14] - adds r4, r5, 0 - adds r4, o_MusicPlayerTrack_ToneData_type - ldrb r2, [r4] - movs r0, TONEDATA_TYPE_RHY | TONEDATA_TYPE_SPL - tst r0, r2 - beq _081DDB98 - ldrb r3, [r5, o_MusicPlayerTrack_key] - movs r0, TONEDATA_TYPE_SPL - tst r0, r2 - beq _081DDB66 - ldr r1, [r5, o_MusicPlayerTrack_ToneData_keySplitTable] - adds r1, r3 - ldrb r0, [r1] - b _081DDB68 -_081DDB66: - adds r0, r3, 0 -_081DDB68: - lsls r1, r0, 1 - adds r1, r0 - lsls r1, 2 - ldr r0, [r5, o_MusicPlayerTrack_ToneData_wav] - adds r1, r0 - mov r9, r1 - mov r6, r9 - ldrb r1, [r6] - movs r0, 0xC0 - tst r0, r1 - beq _081DDB80 - b _081DDCEA -_081DDB80: - movs r0, 0x80 - tst r0, r2 - beq _081DDB9C - ldrb r1, [r6, 0x3] - movs r0, 0x80 - tst r0, r1 - beq _081DDB94 - subs r1, 0xC0 - lsls r1, 1 - str r1, [sp, 0x14] -_081DDB94: - ldrb r3, [r6, 0x1] - b _081DDB9C -_081DDB98: - mov r9, r4 - ldrb r3, [r5, 0x5] -_081DDB9C: - str r3, [sp, 0x8] - ldr r6, [sp] - ldrb r1, [r6, 0x9] - ldrb r0, [r5, 0x1D] - adds r0, r1 - cmp r0, 0xFF - bls _081DDBAC - movs r0, 0xFF -_081DDBAC: - str r0, [sp, 0x10] - mov r6, r9 - ldrb r0, [r6] - movs r6, 0x7 - ands r6, r0 - str r6, [sp, 0xC] - beq _081DDBEC - ldr r0, [sp, 0x4] - ldr r4, [r0, 0x1C] - cmp r4, 0 - bne _081DDBC4 - b _081DDCEA -_081DDBC4: - subs r6, 0x1 - lsls r0, r6, 6 - adds r4, r0 - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _081DDC40 - movs r0, 0x40 - tst r0, r1 - bne _081DDC40 - ldrb r1, [r4, 0x13] - ldr r0, [sp, 0x10] - cmp r1, r0 - bcc _081DDC40 - beq _081DDBE4 - b _081DDCEA -_081DDBE4: - ldr r0, [r4, 0x2C] - cmp r0, r5 - bcs _081DDC40 - b _081DDCEA -_081DDBEC: - ldr r6, [sp, 0x10] - adds r7, r5, 0 - movs r2, 0 - mov r8, r2 - ldr r4, [sp, 0x4] - ldrb r3, [r4, 0x6] - adds r4, 0x50 -_081DDBFA: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _081DDC40 - movs r0, 0x40 - tst r0, r1 - beq _081DDC14 - cmp r2, 0 - bne _081DDC18 - adds r2, 0x1 - ldrb r6, [r4, 0x13] - ldr r7, [r4, 0x2C] - b _081DDC32 -_081DDC14: - cmp r2, 0 - bne _081DDC34 -_081DDC18: - ldrb r0, [r4, 0x13] - cmp r0, r6 - bcs _081DDC24 - adds r6, r0, 0 - ldr r7, [r4, 0x2C] - b _081DDC32 -_081DDC24: - bhi _081DDC34 - ldr r0, [r4, 0x2C] - cmp r0, r7 - bls _081DDC30 - adds r7, r0, 0 - b _081DDC32 -_081DDC30: - bcc _081DDC34 -_081DDC32: - mov r8, r4 -_081DDC34: - adds r4, 0x40 - subs r3, 0x1 - bgt _081DDBFA - mov r4, r8 - cmp r4, 0 - beq _081DDCEA -_081DDC40: - adds r0, r4, 0 - bl ClearChain - movs r1, 0 - str r1, [r4, 0x30] - ldr r3, [r5, 0x20] - str r3, [r4, 0x34] - cmp r3, 0 - beq _081DDC54 - str r4, [r3, 0x30] -_081DDC54: - str r4, [r5, 0x20] - str r5, [r4, 0x2C] - ldrb r0, [r5, 0x1B] - strb r0, [r5, 0x1C] - cmp r0, r1 - beq _081DDC66 - adds r1, r5, 0 - bl clear_modM -_081DDC66: - ldr r0, [sp] - adds r1, r5, 0 - bl TrkVolPitSet - ldr r0, [r5, 0x4] - str r0, [r4, 0x10] - ldr r0, [sp, 0x10] - strb r0, [r4, 0x13] - ldr r0, [sp, 0x8] - strb r0, [r4, 0x8] - ldr r0, [sp, 0x14] - strb r0, [r4, 0x14] - mov r6, r9 - ldrb r0, [r6] - strb r0, [r4, 0x1] - ldr r7, [r6, 0x4] - str r7, [r4, 0x24] - ldr r0, [r6, 0x8] - str r0, [r4, 0x4] - ldrh r0, [r5, 0x1E] - strh r0, [r4, 0xC] - bl ChnVolSetAsm - ldrb r1, [r4, 0x8] - movs r0, 0x8 - ldrsb r0, [r5, r0] - adds r3, r1, r0 - bpl _081DDCA0 - movs r3, 0 -_081DDCA0: - ldr r6, [sp, 0xC] - cmp r6, 0 - beq _081DDCCE - mov r6, r9 - ldrb r0, [r6, 0x2] - strb r0, [r4, 0x1E] - ldrb r1, [r6, 0x3] - movs r0, 0x80 - tst r0, r1 - bne _081DDCBA - movs r0, 0x70 - tst r0, r1 - bne _081DDCBC -_081DDCBA: - movs r1, 0x8 -_081DDCBC: - strb r1, [r4, 0x1F] - ldrb r2, [r5, 0x9] - adds r1, r3, 0 - ldr r0, [sp, 0xC] - ldr r3, [sp, 0x4] - ldr r3, [r3, 0x30] - bl call_r3 - b _081DDCDC -_081DDCCE: - ldr r0, [r5, o_MusicPlayerTrack_unk_3C] - str r0, [r4, 0x18] - ldrb r2, [r5, 0x9] - adds r1, r3, 0 - adds r0, r7, 0 - bl MidiKeyToFreq -_081DDCDC: - str r0, [r4, 0x20] - movs r0, 0x80 - strb r0, [r4] - ldrb r1, [r5] - movs r0, 0xF0 - ands r0, r1 - strb r0, [r5] -_081DDCEA: - add sp, 0x18 - pop {r0-r7} - mov r8, r0 - mov r9, r1 - mov r10, r2 - mov r11, r3 - pop {r0} - bx r0 - .pool - thumb_func_end ply_note - - thumb_func_start ply_endtie -ply_endtie: - push {r4,r5} - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r3, [r2] - cmp r3, 0x80 - bhs _081DDD16 - strb r3, [r1, o_MusicPlayerTrack_key] - adds r2, 0x1 - str r2, [r1, o_MusicPlayerTrack_cmdPtr] - b _081DDD18 -_081DDD16: - ldrb r3, [r1, o_MusicPlayerTrack_key] -_081DDD18: - ldr r1, [r1, o_MusicPlayerTrack_chan] - cmp r1, 0 - beq _081DDD40 - movs r4, 0x83 - movs r5, 0x40 -_081DDD22: - ldrb r2, [r1, o_SoundChannel_status] - tst r2, r4 - beq _081DDD3A - tst r2, r5 - bne _081DDD3A - ldrb r0, [r1, o_SoundChannel_mk] - cmp r0, r3 - bne _081DDD3A - movs r0, 0x40 - orrs r2, r0 - strb r2, [r1, o_SoundChannel_status] - b _081DDD40 -_081DDD3A: - ldr r1, [r1, o_SoundChannel_np] - cmp r1, 0 - bne _081DDD22 -_081DDD40: - pop {r4,r5} - bx lr - thumb_func_end ply_endtie - - thumb_func_start clear_modM -clear_modM: - movs r2, 0 - strb r2, [r1, o_MusicPlayerTrack_modM] - strb r2, [r1, o_MusicPlayerTrack_lfoSpeedC] - ldrb r2, [r1, o_MusicPlayerTrack_modT] - cmp r2, 0 - bne _081DDD54 - movs r2, 0xC - b _081DDD56 -_081DDD54: - movs r2, 0x3 -_081DDD56: - ldrb r3, [r1, o_MusicPlayerTrack_flags] - orrs r3, r2 - strb r3, [r1, o_MusicPlayerTrack_flags] - bx lr - thumb_func_end clear_modM - - thumb_func_start ld_r3_tp_adr_i -ld_r3_tp_adr_i_unchecked: - ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] - adds r3, r2, 1 - str r3, [r1, o_MusicPlayerTrack_cmdPtr] - ldrb r3, [r2] - bx lr - thumb_func_end ld_r3_tp_adr_i - - thumb_func_start ply_lfos -ply_lfos: - mov r12, lr - bl ld_r3_tp_adr_i_unchecked - strb r3, [r1, o_MusicPlayerTrack_lfoSpeed] - cmp r3, 0 - bne _081DDD7C - bl clear_modM -_081DDD7C: - bx r12 - thumb_func_end ply_lfos - - thumb_func_start ply_mod -ply_mod: - mov r12, lr - bl ld_r3_tp_adr_i_unchecked - strb r3, [r1, o_MusicPlayerTrack_mod] - cmp r3, 0 - bne _081DDD90 - bl clear_modM -_081DDD90: - bx r12 - thumb_func_end ply_mod - - .align 2, 0 @ Don't pad with nop. -``` +[Mixer code](https://gist.github.com/ShinyDragonHunter/b65599431adfaefead614763bf1b9f92) This is the code for the mixer. |