summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinyDragonHunter <32826900+ShinyDragonHunter@users.noreply.github.com>2018-11-05 21:44:00 +0000
committerShinyDragonHunter <32826900+ShinyDragonHunter@users.noreply.github.com>2018-11-05 21:44:00 +0000
commitd3a263f09c9e304a8bf1b3bbb4c51fc0668c55f6 (patch)
tree5259e3f99899b6374b401c685da5b1a7499cf196
parent7c7221465456927d2f853a045d1ea0bb945e799f (diff)
Updated Reduce noise and improve sound quality of music (markdown)
-rw-r--r--Reduce-noise-and-improve-sound-quality-of-music.md2553
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.