home *** CD-ROM | disk | FTP | other *** search
- *********************************************************
- * *
- * FurLess.a - Produced for an entry to the 'neatest *
- * program under 2K' contest at the ASDF 010th *
- * annual GURU meditation by: *
- * *
- * Wesley Howe *
- * 10-Jun-90 *
- * *
- * Assembled with CAPE (of course.) *
- * *
- *********************************************************
- *
- EXEOBJ ;generate free-standing executable
- OBJFILE "FurLess" ;output filename
- INCLUDE "FurLess.i" ;definitions
- *
- * some register equates
- *
- BR EQUR A5 ;data area
- WN EQUR A4 ;Window Pointer
- CST EQUR A3 ;CUSTOM chips
- *
- * some specific equates for this program
- *
- TEMPO1 EQU 48000
- TEMPO2 EQU 42000
- TEMPO3 EQU 40000
- TEMPO4 EQU 40000
- TEMPO5 EQU 30000
- TEMPO6 EQU 40000
- NUMSONGS EQU 6
- SAMPLELEN EQU 32
- BEETLEN EQU (124*10)*4
- BACHLEN EQU (124*10)*4
- SCARLEN EQU (108*10)*4
- LARLEN EQU (96*10)*4
- RSUNLEN EQU (192*10)*4 ;9680 (192beats*10pairs/beat)*4bytes/pair
- TEARLEN EQU (128*10)*4
- *
- * define our general data memory offsets
- *
- DDEF MACRO ;name,size
- \1 EQU stemp
- stemp SET stemp+\2
- ENDM
- *
- stemp SET 0 ;for DDEF macro
- DDEF IntuitionBase,4 ;to hold a pointer
- DDEF GfxBase,4 ;to hold a pointer
- DDEF Screen,4 ;to hold a pointer
- DDEF Window,4 ;to hold a pointer
- DDEF NewPointer,12 ;used for an empty sprite structure
- DDEF MyScrn,NewScreen.SIZE ;we'll build a NewScreen here
- DDEF MyWin,NewWindow.SIZE ;and a NewWindow here
- DDEF Tempo,2 ;runtime copy of Tempo in use
- DDEF CurSong,2 ;becomes an array index
- DDEF seed,4 ;random number seed goes here
- DDEF NewX,4 ;vars for screen fill routine
- DDEF NewY,4
- DDEF NewH,4
- DDEF NewV,4
- DDEF NewF,4
- DDEF NewB,4
- DDEF WBenchMsg,4 ;saved from startup
- DDEF FMAudio,IOAudio.SIZE ;build an IOAudio struct here
- DDEF BodyIText,IntuiText.SIZE ;and a couple IntuiText structs
- DDEF PosIText,IntuiText.SIZE
- DDEF Note1,SAMPLELEN ;our waveform gets copied here
- DDEF Data0,RSUNLEN*2 ;twice the size of the LARGEST one
- ChipSize EQU stemp
- IFGE ChipSize-32768 ;make sure we don't exceed signed
- FAIL "DataSize too Large" ;limits for addressing mode used
- ENDC
- *
- *-------------------------------------------------------------------------
- * This is our startup initialization and main program loop
- *-------------------------------------------------------------------------
- *
- Strt: movem.l a2-a6/d2-d7,-(sp) ;save the regs in case someone calls us
- movea.l 4,A6 ;good ole execbase
- move.l #ChipSize,d0 ;size defined by the DDEF macros
- move.l #MEMF_CHIP!MEMF_CLEAR,d1 ;put it in chip for the audio stuff
- jsr AllocMem(A6) ;but do it all so we only need one
- movea.l d0,BR ;data area for baseregister addressing
- tst.l d0
- bne.s 10$
- moveq #103,d0 ;insufficient free store error code
- bra 999$
- 10$: movea.l ExecBase.ThisTask(a6),a2 ;our task address
- tst.l Process.pr_CLI(a2) ;see if we came from a CLI
- bne.s 40$
- lea Process.pr_MsgPort(a2),a0 ;else get the WorkBench message
- jsr WaitPort(a6) ;so we can reply it later
- lea Process.pr_MsgPort(a2),a0 ;or else we'll eat memory
- jsr GetMsg(a6) ;as WorkBench won't unload us
- move.l d0,WBenchMsg(BR) ;if we don't reply
- 40$: lea CUSTOM,CST ;for the hardware hacking
- lea IntuitionName(pc),a1 ;open needed libs
- moveq #33,d0 ;version 33
- jsr OpenLibrary(a6)
- move.l d0,IntuitionBase(BR)
- beq 980$ ;handle unlikely failure
- lea GfxName(pc),a1
- moveq #33,d0
- jsr OpenLibrary(a6)
- move.l d0,GfxBase(BR)
- beq 980$ ;handle unlikely failure
- bsr ScrnSet ;this routine initializes the screen
- beq 900$
- bsr HogAudio ;this allocates all the audio chans
- tst.l d0 ;so we can hack on the hardware
- bne 900$
- lea wavedata(pc),a0 ;build a waveform in chip ram
- lea Note1(BR),a1
- moveq #(SAMPLELEN/2)-1,d1 ;samples in note
- 70$: move.b (a0)+,d0
- move.b d0,(a1)+ ;copy of first half
- neg.b d0 ;second half is mirror image
- move.b d0,((SAMPLELEN/2)-1)(a1) ;we preincremented this!
- dbra d1,70$
- bsr NewSong ;start the music
- 100$: bsr ColorOne ;draw a pretty square
- movea.l Window.UserPort(WN),a0 ;and see if we have any key-presses
- jsr GetMsg(a6)
- tst.l d0
- beq.s 100$ ;nada, reloop
- movea.l d0,a1
- move.l IntuiMessage.Code(a1),d2 ;stash Code & Qualifier
- jsr ReplyMsg(a6)
- andi.b #$3f,d2 ;LSHIFT!RSHIFT!CAPSLOCK!CONTROL!LALT!RALT
- bne.s 100$ ;if any of above, reject 'em
- swap d2 ;we got two words with one long read
- cmpi.b #$45,d2 ;ESC raw keycode
- beq.s 200$
- cmpi.b #$4c,d2 ;UP ARROW raw keycode
- bne.s 120$
- move.w Tempo(BR),d2 ;to go faster, we make the period smaller
- cmpi.w #5000,d2 ;but let's not get too small
- bls 100$
- sub.w #400,d2 ;a handy step size
- move.w d2,Tempo(BR)
- jsr Disable(a6) ;so the next 2 instructions aren't apart
- move.w d2,AUD0PER(CST) ;note here the order.. when we step the
- move.w d2,AUD2PER(CST) ;other way, we'll reverse this order
- jsr Enable(a6) ;restore normal state
- bra 100$
- 120$: cmpi.b #$4d,d2 ;DOWN ARROW raw keycode
- bne.s 130$
- move.w Tempo(BR),d2
- cmpi.w #65000,d2 ;we can't get larger than 64K
- bhi 100$
- add.w #400,d2
- move.w d2,Tempo(BR)
- jsr Disable(a6) ;the order is changed because the audio
- move.w d2,AUD2PER(CST) ;state machine will keep going and we can't
- move.w d2,AUD0PER(CST) ;actually write both at once. This way we
- jsr Enable(a6) ;will erase the small accumulated error.
- bra 100$
- 130$: cmpi.b #$5f,d2 ;HELP raw keycode
- bne.s 150$
- bsr DoRequest ;routine to pop up our Auto Requester
- bra 100$
- 150$: cmpi.b #$50,d2 ;F1 raw keycode
- bne 100$
- bsr musoff ;stop the old song
- bsr Slower ;make sure audio stays shut off a while so it won't
- bsr NewSong ;restart at the same location it was at.
- bra 100$
- 200$: bsr musoff
- bsr ShareAudio ;return the resources
- 900$: movea.l IntuitionBase(BR),a6 ;close the window
- move.l Window(BR),d0
- beq.s 910$
- movea.l d0,a0
- jsr CloseWindow(a6)
- 910$: move.l Screen(BR),d0 ;and the screen
- beq.s 980$
- movea.l d0,a0
- jsr CloseScreen(a6)
- 980$: movea.l 4,a6 ;and the libraries we opened
- move.l IntuitionBase(BR),d0
- beq.s 990$
- movea.l d0,a1
- jsr CloseLibrary(a6)
- move.l GfxBase(BR),d0
- beq.s 990$
- movea.l d0,a1
- jsr CloseLibrary(a6)
- 990$: move.l WBenchMsg(BR),d2 ;if we came from WorkBench
- beq.s 995$ ;we need to reply our startup msg
- jsr Forbid(a6) ;so we don't get unloaded early
- movea.l d2,a1
- jsr ReplyMsg(a6)
- 995$: movea.l BR,a1 ;return the memory to the system
- move.l #ChipSize,d0
- jsr FreeMem(A6)
- moveq #0,d0
- 999$: movem.l (sp)+,a2-a6/d2-d7 ;restore the saved registers
- rts ;this send us back to our caller
- *
- *------------------------------------------------------------------------
- * This routine is based on code developed by Erik Quackenbush. I just
- * shamelessly expropriated it for my own use, by permission. Thanks, Erik.
- * It uses a dithering pattern to get many effective colors out of a 3 plane
- * (8-color) screen.
- *------------------------------------------------------------------------
- *
- MyFlags EQU BORDERLESS!BACKDROP!ACTIVATE!SMART_REFRESH!NOCAREREFRESH
- ColorOne:
- movem.l a6/d2-d3,-(sp) ;save the regs we use
- movea.l GfxBase(BR),a6 ;we need this here
- bsr Rand ;get a new number
- move.l d0,d1 ;here we chop it up into the pieces we
- andi.l #7,d0 ;will need later
- move.l d0,NewF(BR)
- lsr.l #3,d1
- move.l d1,d0
- andi.l #7,d0
- move.l d0,NewB(BR)
- lsr.l #3,d1
- move.l d1,d0
- andi.l #127,d0
- move.l d0,NewH(BR)
- lsr.l #7,d1
- move.l d1,d0
- andi.l #127,d0
- move.l d0,NewV(BR)
- lsr.l #7,d1
- move.l d1,d0
- andi.l #1023,d0
- subi.l #200,d0
- move.l d0,NewX(BR)
- move.l NewF(BR),d0
- add.l NewB(BR),d0
- move.l seed(BR),d1
- lsr.l d0,d1
- andi.l #511,d1
- subi.l #75,d1
- move.l d1,NewY(BR)
- movea.l Window.RPort(WN),a1
- move.l NewF(BR),d0
- jsr SetAPen(a6) ;set a new Front Pen color
- movea.l Window.RPort(WN),a1
- move.l NewB(BR),d0
- jsr SetBPen(a6) ;and a new Back Pen color
- movea.l Window.RPort(WN),a1
- move.l NewX(BR),d0
- move.l NewY(BR),d1
- move.l d0,d2
- add.l NewH(BR),d2
- move.l d1,d3
- add.l NewV(BR),d3
- jsr RectFill(a6) ;this does the coloring for us
- movem.l (sp)+,a6/d2-d3
- rts
- *
- *---------------------------------------------------------------------------
- * This routine opens the screen and window. If it returns a zero (NULL)
- * the calling code will know that we had a failure to open one or the
- * other. The cleanup code will only close what was opened, so all resources
- * will get returned even if only the OpenWindow fails. In order to stay
- * pure, we initialize everything on the fly here, and some of the word sized
- * fields that are adjacent get initialized as a single longword write.
- *---------------------------------------------------------------------------
- *
- ScrnSet:
- movem.l a6/d2-d3,-(sp)
- lea MyScrn(BR),a0
- move.l #(640<<16)!400,NewScreen.Width(a0)
- move.l #(3<<16)!1,NewScreen.Depth(a0)
- move.l #((HIRES!LACE)<<16)!CUSTOMSCREEN,NewScreen.ViewModes(a0)
- lea furname(pc),a1
- move.l a1,NewScreen.DefaultTitle(a0)
- movea.l IntuitionBase(BR),a6
- jsr OpenScreen(A6)
- move.l d0,Screen(BR) ;sets flags
- beq 999$ ;a failure if zero
- lea MyWin(BR),a0
- move.l d0,NewWindow.Screen(a0)
- move.l #(640<<16)!400,NewWindow.Width(a0)
- move.b #1,NewWindow.DetailPen(a0)
- move.l #RAWKEY,NewWindow.IDCMPFlags(a0)
- move.l #MyFlags,NewWindow.Flags(a0)
- move.l #(256<<16)!20,NewWindow.MinWidth(a0)
- move.l #(640<<16)!400,NewWindow.MaxWidth(a0)
- move.w #CUSTOMSCREEN,NewWindow.Type(a0)
- jsr OpenWindow(a6)
- move.l d0,Window(BR) ;sets flags
- beq.s 999$ ;a failure if zero
- movea.l d0,WN ;Window
- movea.l WN,a0
- lea NewPointer(BR),a1
- moveq #1,d0
- moveq #16,d1
- moveq #0,d2
- move.l #0,d3
- jsr SetPointer(a6) ;sets an invisible pointer up
- movea.l Window.RPort(WN),a1 ;this is the same as the
- lea pattern(pc),a0 ;SetAfPt macro
- move.l a0,RastPort.AreaPtrn(a1)
- move.b #1,RastPort.AreaPtSz(a1)
- movea.l WN,a0
- jsr ViewPortAddress(a6)
- movea.l d0,a0
- lea palette(pc),a1
- moveq #8,d0
- movea.l GfxBase(BR),a6
- jsr LoadRGB4(a6) ;our colors
- moveq #1,d0 ;flag set! shows we were successful
- 999$: movem.l (sp)+,a6/d2-d3 ;don't disturb the flags here
- rts
- *
- *--------------------------------------------------------------------------
- * The next routine initializes an IOAudio structure and uses it to
- * allocate all 4 audio channels for us. It returns NON-ZERO if we failed
- * to get all 4 channels. Once we have allocated all the channels, we can
- * ignore the audio.device and bang on the hardware registers ourselves
- * for our own magic stuff.
- *--------------------------------------------------------------------------
- *
- HogAudio: ;Err:D0 = HogAudio(execBase:A6)
- lea FMAudio(BR),a1
- lea AllUnits(pc),a0
- move.l a0,IOAudio.ioa_Data(a1) ;allocation map
- moveq #1,d0 ;map size
- move.l d0,IOAudio.ioa_Length(a1)
- move.b #127,Node.ln_Pri(a1) ;full priority.. no stealing!
- move.w #ADCMD_ALLOCATE,IORequest.io_Command(a1)
- move.b #ADIOF_NOWAIT,IORequest.io_Flags(a1)
- lea AudName(pc),a0 ;devname
- moveq #0,d0 ;unit
- moveq #0,d1 ;flags
- jmp OpenDevice(a6) ;this will rts for us
- *
- *--------------------------------------------------------------------------
- * Pretty simple, just closes the device. Just be sure not to call this
- * if the open wasn't successful.
- *--------------------------------------------------------------------------
- *
- ShareAudio:
- lea FMAudio(BR),a1
- jmp CloseDevice(a6) ;this will rts for us
- *
- *--------------------------------------------------------------------------
- * A quick and dirty pseudo-random number generator.
- *--------------------------------------------------------------------------
- *
- Rand: move.l seed(BR),d0 ;get the old seed
- add.l d0,d0 ;double it
- bhi.s 999$ ;branch if no carry OR not zero
- eori.l #$2de1ad29,d0 ;somewhat random bits flipped
- 999$: move.l d0,seed(BR) ;save the new value as the next seed
- rts
- *
- *--------------------------------------------------------------------------
- * This initializes and pops up an Auto Requester, giving information about
- * the program usage. In order to stay pure, all the initialization of the
- * IntuiText structures is done on the fly here.
- *--------------------------------------------------------------------------
- *
- DoRequest:
- movem.l a2-a3/a6/d2-d3,-(sp)
- lea BodyIText(BR),a1
- lea BodyText(pc),a0
- move.l a0,IntuiText.IText(a1)
- lea PosIText(BR),a2
- movea.l a2,a3
- lea PosText(pc),a0
- move.l a0,IntuiText.IText(a2)
- moveq #2,d0
- move.b d0,IntuiText.FrontPen(a1)
- move.b d0,IntuiText.FrontPen(a2)
- move.b d0,IntuiText.FrontPen(a3)
- moveq #4,d0
- move.w d0,IntuiText.LeftEdge(a2)
- move.w d0,IntuiText.LeftEdge(a3)
- move.w d0,IntuiText.TopEdge(a2)
- move.w d0,IntuiText.TopEdge(a3)
- moveq #10,d0
- move.w d0,IntuiText.LeftEdge(a1)
- move.w d0,IntuiText.TopEdge(a1)
- movea.l WN,a0
- moveq #0,d0
- move.l d0,d1
- move.w #640,d2 ;width
- moveq #66,d3 ;height
- movea.l IntuitionBase(BR),a6
- jsr AutoRequest(a6) ;won't return until 'OK' is clicked
- movem.l (sp)+,a2-a3/a6/d2-d3
- rts
- *
- *--------------------------------------------------------------------------
- * This routine is here merely to ensure that more than two cycle times for
- * the audio channels passes so that when we restart we will be starting at
- * the beginning instead of part way through a previous song. This would be
- * bad if the new song was shorter than the old one was.
- *--------------------------------------------------------------------------
- *
- Slower move.l a6,-(sp)
- movea.l GfxBase(BR),a6
- jsr WaitTOF(a6) ;waits for the next VBlank interval
- jsr WaitTOF(a6) ;twice to be sure of one whole frame time
- movea.l (sp)+,a6
- rts
- *
- *-----------------------------------------------------------------------
- * This is the workhorse that builds the sequence tables that will be used
- * by audio channels 0 and 2 (which we will set up to control channels
- * 1 and 3). These table will become pairs of words alternating volume
- * and period. The volume is computed by steadily decreasing the initial
- * value used, while the period comes from a table which was indexed by
- * a note number in the lower nibble of the song table. The upper nibble
- * is the number of 'beats' for this note. The routine executes the code
- * twice, once to build the right channels, and the second for the left.
- *-----------------------------------------------------------------------
- *
- buildtab: ;newbuff:a1 = buildtab(nibtab:a0, buff:a1)
- movem.l a2/d2-d5,-(sp)
- lea note_table(pc),a2 ;used for the whole routine
- moveq #0,d1 ;controls the execution path for left
- 10$: move.b (a0)+,d2 ;null-term tables for each side
- beq.s 990$
- moveq #64,d5 ;full volume for right
- tst.w d1
- beq.s 12$
- moveq #44,d5 ;a little softer for the accompaniement
- 12$: move.b d2,d3
- lsr.b #4,d3 ;upper nibble to lower nibble
- ext.w d3 ;zeroes upper byte of word
- mulu #10,d3 ;times ten gives beats for this note
- andi.w #15,d2 ;extract lower nibble
- add.w d2,d2 ;time 2 for word sized table
- move.w 0(a2,d2.w),d4 ;get the period from the table
- bne.s 20$
- moveq #0,d5 ;silence indicated by note nibble of zero
- moveq #127,d4 ;some period needed for audio chip
- 20$: cmpi.w #1,d3 ;make the last sample always a lower volume
- bne.s 25$ ;to provide some wave shaping
- lsr.w #1,d5 ;by cutting it in half
- 25$: move.w d5,(a1)+ ;write the volume
- beq.s 30$ ;never go below zero
- subq.w #1,d5 ;volume decremented here
- 30$: move.w d4,d0 ;retreive the period we got
- tst.b d1 ;for left half we use a lower octave
- beq.s 40$
- add.w d0,d0 ;which we get by doubling the period here
- 40$: move.w d0,(a1)+ ;we write the period
- subq.w #1,d3 ;reduce the count
- bne.s 20$ ;needs more beats to complete this note
- bra.s 10$ ;else do next note
- 990$: tst.w d1
- bne.s 999$ ;if nonzero we did two sides
- moveq #1,d1 ;otherwise, make nonzero and reloop
- bra.s 10$
- 999$: movem.l (sp)+,a2/d2-d5
- rts
- *
- *-------------------------------------------------------------------------
- * This builds a table for the next song, wrapping from the last song back
- * to the first one. When initially called, the song number is zero, and we
- * start out on song number one. Thereafter, every time it is called it
- * increments the current song.
- *-------------------------------------------------------------------------
- *
- NewSong:
- move.l d2,-(sp)
- move.w CurSong(BR),d2 ;get former song number
- addq.w #1,d2 ;and bump it up one
- cmpi.w #NUMSONGS,d2 ;check our limits
- bls.s 10$
- moveq #1,d2 ;wrap back to the first one after the last
- 10$: move.w d2,CurSong(BR) ;save computed number
- add.w d2,d2 ;double it.. we're using word-sized tables
- lea TempoTab(pc),a0
- move.w -2(a0,d2.w),Tempo(BR) ;lets us have element 1 in slot 0
- lea Data0(BR),a1 ;our buffer (in chip ram!)
- lea SongTab(pc),a0 ;some address arithmetic
- adda.w -2(a0,d2.w),a0
- bsr buildtab ;build the table
- lea LenTab(pc),a0 ;lookup the length
- move.w -2(a0,d2.w),d1
- bsr.s muson ;start (or restart) the music
- move.l (sp)+,d2
- rts
- *
- *------------------------------------------------------------------------
- * Way down here is where we write to the hardware registers. What we will
- * do is attach channels 0 and 2 to channels 1 and 3 for period and volume.
- * This pairing makes one channel write the volume and period alternately
- * to the next numbered channel. Channels 1 and 3 always play the same
- * waveform, but by being controlled by channels 0 and 2 the actual pitch
- * and volume vary depending on the data used by channels 0 and 2. This data
- * came from the buildtab() routine, which expanded the compressed stuff
- * in the nibbleized song tables.
- *------------------------------------------------------------------------
- *
- muson: ;muson(LEN:D1)
- lea Data0(BR),a0 ;the chip ram buffer we used
- move.l a0,AUD0LC(CST) ;right table starts at the start
- adda.w d1,a0 ;while the left table is right after it
- move.l a0,AUD2LC(CST)
- lsr.w #1,d1 ;half for len_in_words (chip requirement)
- move.w d1,AUD0LEN(CST) ;set length to channels
- move.w d1,AUD2LEN(CST)
- move.w Tempo(BR),d0 ;speed for our particular song
- move.w d0,AUD0PER(CST)
- move.w d0,AUD2PER(CST)
- lea Note1(BR),a0 ;the modified sine wave we used
- move.l a0,AUD1LC(CST) ;initialize registers
- move.l a0,AUD3LC(CST)
- moveq #SAMPLELEN/2,d0 ;half for len_in_words (chip requirement)
- move.w d0,AUD1LEN(CST) ;length of wave data to chip registers
- move.w d0,AUD3LEN(CST)
- move.w #MSET!ATVOL0!ATPER0!ATVOL2!ATPER2,ADKCONW(CST) ;attach stuff
- move.w #MSET!DMAEN!AUD3EN!AUD2EN!AUD1EN!AUD0EN,DMACONW(CST) ;Play it!
- rts
- *
- *--------------------------------------------------------------------------
- * This just shuts the sound channels off and unattaches them from each
- * other, to restore things to more or less normal.
- *--------------------------------------------------------------------------
- *
- musoff: move.w #CLEAR!AUD3EN!AUD2EN!AUD1EN!AUD0EN,DMACONW(CST) ;sound off
- move.w #CLEAR!ATVOL0!ATPER0!ATVOL2!ATPER2,ADKCONW(CST) ;unattach
- rts
- *
- *--------------------------------------------------------------------------
- * From here on are all static data tables used by various of the routines.
- *--------------------------------------------------------------------------
- *
- *--------------------------------------------------------------------------
- * The addresses of these two arrays are passed to the graphics routines.
- *--------------------------------------------------------------------------
- *
- palette DC.W $888,$111,$f11,$1f1,$11f,$ff1,$f1f,$1ff
- pattern DC.L $AAAA5555
- *
- *--------------------------------------------------------------------------
- * The wave was computed by creating a sine wave, and adding 10% third
- * harmonic and 1% fifth harmonic content. Only the positive half of the
- * wave form is here, the negative half is computed at the time we copy
- * this data to the chip ram area.
- *--------------------------------------------------------------------------
- *
- wavedata
- DC.B 0,32,61,84,98,106,112,114,115,114,112,106,98,84,61,32
- *
- *--------------------------------------------------------------------------
- * This table is the lookup for each note's proper period value. We shift
- * this value left once to double the duration for a lower octave when we
- * are building the left channel (accompaniement voice).
- *--------------------------------------------------------------------------
- *
- note_table
- DC.W 0 ;dummy note = silence
- DC.W 285 ;G 1
- DC.W 269 ;G# 2
- DC.W 254 ;A 3
- DC.W 240 ;A# 4
- DC.W 226 ;B 5
- DC.W 214 ;C 6
- DC.W 202 ;C# 7
- DC.W 190 ;D 8
- DC.W 180 ;D# 9
- DC.W 170 ;E A
- DC.W 160 ;F B
- DC.W 151 ;F# C
- DC.W 144 ;G D
- DC.W 135 ;G# E
- DC.W 127 ;A F
- *
- *--------------------------------------------------------------------------
- * These lengths are used in address arithmetic to split the larger buffer
- * into two halves and to calculate the correct length for the chip regs.
- *--------------------------------------------------------------------------
- *
- LenTab: DC.W BEETLEN
- DC.W BACHLEN
- DC.W SCARLEN
- DC.W LARLEN
- DC.W RSUNLEN
- DC.W TEARLEN
- *
- *--------------------------------------------------------------------------
- * These are the default speeds for each song.
- *--------------------------------------------------------------------------
- *
- TempoTab:
- DC.W TEMPO1
- DC.W TEMPO2
- DC.W TEMPO3
- DC.W TEMPO4
- DC.W TEMPO5
- DC.W TEMPO6
- *
- *--------------------------------------------------------------------------
- * The address of the base of this table plus the difference stored at the
- * proper offset gives us the start of the proper nibble table.
- *--------------------------------------------------------------------------
- *
- SongTab DC.W beettab-SongTab
- DC.W bachtab-SongTab
- DC.W scbftab-SongTab
- DC.W lrdotab-SongTab
- DC.W rsuntab-SongTab
- DC.W teartab-SongTab
- *
- *-------------------------------------------------------------------------
- * This is where data for the actual songs is stored. It is compressed into
- * bytes containing packed nibbles of duration:note. A note nibble of zero
- * means silence, while the number in the duration is the number of beats
- * each note is to play. Each beat will be multiplied by 10 samples when
- * the sequences are used. Each song's data here is the right channel first,
- * with a null byte marking the end, followed by the left channel, which is
- * also null-terminated. It is important that the two halves contain the
- * same number of beats. The number of beats in one side is counted and is
- * used 'way up top to calculate the length needed for each song. The memory
- * required is calculated from the largest song in these tables. For proper
- * operation, this part should be right after the SongTab table.
- *-------------------------------------------------------------------------
- *
- beettab DC.B $1A,$19,$1A,$19,$1A,$15,$18,$16,$63,$65,$46 ;24
- DC.B $1A,$19,$1A,$19,$1A,$15,$18,$16,$63,$45,$16,$15,$43 ;24
- DC.B $1A,$19,$1A,$19,$1A,$15,$18,$16,$63,$65,$46 ;24
- DC.B $1A,$19,$1A,$19,$1A,$15,$18,$16,$63,$45,$16,$15,$43 ;24
- DC.B $18,$16,$18,$4A,$1B,$1A,$48,$1A,$18,$46,$18,$16,$75,0 ;28
- DC.B $A0,$13,$16,$2A,$20,$15,$1A,$2D,$20,$16,$1A ;24
- DC.B $A0,$13,$16,$2A,$20,$15,$1A,$2D,$46 ;24
- DC.B $A0,$13,$16,$2A,$20,$15,$1A,$2D,$20,$16,$1A ;24
- DC.B $A0,$13,$16,$2A,$20,$15,$1A,$2D,$46 ;24
- DC.B $50,$13,$16,$40,$1D,$15,$40,$1A,$1D,$40,$1A,$2E,$20,0 ;28
- bachtab DC.B $1D,$11,$13,$15,$18,$16,$16,$1A,$18,$18,$1D,$1C
- DC.B $1D,$18,$15,$11,$13,$15,$16,$18,$1A,$18,$16,$15
- DC.B $13,$15,$13,$13,$15,$18 ;30
- DC.B $1D,$11,$13,$15,$18,$16,$16,$1A,$18,$18,$1D,$1C
- DC.B $1D,$18,$15,$11,$13,$25,$1A,$18,$16,$15,$13
- DC.B $13,$11,$13,$31 ;30
- DC.B $65,$36,$38,$31,$38,$36,$35,$63 ;30
- DC.B $1D,$11,$13,$15,$18,$16,$16,$1A,$18,$18,$1D,$1C
- DC.B $1D,$18,$15,$11,$13,$25,$1A,$18,$16,$15,$13
- DC.B $11,$15,$18,$7D,0 ;34
- DC.B $30,$31,$3A,$38,$31,$35,$36,$38,$33,$33 ;30
- DC.B $38,$31,$3A,$38,$31,$35,$36,$35,$33,$31 ;30
- DC.B $65,$3A,$33,$35,$38,$36,$35,$63 ;30
- DC.B $38,$31,$3A,$38,$31,$35,$36,$35,$38,$71,0 ;34
- scbftab DC.B $33,$33,$2A,$2A,$2A,$25,$26,$25,$93 ;27
- DC.B $3A,$3D,$4F,$2D,$2A,$2C,$2A,$6A,$3F ;27
- DC.B $3F,$3F,$2D,$2A,$2A,$2A,$28,$26,$28,$75 ;27
- DC.B $33,$3A,$38,$36,$25,$23,$21,$93,0 ;27
- DC.B $63,$61,$6A,$93,$66,$68,$6A,$9A
- DC.B $63,$61,$6B,$9A,$63,$61,$6A,$93,0 ;120
- lrdotab DC.B $2d,$2d,$2b,$2a,$2b,$2d,$2b,$2a,$28,$26,$25,$31 ;25
- DC.B $11,$26,$26,$26,$28,$2a,$2b,$2a,$28,$26,$48 ;23
- DC.B $2d,$2d,$2b,$2a,$2b,$2d,$2b,$2a,$28,$26,$25,$31 ;25
- DC.B $11,$26,$26,$26,$28,$2a,$2b,$2a,$26,$26,$46,0 ;23
- DC.B $20,$66,$6f,$66,$61,$66,$61,$66,$61
- DC.B $66,$6b,$66,$61,$66,$61,$66,$46,0 ;96
- rsuntab DC.B $30,$33,$93,$33,$96,$3a,$98,$23,$13,$96 ;51
- DC.B $3f,$9f,$3f,$9d,$2a,$18,$aa,$b0 ;48
- DC.B $2f,$1f,$9f,$3f,$2d,$7a,$38,$2a,$53,$23,$33,$96 ;48
- DC.B $33,$93,$33,$91,$33,$a3,$80,0 ;45
- DC.B $2a,$25,$22,$23,$26,$2A,$2f,$2A,$26 ;18 E,Am
- DC.B $26,$2a,$2d,$26,$2a,$2d ;12 C
- DC.B $28,$2c,$2f,$28,$2f,$2c ;12 D
- DC.B $2b,$23,$26,$2b,$26,$23 ;12 F
- DC.B $23,$26,$2A,$2f,$2A,$26 ;12 Am
- DC.B $26,$2a,$2d,$26,$2a,$2d ;12 C
- DC.B $2a,$22,$25,$2a,$25,$22 ;12 E
- DC.B $2a,$22,$25,$2a,$25,$22 ;12 E
- DC.B $23,$26,$2A,$2f,$2A,$26 ;12 Am
- DC.B $26,$2a,$2d,$26,$2a,$2d ;12 C
- DC.B $28,$2c,$2f,$28,$2f,$2c ;12 D
- DC.B $2b,$23,$26,$2b,$26,$23 ;12 F
- DC.B $23,$26,$2A,$2f,$2A,$26 ;12 Am
- DC.B $2a,$22,$25,$2a,$25,$22 ;12 E
- DC.B $23,$26,$2A,$2f,$2A,$26 ;12 Am
- DC.B $2a,$22,$25,0 ;6 E
- teartab DC.B $20,$26,$28,$2a,$28,$28,$23,$26,$56,$13,$26,$a5 ;34
- DC.B $26,$28,$2a,$28,$28,$23,$26,$56,$13,$26,$a5 ;32
- DC.B $1b,$1b,$2b,$2a,$28,$28,$26,$48,$2a,$2a,$28,$26,$83 ;32
- DC.B $2f,$2f,$2f,$3f,$13,$25,$26,$58,$16,$18,$16,$85,0 ;30
- DC.B $46,$46,$48,$48,$4b,$4b,$4d,$4b ;32
- DC.B $46,$46,$48,$48,$4b,$4b,$4d,$4b ;32
- DC.B $4b,$4b,$4d,$4d,$46,$46,$43,$43 ;32
- DC.B $4b,$4b,$4b,$4b,$41,$41,$4d,$4b,0 ;32
- *
- *---------------------------------------------------------------------------
- * These are just strings for some of the routines.
- *---------------------------------------------------------------------------
- *
- furname CSTRING ' FurLess by Wesley Howe '
- AudName CSTRING 'audio.device'
- IntuitionName CSTRING 'intuition.library'
- GfxName CSTRING 'graphics.library'
- BodyText CSTRING ' ESC=QUIT, F1=Song, UP/DOWN=Chg Tempo'
- PosText CSTRING 'OK'
- *
- *---------------------------------------------------------------------------
- * This is the allocation map for all four audio channelsthat we used to
- * indicate we wanted all the channels when we opened the audio.device.
- *---------------------------------------------------------------------------
- AllUnits DC.B $0f
- DS.W 0
- *
- END ;and that's all, folks!
- *
-