CLIPTO8BIT MACRO cmp.w #-$80,\1 bge.s .nominclip\@ moveq.l #-$80,\1 .nominclip\@ cmp.w #$7f,\1 ble.s .nomaxclip\@ moveq.l #$7f,\1 .nomaxclip\@ ENDM CLIPORTRUNC8BIT MACRO beq.s .unboosted\@ asr.l #6,\1 cmp.w #-$80,\1 bge.s .nominclip\@ moveq.l #-$80,\1 .nominclip\@ cmp.w #$7f,\1 ble.s .nomaxclip\@ moveq.l #$7f,\1 bra.s .nomaxclip\@ .unboosted\@ asr.l #8,\1 .nomaxclip\@ ENDM CLIPTO8BITAFTERADD MACRO bvc.s .noclip\@ spl \1 eor.b #$7f,\1 .noclip\@ ENDM ; ---------------------------------------- ; proposed register assignment: ; a1 = Wave table order ; a4 = MyPlayer ; a6 = MySong / waveinfo pre_WaveGen: ; ---------------------------------------- lea .pre_log12_table(pc),a0 ; 128, 121, 114, 107, 102, 96, 90, 85, 80, 76, 72, 67 lea pv_osc_buffers+owb_sqr_waves(a4),a3 moveq.l #NOTES_IN_OCTAVE-1,d7 .noteloop swap d7 moveq.l #0,d6 move.w d6,d7 ; tabpos move.b (a0)+,d6 ; period move.l #$ff00,d5 divu d6,d5 ; frac increment move.w d6,d4 lsr.w #1,d4 ; half-period move.w d4,d3 lsr.w #1,d3 ; quarter-period moveq.l #0,d0 ; acc lea (a3,d6.w),a2 lea owb_tri_waves-owb_sqr_waves(a2),a2 suba.w d3,a2 .notewaveloop move.w d0,d2 lsr.w #8,d2 moveq.l #$7f,d1 sub.b d2,d1 move.b d1,owb_saw_waves-owb_sqr_waves(a3,d7.w) add.b d2,d2 cmp.w d7,d3 ; tabpos == negquarter bne.s .nowrapback suba.w d6,a2 ; go back to start of period .nowrapback cmp.w d0,d7 ble.s .otherhalf moveq.l #$7f,d1 sub.b d2,d1 move.b d1,(a2)+ bra.s .clip80 .otherhalf add.b #$80,d2 move.b d2,(a2)+ moveq.l #$7f,d2 cmp.w d7,d4 bne.s .noclip80 .clip80 moveq.l #-$80,d2 .noclip80 move.b d2,owb_sqr_waves-owb_sqr_waves(a3,d7.w) add.w d5,d0 ; increment acc by frac addq.w #1,d7 ; increment pos cmp.w d7,d6 bne.s .notewaveloop swap d7 lea owb_SIZEOF(a3),a3 dbra d7,.noteloop ; ---------------------------------------- ; proposed register assignment: ; a0 = sample output ; a1 = scratch ; a3 = waveinfo ; a4 = MyPlayer ; a6 = MySong / waveinfo .wavegenloop ;movea.l pv_my_song(a4),a6 moveq.l #0,d1 move.b (a1)+,d1 ; apply wave order redirection move.l a1,-(sp) ; what used to be sv_wavegen_order_table IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker move.b d1,pv_wg_curr_wave_num_b(a4) ENDC lsl.w #2,d1 move.l pv_wave_sample_table(a4,d1.w),a0 move.l a0,pv_wg_curr_sample_ptr(a4) IFND PRESTO_UNIFIED_STRUCT add.w #sv_wavelength_table,d1 adda.w d1,a6 move.l sv_wavelength_table-sv_wavelength_table(a6),d0 move.l d0,pv_wg_curr_sample_len_l(a4) IFNE PRETRACKER_PROGRESS_SUPPORT move.l sv_wavetotal_table-sv_wavelength_table(a6),pv_precalc_sample_size(a4) ENDC move.l sv_waveinfo_table-sv_wavelength_table(a6),a3 ELSE ; PRESTO_UNIFIED_STRUCT ; Presto has no MySong structure lea pv_wavelength_table(a4,d1.w),a6 ; copied from raspberry_casket moveq.l #0,d0 move.b wi_sam_len_b(a3),d0 addq.w #1,d0 lsl.w #7,d0 move.l d0,pv_wavelength_table-pv_wavelength_table(a6) move.l d0,d1 btst #2,wi_flags_b(a3) beq.s .onlythreeocts mulu #15,d1 lsr.l #3,d1 ; * 1.875 .onlythreeocts move.l d1,pv_wavetotal_table-pv_wavelength_table(a6) ; end stuff move.l d0,pv_wg_curr_sample_len_l(a4) IFNE PRETRACKER_PROGRESS_SUPPORT move.l d1,pv_precalc_sample_size(a4) ENDC move.l pv_waveinfo_table-pv_wavelength_table(a6),a3 ENDC ; PRESTO_UNIFIED_STRUCT ; clear sample data (a0 and d0 from above) bsr pre_MemClr move.l a0,pv_wg_curr_samend_ptr(a4) ; read out chord information lea wi_chord_note1_b(a3),a1 move.b (a1)+,d1 move.b (a1)+,d2 move.b (a1)+,d3 moveq.l #0,d4 move.b d1,d4 or.b d2,d4 or.b d3,d4 seq d4 neg.b d4 move.w d4,pv_wg_chord_flag_w(a4) ; has chord flag (0/1) move.b wi_osc_basenote_b(a3),d0 add.b d0,d1 add.b d0,d2 add.b d0,d3 lea pv_wg_chord_pitches(a4),a1 move.b d0,(a1)+ move.b d1,(a1)+ move.b d2,(a1)+ move.b d3,(a1)+ clr.w pv_wg_chord_note_num_b(a4) ; and pv_wg_chord_note_num_b .wavegen_chordloop lea pv_wg_chord_pitches(a4),a1 moveq.l #0,d1 move.b pv_wg_chord_note_num_b(a4),d1 ; chord note counter move.b (a1,d1.w),d0 ; get chord note ext.w d0 tst.w d1 beq.s .base_note_is_never_skipped ; is base note? cmp.b wi_osc_basenote_b(a3),d0 beq .wave_gen_tone_done ; skip chord notes that are same as base note .base_note_is_never_skipped moveq.l #0,d5 moveq.l #NOTES_IN_OCTAVE,d2 move.w d0,d5 move.w d0,a2 ; save base note, used later (much later, noise generator)! add.w #NOTES_IN_OCTAVE*NOTES_IN_OCTAVE,d5 ; make sure we don't run into negative modulo divu d2,d5 sub.w d2,d5 ; restore octave, result may be negative move.w d5,d1 ; +-octave swap d5 ; note within octave moveq.l #0,d7 move.b .pre_log12_table(pc,d5.w),d7 ; 128, 121, 114, 107, 102, 96, 90, 85, 80, 76, 72, 67 moveq.l #3,d0 mulu d0,d5 and.b wi_flags_b(a3),d0 beq.s .osc_selected addq.w #2,d5 subq.w #1,d0 beq.s .osc_selected subq.w #1,d5 subq.w #1,d0 .osc_selected lea pv_osc_buffers+owb_saw_waves(a4),a6 lsl.w #7,d5 adda.w d5,a6 ; ---------------------------------------- ; pitch ramp move.b wi_pitch_ramp_b(a3),d2 ext.w d2 ext.l d2 btst #4,wi_flags_b(a3) ; pitch linear flag beq.s .pitch_not_linear tst.w d2 bgt.s .pitch_ramp_positive ; FIXME what happens if d1 is negative? rolls out by 63? lsl.l d1,d2 add.l d2,d2 bra.s .pitch_ramp_cont .pre_log12_table dc.b $400000/$8000,$400000/$871d,$400000/$8f2f,$400000/$97b7,$400000/$9fc4,$400000/$a9de dc.b $400000/$b505,$400000/$bf49,$400000/$cb31,$400000/$d645,$400000/$e215,$400000/$f1a0 .pitch_not_linear tst.w d2 ble.s .pitch_ramp_cont .pitch_ramp_positive muls d2,d2 .pitch_ramp_cont lsl.l #8,d2 lsl.l #2,d2 ; check whether we have a noise oscillator or something else tst.w d0 beq .no_noise ; ---------------------------------------- ; d0 = scratch ; d1 = octave ; d2 = pitch ramping value ; d4 = scratch ; a2 = base note .gen_noise suba.l a6,a6 IFNE PRETRACKER_PARANOIA_MODE tst.w pv_wg_curr_sample_len_w(a4) beq .wave_gen_tone_done ENDC moveq.l #1,d5 ror.w #1,d5 ; $00008000 move.l d5,a5 tst.w d1 bge.s .gen_noise_positive_octave .gen_noise_negative_octave moveq.l #NOTES_IN_OCTAVE,d1 move.l a2,d3 neg.l d3 move.l d3,d0 divu d1,d0 IFNE PRETRACKER_PARANOIA_MODE bvs.s .divisionoverflow ENDC addq.w #1,d0 lsr.w d0,d5 moveq.l #0,d0 move.w d5,d0 divu d1,d0 moveq.l #0,d4 move.w d0,d4 IFNE PRETRACKER_PARANOIA_MODE bra.s .returnfromoverflow .divisionoverflow move.l #$AAA,d4 ; some dummy value, I would expect .returnfromoverflow ENDC moveq.l #0,d0 move.w d3,d0 .cheap_mod12 sub.w d1,d0 bpl.s .cheap_mod12 neg.w d0 mulu d4,d0 add.l d0,d5 .gen_noise_positive_octave moveq.l #0,d0 move.b wi_osc_phase_min_b(a3),d0 moveq.l #0,d1 move.b wi_chord_shift_b(a3),d1 add.w d1,d0 addq.w #1,d0 ; sum of phase min and shift are used as root for noise movea.l d5,a1 movea.l pv_wg_curr_sample_ptr(a4),a0 moveq.l #0,d1 moveq.l #0,d6 moveq.l #0,d3 move.b wi_osc_gain_b(a3),d3 .gen_noise_outerloop move.w d0,d1 ; random noise generator lsl.w #8,d1 lsl.w #5,d1 eor.w d1,d0 move.w d0,d1 lsr.w #8,d1 lsr.w #1,d1 eor.w d1,d0 move.w d0,d1 lsl.w #7,d1 eor.w d1,d0 move.b d0,d1 ; take the random seed ext.w d1 muls d3,d1 ; multiply by gain asr.w #7,d1 CLIPTO8BIT d1 add.b (a0),d1 move.w a5,d4 subq.w #1,d4 and.w #$7fff,d4 move.w d4,a5 addq.w #1,a5 .gen_noise_innerloop move.b d1,(a0)+ cmp.l pv_wg_curr_samend_ptr(a4),a0 beq .wave_gen_tone_done adda.l a1,a5 tst.l d2 beq.s .gen_noise_no_pitch_ramping add.l d2,d6 move.l d6,d4 asr.l #8,d4 asr.l #2,d4 add.l d5,d4 movea.l d4,a1 btst #4,wi_flags_b(a3) ; pitch linear flag beq.s .noise_nonlinear_pitch move.l d2,d4 ; filter pitch speed asr.l #7,d4 sub.l d4,d2 .noise_nonlinear_pitch cmp.w #$1ff,a1 bgt.s .gen_noise_no_end_of_pitch_ramp moveq.l #0,d2 ; stop pitch ramping move.l d2,a5 movea.w #$200,a1 .gen_noise_no_end_of_pitch_ramp .gen_noise_no_pitch_ramping cmp.w a5,a5 beq.s .gen_noise_innerloop bra .gen_noise_outerloop ; ---------------------------------------- ; d1 = octave ; d2 = pitch ramping value ; d5 = osc phase speed ; a2 = base note .no_noise moveq.l #15,d5 lsl.l d5,d7 sub.w d1,d5 ; 15-octave lsl.w #3,d5 moveq.l #0,d3 move.b wi_osc_phase_min_b(a3),d3 mulu d5,d3 lsl.l #6,d3 moveq.l #0,d0 move.b wi_osc_phase_max_b(a3),d0 mulu d5,d0 lsl.l #6,d0 move.l d0,a5 moveq.l #0,d5 move.b wi_osc_phase_spd_b(a3),d5 lsl.l #8,d5 lsl.l #3,d5 cmp.l d3,d0 bge.s .osc_with_positive_phase_speed neg.l d5 movea.l d3,a5 bra.s .osc_continue .osc_with_positive_phase_speed move.l d3,d0 .osc_continue move.l d0,pv_wg_osc_speed_l(a4) ; I think this calculates the base oscillator speed for higher and lower octaves moveq.l #1,d6 moveq.l #15,d0 add.w d1,d0 lsl.l d0,d6 ; d0 = d6 * chord_shift * chordnum + d6 * phase_min = d6 * (chord_shift * chordnum + phase_min) moveq.l #0,d4 move.b wi_chord_shift_b(a3),d4 move.w pv_wg_chord_flag_w(a4),d0 add.b pv_wg_chord_note_num_b(a4),d0 mulu d0,d4 moveq.l #0,d0 move.b wi_osc_phase_min_b(a3),d0 add.w d0,d4 move.l d6,d0 lsr.l #4,d0 lsl.l #4,d4 mulu d4,d0 .osc_loop_until_in_range sub.l d7,d0 bgt.s .osc_loop_until_in_range add.l d7,d0 move.l d6,d1 tst.b pv_wg_unisono_run_b(a4) beq.s .is_not_in_unisono moveq.l #3<<3,d1 and.b wi_mod_density_b(a3),d1 lsr.w #3,d1 moveq.l #9,d4 sub.w d1,d4 move.l d6,d1 asr.l d4,d1 add.l d6,d1 .is_not_in_unisono IFNE PRETRACKER_PARANOIA_MODE tst.w pv_wg_curr_sample_len_w(a4) beq .wave_gen_tone_done ENDC ; ---------------------------------------- ; chord gen ; in: d0/d1/d2/d3/d5/d7 ; in: a0 move.l d3,a1 movea.l pv_wg_curr_sample_ptr(a4),a0 suba.l a2,a2 .chordtoneloop move.l d0,d4 sub.l a1,d4 bpl.s .noclip_osc_phase moveq.l #0,d4 .noclip_osc_phase asr.l #8,d4 asr.l #7,d4 move.b (a6,d4.w),d4 ; fetch precalced sample ext.w d4 moveq.l #0,d3 move.b wi_osc_gain_b(a3),d3 muls d4,d3 asr.w #7,d3 move.b (a0),d4 ext.w d4 add.w d3,d4 CLIPTO8BIT d4 move.b d4,(a0)+ add.l d1,d0 cmp.l d7,d0 blt.s .lbC0025A2 sub.l d7,d0 add.l d5,a1 cmp.l a5,a1 blt.s .lbC00259A neg.l d5 move.l a5,a1 .lbC00259A cmp.l pv_wg_osc_speed_l(a4),a1 bgt.s .lbC0025A2 neg.l d5 move.l pv_wg_osc_speed_l(a4),a1 .lbC0025A2 tst.l d2 beq.s .chordtone_done adda.l d2,a2 move.l a2,d1 asr.l #8,d1 asr.l #2,d1 add.l d6,d1 btst #4,wi_flags_b(a3) ; pitch linear flag beq.s .no_linear_pitch move.l d2,d4 asr.l #7,d4 sub.l d4,d2 .no_linear_pitch cmp.l d7,d1 bcs.s .chordtone_done moveq.l #0,d2 moveq.l #0,d1 .chordtone_done cmp.l pv_wg_curr_samend_ptr(a4),a0 bne.s .chordtoneloop .wave_gen_tone_done addq.b #1,pv_wg_chord_note_num_b(a4) cmp.b #4,pv_wg_chord_note_num_b(a4) bne .wavegen_chordloop moveq.l #3<<3,d0 and.b wi_mod_density_b(a3),d0 ; unisono beq.s .chords_done move.l a6,d1 beq.s .chords_done tst.b pv_wg_unisono_run_b(a4) bne.s .chords_done move.w #$0001,pv_wg_chord_note_num_b(a4) ; sets also pv_wg_unisono_run_b bra .wavegen_chordloop .chords_done ; ---------------------------------------- ; filters ; proposed register assignment: ; a0 = sample output ; a1 = end of filter chunk ; a2 = filter func ; d7/a6 = filter start ; a4 = MyPlayer ; a5 = unused ; a3 = waveinfo ; d3/d4/d5/d6 = filter taps ; d0/d1/d7 = scratch moveq.l #0,d0 move.b wi_flt_type_b(a3),d0 beq .filter_done IFNE PRETRACKER_PARANOIA_MODE tst.w pv_wg_curr_sample_len_w(a4) beq .filter_done ENDC add.w d0,d0 lea .filterfunc_jmptable(pc),a2 add.w -1*2(a2,d0.w),a2 moveq.l #0,d4 ; filter tap values moveq.l #0,d5 ; filter tap values movem.l d4-d5,pv_wg_flt_taps(a4) lea wi_flt_start_b(a3),a0 moveq.l #0,d0 move.b (a0)+,d0 ; wi_flt_start_b lsl.w #8,d0 move.b (a0)+,d4 ; wi_flt_min_b lsl.w #8,d4 ; flt_min*256 move.b (a0)+,d5 ; wi_flt_max_b lsl.w #8,d5 ; flt_max*256 move.b (a0)+,d3 ; wi_flt_speed_b ext.w d3 ext.l d3 ; flt_speed*128 lsl.l #7,d3 movea.l pv_wg_curr_sample_ptr(a4),a0 .entry_to_filter_loop move.l d0,a6 move.l d3,d1 ; flt_speed_b*128 adda.l d1,a6 ; suppress M68kUnexpectedConditionalInstruction bgt.s .filter_speed_pos .filter_speed_neg move.l d4,d1 ; flt_min*256 cmp.l d1,d0 blt.s .lbC002790 cmp.l d1,a6 bgt.s .lbC002936 move.l d1,a6 cmp.l d5,d1 ; flt_max*256 beq.s .filter_load_min neg.l d3 ; flt_speed_b*128 bra.s .filter_load_min .filterfunc_jmptable dc.w .lowpassfilter-.filterfunc_jmptable dc.w .highpassfilter-.filterfunc_jmptable dc.w .bandpassfilter-.filterfunc_jmptable dc.w .notchfilter-.filterfunc_jmptable .lbC002790 tst.l d0 blt.s .lbC002936 move.l a6,d7 bgt.s .lbC002936 neg.l d3 ; flt_speed_b*128 move.w #$FF,d2 move.w d2,d1 sub.l a6,a6 bra.s .filter_cont .filter_speed_pos cmp.l d5,d0 ; flt_max*256 bgt.s .lbC002D2A cmp.l d5,a6 ; flt_max*256 blt.s .lbC002936 move.l d4,d2 ; flt_min*256 cmp.l d5,d2 ; flt_max*256 beq.s .filter_load_max_no_flip neg.l d3 ; flt_speed_b*128 move.l d5,a6 ; flt_max*256 bra.s .filter_load_max .lbC002D2A cmpi.l #$FF00,d0 bgt.s .lbC002936 cmp.l #$FEFF,a6 ble.s .lbC002936 neg.l d3 ; flt_speed_b*128 moveq.l #0,d2 move.l #$FF00,a6 bra.s .filter_cont .lbC002936 move.w a6,d2 lsr.w #8,d2 not.b d2 bra.s .filter_cont .filter_load_max_no_flip movea.l d2,a6 .filter_load_max moveq.l #0,d2 move.b wi_flt_max_b(a3),d2 not.b d2 bra.s .filter_cont .filter_load_min moveq.l #0,d2 move.b wi_flt_min_b(a3),d2 not.b d2 .filter_cont btst #0,wi_flt_type_b(a3) bne.s .not_notch_or_highpass .highpass_or_notch ; entered for 2 or 4 not.b d2 .not_notch_or_highpass ; entered for 1 or 3 move.w d2,d0 add.w d0,d0 moveq.l #0,d7 move.b wi_flt_resonance_b(a3),d7 beq.s .filter_no_resonance move.w d2,d1 ext.l d1 lsl.l #8,d1 moveq.l #$B6/2,d0 sub.w d7,d0 add.w d0,d0 cmpi.w #$36,d0 bge.s .filter_no_clip_resonance moveq.l #$36,d0 .filter_no_clip_resonance divu d0,d1 move.w d2,d0 add.w d1,d0 .filter_no_resonance lea $40(a0),a1 ; end of sample chunk movem.l d3-d5,-(sp) movem.w pv_wg_flt_taps(a4),d3-d6 ; d0/d2 relevant for inner loop .filter_innerloop move.b (a0),d1 ext.w d1 move.w d4,d7 sub.w d5,d7 muls d0,d7 asr.l #8,d7 sub.w d4,d7 add.w d1,d7 muls d2,d7 asr.l #8,d7 add.w d7,d4 move.w d4,d7 sub.w d5,d7 muls d2,d7 asr.l #8,d7 add.w d7,d5 move.w d5,d7 sub.w d6,d7 muls d2,d7 asr.l #8,d7 add.w d7,d6 move.w d6,d7 sub.w d3,d7 muls d2,d7 asr.l #8,d7 add.w d7,d3 move.w d3,d7 jmp (a2) .highpassfilter sub.w d1,d7 bra.s .filterclipresult .bandpassfilter sub.w d4,d7 sub.w d5,d7 sub.w d6,d7 asr.w #1,d7 bra.s .filterclipresult .notchfilter sub.w d4,d7 neg.w d7 .lowpassfilter .filterclipresult CLIPTO8BIT d7 .filter_outputbyte move.b d7,(a0)+ cmp.l a0,a1 bne.s .filter_innerloop .filterloop_end_test movem.w d3-d6,pv_wg_flt_taps(a4) movem.l (sp)+,d3-d5 cmp.l pv_wg_curr_samend_ptr(a4),a0 bhs.s .filter_done move.l a6,d0 bra .entry_to_filter_loop .filter_done ; ---------------------------------------- ; Optional Pre-Modulator btst #5,wi_mod_density_b(a3) ; post bit bne.s .nopremodulator bsr pre_Modulator .nopremodulator ; ---------------------------------------- ; start with volume envelope ; a0 = output sample buffer ; d0 = scratch (e.g. sample) ; d1 = increment for attack phase ; d3 = current volume for attack and decay phases ; d4 = remaining sample length - 1 ; a3 = wave info .vol_do_envelope move.l pv_wg_curr_sample_ptr(a4),a0 ; load buffer pointer move.w pv_wg_curr_sample_len_w(a4),d4 ; load length IFNE PRETRACKER_PARANOIA_MODE beq .vol_envelope_finished ; paranoia ENDC subq.w #1,d4 ; we use length-1, <0 is end moveq.l #2,d1 ; turns into $20000 through swap moveq.l #0,d0 move.b wi_vol_attack_b(a3),d0 bne.s .has_attack_volume cmp.b #$ff,wi_vol_sustain_b(a3) beq .vol_envelope_finished ; no attack but not full sustain -> go to delay ;move.l #$100<<16,d3 bra.s .vol_skip_attack .vol_avoid_overflow_with_1 moveq.l #1,d1 bra.s .cont_vol_envelope .has_attack_volume moveq.l #0,d3 cmp.w #1,d0 beq.s .cont_vol_envelope cmp.w #2,d0 beq.s .vol_avoid_overflow_with_1 swap d1 ; turn into $20000 divu d0,d1 swap d1 clr.w d1 ; swap is done below .cont_vol_envelope swap d1 ; move to high word (should be max $20000 then) btst #5,wi_flags_b(a3) ; vol fast flag beq.s .vol_no_fast lsl.l #4,d1 ; multiply speed by 16 .vol_no_fast add.l d1,d3 ; increase volume cmp.l #$ffffff,d3 ble.s .vol_do_attack ; first step overshooting? .vol_skip_attack btst #3,wi_flags_b(a3) ; boost flag bne.s .vol_delay_boosted bra.s .vol_delay_normal .vol_do_attack btst #3,wi_flags_b(a3) ; boost flag bne.s .vol_attack_boosted ; ---------------------------------------- ; attack phase with volume boosted .vol_attack_normal .vol_attack_normal_loop move.b (a0),d0 ext.w d0 swap d3 muls d3,d0 swap d3 asr.w #8,d0 move.b d0,(a0)+ subq.w #1,d4 bmi .vol_envelope_finished add.l d1,d3 ; increase volume cmp.l #$ffffff,d3 ble.s .vol_attack_normal_loop ; ---------------------------------------- ; delay phase (normal) .vol_delay_normal ; moved this label two inst up, didn't make sense there moveq.l #0,d0 move.b wi_vol_delay_b(a3),d0 lsl.w #4,d0 IFNE PRETRACKER_FASTER_CODE ; skip the delay -- we don't change the volume for this section addq.w #1,d0 sub.w d0,d4 bmi .vol_envelope_finished lea 1(a0,d0.w),a0 ELSE lea 2(a0,d0.w),a1 move.w #$ff,d3 ; FIXME I don't think that this is quite right. Shouldn't the max volume NOT change the value? .vol_delay_normal_loop move.b (a0),d0 IFNE 1 ext.w d0 muls d3,d0 asr.w #8,d0 ELSE ; this should be the same as above (*(256-1)) spl d3 add.b d3,d0 ENDC move.b d0,(a0)+ cmp.l a1,a0 dbeq d4,.vol_delay_normal_loop bne .vol_envelope_finished ENDC bra.s .vol_delay_end_reached ; ---------------------------------------- ; attack with volume boosted .vol_attack_boosted .vol_attack_boosted_loop move.b (a0),d0 ext.w d0 swap d3 muls d3,d0 swap d3 asr.w #6,d0 CLIPTO8BIT d0 move.b d0,(a0)+ subq.w #1,d4 bmi .vol_envelope_finished add.l d1,d3 cmp.l #$ffffff,d3 ble.s .vol_attack_boosted_loop ; ---------------------------------------- ; delay with max volume boosted .vol_delay_boosted moveq.l #0,d0 move.b wi_vol_delay_b(a3),d0 lsl.w #4,d0 lea 2(a0,d0.w),a1 IFNE PRETRACKER_FASTER_CODE .vol_delay_boosted_loop move.b (a0),d0 add.b d0,d0 CLIPTO8BITAFTERADD d0 add.b d0,d0 CLIPTO8BITAFTERADD d0 ELSE move.w #$ff,d3 ; FIXME I don't think that this is quite right. It should be $100 to boost by full volume .vol_delay_boosted_loop move.b (a0),d0 ext.w d0 muls d3,d0 asr.w #6,d0 CLIPTO8BIT d0 ENDC move.b d0,(a0)+ cmp.l a1,a0 dbeq d4,.vol_delay_boosted_loop bne .vol_envelope_finished .vol_delay_end_reached subq.w #1,d4 ; ---------------------------------------- ; decay phase ; d0 = scratch ; d1 = current volume decrement ; d2 = table index boundary ; d3 = 16:16 decay pos ; d4 = sample length counter ; d5 = volume ; d6 = scratch ; d7 = decay increment ; a0 = sample pointer ; a1 = (current) roll off table pointer (points to upper bound) ; a2 = lower bound .vol_do_decay moveq.l #0,d3 move.b wi_vol_decay_b(a3),d3 beq .vol_do_sustain move.w d3,d7 mulu d7,d7 lsr.w #2,d7 add.w d3,d7 ; d7 = (d3^2)/4+d3 (<= 16511) btst #5,wi_flags_b(a3) ; vol fast flag beq.s .vol_decay_not_fast moveq.l #0,d3 ; will cause a5=$400,a2=$200,d2=0, decay value has no effect on the ramp used .vol_decay_not_fast lsl.w #8,d3 lsl.l #4,d3 move.l d3,d2 swap d2 lea pre_roll_off_table(pc),a1 add.w d2,d2 adda.w d2,a1 move.w (a1)+,a2 ; first index in table lsr.w #1,d2 ; update next boundary moveq.l #0,d1 ; current volume decrement moveq.l #0,d5 not.w d5 ; set maximum volume .vol_decay_normal_loop add.l d7,d3 ; increment position in decay swap d3 cmp.w #$8e,d3 ; pos in table where it makes no sense to do lerp anymore bhi.s .vol_keep_voldec cmp.w d2,d3 bls.s .vol_do_lerp .vol_lerp_next_section move.w (a1),a2 IFNE PRETRACKER_BUGFIX_CODE lea pre_roll_off_table+2(pc),a1 ; Take the right boundary value ELSE lea pre_roll_off_table(pc),a1 ; This will set a wrong boundary and thus plateau the slope decay speed ENDC add.w d3,a1 add.w d3,a1 move.w d3,d2 ; update next boundary .vol_do_lerp ; ((lowerbound-upperbound)*(d3<<8))>>8 + upperbound move.w a2,d1 move.w (a1),d0 sub.w d1,d0 ; delta between lower and upper bound (negative value) beq.s .vol_skip_lerp swap d3 move.w d3,d1 lsr.w #8,d1 muls d0,d1 asr.l #8,d1 add.w a2,d1 swap d3 .vol_keep_voldec .vol_skip_lerp swap d3 sub.w d1,d5 bls.s .vol_do_sustain move.w d5,d6 lsr.w #8,d6 cmp.b wi_vol_sustain_b(a3),d6 bls.s .vol_do_sustain move.b (a0),d0 ext.w d0 muls d6,d0 btst #3,wi_flags_b(a3) ; boost flag CLIPORTRUNC8BIT d0 move.b d0,(a0)+ dbra d4,.vol_decay_normal_loop bra.s .vol_envelope_finished ; ---------------------------------------- ; sustain phase .vol_do_sustain moveq.l #0,d3 move.b wi_vol_sustain_b(a3),d3 beq.s .vol_sustain_silence btst #3,wi_flags_b(a3) ; boost flag beq.s .vol_sustain_normal .vol_sustain_boosted .vol_sustain_boosted_loop move.b (a0),d0 ext.w d0 muls d3,d0 asr.w #6,d0 CLIPTO8BIT d0 move.b d0,(a0)+ dbra d4,.vol_sustain_boosted_loop bra.s .vol_envelope_finished .vol_sustain_silence moveq.l #0,d0 .vol_sustain_silence_loop move.b d0,(a0)+ dbra d4,.vol_sustain_silence_loop bra.s .vol_envelope_finished .vol_sustain_normal IFNE PRETRACKER_FASTER_CODE cmp.b #$ff,d3 beq.s .vol_envelope_finished ENDC .vol_sustain_normal_loop move.b (a0),d0 ext.w d0 muls d3,d0 asr.w #8,d0 move.b d0,(a0)+ dbra d4,.vol_sustain_normal_loop .vol_envelope_finished ; ---------------------------------------- ; Optional Post-Modulator btst #5,wi_mod_density_b(a3) ; post bit beq.s .nopostmodulator bsr.s pre_Modulator .nopostmodulator ; ---------------------------------------- ; wave mixing (removed some code here that was doing nothing as result ; because below higher octaves code would overwrite it anyway). IFND PRESTO_UNIFIED_STRUCT movea.l pv_my_song(a4),a6 ENDC moveq.l #0,d0 move.b wi_mix_wave_b(a3),d0 beq.s .mix_no_wave_mixing ; no mixing selected subq.b #1,d0 IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker cmp.b pv_wg_curr_wave_num_b(a4),d0 beq .mix_no_wave_mixing ; same wave number! ENDC lsl.w #2,d0 move.l pv_wave_sample_table(a4,d0.w),a1 IFND PRESTO_UNIFIED_STRUCT add.w #sv_wavelength_table,d0 move.l (a6,d0.w),d3 ELSE move.l pv_wavelength_table(a4,d0.w),d3 ENDC move.w pv_wg_curr_sample_len_w(a4),d4 ; length of the sample to mix to cmp.w d3,d4 ble.s .mix_picked_shorter move.w d3,d4 .mix_picked_shorter move.l pv_wg_curr_sample_ptr(a4),a0 subq.w #1,d4 .mix_mixloop move.b (a0),d0 add.b (a1)+,d0 CLIPTO8BITAFTERADD d0 move.b d0,(a0)+ dbra d4,.mix_mixloop .mix_no_wave_mixing ; ---------------------------------------- ; create higher octaves (this has been massively shortened) btst #2,wi_flags_b(a3) beq.s .oct_has_no_extra_octaves move.l pv_wg_curr_sample_len_l(a4),d4 IFNE PRETRACKER_PARANOIA_MODE beq.s .oct_has_no_extra_octaves ENDC movea.l pv_wg_curr_sample_ptr(a4),a1 lea (a1,d4.l),a0 ; needs to be .l due to 32678 max length mulu #7,d4 lsr.l #3,d4 ; * 0.875 subq.w #1,d4 .oct_downsample_loop move.b (a1),(a0)+ addq.l #2,a1 dbra d4,.oct_downsample_loop .oct_has_no_extra_octaves ; ---------------------------------------- IFNE PRETRACKER_PROGRESS_SUPPORT move.l pv_precalc_progress_ptr(a4),d0 beq.s .no_progress_out move.l d0,a0 move.l pv_precalc_sample_size(a4),d0 add.l d0,(a0) .no_progress_out ENDC move.l (sp)+,a1 subq.w #1,pv_wg_wave_counter_w(a4) bgt .wavegenloop rts ;-------------------------------------------------------------------- ; a3: waveinfo ; ; uses all data registers and a0-a1 (a2/a3 unchanged) pre_Modulator: tst.b wi_mod_wetness_b(a3) beq.s .earlyexit moveq.l #7,d0 and.b wi_mod_density_b(a3),d0 bne.s .has_density .earlyexit rts .has_density move.l pv_wg_curr_sample_ptr(a4),a0 move.w pv_wg_curr_sample_len_w(a4),d4 IFNE PRETRACKER_PARANOIA_MODE bne.s .not_zero rts .not_zero ENDC moveq.l #0,d6 move.b wi_mod_wetness_b(a3),d6 moveq.l #0,d7 lea pre_modulator_ramp_8(pc),a1 .loop moveq.l #0,d5 move.b wi_mod_length_b(a3),d5 mulu (a1)+,d5 ; result is a long value moveq.l #0,d1 move.b wi_mod_predelay_b(a3),d1 btst #5,wi_mod_density_b(a3) ; post-modulator? bne.s .factor1_256 ; factor 1/4 and 64 lsr.l #2,d5 lsl.l #6,d1 bra.s .cont .factor1_256 lsl.w #8,d1 .cont add.l d1,d5 ; sum up length and predelay moveq.l #0,d2 moveq.l #0,d3 .innerloop moveq.l #0,d1 add.w d7,d3 addq.w #8,d3 smi d1 ext.w d1 eor.w d3,d1 ; flip order if it was negative lsr.w #6,d1 ; 4 bit key is bits 14 to 11, needs to be 8 to 5 and.w #15<<5,d1 add.l d5,d1 lsr.l #6,d1 move.w d2,d0 sub.w d1,d0 bmi.s .is_outside_sample move.b (a0,d0.w),d1 ext.w d1 btst #0,d7 beq.s .keep_dc neg.w d1 .keep_dc muls d6,d1 asr.w #8,d1 add.b (a0,d2.w),d1 CLIPTO8BITAFTERADD d1 move.b d1,(a0,d2.w) .is_outside_sample addq.w #1,d2 cmp.w d4,d2 bcs.s .innerloop .restartloop addq.w #1,d7 moveq.l #7,d0 and.b wi_mod_density_b(a3),d0 cmp.w d0,d7 bcs.s .loop rts ;-------------------------------------------------------------------- pre_MemClr lsr.w #1,d0 subq.w #1,d0 bmi.s .skipmemclr moveq.l #0,d1 .fillmemloop move.w d1,(a0)+ dbra d0,.fillmemloop .skipmemclr rts