diff --git a/README.md b/README.md index fa23dc3..91c84bf 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ The original code compressed with *Blueberry's* Shrinkler goes from 18052 bytes down to 9023 bytes. Raspberry Casket, depending on the features compiled in, is about -5802 bytes and shrinkles down to ~4125 bytes (in isolation). +5784 bytes and shrinkles down to ~4118 bytes (in isolation). So this means that the optimization is not just "on the outside". @@ -165,10 +165,11 @@ solve this problem. - This also fixes usages of illegal period 0 in the lead-in that could cause the replay to miss the first trigger. - Moved pattern table init from PlayerInit to SongInit, optimized SongInit a bit. - Wave order table filling moved and optimized in SongInit. -- Added Presto player draft. - Bugfix: Songend detection for back-jumps was broken since at least V1.1. - Optimized some more wave selection code. -- Drop-in replacement code size: 5802 bytes. +- Nosync/sync wave selection optimized. +- Added Presto player draft. +- Drop-in replacement code size: 5784 bytes. ### V1.x (unreleased) - Fixed a bug regarding the copper output mode with looping waves having a loop-offset. diff --git a/binaries/raspberry_casket.bin b/binaries/raspberry_casket.bin index 39a1ae5..65ea3cc 100644 Binary files a/binaries/raspberry_casket.bin and b/binaries/raspberry_casket.bin differ diff --git a/src/raspberry_casket.asm b/src/raspberry_casket.asm index e7cc6e5..ec54cba 100755 --- a/src/raspberry_casket.asm +++ b/src/raspberry_casket.asm @@ -1,5 +1,5 @@ ;-------------------------------------------------------------------- -; Raspberry Casket Player V2.x (19-Aug-2023) +; Raspberry Casket Player V2.x (20-Aug-2023) ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ; Provided by Chris 'platon42' Hodges @@ -96,7 +96,7 @@ ; 18052 bytes down to 9023 bytes. ; ; Raspberry Casket, depending on the features compiled in, is about -; 5802 bytes and shrinkles down to ~4125 bytes (in isolation). +; 5784 bytes and shrinkles down to ~4118 bytes (in isolation). ; ; So this means that the optimization is not just "on the outside". ; @@ -433,7 +433,7 @@ pre_SongInit: dbra d3,.waveorderloop .hasnowaveordering - + lea sv_pattern_table(a1),a0 .pattableloop move.l a4,(a0)+ @@ -1476,7 +1476,6 @@ pre_PlayerTick: IFNE PRETRACKER_PARANOIA_MODE moveq.l #0,d2 ; default to not stitched move.b (a0)+,d1 ; pdb_pitch_ctrl get pitch byte - move.b d1,d6 bpl.s .inst_note_is_not_stitched ; means that note is stitched tst.w d4 @@ -1486,15 +1485,15 @@ pre_PlayerTick: moveq.l #1,d2 ; next note will be fetched immediately .inst_note_is_not_stitched ELSE - move.b (a0)+,d1 ; pdb_pitch_ctrl get pitch byte - move.b d1,d6 + move.b (a0)+,d6 ; pdb_pitch_ctrl get pitch byte smi d2 ; note stitched? ;neg.b d2 ENDC tst.b d3 bne.s .skippitchloading - and.w #$3f,d1 + moveq.l #$3f,d1 + and.w d6,d1 beq.s .skippitchloading ; no new note subq.w #1,d1 lsl.w #4,d1 @@ -1508,9 +1507,9 @@ pre_PlayerTick: moveq.l #15,d6 and.b (a0)+,d6 ; pdb_effect_cmd command number add.w d6,d6 - moveq.l #0,d5 - move.b (a0)+,d5 ; pdb_effect_data command parameter byte move.w .inst_command_jmptable(pc,d6.w),d3 + moveq.l #0,d5 + move.b (a0)+,d5 ; pdb_effect_data command parameter byte, note that condition codes are used in inst_set_speed jmp .inst_command_jmptable(pc,d3.w) .inst_command_jmptable @@ -1534,6 +1533,7 @@ pre_PlayerTick: ; d0 = current step / next step ; d5 = command parameter data / scratch ; d2 = note stitched flag +; d1 = scratch ; d3 = scratch ; d6 = scratch ; ---------------------------------------- @@ -1546,7 +1546,7 @@ pre_PlayerTick: add.w d5,d5 cmp.w pcd_inst_wave_num4_w(a5),d5 beq.s .inst_set_wave_rts - + .inst_select_wave_subroutine move.w d5,pcd_inst_wave_num4_w(a5) move.l sv_waveinfo_table(a6,d5.w),a3 @@ -1560,16 +1560,58 @@ pre_PlayerTick: moveq.l #0,d3 - tst.w d6 - bne.s .inst_select_wave_nosync + move.w wi_loop_offset_w(a3),d1 ; is unlikely >= 32768 -- if it is, it will be past end of sample - move.w wi_loop_offset_w(a3),d6 ; is unlikely >= 32768 -- if it is, it will be past end of sample tst.w wi_subloop_len_w(a3) - bne.s .inst_set_wave_has_subloop -.inst_set_wave_has_no_subloop - adda.w d6,a1 ; add loop offset (which is actually not a loop offset for one-shot samples) + beq.s .inst_set_wave_has_no_subloop - sub.w d6,d5 + tst.w d6 + beq.s .inst_set_wave_has_subloop + + ; nosync version +.inst_set_wave_ns_has_subloop + move.w d3,pcd_out_lof_w(a5) + move.l a1,pcd_out_ptr_l(a5) + + IFEQ PRETRACKER_BUGFIX_CODE + move.w pcd_inst_loop_offset_w(a5),d1 + cmp.w d1,d5 + ELSE + cmp.w pcd_inst_loop_offset_w(a5),d5 + ENDC + bhs.s .inst_set_wave_ns_keep_pp + st pcd_inst_ping_pong_dir_b(a5) +.inst_set_wave_ns_keep_pp + clr.w pcd_inst_subloop_wait_w(a5) + + IFEQ PRETRACKER_BUGFIX_CODE ; This adds an extra jump to the wave that's not desired + sub.w wi_subloop_step_w(a3),d1 + move.w d1,pcd_inst_loop_offset_w(a5) + ENDC + rts + +.inst_set_wave_has_no_subloop + IFEQ PRETRACKER_BUGFIX_CODE + tst.w d6 + beq.s .inst_select_wave_nosync_no_subloop + + ; note that nosync on non-looping waves doesn't effectivly do anything special + adda.w d1,a1 + sub.w d1,d5 + ;cmp.w #1,d5 ; not necessary as increases in steps of 2 + bhi.s .inst_set_wave_ns_has_min_length + moveq.l #2,d5 +.inst_set_wave_ns_has_min_length + move.w d5,pcd_out_len_w(a5) + moveq.l #-1,d3 + + bra.s .inst_set_wave_ns_has_subloop + +.inst_select_wave_nosync_no_subloop + ENDC + + adda.w d1,a1 ; add loop offset (which is actually not a loop offset for one-shot samples) + sub.w d1,d5 ;cmp.w #1,d5 ; not necessary as increases in steps of 2 bhi.s .inst_set_wave_has_min_length moveq.l #2,d5 @@ -1583,7 +1625,7 @@ pre_PlayerTick: .inst_set_wave_has_subloop move.w d3,pcd_out_lof_w(a5) move.l a1,pcd_out_ptr_l(a5) - move.w d6,pcd_inst_loop_offset_w(a5) + move.w d1,pcd_inst_loop_offset_w(a5) st pcd_inst_ping_pong_dir_b(a5) moveq.l #0,d5 @@ -1593,57 +1635,6 @@ pre_PlayerTick: .inst_set_wave_rts rts -; ---------------------------------------- -.inst_select_wave_nosync - IFNE PRETRACKER_BUGFIX_CODE - move.w wi_loop_offset_w(a3),d6 - tst.w wi_subloop_len_w(a3) - beq.s .inst_set_wave_has_no_subloop - ELSE - tst.w wi_subloop_len_w(a3) - bne.s .inst_set_wave_ns_has_subloop - - ; note that nosync on non-looping waves doesn't effectivly do anything special - move.w wi_loop_offset_w(a3),d6 - adda.w d6,a1 - - sub.w d6,d5 - ;cmp.w #1,d5 ; not necessary as increases in steps of 2 - bhi.s .inst_set_wave_ns_has_min_length - moveq.l #2,d5 -.inst_set_wave_ns_has_min_length - move.w d5,pcd_out_len_w(a5) - - moveq.l #-1,d3 - ENDC -.inst_set_wave_ns_has_subloop - move.w d3,pcd_out_lof_w(a5) - move.l a1,pcd_out_ptr_l(a5) - - IFEQ PRETRACKER_BUGFIX_CODE - move.w pcd_inst_loop_offset_w(a5),d6 - cmp.w d6,d5 - ELSE - cmp.w pcd_inst_loop_offset_w(a5),d5 - ENDC - bhs.s .inst_set_wave_ns_keep_pp - st pcd_inst_ping_pong_dir_b(a5) -.inst_set_wave_ns_keep_pp - clr.w pcd_inst_subloop_wait_w(a5) - - IFEQ PRETRACKER_BUGFIX_CODE ; This adds an extra jump to the wave that's not desired - sub.w wi_subloop_step_w(a3),d6 - move.w d6,pcd_inst_loop_offset_w(a5) - ENDC - rts - -; ---------------------------------------- -.inst_slide_down - neg.w d5 -.inst_slide_up - move.w d5,pcd_inst_pitch_slide_w(a5) - bra .inst_cmd_cont_next - ; ---------------------------------------- .inst_adsr subq.w #1,d5 @@ -1681,7 +1672,7 @@ pre_PlayerTick: bra.s .inst_cmd_cont_next .inst_vol_slide_up - lsr.b #4,d5 + lsr.w #4,d5 move.b d5,pcd_inst_vol_slide_b(a5) bra.s .inst_cmd_cont_next @@ -1708,12 +1699,12 @@ pre_PlayerTick: movea.l sv_inst_patterns_table-4(a6,d1.w),a0 add.w d5,a0 - add.w d5,d5 + add.w d5,a0 add.w d5,a0 bra.s .inst_fetch_next .inst_we_were_stitched - move.b pcd_inst_speed_stop_b(a5),d2 + moveq.l #0,d2 bra.s .inst_cont_from_nasty_double_jump ; ---------------------------------------- @@ -1753,12 +1744,17 @@ pre_PlayerTick: addq.w #1,d0 bra.s .inst_fetch_next +; ---------------------------------------- +.inst_slide_down + neg.w d5 +.inst_slide_up + move.w d5,pcd_inst_pitch_slide_w(a5) + bra.s .inst_cmd_cont_next + ; ---------------------------------------- .inst_set_speed - tst.w d5 - bne.s .inst_set_speed_nostop - st d5 -.inst_set_speed_nostop + seq d3 + or.b d3,d5 move.b d5,pcd_inst_speed_stop_b(a5) ; ---------------------------------------- @@ -1777,8 +1773,8 @@ pre_PlayerTick: .inst_pat_loop_exit st d2 .inst_pat_loop_exit2 - add.b pcd_inst_speed_stop_b(a5),d2 .inst_cont_from_nasty_double_jump + add.b pcd_inst_speed_stop_b(a5),d2 move.b d2,pcd_inst_line_ticks_b(a5) move.b d0,pcd_inst_step_pos_b(a5) ; update inst step pos @@ -1830,8 +1826,9 @@ pre_PlayerTick: ; same code for both release and decay .adsr_decay_and_release moveq.l #0,d4 + moveq.l #-$71,d5 ; same as $8f, we only need the byte move.b pcd_adsr_phase_speed_b(a5),d4 - cmp.b #$8f,d4 + cmp.b d5,d4 bhs.s .adsr_absurd_slow_release move.b d4,d5 addq.b #1,d5 @@ -1842,7 +1839,6 @@ pre_PlayerTick: .adsr_absurd_slow_release moveq.l #2,d4 ; FIXME I guess this should be 1, if I look at the roll-off table - moveq.l #-$71,d5 ; same as $8f, we only need the byte .adsr_release_cont move.b d5,pcd_adsr_phase_speed_b(a5) @@ -1998,7 +1994,7 @@ pre_PlayerTick: move.w wi_loop_start_w(a3),d4 move.w d4,d2 - sub.w d1,d2 ; calc how many bytes we are part front + sub.w d1,d2 ; calc how many bytes we are past front bmi.s .wave_new_loop_pos_fits .wave_hit_front_of_loop