******************************************************************************** * AlienSCApe: A musical journey in 256 bytes. Coded by Saturnus the Invincible * * The Mega-Mighty Swiss Cracking Association - reaching out to you! 2024-06-06 * ******************************************************************************** SECTION text,CODE_C ; wave needs CHIP mem include "hardware/custom.i" include "hardware/intbits.i" include "hardware/dmabits.i" _custom equ $dff000 ; no audio.device ;-) ; these regs hold one byte per voice (conveniently, 4 bytes for 4 voices): ; D7: volume (63..0) ; D6: fadeout timer, d6 and d5 implement a logarithmicish fadeout curve ; D5: fadeout timer decrement timer initial value ; ; these regs are used normally: ; D4: note timer ; D3: speed of current 5-tone-sequence (global) ; D2: voice counter (3..0) ; D1: octave (0..3) ; A1: points to current position within melody _main: lea _custom+aud,a5 ; aud saves 2 bytes move.w #INTF_INTEN,intena-aud(a5) ; disable() move.w dmaconr-aud(a5),-(SP) ; save dmacon for later move.w #$7fff,dmacon-aud(a5) ; turn all dma off moveq #3,d2 ; 4 voices movea.l a5,a0 ; 1st voice lea wave(pc),a2 .initloop: move.l a2,(a0)+ ; ac_ptr move.w #(wave_end-wave)/2,(a0) ; ac_len (words) lea ac_SIZEOF-4(a0),a0 ; next channel dbf d2,.initloop move.w #DMAF_SETCLR|DMAF_MASTER|DMAF_AUDIO,dmacon-aud(a5) movea.l a5,a0 ; 1st voice moveq #3,d2 ; 4 voices moveq #1,d4 ; reset note timer ;;; moveq #0,d7 ; not needed, save space ; start the song from the beginning .initsong: lea five_tones(pc),a1 lsl.w #3,d4 ; 8x delay after last note moveq #64,d3 ; minimal speed: 64 or.b vhposr-aud(a5),d3 ; rand(64..255) move.b d3,d1 neg.b d1 ; neg to get long low notes lsr.b #6,d1 ; use bits 7 and 5 (6 is always set) bcc.b .1 ; bit 5 is now in carry addq.b #1,d1 ; bit 5 was set: set bit 0 in d1 .1: bra.b .noplay ; keep last note playing ; envelope generator .loop: movea.l a5,a0 ; 1st voice moveq #3,d2 ; 4 voices .voiceloop: moveq #0,d0 move.b d7,d0 ; current volume move.w d0,ac_vol(a0) beq.b .nofade ; silent --> done subq.b #1,d6 ; decrement fadeout timer bne.b .nofade ; not time yet --> done subq.b #1,d7 ; fade volume down move.b d5,d6 ; restart fadeout timer lsr.b #3,d6 ; convert fixed to int addq.b #1,d5 ; inc timer start for smooth fadeout .nofade: subq.w #1,d4 ; decrement note timer bne.b .noplay ; not time yet --> move.w d3,d4 ; restart note timer move.w (a1)+,d0 ; next note from five_tones beq.b .initsong ; five_tones done --> lsr.w d1,d0 ; calculate octave shift move.w d0,ac_per(a0) move.b #15,d5 ; init fade timer timer (5.3 fixed) move.b #1,d6 ; init fade timer move.b #63,d7 ; set initial volume .noplay: lea ac_SIZEOF(a0),a0 ror.l #8,d7 ; next voice's volume ror.l #8,d6 ; next voice's fade timer ror.l #8,d5 ; next voice'a fade timer timer dbf d2,.voiceloop move.l d7,d0 lsr.l #2,d0 ; volume 63..0 --> brightness 15..0 lsl.b #4,d0 ; 000r0gb0 lsl.w #4,d0 ; 000rgb00 lsr.l #8,d0 ; 00000rgb move.w d0,color-aud(a5) ; volumes of 3 voices as r/g/b ; delay for 5 ms so a full speed volume fade takes 5*64 = 320 ms moveq #4800/64,d0 ; number of lines to wait .delay: move.b vhposr-aud(a5),d2 ; vpos .waitline: cmp.b vhposr-aud(a5),d2 beq.b .waitline dbf d0,.delay ; so many bytes left, might as well nicely exit to OS after left mouse button press btst #6,$bfe001 bne.b .loop .done: move.w #DMAF_AUDIO,dmacon-aud(a5) ; turn off audio DMA bset #7,(SP) ; set DMAF_SETCLR move.w (SP)+,dmacon-aud(a5) ; restore dmacon moveq #0,d0 ; CLI return code rts wave: dc.b 127,-127 ; our patented wave with lots of harmonics wave_end: five_tones: dc.w 15043,13401,16885,33769,22538,0 ; ®ipped from movie by STI\SCA !!! END