From 0c48975fa07e3e4e1ed53c9474600edbe1086c8e Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 22:18:02 +0100 Subject: [PATCH 01/11] Do 2 mulitplications at once --- agb/crt0.s | 2 + agb/src/asm_include.s | 15 ++++++ agb/src/sound/mixer/mixer.s | 84 ++++++++++++++------------------- agb/src/sound/mixer/sw_mixer.rs | 15 +++--- 4 files changed, 61 insertions(+), 55 deletions(-) create mode 100644 agb/src/asm_include.s diff --git a/agb/crt0.s b/agb/crt0.s index 6696eca6..b2c327d0 100644 --- a/agb/crt0.s +++ b/agb/crt0.s @@ -1,3 +1,5 @@ +.include "src/asm_include.s" + .arm .global __start __start: diff --git a/agb/src/asm_include.s b/agb/src/asm_include.s new file mode 100644 index 00000000..424e9daa --- /dev/null +++ b/agb/src/asm_include.s @@ -0,0 +1,15 @@ +.macro agb_arm_func functionName:req +.section .iwram, "ax", %progbits @ "ax" = allocatable and executable, %progbits = contains data +.arm +.align 2 +.global \functionName +.type \functionName, %function +.func \functionName +\functionName: +.endm + +.macro agb_arm_end functionName:req +.pool +.size \functionName,.-\functionName +.endfunc +.endm diff --git a/agb/src/sound/mixer/mixer.s b/agb/src/sound/mixer/mixer.s index 8acc9f75..af28f05a 100644 --- a/agb/src/sound/mixer/mixer.s +++ b/agb/src/sound/mixer/mixer.s @@ -1,86 +1,72 @@ -.arm -.global agb_rs__mixer_add -.section .iwram, "ax" -.align -agb_rs__mixer_add: +.equ SOUND_BUFFER_SIZE, 176 + +agb_arm_func agb_rs__mixer_add @ Arguments @ r0 - pointer to the data to be copied (u8 array) - @ r1 - pointer to the sound buffer (i16 array) + @ r1 - pointer to the sound buffer (i16 array which will alternate left and right channels, 32-bit aligned) @ r2 - playback speed (usize fixnum with 8 bits) @ r3 - amount to modify the left channel by (u16 fixnum with 4 bits) @ stack position 1 - amount to modify the right channel by (u16 fixnum with 4 bits) @ @ The sound buffer must be SOUND_BUFFER_SIZE * 2 in size = 176 * 2 - - @ r9 = amount to modify right channel by - push {r4-r10} ldr r9, [sp, #28] @ load the right channel modification amount into r9 - mov r12, #0 @ current write offset into the resulting buffer - mov r8, #352 @ the offset for writing to the resulting buffer between left and right channels + orr r9, r9, r3, lsl #16 @ r9 now is the left channel followed by the right channel modifications. mov r5, #0 @ current index we're reading from + mov r8, #SOUND_BUFFER_SIZE @ the number of steps left - @ kept between iterations: - @ r12 - current write offset into the output buffer (r1) - @ r9 - the amount to modify the right channel by - @ r8 - the constant 352 - @ r5 - the current index from the input buffer we're reading from (r0) - @ the provided arguments are all unmodified - - @ all other registers are temporary 1: - add r4, r0, r5, asr #8 @ calculate the address of the next read form the sound buffer - ldrsb r10, [r4] @ load the current value we want to read - add r5, r5, r2 @ calculate the position to read the next step from + add r4, r0, r5, asr #8 @ calculate the address of the next read from the sound buffer + ldrsb r6, [r4] @ load the current sound sample to r6 + add r5, r5, r2 @ calculate the position to read the next sample from - mov r6, r1 @ r6 = current buffer location + ldr r4, [r1] @ read the current value - ldrh r4, [r6, r12]! @ load the current buffer value (r12 being the offset) but pre-increment r6 by r12 - mla r7, r10, r3, r4 @ r7 = r10 * r3 + r9 = current sound value * left amount + previous buffer value - strh r7, [r6], r8 @ *r6 = r7, r6 += r8 where r8 = 352 = offset for the right hand side + mla r4, r6, r9, r4 @ r4 += r6 * r9 (calculating both the left and right samples together) - ldrh r7, [r6] @ same for the right hand side, r6 now points to the right hand side location - mla r4, r10, r9, r7 - strh r4, [r6] + str r4, [r1], #4 @ store the new value, and increment the pointer - add r12, r12, #2 @ increment the current write offset in the resulting buffer - cmp r12, #352 @ check if we're done - bne 1b + subs r8, r8, #1 @ loop counter + bne 1b @ jump back if we're done with the loop pop {r4-r10} bx lr -.pool +agb_arm_end agb_rs__mixer_add -.arm -.global agb_rs__mixer_collapse -.section .iwram -.align -agb_rs__mixer_collapse: +.macro clamp_s8 reg:req + cmn \reg, #127 + mvnlt \reg, #127 + + cmp \reg, #128 + movgt \reg, #128 +.endm + +agb_arm_func agb_rs__mixer_collapse @ Arguments: @ r0 = target buffer (i8) - @ r1 = input buffer (i16) of fixnums with 4 bits of precision + @ r1 = input buffer (i16) of fixnums with 4 bits of precision (read in sets of i16 in an i32) - mov r2, #352 + mov r2, #SOUND_BUFFER_SIZE @ loop counter 1: @ r12 = *r1; r1++ - ldrsh r12, [r1], #2 + ldr r12, [r1], #4 - lsr r3, r12, #4 @ r3 = r12 >> 4 + lsl r3, r12, #16 @ r3 is going to be the right sample, push r12 left 16 bits first + asr r3, r3, #20 @ move r3 back to being the correct value + mov r12, r12, asr #20 @ r12 = left sample - cmn r12, #2048 @ compare r12 against -2048 - mvnlt r3, #127 @ r3 = -127 if r12 <= 2048 + clamp_s8 r12 @ clamp the audio to 8 bit values + clamp_s8 r3 - cmp r12, #2048 @ compare r12 against 2048 - movge r3, #127 @ r3 = 127 if r12 >= 2048 - - strb r3, [r0], #1 @ *r0 = r3; r0++ + strb r3, [r0, #SOUND_BUFFER_SIZE] @ *(r0 + SOUND_BUFFER_SIZE) = r3 + strb r12, [r0], #1 @ *r0 = r12; r0++ subs r2, r2, #1 @ r2 -= 1 bne 1b @ loop if not 0 bx lr -.pool \ No newline at end of file +agb_arm_end agb_rs__mixer_collapse \ No newline at end of file diff --git a/agb/src/sound/mixer/sw_mixer.rs b/agb/src/sound/mixer/sw_mixer.rs index 333c4550..ed58eb51 100644 --- a/agb/src/sound/mixer/sw_mixer.rs +++ b/agb/src/sound/mixer/sw_mixer.rs @@ -92,9 +92,12 @@ impl Mixer { const SOUND_FREQUENCY: i32 = 10512; const SOUND_BUFFER_SIZE: usize = 176; +#[repr(C, align(4))] +struct SoundBuffer([i8; SOUND_BUFFER_SIZE * 2]); + struct MixerBuffer { - buffer1: [i8; SOUND_BUFFER_SIZE * 2], // first half is left, second is right - buffer2: [i8; SOUND_BUFFER_SIZE * 2], + buffer1: SoundBuffer, // alternating bytes left and right channels + buffer2: SoundBuffer, buffer_1_active: bool, } @@ -102,8 +105,8 @@ struct MixerBuffer { impl MixerBuffer { fn new() -> Self { MixerBuffer { - buffer1: [0; SOUND_BUFFER_SIZE * 2], - buffer2: [0; SOUND_BUFFER_SIZE * 2], + buffer1: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]), + buffer2: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]), buffer_1_active: true, } @@ -164,9 +167,9 @@ impl MixerBuffer { fn get_write_buffer(&mut self) -> &mut [i8; SOUND_BUFFER_SIZE * 2] { if self.buffer_1_active { - &mut self.buffer2 + &mut self.buffer2.0 } else { - &mut self.buffer1 + &mut self.buffer1.0 } } } From 1be6dfbf360df4f8cc8288b49243ccce7ecc4d30 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 22:36:32 +0100 Subject: [PATCH 02/11] Unwind loop 4 times --- agb/src/sound/mixer/mixer.s | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/agb/src/sound/mixer/mixer.s b/agb/src/sound/mixer/mixer.s index af28f05a..b37052e3 100644 --- a/agb/src/sound/mixer/mixer.s +++ b/agb/src/sound/mixer/mixer.s @@ -19,6 +19,7 @@ agb_arm_func agb_rs__mixer_add mov r8, #SOUND_BUFFER_SIZE @ the number of steps left 1: +.macro mixer_add_loop add r4, r0, r5, asr #8 @ calculate the address of the next read from the sound buffer ldrsb r6, [r4] @ load the current sound sample to r6 add r5, r5, r2 @ calculate the position to read the next sample from @@ -28,8 +29,14 @@ agb_arm_func agb_rs__mixer_add mla r4, r6, r9, r4 @ r4 += r6 * r9 (calculating both the left and right samples together) str r4, [r1], #4 @ store the new value, and increment the pointer +.endm + + mixer_add_loop + mixer_add_loop + mixer_add_loop + mixer_add_loop - subs r8, r8, #1 @ loop counter + subs r8, r8, #4 @ loop counter bne 1b @ jump back if we're done with the loop pop {r4-r10} From a2f0c43f26bd12145f429bcd61d973e9b823270f Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:00:17 +0100 Subject: [PATCH 03/11] Reduce the number of registers stored and used --- agb/src/sound/mixer/mixer.s | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/agb/src/sound/mixer/mixer.s b/agb/src/sound/mixer/mixer.s index b37052e3..3ea6f64e 100644 --- a/agb/src/sound/mixer/mixer.s +++ b/agb/src/sound/mixer/mixer.s @@ -9,11 +9,11 @@ agb_arm_func agb_rs__mixer_add @ stack position 1 - amount to modify the right channel by (u16 fixnum with 4 bits) @ @ The sound buffer must be SOUND_BUFFER_SIZE * 2 in size = 176 * 2 - push {r4-r10} + push {r4-r8} - ldr r9, [sp, #28] @ load the right channel modification amount into r9 + ldr r7, [sp, #20] @ load the right channel modification amount into r7 - orr r9, r9, r3, lsl #16 @ r9 now is the left channel followed by the right channel modifications. + orr r7, r7, r3, lsl #16 @ r7 now is the left channel followed by the right channel modifications. mov r5, #0 @ current index we're reading from mov r8, #SOUND_BUFFER_SIZE @ the number of steps left @@ -26,7 +26,7 @@ agb_arm_func agb_rs__mixer_add ldr r4, [r1] @ read the current value - mla r4, r6, r9, r4 @ r4 += r6 * r9 (calculating both the left and right samples together) + mla r4, r6, r7, r4 @ r4 += r6 * r7 (calculating both the left and right samples together) str r4, [r1], #4 @ store the new value, and increment the pointer .endm @@ -39,7 +39,7 @@ agb_arm_func agb_rs__mixer_add subs r8, r8, #4 @ loop counter bne 1b @ jump back if we're done with the loop - pop {r4-r10} + pop {r4-r8} bx lr agb_arm_end agb_rs__mixer_add From dffd57204c5a02b75f694e6b1f90c250bf943bea Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:04:02 +0100 Subject: [PATCH 04/11] Remove trailing space --- agb/src/sound/mixer/mixer.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/src/sound/mixer/mixer.s b/agb/src/sound/mixer/mixer.s index 3ea6f64e..4d078f01 100644 --- a/agb/src/sound/mixer/mixer.s +++ b/agb/src/sound/mixer/mixer.s @@ -30,7 +30,7 @@ agb_arm_func agb_rs__mixer_add str r4, [r1], #4 @ store the new value, and increment the pointer .endm - + mixer_add_loop mixer_add_loop mixer_add_loop From 7e268ba8cef5e0b72f176618e949e4042514af45 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:12:18 +0100 Subject: [PATCH 05/11] Update agb's cargo.toml when updating a dependency --- release.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release.sh b/release.sh index 6083308d..991ca66c 100755 --- a/release.sh +++ b/release.sh @@ -70,6 +70,12 @@ if [ "$PROJECT" = "agb" ]; then # also update the agb version in the template sed -i -e "s/^agb = \".*\"/agb = \"$VERSION\"/" template/Cargo.toml git add template/Cargo.toml +else + local PROJECT_NAME_WITH_UNDERSCORES=$(echo -n "$PROJECT" | tr - _) + sed -i -E -e "s/($PROJECT_NAME_WITH_UNDERSCORES = .*version = \")[^\"]+(\".*)/\1$VERSION\2/" agb/Cargo.toml + + (cd agb && cargo update) + git add agb/Cargo.toml agb/Cargo.lock fi # Commit the Cargo.toml changes From 2f12748004cc807c7e75f771627baded98b0fa5c Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:15:25 +0100 Subject: [PATCH 06/11] Allow for easier testing --- release.sh | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/release.sh b/release.sh index 991ca66c..c1e75dcc 100755 --- a/release.sh +++ b/release.sh @@ -5,10 +5,11 @@ set -e PROJECT=$1 VERSION=$2 +NO_COMMIT=$3 # Sanity check that we actually have a version if [ "$VERSION" = "" ]; then - echo "Usage $0 " + echo "Usage $0 [--no-commit]" exit 1 fi @@ -18,6 +19,12 @@ if [ ! "$(echo "$VERSION" | grep -E "^[0-9]+\.[0-9]+\.[0-9]+$")" ]; then exit 1 fi +# Check if no commit option is valid +if [ ! "$NO_COMMIT" = "" ] || [ ! "$NO_COMMIT" = "--no-commit" ]; then + echo "Must pass either no last argument or --no-commit" + exit 1 +fi + # Set up $DIRECTORY and $TAGNAME case "$PROJECT" in agb) @@ -49,8 +56,8 @@ if [ ! -z "$(git status --porcelain)" ]; then exit 1 fi -# Check that we are in the master branch -if [ "$(git symbolic-ref --short HEAD)" != "master" ]; then +# Check that we are in the master branch, but only if actually committing +if [ ! "$NO_COMMIT" = "--no-commit" ] && [ "$(git symbolic-ref --short HEAD)" != "master" ]; then echo "You must be in the master branch before releasing" exit 1 fi @@ -78,11 +85,13 @@ else git add agb/Cargo.toml agb/Cargo.lock fi -# Commit the Cargo.toml changes -git commit -m "Release $PROJECT v$VERSION" +if [ ! "$NO_COMMIT" = "--no-commit" ]; then + # Commit the Cargo.toml changes + git commit -m "Release $PROJECT v$VERSION" -# Tag the version -git tag -a $TAGNAME -m "$PROJECT - v$VERSION" + # Tag the version + git tag -a $TAGNAME -m "$PROJECT - v$VERSION" -echo "Done! Push with" -echo "git push --atomic origin master $TAGNAME" \ No newline at end of file + echo "Done! Push with" + echo "git push --atomic origin master $TAGNAME" +fi \ No newline at end of file From 8b2bd66b1953f6f9b0c225b6b3194fe886b03e0a Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:15:52 +0100 Subject: [PATCH 07/11] Also check if agb-macros works --- release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release.sh b/release.sh index c1e75dcc..0c6e6522 100755 --- a/release.sh +++ b/release.sh @@ -65,6 +65,7 @@ fi # Sanity check to make sure the build works (cd agb && cargo test) (cd agb-image-converter && cargo test) +(cd agb-macros && cargo test) # Update the version in Cargo.toml sed -i -e "s/^version = \".*\"/version = \"$VERSION\"/" "$DIRECTORY/Cargo.toml" From 2e7c2be11e868c42c0bd6d1416470e8cf0e91545 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:16:30 +0100 Subject: [PATCH 08/11] Get the booleans correct --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 0c6e6522..ac66b45b 100755 --- a/release.sh +++ b/release.sh @@ -20,7 +20,7 @@ if [ ! "$(echo "$VERSION" | grep -E "^[0-9]+\.[0-9]+\.[0-9]+$")" ]; then fi # Check if no commit option is valid -if [ ! "$NO_COMMIT" = "" ] || [ ! "$NO_COMMIT" = "--no-commit" ]; then +if [ ! "$NO_COMMIT" = "" ] && [ ! "$NO_COMMIT" = "--no-commit" ]; then echo "Must pass either no last argument or --no-commit" exit 1 fi From 2b1ba6c849c1a2c99f285de3a0f1477a63c693fa Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:18:55 +0100 Subject: [PATCH 09/11] local can only be used in functions --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index ac66b45b..23db2993 100755 --- a/release.sh +++ b/release.sh @@ -79,7 +79,7 @@ if [ "$PROJECT" = "agb" ]; then sed -i -e "s/^agb = \".*\"/agb = \"$VERSION\"/" template/Cargo.toml git add template/Cargo.toml else - local PROJECT_NAME_WITH_UNDERSCORES=$(echo -n "$PROJECT" | tr - _) + PROJECT_NAME_WITH_UNDERSCORES=$(echo -n "$PROJECT" | tr - _) sed -i -E -e "s/($PROJECT_NAME_WITH_UNDERSCORES = .*version = \")[^\"]+(\".*)/\1$VERSION\2/" agb/Cargo.toml (cd agb && cargo update) From 919339173164975c22b191fb1aeb8e04096c22cd Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:20:51 +0100 Subject: [PATCH 10/11] Makes sense to me to do the testing later --- release.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/release.sh b/release.sh index 23db2993..7ff20ea3 100755 --- a/release.sh +++ b/release.sh @@ -62,11 +62,6 @@ if [ ! "$NO_COMMIT" = "--no-commit" ] && [ "$(git symbolic-ref --short HEAD)" != exit 1 fi -# Sanity check to make sure the build works -(cd agb && cargo test) -(cd agb-image-converter && cargo test) -(cd agb-macros && cargo test) - # Update the version in Cargo.toml sed -i -e "s/^version = \".*\"/version = \"$VERSION\"/" "$DIRECTORY/Cargo.toml" @@ -86,6 +81,11 @@ else git add agb/Cargo.toml agb/Cargo.lock fi +# Sanity check to make sure the build works +(cd agb && cargo test) +(cd agb-image-converter && cargo test) +(cd agb-macros && cargo test) + if [ ! "$NO_COMMIT" = "--no-commit" ]; then # Commit the Cargo.toml changes git commit -m "Release $PROJECT v$VERSION" From 5d255fddea2643465c62e32971f2034ed389a6f7 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 15 Aug 2021 23:27:39 +0100 Subject: [PATCH 11/11] Add asm_include.s to the rerun-if-changed in build.rs --- agb/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/agb/build.rs b/agb/build.rs index b72b8b5d..8a63cb42 100644 --- a/agb/build.rs +++ b/agb/build.rs @@ -2,6 +2,7 @@ fn main() { println!("cargo:rerun-if-changed=crt0.s"); println!("cargo:rerun-if-changed=gba_mb.ld"); println!("cargo:rerun-if-changed=src/sound/mixer/mixer.s"); + println!("cargo:rerun-if-changed=src/asm_include.s"); println!("cargo:rerun-if-changed=interrupt_handler.s"); println!("cargo:rerun-if-changed=gfx/test_logo.png");