amos-professional/AMOS/Tutorial/Extensions/__uae____Music_s

4615 lines
93 KiB
Plaintext
Raw Blame History

;---------------------------------------------------------------------
; ** ** ** *** *** **** ** *** ** ****
; **** *** *** ** ** ** ** ** **** ** ** ** **
; ** ** ** * ** ** ** *** ***** ** ** *** ** **
; ****** ** ** ** ** ** ** ** ****** ** ** **
; ** ** ** ** ** ** * ** ** ** ** ** * ** ** ** **
; ** ** ** ** *** *** ***** ** ** *** ** ****
;---------------------------------------------------------------------
; Music extension source code for AMOSPro, Last change 29/09/1992
; By Francois Lionet
; AMOS, AMOSPro AMOS Compiler (c) Europress Software 1990-1992
; To be used with AMOSPro 1.0 and over
;---------------------------------------------------------------------
; This file is public domain
;---------------------------------------------------------------------
;
Version MACRO
dc.b "1.0"
ENDM
;
;
; This listing explains how to create an extension for AMOSPro.
; The AMOSPro compiler will be compatible with these extension.
;
; If you have made an extension for AMOS 1.3, just read the
; file called New_In_Pro.Asc to know the difference between the
; extension format. Not many changes, only new equates, and some
; new functions.
;
; >>> What's an extension?
;
; An extension to AMOS is a machine language program that adds new
; instructions to the already huge AMOS instruction set. This system is
; designed to be as powerfull as AMOS itself: the extension includes its
; own token list, its own routines. It can even access some main AMOS
; routines via special macros. It has a total access to the internal AMOS
; data zone, and to the graphic library functions.
;
; To produce your own extension, I suggest you copy and rename this
; file, and remove the used code. This way you will not forgive one line.
; Also keep in mind that you can perfectly call AMOS from within MONAM2,
; and set some ILLEGAL instructions where you want to debug. To flip back to
; MONAM2 display, just press AMIGA-A.
;
; I have designed the extension system so that one only file works with
; both AMOS interpretor and compiler.
; - The extension is more a compiler library than a one chunk program:
; it is done so that the compiler can pick one routine here and there
; to cope with the program it is compiling.
; - AMOSPro extension loader works a little like the compiler, exept
; that all instructions are loaded and relocated.
;
; This code was assembled with GENIM2 on a A3000 25 Mhz machine, but a
; A500 can do it very well!
; The assembled program must be ONE CHUNK only, you must not link the
; the symbol table with it. Also be sure that you program is totally
; relocatable (see later) : if not it will add a relocation chunk to
; the output code, and your extension will simply crash AMOS on loading
; (and the compiler too!).
;
; Here we go now!
;
; Here comes the number of the extension in the list of extensions in
; AMOSPro_Interpretor_Config program (minus one).
; This number is used later to reference the extension in internal AMOS
; tables...
;
ExtNb equ 1-1
; You must include this file, it will decalre everything for you.
Include "|AMOS_Includes.s"
; A usefull macro to find the address of data in the extension's own
; datazone (see later)...
DLea MACRO
move.l ExtAdr+ExtNb*16(a5),\2
add.w #\1-MB,\2
ENDM
; Another macro to load the base address of the datazone...
DLoad MACRO
move.l ExtAdr+ExtNb*16(a5),\1
ENDM
; Now some equates used by the music extension itself. Ignore this in your
; code!
Translate equ -30
*************** Enveloppes definitions
RsReset
EnvNb: rs.w 1
EnvDVol: rs.w 1
EnvVol: rs.l 1
EnvDelta: rs.l 1
EnvAd: rs.l 1
EnvDeb: rs.l 1
EnvLong: equ __Rs
*************** Wave definition
LWave: equ 256+128+64+32+16+8+4+2
LNoise: equ LWave
RsReset
WaveNext: rs.l 1
WaveNb: rs.w 1
WaveEnv: rs.w 16*2
WaveDeb: rs.b LWave
WaveLong: equ __Rs
*************** Music voice data
RsReset
VoiAdr rs.l 1
VoiDeb rs.l 1
VoiInst rs.l 1
VoiDPat rs.l 1
VoiPat rs.l 1
VoiCpt rs.w 1
VoiRep rs.w 1
VoiNote rs.w 1
VoiDVol rs.w 1
VoiVol rs.w 1
VoiEffect rs.l 1
VoiValue rs.w 1
VoiPToTo rs.w 1
VoiPTone rs.b 1
VoiVib rs.b 1
VoiLong equ __Rs
*************** MUBASE table
RsReset
* Voix 0
MuVoix0 equ __Rs
VoiAdr0 rs.l 1
VoiDeb0 rs.l 1
VoiInst0 rs.l 1
VoiDPat0 rs.l 1
VoiPat0 rs.l 1
VoiCpt0 rs.w 1
VoiRep0 rs.w 1
VoiNote0 rs.w 1
VoiDVol0 rs.w 1
VoiVol0 rs.w 1
VoiEffect0 rs.l 1
VoiValue0 rs.w 1
VoiPToTo0 rs.w 1
VoiPTone0 rs.b 1
VoiVib0 rs.b 1
* Voix 1
MuVoix1 equ __Rs
VoiAdr1 rs.l 1
VoiDeb1 rs.l 1
VoiInst1 rs.l 1
VoiDPat1 rs.l 1
VoiPat1 rs.l 1
VoiCpt1 rs.w 1
VoiRep1 rs.w 1
VoiNote1 rs.w 1
VoiDVol1 rs.w 1
VoiVol1 rs.w 1
VoiEffect1 rs.l 1
VoiValue1 rs.w 1
VoiPToTo1 rs.w 1
VoiPTone1 rs.b 1
VoiVib1 rs.b 1
* Voix 2
MuVoix2 equ __Rs
VoiAdr2 rs.l 1
VoiDeb2 rs.l 1
VoiInst2 rs.l 1
VoiDPat2 rs.l 1
VoiPat2 rs.l 1
VoiCpt2 rs.w 1
VoiRep2 rs.w 1
VoiNote2 rs.w 1
VoiDVol2 rs.w 1
VoiVol2 rs.w 1
VoiEffect2 rs.l 1
VoiValue2 rs.w 1
VoiPToTo2 rs.w 1
VoiPTone2 rs.b 1
VoiVib2 rs.b 1
* Voix 3
MuVoix3 equ __Rs
VoiAdr3 rs.l 1
VoiDeb3 rs.l 1
VoiInst3 rs.l 1
VoiDPat3 rs.l 1
VoiPat3 rs.l 1
VoiCpt3 rs.w 1
VoiRep3 rs.w 1
VoiNote3 rs.w 1
VoiDVol3 rs.w 1
VoiVol3 rs.w 1
VoiEffect3 rs.l 1
VoiValue3 rs.w 1
VoiPToTo3 rs.w 1
VoiPTone3 rs.b 1
VoiVib3 rs.b 1
* Other data
MuCpt rs.w 1
MuTempo rs.w 1
MuStart rs.w 1
MuStop rs.w 1
* Total length
MuLong equ __Rs
IntEnaR equ $1c
IntReqR equ $1e
is_data equ $0e
is_code equ $12
ln_pri equ $09
ln_type equ $08
; All the above did not produce any byte of code. Here is the real beginning
; of the program. It MUST begin by a small table of pointers so that both
; AMOS and the compiler know where to get their data...
; Please remark that everything is relocatable...
******************************************************************
* AMOSPro MUSIC EXTENSION
;
; First, a pointer to the token list
Start dc.l C_Tk-C_Off
;
; Then, a pointer to the first library function
dc.l C_Lib-C_Tk
;
; Then to the title
dc.l C_Title-C_Lib
;
; From title to the end of the program
dc.l C_End-C_Title
;
; An important flag. Imagine a program does not call your extension, the
; compiler will NOT copy any routine from it in the object program. For
; certain extensions, like MUSIC, COMPACT, it is perfect.
; But for the REQUEST extension, even if it is not called, the first routine
; MUST be called, otherwise AMOS requester will not work!
; So, a value of 0 indicates to copy if needed only,
; A value of -1 forces the copy of the first library routine...
dc.w 0
******************************************************************
* Offset to library
;
; This list contains all informations for the compiler
; and AMOS to locate your routines, in a relocatable way.
; You can produce such tables using the MAKE_LABEL.AMOS utility, found
; on this very disc.
; All labels MUST be in order. The size of each routine MUST BE EVEN,
; as the size is divided by two. So be carefull to put an EVEN instruction
; after some text...
; You easily understand that the size of each routine can reach 128K,
; which is largely enough. You can have up to 2000 routines in the list.
; The main AMOS.Lib library has 1100 labels...
C_Off dc.w (L1-L0)/2,(L2-L1)/2,(L3-L2)/2,(L4-L3)/2
dc.w (L5-L4)/2,(L6-L5)/2,(L7-L6)/2,(L8-L7)/2
dc.w (L9-L8)/2,(L10-L9)/2,(L11-L10)/2,(L12-L11)/2
dc.w (L13-L12)/2,(L14-L13)/2,(L15-L14)/2,(L16-L15)/2
dc.w (L17-L16)/2,(L18-L17)/2,(L19-L18)/2,(L20-L19)/2
dc.w (L21-L20)/2,(L22-L21)/2,(L23-L22)/2,(L24-L23)/2
dc.w (L25-L24)/2,(L26-L25)/2,(L27-L26)/2,(L28-L27)/2
dc.w (L29-L28)/2,(L30-L29)/2,(L31-L30)/2,(L32-L31)/2
dc.w (L33-L32)/2,(L34-L33)/2,(L35-L34)/2,(L36-L35)/2
dc.w (L37-L36)/2,(L38-L37)/2,(L39-L38)/2,(L40-L39)/2
dc.w (L41-L40)/2,(L42-L41)/2,(L43-L42)/2,(L44-L43)/2
dc.w (L45-L44)/2,(L46-L45)/2,(L47-L46)/2,(L48-L47)/2
dc.w (L49-L48)/2,(L50-L49)/2,(L51-L50)/2,(L52-L51)/2
dc.w (L53-L52)/2,(L54-L53)/2,(L55-L54)/2,(L56-L55)/2
dc.w (L57-L56)/2,(L58-L57)/2,(L59-L58)/2,(L60-L59)/2
dc.w (L61-L60)/2,(L62-L61)/2,(L63-L62)/2,(L64-L63)/2
dc.w (L65-L64)/2,(L66-L65)/2,(L67-L66)/2,(L68-L67)/2
dc.w (L69-L68)/2,(L70-L69)/2,(L71-L70)/2,(L72-L71)/2
dc.w (L73-L72)/2,(L74-L73)/2,(L75-L74)/2,(L76-L75)/2
dc.w (L77-L76)/2,(L78-L77)/2,(L79-L78)/2,(L80-L79)/2
dc.w (L81-L80)/2,(L82-L81)/2,(L83-L82)/2,(L84-L83)/2
dc.w (L85-L84)/2,(L86-L85)/2,(L87-L86)/2,(L88-L87)/2
dc.w (L89-L88)/2,(L90-L89)/2,(L91-L90)/2,(L92-L91)/2
dc.w (L93-L92)/2,(L94-L93)/2,(L95-L94)/2,(L96-L95)/2
dc.w (L97-L96)/2,(L98-L97)/2,(L99-L98)/2,(L100-L99)/2
dc.w (L101-L100)/2,(L102-L101)/2,(L103-L102)/2,(L104-L103)/2
dc.w (L105-L104)/2,(L106-L105)/2,(L107-L106)/2,(L108-L107)/2
dc.w (L109-L108)/2,(L110-L109)/2,(L111-L110)/2,(L112-L111)/2
dc.w (L113-L112)/2,(L114-L113)/2
; Do not forget the LAST label!!!
******************************************************************
* TOKEN TABLE
;
;
;
; This table is the crucial point of the extension! It tells
; everything the tokenisation process needs to know. You have to
; be carefull when writing it!
;
; The format is simple:
; dc.w Number of instruction,Number of function
; dc.b "instruction nam","e"+$80,"Param list",-1[or -2]
;
; (1) Number of instruction / function
; You must state the one that is needed for this token.
; I suggest you keep the same method of referencing the
; routines than mine: L_name, this label being defined
; in the main program. (If you come from a 1.23 extension,
; changing your program is easy: just add L_ before the
; name of each routine.
; A -1 means take no routine is called (example a
; instruction only will have a -1 in the function space...)
;
; (2) Instruction name
; It must be finished by the letter plus $80. Be carefull
; ARGASM assembler produces bad code if you do "a"+$80,
; he wants $80+"a"!!!
; - You can SET A MARK in the token table with a "!" before
; the name. See later
; -Using a $80 ALONE as a name definition, will force AMOS
; to point to the previous "!" mark...
;
; (3) Param list
; This list tells AMOS everything about the instruction.
;
; - First character:
; The first character defines the TYPE on instruction:
; I--> instruction
; 0--> function that returns a integer
; 1--> function that returns a float
; 2--> function that returns a string
; V--> reserved variable. In that case, you must
; state the type int-float-string
; - If your instruction does not need parameters, then you stop
; - Your instruction needs parameters, now comes the param list
; Type,TypetType,Type...
; Type of the parameter (0 1 2)
; Comma or "t" for TO
;
; (4) End of instruction
; "-1" states the end of the instruction
; "-2" tells AMOS that another parameter list
; can be accepted. if so, MUST follow the
; complete instruction definition as explained
; but with another param list.
; If so, you can use the "!" and $80 facility not to rewrite the
; full name of the instruction...See SAM LOOP ON instruction for an
; example...
;
; Remember that AMOS token list comes first, so names like:
; PRINTHELLO will never work: AMOS will tokenise PRINT first!
; Extension token list are explored in order of number...
; The next two lines needs to be unchanged...
C_Tk: dc.w 1,0
dc.b $80,-1
; Now the real tokens...
dc.w -1,L_FMB
dc.b "mubas","e"+$80,"0",-1
dc.w -1,L_FVu
dc.b "vumete","r"+$80,"00",-1
dc.w L_IVoice,-1
dc.b "voic","e"+$80,"I0",-1
dc.w L_IMusOff,-1
dc.b "music of","f"+$80,"I",-1
dc.w L_IMuStop,-1
dc.b "music sto","p"+$80,"I",-1
dc.w L_ITempo,-1
dc.b "temp","o"+$80,"I0",-1
dc.w L_IMusic,-1
dc.b "musi","c"+$80,"I0",-1
dc.w L_INoTo,-1
dc.b "noise t","o"+$80,"I0",-1
dc.w L_Boom,-1
dc.b "boo","m"+$80,"I",-1
dc.w L_Shoot,-1
dc.b "shoo","t"+$80,"I",-1
dc.w L_ISBank,-1
dc.b "sam ban","k"+$80,"I0",-1
dc.w L_ISLOn0,-1
dc.b "!sam loop o","n"+$80,"I",-2
dc.w L_ISLOn1,-1
dc.b $80,"I",-1
dc.w L_ISLOf0,-1
dc.b "sam loop of","f"+$80,"I",-2
dc.w L_ISLOf1,-1
dc.b $80,"I0",-1
dc.w L_ISamTo,-1
dc.b "sampl","e"+$80,"I0t0",-1
dc.w L_ISam1,-1
dc.b "!sam pla","y"+$80,"I0",-2
dc.w L_ISam2,-1
dc.b $80,"I0,0",-2
dc.w L_ISam3,-1
dc.b $80,"I0,0,0",-1
dc.w L_ISamR,-1
dc.b "sam ra","w"+$80,"I0,0,0,0",-1
dc.w L_Bell0,-1
dc.b "!bel","l"+$80,"I",-2
dc.w L_Bell1,-1
dc.b $80,"I0",-1
dc.w L_IPlOf0,-1
dc.b "!play of","f"+$80,"I",-2
dc.w L_IPlOf1,-1
dc.b $80,"I0",-1
dc.w L_IPlay2,-1
dc.b "!pla","y"+$80,"I0,0",-2
dc.w L_IPlay3,-1
dc.b $80,"I0,0,0",-1
dc.w L_ISWave,-1
dc.b "set wav","e"+$80,"I0,2",-1
dc.w L_IDWave1,-1
dc.b "del wav","e"+$80,"I0",-1
dc.w L_ISEnv,-1
dc.b "set enve","l"+$80,"I0,0t0,0",-1
dc.w L_IMVol,-1
dc.b "mvolum","e"+$80,"I0",-1
dc.w L_IVol1,-1
dc.b "!volum","e"+$80,"I0",-2
dc.w L_IVol2,-1
dc.b $80,"I0,0",-1
dc.w L_IWave,-1
dc.b "wav","e"+$80,"I0t0",-1
dc.w L_LedOn,-1
dc.b "led o","n"+$80,"I",-1
dc.w L_LedOf,-1
dc.b "led of","f"+$80,"I",-1
dc.w L_ISay1,-1
dc.b "!sa","y"+$80,"I2",-2
dc.w L_ISay2,-1
dc.b $80,"I2,0",-1
dc.w L_ITalk,-1
dc.b "set tal","k"+$80,"I0,0,0,0",-1
dc.w L_SLoad,-1
dc.b "sloa","d"+$80,"I0t0,0",-1
dc.w -1,L_Samswapped
dc.b "sam swappe","d"+$80,"00",-1
dc.w L_SamSwap,-1
dc.b "sam swa","p"+$80,"I0t0,0",-1
dc.w L_SamStop0,-1
dc.b "!sam sto","p"+$80,"I",-2
dc.w L_SamStop1,-1
dc.b $80,"I0",-1
dc.w L_TrackStop,-1
dc.b "track sto","p"+$80,"I",-1
dc.w L_TrackLoopon,-1
dc.b "track loop o","n"+$80,"I",-1
dc.w L_TrackLoopof,-1
dc.b "track loop o","f"+$80,"I",-1
dc.w L_TrackPlay0,-1
dc.b "!track pla","y"+$80,"I",-2
dc.w L_TrackPlay1,-1
dc.b $80,"I0",-2
dc.w L_TrackPlay2,-1
dc.b $80,"I0,0",-1
dc.w L_TrackLoad,-1
dc.b "track loa","d"+$80,"I2,0",-1
dc.w -1,L_LipsX
dc.b "mouth widt","h"+$80,"0",-1
dc.w -1,L_LipsY
dc.b "mouth heigh","t"+$80,"0",-1
dc.w L_Lips,-1
dc.b "mouth rea","d"+$80,"I",-1
dc.w L_NarStop,-1
dc.b "talk sto","p"+$80,"I",-1
dc.w L_TalkMisc,-1
dc.b "talk mis","c"+$80,"I0,0",-1
dc.w L_SSave,-1
dc.b "ssav","e"+$80,"I0,0t0",-1
dc.w L_MedLoad,-1
dc.b "med loa","d"+$80,"I2,0",-1
dc.w L_MedPlay0,-1
dc.b "!med pla","y"+$80,"I",-2
dc.w L_MedPlay1,-1
dc.b $80,"I0",-2
dc.w L_MedPlay2,-1
dc.b $80,"I0,0",-1
dc.w L_MedStop,-1
dc.b "med sto","p"+$80,"I",-1
dc.w L_MedCont,-1
dc.b "med con","t"+$80,"I",-1
dc.w L_MedMidiOn,-1
dc.b "med midi o","n"+$80,"I",-1
dc.w 0
;
; Now come the big part, the library. Every routine is delimited by the
; two labels: L(N) and L(N+1).
; AMOS loads the whole extension, but the compiler works differently:
; The compiler picks each routine in the library and copy it into the
; program, INDIVIDUALLY. It means that you MUST NEVER perform a JMP, a
; BSR or get an address from one library routine to another: the distance
; between them may change!!! Use the special macros instead...
;
; Importants points to follow:
;
; - Your code must be (pc), TOTALLY relocatable, check carefully your
; code!
; - You cannot directly call other library routines from one routine
; by doing a BSR, but I have defined special macros (in S_CEQU file)
; to allow you to easily do so. Here is the list of available macros:
;
; RBsr L_Routine does a simple BSR to the routine
; RBra L_Routine as a normal BRA
; RBeq L_Routine as a normal Beq
; RBne L_Routine ...
; RBcc L_Routine
; RBcs L_Routine
; RBlt L_Routine
; RBge L_Routine
; RBls L_Routine
; RBhi L_Routine
; RBle L_Routine
; RBpl L_Routine
; RBmi L_Routine
;
; I remind you that you can only use this to call an library routine
; from ANOTHER routine. You cannot do a call WITHIN a routine, or call
; the number of the routine your caling from...
; The compiler (and AMOSPro extension loading part) will manage to find
; the good addresses in your program from the offset table.
;
; You can also call some main AMOS.Lib routines, to do so, use the
; following macros:
;
; RJsr L_Routine
; RJmp L_Routine
;
;
; As you do not have access any more to the small table with jumps to the
; routines within AMOS, here is the concordance of the routines (the numbers
; are just refecrences to the old AMOS 1.23 calling table, and is not of
; any use in AMOS1.3):
;
;
; RJsr L_Error
; ~~~~~~~~~~~~~~~~~~~~~
; Jump to normal error routine. See end of listing
;
; RJsr L_ErrorExt
; ~~~~~~~~~~~~~~~~~~~~~~~~
; Jump to specific error routine. See end of listing.
;
; RJsr L_Tests
; ~~~~~~~~~~~~~~~~~~~~~
; Perform one AMOSPro updating procedure, update screens, sprites,
; bobs etc. You should use it for wait loops.
;
; RJsr L_WaitRout
; ~~~~~~~~~~~~~~~~~~~~~~~~
; See play instruction.
;
; RJsr L_GetEc
; ~~~~~~~~~~~~~~~~~~~~~
; Get screen address: In: D0.l= number, Out: A0=address
;
; RJsr L_Demande
; ~~~~~~~~~~~~~~~~~~~~~~~
; Ask for string space.
; D3.l is the length to ask for. Return A0/A1 point to free space.
; Poke your string there, add the length of it to A0, EVEN the
; address to the highest multiple of two, and move it into
; HICHAINE(a5) location...
;
; RJsr L_RamChip
; ~~~~~~~~~~~~~~~~~~~~~
; Ask for PUBLIC|CLEAR|CHIP ram, size D0, return address in D0, nothing
; changed, Z set according to the success.
;
; RJsr L_RamChip2
; ~~~~~~~~~~~~~~~~~~~~~~
; Same for PUBLIC|CHIP
;
; RJsr L_RamFast
; ~~~~~~~~~~~~~~~~~~~~~
; Same for PUBLIC|CLEAR
;
; RJsr L_RamFast2
; ~~~~~~~~~~~~~~~~~~~~~~~~
; Same for PUBLIC
;
; RJsr L_RamFree
; ~~~~~~~~~~~~~~~~~~~~~~~
; Free memory A1/D0
;
; RJsr L_Bnk.OrAdr
; ~~~~~~~~~~~~~~~~~~~~~~~~~
; Find whether a number is a address or a memory bank number
; IN: D0.l= number
; OUT: D0/A0= number or start(number)
;
; RJsr L_Bnk.GetAdr
; ~~~~~~~~~~~~~~~~~~~~~~~~~~
; Find the start of a memory bank.
; IN: D0.l= Bank number
; OUT: A0= Bank address
; D0.w= Bank flags
; Z set if bank not defined.
;
; RJsr L_Bnk.GetBobs
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Returns the address of the bob's bank
; IN:
; OUT: Z Set if not defined
; A0= address of bank
;
; RJsr L_Bnk.GetIcons
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Returns the address of the icons bank
; IN:
; OUT: Z Set if not defined
; A0= address of bank
;
; RJsr L_Bnk.Reserve
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Reserve a memory bank.
; IN: D0.l Number
; D1 Flags
; D2 Length
; A0 Name of the bank (8 bytes)
; OUT: Z Set inf not successfull
; A0 Address of bank
; FLAGS:
; Bnk_BitData Data bank
; Bnk_BitChip Chip bank
; Example: Bset #Bnk_BitData|Bnk_BitChip,d1
; NOTE: you should call L_Bnk.Change after reserving/erasing a bank.
;
; RJsr L_Bnk.Eff
; ~~~~~~~~~~~~~~~~~~~~~~~
; Erase one memory bank.
; IN: D0.l Number
; OUT:
;
; RJsr L_Bnk.EffA0
; ~~~~~~~~~~~~~~~~~~~~~~~~~
; Erase a bank from its address.
; IN: A0 Start(bank)
; OUT:
;
; RJsr L_Bnk.EffTemp
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Erase all temporary banks
; IN:
; OUT:
;
; RJsr L_Bnk.EffAll
; ~~~~~~~~~~~~~~~~~~~~~~~~~~
; Erase all banks
; IN:
; OUT:
;
; RJsr L_Bnk.Change
; ~~~~~~~~~~~~~~~~~~~~~~~~~~
; Inform the extension, the bob handler that something has changed
; in the banks. You should use this function after every bank
; reserve / erase.
; IN:
; OUT:
;
; RJsr L_Dsk.PathIt
; ~~~~~~~~~~~~~~~~~~~~~~~~~~
; Add the current AMOS path to a file name.
; IN: (Name1(a5)) contains the name, finished by zero
; OUT: (Name1(a5)) contains the name with new path
; Example:
; move.l Name1(a5),a0
; move.l #"Kiki",(a0)+
; clr.b (a0)
; RJsr L_Dsk.PathIt
; ... now I load in the current directory
;
; RJsr L_Dsk.FileSelector
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Call the file selector.
; IN: 12(a3) Path+filter
; 8(a3) Default name
; 4(a3) Title 2
; 0(a3) Title 1
; All strings must be in AMOS string format:
; dc.w Length
; dc.b "String"
; OUT: D0.w Length of the result. 0 if no selection
; A0 Address of first character of the result.
;
; HOW DOES IT WORK?
;
; Having a look at the |CEQU file, you see that I use special codes
; to show the compiler that it has to copy the asked routine and relocate
; the branch. Some remarks:
; - The size of a Rbsr is 4 bytes, like the normal branch, it does
; not change the program (you can make some jumps over it)
; - Although I have coded the signal, and put a lot a security,
; a mischance may lead to the compiler thinking there is a RBsr where
; there is nothing than normal data. The result may be disastrous! So if
; you have BIG parts of datas in which you do not make any special calls,
; you can put before it the macro: RDATA. It tells the compiler that
; the following code, up to the end of the library routine (up to the next
; L(N) label) is normal data: the compiler will not check for RBranches...
; Up to now, I have not been forced to do so, but if something goes wrong,
; try that!
;
;
C_Lib
******************************************************************
* COLD START
*
; The first routine of the library will perform all initialisations in the
; booting of AMOS.
;
; I have put here all the music datazone, and all the interrupt routines.
; I suggest you put all you C-Code here too if you have some...
; ALL the following code, from L0 to L1 will be copied into the compiled
; program (if any music is used in the program) at once. All RBSR, RBRA etc
; will be detected and relocated. AMOSPro extension loader does the same.
L0 movem.l a3-a6,-(sp)
;
; Here I store the address of the extension data zone in the special area
lea MB(pc),a3
move.l a3,ExtAdr+ExtNb*16(a5)
;
; Here, I store the address of the routine called by DEFAULT, or RUN
lea MusDef(pc),a0
move.l a0,ExtAdr+ExtNb*16+4(a5)
;
; Here, the address of the END routine,
lea MusEnd(pc),a0
move.l a0,ExtAdr+ExtNb*16+8(a5)
;
; And now the Bank check routine..
lea BkCheck(pc),a0
move.l a0,ExtAdr+ExtNb*16+12(a5)
; You are not obliged to store something in the above areas, you can leave
; them to zero if no routine is to be called...
;
; In AMOS data zone, stands 8 long words allowing you to simply
; put a patch in the VBL interrupt. The first on is at VBLRout.
; At each VBL, AMOS explores this list, and call all address <> 0
; It stops at the FIRST zero. The music patch is the first routine
; called.
lea MusInt(pc),a0 * Interrupt routine
move.l a0,VBLRout(a5)
; 50/60 herz?
move.l #3546895,MusClock-MB(a3)
move.w #100,TempoBase-MB(a3)
EcCall NTSC * Is system NTSC?
tst.w d1
beq.s ItsPAL
move.w #120,TempoBase-MB(a3)
move.l #3579545,MusClock-MB(a3)
ItsPAL
; Install sample interrupts
lea Sami_handler(pc),a0
move.l a0,Sami_handad-MB(a3)
; As you can see, you MUST preserve A3-A6, and return in D0 the
; Number of the extension if everything went allright. If an error has
; occured (no more memory, no file found etc...), return -1 in D0 and
; AMOS will refuse to start.
movem.l (sp)+,a3-a6
moveq #ExtNb,d0 * NO ERRORS
rts
******* SCREEN RESET
; This routine is called each time a DEFAULT occurs...
;
; The next instruction loads the internal datazone address. I could have
; of course done a load MB(pc),a3 as the datazone is in the same
; library chunk.
MusDef DLoad a3
* Stop/Init narrator
Rbsr L_NarStop
Rbsr L_NarInit
* Reset TRACKER music
Rbsr L_TrackStop
* Reset MED music
Rbsr L_MedClose
clr.b Med_Midi-MB(a3)
* Reset Sam_interrupts
move.w #$000F,Circuits+DmaCon
Rbsr L_Sami_install
* Init musique
Rbsr L_RazWave * Reset waves
move.l Buffer(a5),a0 * Draw square wave
move.l a0,a1
moveq #127,d0
MuDf1 move.b #-127,128(a0)
move.b #127,(a0)+
dbra d0,MuDf1
moveq #0,d1 * 0-> Noise
Rbsr L_NeWave
moveq #1,d1 * 1-> Square wave
Rbsr L_NeWave
move.w #LNoise/2-1,d2 * Draw first noise
move.w BSeed-MB(a3),d1
move.l WaveBase-MB(a3),a0
lea WaveDeb(a0),a0
MuDf2 add.w Circuits+6,d1
mulu #$3171,d1
lsr.l #8,d1
move.w d1,(a0)+
dbra d2,MuDf2
move.w d1,BSeed-MB(a3)
moveq #56,d0 * Default settings
moveq #%1111,d1
Rbsr L_Vol
Rbsr L_MVol
move.w #5,SamBank-MB(a3) * Sample bank=5
moveq #-1,d0 * Sam loop off
moveq #-1,d1
Rbsr L_SL0
Rbra L_MuInit
******* QUIT
; This routine is called when you quit AMOS or when the compiled program
; ends. If you have opend devices, reserved memory you MUST close and
; restore everything to normal.
MusEnd: DLoad a3
; Ferme le narrator
Rbsr L_NarStop
move.l $4.w,a6
move.l WriteIo-MB(a3),d0
beq.s .Skip1
move.l d0,a1
move.l WriteIo-MB(a3),a1
jsr _LVOCloseDevice(a6)
; Enleve la structure
move.l WriteIo-MB(a3),-(sp)
moveq #3,d0
Rbsr L_Amiga.Lib
addq.l #4,sp
; Enleve les ports
move.l WritePort-MB(a3),-(sp)
moveq #1,d0
Rbsr L_Amiga.Lib
addq.l #4,sp
move.l ReadPort-MB(a3),-(sp)
moveq #1,d0
Rbsr L_Amiga.Lib
addq.l #4,sp
; Enleve le translator
.Skip1 move.l TranBase-MB(a3),d0
beq.s NarEnd
move.l d0,a1
jsr CloseLib(a6)
NarEnd
* No more TRACKER music
Rbsr L_TrackStop
* No more MED music
Rbsr L_MedClose
* No more VBL
clr.l VBLRout(a5)
* No more Sami
RBsr L_Sami_remove
* End music
Rbsr L_MOff
moveq #%1111,d0
Rbsr L_EnvOff
Rbsr L_RazWave
lea Circuits,a0
move.w #$000F,DmaCon(a0)
clr.w $a8(a0)
clr.w $b8(a0)
clr.w $c8(a0)
clr.w $d8(a0)
* Finished!
rts
******* LOOK FOR MUSIC BANK
; This routine is called after any bank has been loaded, reserved or erased.
; Here, if a music is being played and if the music bank is erased, I MUST
; stop the music, otherwise it might crash the computer. That's why I
; do a checksum on the first bytes of the bank to see if they have changed...
BkCheck
Rbsr L_TrackCheck * Check Tracker
Rbsr L_MedCheck * Check Med
* Check normal music.
DLoad a3
move.l MusBank-MB(a3),d2 Old music bank address
moveq #3,d0 Ask for music bank address
Rjsr L_Bnk.GetAdr
beq.s BkNo
move.l -8(a0),d0 Looks for "Musi"
cmp.l BkMus-MB(a3),d0
bne.s BkNo
moveq #0,d0 Performs a check sum
add.l (a0),d0
add.l 4(a0),d0
add.l 8(a0),d0
add.l 12(a0),d0
cmp.l d2,a0
bne.s BkNew
cmp.l MusCheck-MB(a3),d0
bne.s BkNew
* Same bank! Do nothing!
rts
* No more bank!
BkNo tst.l d2
beq.s BkNo1
Rbsr L_MuInit
clr.l MusBank-MB(a3)
BkNo1 rts
* A NEW bank
BkNew move.l a0,MusBank-MB(a3)
move.l d0,MusCheck-MB(a3)
Rbsr L_MuInit
move.l MusBank-MB(a3),a0
move.l a0,a1
add.l (a0),a1
move.l a1,BankInst-MB(a3)
move.l a0,a1
add.l 4(a0),a1
move.l a1,BankSong-MB(a3)
add.l 8(a0),a0
move.l a0,BankPat-MB(a3)
rts
***********************************************************
*
* INTERRUPT ROUTINES
*
***********************************************************
******* Sami interrupt handlers
Sami_handler
add.w Sami_reg(a1),a0
move.l Sami_pos(a1),d0
cmp.l Sami_long(a1),d0
bcc.s .whatnow
* Poursuit la lecture du sample
.samloop
move.l d0,d1
add.l #Sami_lplay,d1
cmp.l Sami_long(a1),d1
bls.s .skip
move.l Sami_long(a1),d1
.skip move.l d1,Sami_pos(a1)
sub.l d0,d1
lsr.l #1,d1
add.l Sami_adr(a1),d0
move.l d0,(a0) * AUDxLOC
move.w d1,4(a0) * AUDxLEN
move.w Sami_dvol(a1),d0
bmi.s .skip1
move.w d0,8(a0) * AUDxVOL
.skip1 move.w Sami_bit(a1),Circuits+IntReq
rts
* Sample termine. Que faire?
.whatnow
move.l d0,d1
move.l Sami_radr(a1),d0 * Double buffer?
bne.s .swap
move.l Sami_rpos(a1),d0 * Boucler?
bpl.s .samloop
bset #7,Sami_pos(a1) * Attend?
tst.l d1
bpl.s .skip1
* Fin du sample-> met du blanc!
move.w #0,$a(a0)
move.w Sami_dma(a1),d0
moveq #0,d1
bset d0,d1
move.w d1,Circuits+DmaCon
tst.w Sami_dvol(a1)
bmi.s .skip2
lea MB(pc),a0 * Restart music
bset d0,MuReStart+1-MB(a0)
.skip2 move.w Sami_bit(a1),Circuits+IntEna * No more interrupts
move.w Sami_bit(a1),Circuits+IntReq
rts
* Change de buffer
.swap clr.l Sami_radr(a1)
move.l d0,Sami_adr(a1)
move.l Sami_rlong(a1),Sami_long(a1)
moveq #0,d0
bra .samloop
******* VBL Entry
MusInt lea MB(pc),a3
move.w EnvOn-MB(a3),d0
beq Music
lea EnvBase-MB(a3),a0
lea $a0(a6),a2
moveq #0,d1
moveq #3,d2
moveq #0,d5
MuInt1 btst d1,d0
beq.s MuIntN
move.l EnvDelta(a0),d3
add.l EnvVol(a0),d3
move.l d3,EnvVol(a0)
swap d3
move.w d3,8(a2)
MuInt2 subq.w #1,EnvNb(a0)
bne.s MuIntN
Rbsr L_MuIntE
MuIntN lea EnvLong(a0),a0
lea $10(a2),a2
addq.w #1,d1
dbra d2,MuInt1
move.w d0,EnvOn-MB(a3)
move.w d5,DmaCon(a6)
lsl.w #7,d5
move.w d5,IntEna(a6)
******* Make noise?
tst.w Noise-MB(a3)
beq.s Music
move.w PNoise-MB(a3),d0
moveq #7,d2
move.w BSeed-MB(a3),d1
move.l WaveBase-MB(a3),a0
INoi1 add.w 6(a6),d1
mulu #$3171,d1
lsr.l #8,d1
move.w d1,WaveDeb(a0,d0.w)
subq.w #2,d0
bpl.s INoi2
move.w #LNoise-2,d0
INoi2 dbra d2,INoi1
move.w d0,PNoise-MB(a3)
move.w d1,BSeed-MB(a3)
******* Music routine
Music: move.l MuBase-MB(a3),d0
beq Tracker
movem.l a4-a6,-(sp)
move.l d0,a5
bsr MuEvery
* Here is a smart counter, which gives progressive results
* from zero to 100(PAL), 120(NTSC)...
move.w MuCpt(a5),d0
add.w MuTempo(a5),d0
move.w d0,MuCpt(a5)
move.w TempoBase-MB(a3),d1
cmp.w d1,d0
bcs MuEff
sub.w d1,MuCpt(a5)
* Lets go for one step of music!
moveq #0,d5
moveq #0,d7
move.l a5,a4
tst.b VoiCpt+1(a4)
beq.s Mus0
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus0
moveq #0,d6
move.l MuChip0-MB(a3),a6
bsr MuStep
Mus0
lea MuVoix1(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus1
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus1
moveq #1,d6
move.l MuChip1-MB(a3),a6
bsr MuStep
Mus1
lea MuVoix2(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus2
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus2
moveq #2,d6
move.l MuChip2-MB(a3),a6
bsr MuStep
Mus2
lea MuVoix3(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus3
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus3
moveq #3,d6
move.l MuChip3-MB(a3),a6
bsr MuStep
Mus3
and.w MuDMAsk-MB(a3),d7
move.w d7,$DFF096
tst.w d5
beq.s MuFin
bne.s MuEnd
MuEff bsr DoEffects
MuEnd movem.l (sp)+,a4-a6
MuEnd1 rts
* Finished?
MuFin subq.w #1,MuNumber-MB(a3)
beq MuFini
* Restarts previous music
move.w MuNumber-MB(a3),d0
subq.w #1,d0
mulu #MuLong,d0
lea MuBuffer-MB(a3),a0
add.w d0,a0
move.l a0,MuBase-MB(a3)
move.w MuDMAsk-MB(a3),MuReStart-MB(a3)
clr.w MuStart(a0)
clr.w MuStop(a0)
bra.s MuEnd
* Really finished!
MuFini clr.l MuBase-MB(a3)
Rbsr L_MOff
bra.s MuEnd
******* One step of music for one voice
MuStep lea MuJumps(pc),a1
move.l VoiAdr(a4),a2
MuSt0 move.w (a2)+,d0
bpl.s DoNote
move.w d0,d1
and.w #$7F00,d0
lsr.w #6,d0
jmp 0(a1,d0.w)
******* Play a note
DoNote btst #14,d0
bne.s OldNote
* Play normal note
and.w #$0FFF,d0
move.l BankInst-MB(a3),d1
move.l VoiInst(a4),a0
add.l (a0),d1
move.l d1,(a6)
move.w 8(a0),$04(a6)
bset d6,d7
bclr d6,MuStop+1(a5)
bset d6,MuStart+1(a5)
move.b VoiVol+1(a4),0(a3,d6.w)
tst.b VoiPTone(a4)
bne.s MuSt1
* No portamento
move.w d0,VoiNote(a4)
move.w d0,$06(a6)
bra.s MuSt0
* Start portamento
MuSt1 clr.b VoiPTone(a4)
move.w d0,VoiPToTo(a4)
lea MuPTone(pc),a0
move.l a0,VoiEffect(a4)
bra.s MuSt0
* Play note compatible with first version
OldNote move.w d0,VoiCpt(a4)
move.w (a2)+,d0
beq.s ONoteE
and.w #$0FFF,d0
move.w d0,VoiNote(a4)
move.w d0,$06(a6)
move.l BankInst-MB(a3),d0
move.l VoiInst(a4),a0
add.l (a0),d0
move.l d0,(a6)
move.w 8(a0),$04(a6)
bset d6,d7
bclr d6,MuStop+1(a5)
bset d6,MuStart+1(a5)
move.b VoiVol+1(a4),0(a3,d6.w)
ONoteE move.l a2,VoiAdr(a4)
rts
******* Jump table to labels
MuJumps bra EtEnd * 00-> Fin pattern
bra MuSt0 * 01-> Old Slide up
bra MuSt0 * 02-> Old Slide down
bra EtSVol * 03-> Set volume
bra EtStop * 04-> Stop effet
bra EtRep * 05-> Repeat
bra EtLOn * 06-> Led On
bra EtLOff * 07-> Led Off
bra EtTemp * 08-> Set Tempo
bra EtInst * 09-> Set Instrument
bra EtArp * 10-> Arpeggiato
bra EtPort * 11-> Portamento
bra EtVib * 12-> Vibrato
bra EtVSl * 13-> Volume slide
bra EtSlU * 14-> Slide up
bra EtSlD * 15-> Slide down
bra EtDel * 16-> Delay
bra EtJmp * 17-> Position jump
bra MuSt0 * 18-> Free space
bra MuSt0 * 19-> Free space
bra MuSt0 * 20-> Free space
bra MuSt0 * 21-> Free space
bra MuSt0 * 22-> Free space
bra MuSt0 * 23-> Free space
bra MuSt0 * 24-> Free space
bra MuSt0 * 25-> Free space
bra MuSt0 * 26-> Free space
bra MuSt0 * 27-> Free space
bra MuSt0 * 28-> Free space
bra MuSt0 * 29-> Free space
bra MuSt0 * 30-> Free space
bra MuSt0 * 31-> Free space
******* End of a pattern
EtEnd clr.w VoiCpt(a4)
clr.w VoiRep(a4)
clr.l VoiDeb(a4)
lea NoEffect(pc),a0
move.l a0,VoiEffect(a4)
move.l VoiPat(a4),a0
RePat moveq #0,d0
move.w (a0)+,d0
bmi.s EtEnd1
move.l a0,VoiPat(a4)
move.l BankPat-MB(a3),a0
cmp.w (a0),d0
bhi.s EtEndX
lsl.w #2,d0
add.w d6,d0
lsl.w #1,d0
move.w 2(a0,d0.w),d0
beq.s EtEndX
lea 0(a0,d0.l),a2
bra MuSt0
EtEndX rts
EtEnd1 cmp.w #-1,d0
beq.s EtEndX
move.l VoiDPat(a4),a0
bra.s RePat
******* Change instrument
EtInst and.w #$00FF,d1
move.l BankInst-MB(a3),a0
lsl.w #5,d1
lea 2(a0,d1.w),a0
move.l a0,VoiInst(a4)
move.w 12(a0),d0
cmp.w #64,d0
bcs.s EtInst1
moveq #63,d0
EtInst1 move.w d0,VoiDVol(a4)
mulu MuVolume-MB(a3),d0
lsr.w #6,d0
move.w d0,VoiVol(a4)
bra MuSt0
******* Set Volume
EtSVol and.w #$00FF,d1
cmp.w #64,d1
bcs.s EtSVol1
moveq #63,d1
EtSVol1 move.w d1,VoiDVol(a4)
mulu MuVolume-MB(a3),d1
lsr.w #6,d1
move.w d1,VoiVol(a4)
bra MuSt0
******* Set Tempo
EtTemp and.w #$00FF,d1
move.w d1,MuTempo(a5)
bra MuSt0
******* Led On
EtLOn bclr #1,$bfe001
bra MuSt0
******* Led Off
EtLOff bset #1,$bfe001
bra MuSt0
******* Repeat
EtRep and.w #$00FF,d1
bne.s EtRep1
move.l a2,VoiDeb(a4)
bra MuSt0
EtRep1 tst.w VoiRep(a4)
bne.s EtRep2
move.w d1,VoiRep(a4)
bra MuSt0
EtRep2 subq.w #1,VoiRep(a4)
beq MuSt0
move.l VoiDeb(a4),d0
beq MuSt0
move.l d0,a2
bra MuSt0
******* Arpeggio
EtArp move.b d1,VoiValue+1(a4)
lea MuArp(pc),a0
move.l a0,VoiEffect(a4)
bra MuSt0
******* Portamento
EtPort move.b #1,VoiPTone(a4)
lea MuPTone(pc),a0
bra.s EtSetE
******* Vibrato
EtVib lea MuVib(pc),a0
bra.s EtSetE
******* Volume slide
EtVSl and.w #$00FF,d1
move.w d1,d0
lsr.w #4,d0
tst.w d0
bne.s VsEnd
and.w #$000F,d1
neg.w d1
move.w d1,d0
VsEnd move.w d0,VoiValue(a4)
lea MuVSl(pc),a0
move.l a0,VoiEffect(a4)
bra MuSt0
******* Slide up
EtSlU and.w #$00FF,d1
neg.w d1
lea MuSlide(pc),a0
bra.s EtSte
******* Slide Down
EtSlD lea MuSlide(pc),a0
EtSetE and.w #$00FF,d1
EtSte move.w d1,VoiValue(a4)
move.l a0,VoiEffect(a4)
bra MuSt0
******* Stop effect
EtStop lea NoEffect(pc),a0
move.l a0,VoiEffect(a4)
bra MuSt0
******* Jump to pattern
EtJmp and.w #$00FF,d1
lsl.w #1,d1
move.l VoiDPat(a4),a0
add.w d1,a0
move.l a0,VoiPat(a4)
bra EtEnd
******* Delay
EtDel move.w d1,VoiCpt(a4)
move.l a2,VoiAdr(a4)
rts
******* Effect routines
* Performs all effects
DoEffects
move.l a5,a4
move.l MuChip0-MB(a3),a6
move.l VoiEffect(a4),a0
jsr (a0)
move.w VoiVol(a4),$08(a6)
lea MuVoix1(a5),a4
move.l MuChip1-MB(a3),a6
move.l VoiEffect(a4),a0
jsr (a0)
move.w VoiVol(a4),$08(a6)
lea MuVoix2(a5),a4
move.l MuChip2-MB(a3),a6
move.l VoiEffect(a4),a0
jsr (a0)
move.w VoiVol(a4),$08(a6)
lea MuVoix3(a5),a4
move.l MuChip3-MB(a3),a6
move.l VoiEffect(a4),a0
jsr (a0)
move.w VoiVol(a4),$08(a6)
rts
* TONE SLIDE
MuSlide move.w VoiValue(a4),d0
beq.s NoMoreE
add.w VoiNote(a4),d0
cmp.w #$71,d0
bcc.s MuSl1
moveq #$71,d0
bsr NoMoreE
MuSl1 cmp.w #$358,d0
bls.s MuSl2
move.w #$358,d0
bsr NoMoreE
MuSl2 move.w d0,VoiNote(a4)
move.w d0,$06(a6)
rts
NoMoreE lea NoEffect(pc),a0
move.l a0,VoiEffect(a4)
rts
NoEffect
move.w VoiNote(a4),$06(a6)
rts
* ARPEGGIO
MuArp moveq #0,d0
move.b VoiValue+1(a4),d0
move.b VoiValue(a4),d1
cmp.b #3,d1
bcs.s MuArp0
moveq #2,d1
MuArp0 subq.b #1,d1
move.b d1,VoiValue(a4)
beq.s MuArp2
bpl.s MuArp1
lsr.b #4,d0
bra.s MuArp3
MuArp1 and.b #$0f,d0
bra.s MuArp3
MuArp2 move.w VoiNote(a4),d2
bra.s MuArp4
MuArp3 add.w d0,d0
moveq #0,d1
move.w VoiNote(a4),d1
lea Periods(pc),a0
moveq #$24,d3
MuArpL move.w (a0,d0.w),d2
cmp.w (a0),d1
bge.s MuArp4
addq.l #2,a0
dbra d3,MuArpL
rts
MuArp4 move.w d2,$06(a6)
rts
* PORTAMENTO
MuPTone move.w VoiValue(a4),d0
move.w VoiNote(a4),d1
cmp.w VoiPToTo(a4),d1
beq.s MuPTo3
bcs.s MuPTo1
sub.w d0,d1
cmp.w VoiPToTo(a4),d1
bhi.s MuPto4
bra.s MuPTo2
MuPTo1 add.w d0,d1
cmp.w VoiPToTo(a4),d1
bcs.s MuPTo4
MuPTo2 move.w VoiPToTo(a4),d1
MuPTo3 bsr NoMoreE
MuPTo4 move.w d1,VoiNote(a4)
move.w d1,$06(a6)
rts
* VIBRATO
MuVib move.b VoiVib(a4),d0
lea Sinus(pc),a0
lsr.w #2,d0
and.w #$1f,d0
moveq #0,d2
move.b 0(a0,d0.w),d2
move.b VoiValue+1(a4),d0
and.w #$0F,d0
mulu d0,d2
lsr.w #$06,d2
move.w VoiNote(a4),d0
tst.b VoiVib(a4)
bmi.s MuVib1
add.w d2,d0
bra.s MuVib2
MuVib1 sub.w d2,d0
MuVib2 move.w d0,$06(a6)
move.b VoiValue+1(a4),d0
lsr.w #2,d0
and.w #$3C,d0
add.b d0,VoiVib(a4)
rts
* VOLUME SLIDE
MuVSl move.w VoiDVol(a4),d0
add.w VoiValue(a4),d0
bpl.s MuVSl1
clr.w d0
MuVSl1 cmp.w #$40,d0
bcs.s MuVSl2
moveq #$3F,d0
MuVSl2 move.w d0,VoiDVol(a4)
mulu MuVolume-MB(a3),d0
lsr.w #6,d0
move.w d0,VoiVol(a4)
rts
******* Routine called every VBL
MuEvery
* Second step of sample?
move.w MuStop(a5),d0
beq MuEvX
move.l BankInst-MB(a3),d1
btst #0,d0 * Voix 0
beq.s MuEv0
move.l MuChip0-MB(a3),a6
move.l VoiInst0(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv0 btst #1,d0 * Voix 1
beq.s MuEv1
move.l MuChip1-MB(a3),a6
move.l VoiInst1(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv1 btst #2,d0 * Voix 2
beq.s MuEv2
move.l MuChip2-MB(a3),a6
move.l VoiInst2(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv2 btst #3,d0 * Voix 3
beq.s MuEv3
move.l MuChip3-MB(a3),a6
move.l VoiInst3(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv3
* Start a voice
MuEvX move.w MuStart(a5),d1
move.w d1,MuStop(a5)
clr.w MuStart(a5)
or.w d1,d0
and.w MuDMAsk-MB(a3),d0
bset #15,d0
move.w d0,$DFF096
* Restart voices?
move.w MuReStart-MB(a3),d0
beq MuRsX
moveq #0,d3
btst #0,d0 * Voix 0
beq.s MuRs0
lea $DFF0A0,a6
move.l a6,MuChip0-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst0(a5)
beq.s MuRs0
bset #0,d3
MuRs0 btst #1,d0 * Voix 1
beq.s MuRs1
lea $DFF0B0,a6
move.l a6,MuChip1-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst1(a5)
beq.s MuRs1
bset #1,d3
MuRs1 btst #2,d0 * Voix 2
beq.s MuRs2
lea $DFF0C0,a6
move.l a6,MuChip2-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst2(a5)
beq.s MuRs2
bset #2,d3
MuRs2 btst #3,d0 * Voix 3
beq.s MuRs3
lea $DFF0D0,a6
move.l a6,MuChip3-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst3(a5)
beq.s MuRs3
bset #3,d3
MuRs3 clr.w MuReStart-MB(a3)
or.w d0,MuDMAsk-MB(a3)
or.w d3,MuStop(a5)
MuRsX
rts
***********************************************************
*
* TRACKER INTERRUPT ROUTINES
*
***********************************************************
Tracker move.b mt_on(pc),d0
beq.s .Skip
movem.l a4-a6,-(sp)
; Poke les deuxiemes parties des samples
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tst.w mt_dmacon-MB(a3)
beq.s .SkipD
lea mt_voice1(pc),a1
lea $dff000,a0
move.l $a(a1),$a0(a0)
move.w $e(a1),$a4(a0)
move.l $a+$1c(a1),$b0(a0)
move.w $e+$1c(a1),$b4(a0)
move.l $a+$38(a1),$c0(a0)
move.w $e+$38(a1),$c4(a0)
move.l $a+$54(a1),$d0(a0)
move.w $e+$54(a1),$d4(a0)
; Appelle la musique
; ~~~~~~~~~~~~~~~~~~
.SkipD bsr mt_music
movem.l (sp)+,a4-a6
.Skip rts
mt_music:
move.l mt_data(pc),a0
lea mt_voice1(pc),a4
addq.b #1,mt_counter-mt_voice1(a4)
move.b mt_counter(pc),d0
cmp.b mt_speed(pc),d0
blt mt_nonew
moveq #0,d0
move.b d0,mt_counter-mt_voice1(a4)
move.w d0,mt_dmacon-mt_voice1(a4)
move.l mt_data(pc),a0
lea $3b8(a0),a2
lea $43c(a0),a0
moveq #0,d1
move.b mt_songpos(pc),d0
move.b (a2,d0.w),d1
lsl.w #8,d1
lsl.w #2,d1
add.w mt_pattpos(pc),d1
lea $dff0a0,a5
lea mt_samplestarts-4(pc),a1
lea mt_playvoice(pc),a6
jsr (a6)
addq.l #4,d1
lea $dff0b0,a5
lea mt_voice2(pc),a4
jsr (a6)
addq.l #4,d1
lea $dff0c0,a5
lea mt_voice3(pc),a4
jsr (a6)
addq.l #4,d1
lea $dff0d0,a5
lea mt_voice4(pc),a4
jsr (a6)
move.w mt_dmacon(pc),d0
beq.s mt_nodma
or.w #$8000,mt_dmacon-mt_voice4(a4)
mt_nodma:
add.w #$10,mt_pattpos-mt_voice4(a4)
cmp.w #$400,mt_pattpos-mt_voice4(a4)
bne.s mt_exit
mt_next:clr.w mt_pattpos-mt_voice4(a4)
clr.b mt_break-mt_voice4(a4)
addq.b #1,mt_songpos-mt_voice4(a4)
and.b #$7f,mt_songpos-mt_voice4(a4)
move.b -2(a2),d0
cmp.b mt_songpos(pc),d0
bne.s mt_exit
move.b -1(a2),mt_songpos-mt_voice4(a4)
mt_exit:tst.b mt_break-mt_voice4(a4)
bne.s mt_next
; Provoque l'actualisation du DMA
move.w mt_dmacon(pc),d0
beq.s .Skip
moveq #4,d3
.wai2 move.b $dff006,d2
.wai3 cmp.b $dff006,d2
beq.s .wai3
dbf d3,.wai2
move.w d0,$dff096
.Skip rts
mt_nonew:
lea $dff0a0,a5
lea mt_com(pc),a6
jsr (a6)
lea mt_voice2(pc),a4
lea $dff0b0,a5
jsr (a6)
lea mt_voice3(pc),a4
lea $dff0c0,a5
jsr (a6)
lea mt_voice4(pc),a4
lea $dff0d0,a5
jsr (a6)
tst.b mt_break-mt_voice4(a4)
bne mt_next
rts
mt_playvoice:
move.l (a0,d1.l),(a4)
moveq #0,d2
move.b 2(a4),d2
lsr.b #4,d2
move.b (a4),d0
and.b #$f0,d0
or.b d0,d2
beq mt_oldinstr
asl.w #2,d2
move.l (a1,d2.l),4(a4)
move.l mt_mulu(pc,d2.w),a3
move.w (a3)+,8(a4)
move.w (a3)+,$12(a4)
move.l 4(a4),d0
moveq #0,d3
move.w (a3)+,d3
beq mt_noloop
asl.w #1,d3
add.l d3,d0
move.l d0,$a(a4)
move.w -2(a3),d0
add.w (a3),d0
move.w d0,8(a4)
bra mt_hejaSverige
mt_mulu:dcb.l $20,0
mt_noloop:
add.l d3,d0
move.l d0,$a(a4)
mt_hejaSverige:
move.w (a3),$e(a4)
move.w $12(a4),8(a5)
mt_oldinstr:
move.w (a4),d3
and.w #$fff,d3
beq mt_com2
tst.w 8(a4)
beq.s mt_stopsound
move.b 2(a4),d0
and.b #$f,d0
cmp.b #5,d0
beq.s mt_setport
cmp.b #3,d0
beq.s mt_setport
move.w d3,$10(a4)
move.w $1a(a4),$dff096
clr.b $19(a4)
move.l 4(a4),(a5)
move.w 8(a4),4(a5)
move.w $10(a4),6(a5)
move.w $1a(a4),d0
or.w d0,mt_dmacon-mt_playvoice(a6)
bra mt_com2
mt_stopsound:
move.w $1a(a4),$dff096
bra mt_com2
mt_setport:
move.w (a4),d2
and.w #$fff,d2
move.w d2,$16(a4)
move.w $10(a4),d0
clr.b $14(a4)
cmp.w d0,d2
beq.s mt_clrport
bge mt_com2
move.b #1,$14(a4)
bra mt_com2
mt_clrport:
clr.w $16(a4)
rts
mt_port:moveq #0,d0
move.b 3(a4),d2
beq.s mt_port2
move.b d2,$15(a4)
move.b d0,3(a4)
mt_port2:
tst.w $16(a4)
beq.s mt_rts
move.b $15(a4),d0
tst.b $14(a4)
bne.s mt_sub
add.w d0,$10(a4)
move.w $16(a4),d0
cmp.w $10(a4),d0
bgt.s mt_portok
move.w $16(a4),$10(a4)
clr.w $16(a4)
mt_portok:
move.w $10(a4),6(a5)
mt_rts: rts
mt_sub: sub.w d0,$10(a4)
move.w $16(a4),d0
cmp.w $10(a4),d0
blt.s mt_portok
move.w $16(a4),$10(a4)
clr.w $16(a4)
move.w $10(a4),6(a5)
rts
mt_sin:
dc.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd
dc.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18
mt_vib: move.b $3(a4),d0
beq.s mt_vib2
move.b d0,$18(a4)
mt_vib2:move.b $19(a4),d0
lsr.w #2,d0
and.w #$1f,d0
moveq #0,d2
move.b mt_sin(pc,d0.w),d2
move.b $18(a4),d0
and.w #$f,d0
mulu d0,d2
lsr.w #7,d2
move.w $10(a4),d0
tst.b $19(a4)
bmi.s mt_vibsub
add.w d2,d0
bra.s mt_vib3
mt_vibsub:
sub.w d2,d0
mt_vib3:move.w d0,6(a5)
move.b $18(a4),d0
lsr.w #2,d0
and.w #$3c,d0
add.b d0,$19(a4)
rts
mt_arplist:
dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1
mt_arp: moveq #0,d0
move.b mt_counter(pc),d0
move.b mt_arplist(pc,d0.w),d0
beq.s mt_normper
cmp.b #2,d0
beq.s mt_arp2
mt_arp1:move.b 3(a4),d0
lsr.w #4,d0
bra.s mt_arpdo
mt_arp2:move.b 3(a4),d0
and.w #$f,d0
mt_arpdo:
asl.w #1,d0
move.w $10(a4),d1
lea mt_periods(pc),a0
mt_arp3:cmp.w (a0)+,d1
blt.s mt_arp3
move.w -2(a0,d0.w),6(a5)
rts
mt_normper:
move.w $10(a4),6(a5)
rts
mt_com: move.w 2(a4),d0
and.w #$fff,d0
beq.s mt_normper
move.b 2(a4),d0
and.b #$f,d0
beq.s mt_arp
cmp.b #6,d0
beq.s mt_volvib
cmp.b #4,d0
beq mt_vib
cmp.b #5,d0
beq.s mt_volport
cmp.b #3,d0
beq mt_port
cmp.b #1,d0
beq.s mt_portup
cmp.b #2,d0
beq.s mt_portdown
move.w $10(a4),6(a5)
cmp.b #$a,d0
beq.s mt_volslide
rts
mt_portup:
moveq #0,d0
move.b 3(a4),d0
sub.w d0,$10(a4)
move.w $10(a4),d0
cmp.w #$71,d0
bpl.s mt_portup2
move.w #$71,$10(a4)
mt_portup2:
move.w $10(a4),6(a5)
rts
mt_portdown:
moveq #0,d0
move.b 3(a4),d0
add.w d0,$10(a4)
move.w $10(a4),d0
cmp.w #$358,d0
bmi.s mt_portdown2
move.w #$358,$10(a4)
mt_portdown2:
move.w $10(a4),6(a5)
rts
mt_volvib:
bsr mt_vib2
bra.s mt_volslide
mt_volport:
bsr mt_port2
mt_volslide:
moveq #0,d0
move.b 3(a4),d0
lsr.b #4,d0
beq.s mt_vol3
add.b d0,$13(a4)
cmp.b #$40,$13(a4)
bmi.s mt_vol2
move.b #$40,$13(a4)
mt_vol2:move.w $12(a4),8(a5)
rts
mt_vol3:move.b 3(a4),d0
and.b #$f,d0
sub.b d0,$13(a4)
bpl.s mt_vol4
clr.b $13(a4)
mt_vol4:move.w $12(a4),8(a5)
rts
mt_com2:move.b 2(a4),d0
and.b #$f,d0
beq mt_rts
cmp.b #$e,d0
beq.s mt_filter
cmp.b #$d,d0
beq.s mt_pattbreak
cmp.b #$b,d0
beq.s mt_songjmp
cmp.b #$c,d0
beq.s mt_setvol
cmp.b #$f,d0
beq.s mt_setspeed
rts
mt_filter:
move.b 3(a4),d0
and.b #1,d0
asl.b #1,d0
and.b #$fd,$bfe001
or.b d0,$bfe001
rts
mt_pattbreak:
move.b #1,mt_break-mt_playvoice(a6)
rts
mt_songjmp:
move.b #1,mt_break-mt_playvoice(a6)
move.b 3(a4),d0
subq.b #1,d0
move.b d0,mt_songpos-mt_playvoice(a6)
rts
mt_setvol:
cmp.b #$40,3(a4)
bls.s mt_sv2
move.b #$40,3(a4)
mt_sv2: moveq #0,d0
move.b 3(a4),d0
move.b d0,$13(a4)
move.w d0,8(a5)
rts
mt_setspeed:
moveq #0,d0
move.b 3(a4),d0
cmp.b #$1f,d0
bls.s mt_sp2
moveq #$1f,d0
mt_sp2: tst.w d0
bne.s mt_sp3
moveq #1,d0
mt_sp3: move.b d0,mt_speed-mt_playvoice(a6)
rts
*********************************************************************
* MUSIC extension data zone
; Branches for AMOSPro Editor (-4)
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Rbra L_GoSam
MB:
MuVu dc.l 0 * Vu Meters
MuBase dc.l 0 * Curretn music address
MusAdr dc.l 0 * Branch table address
MusClock dc.l 3546895 * Clock speed
WaveBase dc.l 0 * Wave tree
Waves dc.w 0,0,0,0
EnvOn: dc.w 0 * ADSR running?
EnvBase: ds.b EnvLong*4 * ADSR table
SamBank: dc.w 0 * Sample bank
BSeed: dc.w 0 * Random seed
Noise: dc.w 0 * Noise on?
PNoise: dc.w 0 * Pointer to noise buffer
TempoBase: dc.w 0 * 100 (PAL) - 120 (NTSC)
* Musique
MusBank dc.l 0 * Music bank
MusCheck dc.l 0 * Check sum
BankInst dc.l 0 * Instruments
BankSong dc.l 0 * Songs
BankPat dc.l 0 * Patterns
MuNumber dc.w 0 * Music priority
MuVolume dc.w 0 * Music volume
MuDMAsk dc.w 0 * Voice mask
MuReStart dc.w 0 * Restart the voice
MuChip0 dc.l 0 * Circuits 0
MuChip1 dc.l 0 * 1
MuChip2 dc.l 0 * 2
MuChip3 dc.l 0 * 3
FoEnd dc.w $8000 * Fake empty pattern
MuBuffer ds.b MuLong*3 * Music tables
RDATA
*************** Tables for effects
Sinus
dc.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd
dc.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18
Periods
dc.w $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c,$023a,$021a,$01fc,$01e0
dc.w $01c5,$01ac,$0194,$017d,$0168,$0153,$0140,$012e,$011d,$010d,$00fe
dc.w $00f0,$00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097,$008f,$0087
dc.w $007f,$0078,$0071,$0000,$0000
*************** Default enveloppes
EnvDef: dc.w 1,64,4,55,5,50,25,0,0,0
EnvShoot dc.w 1,64,10,0,0,0
EnvBoom dc.w 1,64,10,50,50,0,0,0
EnvBell dc.w 1,64,4,40,25,0,0,0
*************** Bank headers
BkMus: dc.b "Music "
*************** Frequency / notes
TFreq: dc.w 000,256/2
dc.w 000,256/2
dc.w 256,128/2
dc.w 384,64/2
dc.w 448,32/2
dc.w 480,16/2
dc.w 496,8/2
dc.w 504,4/2
dc.w 504,4/2
TNotes: dc.w 00,00,00,33,35,37,39,41,44,46,49,52
dc.w 55,58,62,65,69,73,78,82,87,92,98,104
dc.w 110,117,123,131,139,147,156,165,175,185,196,208
dc.w 220,233,247,262,277,294,311,330,349,370,392,415
dc.w 440,466,494,523,554,587,622,659,698,740,784,830
dc.w 880,932,988,1046,1109,1175,1245,1319,1397,1480,1568,1661
dc.w 1760,1865,1986,2093,2217,2349,2489,2637,2794,2960,3136,3322
dc.w 3520,3729,3952,4186,4435,4699,4978,5274,5588,5920,6272,6645
dc.w 7040,7459,7902,8372
*************** SAMPLE PLAYER INTERRUPT STRUCTURES
Sami_lplay equ 1024*4
Sami_bit equ 22
Sami_dma equ 24
Sami_reg equ 26
Sami_adr equ 28
Sami_long equ 32
Sami_pos equ 36
Sami_rpos equ 40
Sami_radr equ 44
Sami_rlong equ 48
Sami_dvol equ 52
Sami_old equ 54
Sami_intl equ 58
Sami_int ds.b 22 * Channel 0
dc.w %0000000010000000 bit
dc.w 0 dma
dc.w $a0 reg
dc.l 0 adr
dc.l 0 long
dc.l 0 pos
dc.l 0 rpos
dc.l 0 radr
dc.l 0 rlong
dc.w 0 dvol
dc.l 0 old
ds.b 22 * Channel 1
dc.w %0000000100000000 bit
dc.w 1 dma
dc.w $b0 reg
dc.l 0 adr
dc.l 0 long
dc.l 0 pos
dc.l 0 rpos
dc.l 0 radr
dc.l 0 rlong
dc.w 0 dvol
dc.l 0 old
ds.b 22 * Channel 2
dc.w %0000001000000000 bit
dc.w 2 dma
dc.w $c0 reg
dc.l 0 adr
dc.l 0 long
dc.l 0 pos
dc.l 0 rpos
dc.l 0 radr
dc.l 0 rlong
dc.w 0 dvol
dc.l 0 old
ds.b 22 * Channel 3
dc.w %0000010000000000 bit
dc.w 3 dma
dc.w $d0 reg
dc.l 0 adr
dc.l 0 long
dc.l 0 pos
dc.l 0 rpos
dc.l 0 radr
dc.l 0 rlong
dc.w 0 dvol
dc.l 0 old
Sami_OldEna dc.w 0
Sami_empty dc.l 0
Sami_bits dc.w 0
Sami_handad dc.l 0
Sami_flag dc.w 0
SamLoops dc.w 0
*************** NARRATOR
Amaps: dc.b 3,5,10,12
TranBase dc.l 0
even
L_WriteIo equ 88
WriteIo dc.l 0
WritePort: dc.l 0
L_ReadIo equ 92
ReadIo ds.b L_ReadIo
ReadPort dc.l 0
TranName dc.b "translator.library",0
NarDevice dc.b "narrator.device",0
even
; MED data zone
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Med_Bank dc.w 7 Bank number 6= tracker
Med_Base dc.l 0
Med_Adr dc.l 0
Med_On dc.b 0
Med_Midi dc.b 0
Med_Name dc.b "medplayer.library",0
even
_MEDGetPlayer equ -30
_MEDFreePlayer equ -36
_MEDPlayModule equ -42
_MEDContModule equ -48
_MEDStopPlayer equ -54
_MEDDimOffPlayer equ -60
_MEDSetTempo equ -66
_MEDLoadModule equ -72
_MEDUnLoadModule equ -78
_MEDGetCurrentModule equ -84
_MEDResetMIDI equ -90
_MEDSetModnum equ -96
_MEDRelocModule equ -102
*********************************************************************
* mt TRACKER data zone
Track_Bank dc.w 6 Bank number 6= tracker
mt_on dc.b 0
colour dc.w 0
mt_periods:
dc.w $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c,$023a,$021a,$01fc,$01e0
dc.w $01c5,$01ac,$0194,$017d,$0168,$0153,$0140,$012e,$011d,$010d,$00fe
dc.w $00f0,$00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097,$008f,$0087
dc.w $007f,$0078,$0071,$0000
mt_speed: dc.b 6
mt_counter: dc.b 0
mt_pattpos: dc.w 0
mt_songpos: dc.b 0
mt_break: dc.b 0
mt_dmacon: dc.w 0
mt_samplestarts:dcb.l $1f,0
mt_voice1: dcb.w 13,0
dc.w 1
mt_voice2: dcb.w 13,0
dc.w 2
mt_voice3: dcb.w 13,0
dc.w 4
mt_voice4: dcb.w 13,0
dc.w 8
mt_data: dc.l 0
dc.l 0
**********************************************************************
; Please leave 1 or two labels free for future extension. You never
; know!
L1
; Now follow all the music routines. Some are just routines called by others,
; some are instructions.
; See how a adress the internal music datazone, by using a base register
; (usually A3) and adding the offset of the data in the datazone...
; >>> How to get the parameters for the instruction?
;
; When an instruction or function is called, you get the parameters
; pushed in A3. Remember that you unpile them in REVERSE order than
; the instruction syntax.
; As you have a entry point for each set of parameters, you know
; how many are pushed...
; - INTEGER: move.l (a3)+,d0
; - STRING: move.l (a3)+,a0
; move.w (a0)+,d0
; A0---> start of the string.
; D0---> length of the string
; - FLOAT: move.l (a3)+,d0
; fast floatting point format.
;
; IMPORTANT POINT: you MUST unpile the EXACT number of parameters,
; to restore A3 to its original level. If you do not, you will not
; have a immediate error, and AMOS will certainely crash on next
; UNTIL / WEND / ENDIF / NEXT etc...
;
; So, your instruction must:
; - Unpile the EXACT number of parameters from A3, and exit with
; A3 at the original level it was before collecting your parameters)
; - Preserve A4, A5 and A6
; You can use D0-D7/A0-A2 freely...
;
; You can jump to the error routine without thinking about A3 if an error
; occurs in your routine (via a RBra of course). BUT A4, A5 and A6 registers
; MUST be preserved!
;
; You end must end by a RTS.
;
; >>> Functions, how to return the parameter?
;
; To send a function`s parameter back to AMOS, you load it in D3,
; and put its type in D2:
; moveq #0,d2 for an integer
; moveq #1,d2 for a float
; moveq #2,d2 for a string
;
******* Stop sound routine
L_MOff equ 2
L2 lea Circuits,a0
move.w #%0000011110000000,IntEna(a0) * No more interrupts
move.w MuDMAsk-MB(a3),d0
beq.s MOf3
move.w d0,DmaCon(a0)
moveq #3,d1
MOf1 btst d1,d0
beq.s MOf2
move.w #2,$a4(a0)
clr.w $a8(a0)
MOf2 lea $10(a0),a0
dbra d1,MOf1
MOf3 rts
***********************************************************
* NARRATOR!
******* Open narrator
L_OpNar equ 3
L3 movem.l a3-a6,-(sp)
Dload a3
move.l $4.w,a6
move.l TranBase-MB(a3),d0
bne OpNarCheck
; Opens communication port
clr.l -(sp)
clr.l -(sp)
moveq #0,d0
Rbsr L_Amiga.Lib
addq.l #8,sp
move.l d0,WritePort-MB(a3)
; Opens IO structure
move.l #L_WriteIo,-(sp)
move.l d0,-(sp)
moveq #2,d0
Rbsr L_Amiga.Lib
addq.l #8,sp
move.l d0,WriteIo-Mb(a3)
move.l d0,a1
moveq #0,d0
moveq #0,d1
lea NarDevice-MB(a3),a0
jsr OpenDev(a6)
tst.l d0
bne OpNarE
; Open READ structure
clr.l -(sp)
clr.l -(sp)
moveq #0,d0
Rbsr L_Amiga.Lib
addq.l #8,sp
move.l d0,ReadPort-MB(a3)
move.l WriteIo-MB(a3),a0
lea ReadIo-MB(a3),a1
moveq #L_WriteIo/2-1,d0
.Loop move.w (a0)+,(a1)+
dbra d0,.Loop
lea ReadIo-MB(a3),a1
move.l ReadPort-MB(a3),14(a1)
; Open translator
Rbsr L_NarInit
lea TranName-MB(a3),a1
moveq #0,d0
jsr OpenLib(a6)
move.l d0,TranBase-MB(a3)
beq OpNarE
* Restore Sami interrupts
move.l DosBase(a5),a6
moveq #50,d1
jsr -198(a6)
clr.w Sami_Flag-MB(a3)
RBsr L_Sami_Install
* Ok!
movem.l (sp)+,a3-a6
rts
;-----> Annule un speech pr<70>c<EFBFBD>dent
OpNarCheck
RBsr L_NarStop
movem.l (sp)+,a3-a6
rts
;-----> Can't open narrator
OpNarE movem.l (sp)+,a3-a6
NoNar moveq #7,d0
Rbra L_Custom
******* Init narrator (if here)!
L_NarInit equ 4
L4 move.l WriteIO-MB(a3),d0
beq.s .Skip
move.l d0,a1
move.w #150,48(a1)
move.w #110,50(a1)
clr.w 52(a1)
clr.w 54(a1)
lea Amaps-MB(a3),a0
move.l a0,56(a1)
move.w #4,60(a1)
move.w #63,62(a1)
move.w #22200,64(a1)
.Skip rts
******* SAY a$[,multi]
L_ISay2: equ 5
L5 Rbsr L_OpNar
move.l (a3)+,d7
RBra L_ISay
L_ISay1: equ 6
L6 Rbsr L_OpNar
moveq #0,d7
Rbra L_ISay
L_ISay: equ 7
L7 moveq #%0000,d0
Rbsr L_StopDma
Rbsr L_VOnOf
DLoad a0
clr.w EnvOn-MB(a0)
clr.w Noise-MB(a0)
move.l (a3)+,a0
moveq #0,d0
move.w (a0)+,d0
* Phoneme?
cmp.b #"~",(a0)
bne.s ISayN
addq.l #1,a0
move.l Buffer(a5),a1
move.w d0,d1
cmp.w #1024,d1
bcc ISayN
subq.w #2,d1
bmi.s ISayN
ISayP move.b (a0)+,(a1)+
dbra d1,ISayP
move.b #"Q",(a1)+
move.b #"#",(a1)+
move.b #"U",(a1)+
clr.b (a1)+
clr.b (a1)+
addq.w #4,d0
movem.l a3/a6,-(sp)
DLoad a3
bra.s ISayNn
* Call TRANSLATOR
ISayN move.l Buffer(a5),a1
move.l a1,a2
move.l #1024,d1
move.l d1,d2
lsr.w #2,d2
subq.w #2,d2
ISayN1 clr.l (a2)+
dbra d2,ISayN1
movem.l a3/a6,-(sp)
DLoad a3
move.l TranBase-MB(a3),a6
jsr Translate(a6)
tst.w d0
bne.s SayX
move.l #1024,d0
ISayNn
Rbsr L_Sami_remove
move.l WriteIO-MB(a3),a1
move.w #3,28(a1)
move.l d0,36(a1)
move.l Buffer(a5),40(a1)
move.l ExecBase,a6
tst.w d7
bne.s ISayA
; Mode non multitache
clr.b 66(a1)
jsr DoIO(a6)
RBsr L_Sami_install
SayX movem.l (sp)+,a3/a6
moveq #%1111,d0
Rbsr L_VOnOf
rts
; Mode multitache
ISayA move.b #1,66(a1) Generer des mouths!
jsr SendIO(a6)
movem.l (sp)+,a3/a6
rts
******* SET TALK sex,mode,pitch,rate
L_ITalk equ 8
L8 Rbsr L_OpNar
move.l #EntNul,d0
Dload a1
move.l WriteIo-MB(a1),a1
move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd1
cmp.w #40,d1
Rbcs L_IFonc
cmp.w #400,d1
Rbhi L_IFonc
move.w d1,48(a1)
IRd1 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd2
cmp.w #65,d1
Rbcs L_IFonc
cmp.w #320,d1
Rbhi L_IFonc
move.w d1,50(a1)
IRd2 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd3
and.w #$0001,d1
move.w d1,52(a1)
IRd3 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd4
and.w #$0001,d1
move.w d1,54(a1)
IRd4 rts
******* Narrator READ lips
L_LipsX equ 9
L9 Dlea ReadIo,a0
moveq #0,d2
move.b 88(a0),d3
ext.w d3
ext.l d3
rts
L_LipsY equ 10
L10 Dlea ReadIo,a0
moveq #0,d2
move.b 89(a0),d3
ext.w d3
ext.l d3
rts
***********************************************************
* MUSIC INSTRUCTION
******* BELL
L_Bell0 equ 11
L11 moveq #0,d3
moveq #70,d2
moveq #%1111,d1
moveq #1,d5
Dlea EnvBell,a0
move.l a0,d6
Rbra L_GoBel
L_Bell1 equ 12
L12 moveq #0,d3
move.l (a3)+,d2
moveq #%1111,d1
moveq #1,d5
Dlea EnvBell,a0
move.l a0,d6
Rbra L_GoBel
******* BOOM
L_Boom equ 13
L13 moveq #0,d3
moveq #36,d2
moveq #0,d5
Dlea EnvBoom,a0
move.l a0,d6
Rbra L_Shout
******* SHOOT
L_Shoot equ 14
L14 moveq #0,d3
moveq #60,d2
moveq #0,d5
Dlea EnvShoot,a0
move.l a0,d6
Rbra L_Shout
* Gives a stereo effect
L_Shout: equ 15
L15 moveq #%0000,d0
Rbsr L_StopDma
Rbsr L_VOnOf
moveq #%1000,d1
Shot movem.l d0-d7,-(sp)
Rbsr L_GoShot
movem.l (sp)+,d0-d7
addq.w #1,d2
lsr.w #1,d1
bcc.s Shot
rts
******* VOLUME n
L_IVol1 equ 16
L16 move.l (a3)+,d0
moveq #%1111,d1
Rbsr L_Vol
Rbsr L_MVol
rts
******* VOLUME voice,n
L_IVol2 equ 17
L17 move.l (a3)+,d0
move.l (a3)+,d1
Rbra L_Vol
* Set voices volume level
L_Vol equ 18
L18 cmp.l #64,d0
Rbcc L_IFonc
moveq #0,d2
Dlea EnvBase,a0
Dlea Sami_int,a1
Vol1 btst d2,d1
beq.s Vol2
move.w d0,EnvDVol(a0)
tst.w Sami_dvol(a1)
bmi.s Vol2
move.w d0,Sami_dvol(a1)
Vol2 lea EnvLong(a0),a0
lea Sami_intl(a1),a1
addq.w #1,d2
cmp.w #4,d2
bcs.s Vol1
rts
******* Stops Narrator if it was playing in multitask mode!
L_NarStop equ 19
L19 movem.l a3/a6,-(sp)
Dload a3
move.l $4.w,a6
move.l WriteIo-MB(a3),d0
beq.s .Skip2
move.l d0,a1
tst.b 66(a1)
beq.s .Skip2
clr.b 66(a1)
jsr _LVOCheckIO(a6)
tst.l d0
bne.s .Skip1
move.l WriteIo-MB(a3),a1
jsr _LVOAbortIO(a6)
.Skip1 move.l WriteIo-MB(a3),a1
jsr _LVOWaitIO(a6)
Rbsr L_Sami_Install
.Skip2 movem.l (sp)+,a3/a6
rts
******* PLAY note,length
L_IPlay2 equ 20
L20 move.l (a3)+,d3
Rbmi L_IFonc
move.l (a3)+,d2
moveq #%1111,d1
moveq #-1,d5
moveq #0,d6
Rbra L_GoBel
******* Play voice,note,length
L_IPlay3 equ 21
L21 move.l (a3)+,d3
Rbmi L_IFonc
move.l (a3)+,d2
move.l (a3)+,d1
moveq #-1,d5
moveq #0,d6
Rbra L_GoBel
L_GoBel equ 22
L22 cmp.l #96,d2 * <96?
Rbhi L_IFonc
move.w d1,d0 * Stop voices
eor.w #$000F,d0
Rbsr L_StopDma
Rbsr L_VOnOf
Rbra L_GoShot
L_GoShot equ 23
L23 move.l a3,-(sp)
lea Circuits,a2
Dload a3
move.w EnvOn-MB(a3),d7
clr.w EnvOn-MB(a3)
move.w #$8000,Sami_Bits-MB(a3)
* Explores all 4 voices
moveq #0,d0
move.w d1,d4
moveq #3,d1
IPl1 btst d1,d4
beq.s IPl2
Rbsr L_VPlay
IPl2 dbra d1,IPl1
******* Start!
IPlX Rbsr L_DmaWait
bset #15,d0
move.w d0,DmaCon(a2)
move.w Sami_bits-MB(a3),IntEna(a2)
move.w d7,EnvOn-MB(a3)
move.l (sp)+,a3
* Wait?
tst.l d3
beq.s IPlX1
Rjsr L_WaitRout
IPlX1 rts
******* Play voice D1: WAVE orSAMPLE
L_VPlay equ 24
L24 movem.l d0-d6/a0-a2,-(sp)
moveq #0,d3
bset d1,d3
move.w d3,DmaCon(a2) * Stop voice
lsl.w #7,d3
move.w d3,IntEna(a2) * Stop interrupts
bclr d1,Noise-MB(a3) * No more random
tst.w d2
beq VSil
addq.w #3,d2
move.w d5,d0 * Forced wave? (bell)
bpl.s VPl0
move.w d1,d0 * Wave or Sample?
lsl.w #1,d0
lea Waves-MB(a3),a0
move.w 0(a0,d0.w),d0
bmi VPl2
* Play WAVE!
VPl0 beq VPl4
lea $a0(a2),a2
move.w d1,d3
lsl.w #4,d3
add.w d3,a2 * a2-> I/O
movem.l d1-d3/a2,-(sp)
move.w d0,d1
Rbsr L_WaveAd
Rbeq L_WNDef
move.l a2,a1
movem.l (sp)+,d1-d3/a2
pea WaveEnv(a1)
lea WaveDeb(a1),a1
subq.w #1,d2
move.w d2,d3
ext.l d3
divu #12,d3
lsl.w #2,d3
lea TFreq-MB(a3),a0
add.w d3,a0
add.w (a0)+,a1
move.l a1,(a2) * AudAd
move.w (a0)+,d3
move.w d3,4(a2) * AudLen
lsl.w #1,d3
lea TNotes-MB(a3),a1
lsl.w #1,d2
mulu 0(a1,d2.w),d3
move.l MusClock-MB(a3),d2
divu d3,d2
cmp.w #124,d2
bcc.s VPl1
moveq #124,d2
VPl1: move.w d2,6(a2) * AudPer
* Start enveloppe
move.l (sp)+,d5
tst.l d6 * Fixed enveloppe? (bell / shoot)
bne.s VPl1a
move.l d5,d6
VPl1a lea EnvBase-MB(a3),a0
move.w d1,d0
mulu #EnvLong,d0
add.w d0,a0
move.l d6,EnvAd(a0)
move.l d6,EnvDeb(a0)
clr.w EnvVol(a0)
Rbsr L_MuIntE
movem.l (sp)+,a0-a2/d0-d6
bset d1,d0
bset d1,d7
rts
******* Silence!
VSil moveq #0,d0
bset d1,d0
move.w d0,DmaCon(a2)
movem.l (sp)+,a0-a2/d0-d6
bclr d1,d7
rts
******* Play SAMPLE
VPl2 move.l a2,-(sp)
move.w d2,-(sp)
neg.w d0
Rbsr L_GetSam
move.w (sp)+,d0
move.l (sp)+,a2
moveq #0,d6
VPl3 lea TNotes-MB(a3),a0
lsl.w #1,d0
mulu -2(a0,d0.w),d3
divu #440,d3
and.l #$0000FFFF,d3
Rbra L_SPl0
******* Play NOISE
VPl4 bset d1,Noise-MB(a3)
move.w d2,d0
move.l WaveBase-MB(a3),a1
lea WaveEnv(a1),a0
lea WaveDeb(a1),a1
move.l #LNoise,d2
move.l #2000,d3
tst.l d6
bne.s VPl3
move.l a0,d6
bset #0,d6
bra.s VPl3
******* PLAY OFF (voice)
L_IPlOf0 equ 25
L25 moveq #%1111,d0
Rbra L_PlOf
L_IPlOf1 equ 26
L26 move.l (a3)+,d0
Rbra L_Plof
L_PlOf equ 27
L27 move.l a3,-(sp)
Dload a3
Rbsr L_EnvOff
move.l (sp)+,a3
rts
******* Attente DMA
L_DmaWait equ 28
L28 movem.l d2-d3,-(sp)
; A modifier!!! Demander les caracteristiques du DMA!!!
; move.w #$200,d0
;.loop nop
; dbra d0,.loop
.wait moveq #4,d3
.wai2 move.b $dff006,d2
.wai3 cmp.b $dff006,d2
beq.s .wai3
dbf d3,.wai2
moveq #8,d2
.wai4 dbf d2,.wai4
movem.l (sp)+,d2-d3
rts
***********************************************************
* SAMPLE INSTRUCTIONS
******* SAM BANK n
L_ISBank equ 29
L29 move.l (a3)+,d0
Rbls L_IFonc
cmp.l #16,d0
Rbhi L_IFonc
Dlea SamBank,a0
move.w d0,(a0)
rts
******* SAMLOOP ON
L_ISLOn1 equ 30
L30 moveq #0,d0
move.l (a3)+,d1
Rbra L_Sl0
******* STOP DMA / INTERUPTS
* D0= value
L_StopDma equ 31
L31 move.w d0,-(sp)
eor.w #%1111,d0
move.w d0,Circuits+DmaCon
lsl.w #7,d0
move.w d0,Circuits+IntEna
move.w (sp)+,d0
RBra L_DmaWait
L_ISLOn0 equ 32
L32 moveq #0,d0
moveq #%1111,d1
Rbra L_Sl0
******* SAMLOOP OFF
L_ISLOf1 equ 33
L33 moveq #-1,d0
move.l (a3)+,d1
Rbra L_Sl0
L_ISLOf0 equ 34
L34 moveq #-1,d0
moveq #%1111,d1
Rbra L_SL0
L_SL0 equ 35
L35 moveq #0,d2
Dlea Sami_int,a0
Dlea SamLoops+1,a1
Sl1 btst d2,d1
beq.s Sl2
bclr d2,(a1)
move.l d0,Sami_rpos(a0)
bne.s Sl2
bset d2,(a1)
Sl2 lea Sami_intl(a0),a0
addq.w #1,d2
cmp.w #4,d2
bcs.s Sl1
rts
******* NOISE TO voice
L_INoTo equ 36
L36 move.l (a3)+,d1
moveq #0,d0
Rbra L_ISmt
******* SAMPLE n TO voice
L_ISamTo equ 37
L37 move.l 4(a3),d0
Rbsr L_GetSam
move.l (a3)+,d1
move.l (a3)+,d0
neg.w d0
Rbra L_Ismt
* Poke D1-> waves
L_ISmt equ 38
L38 Dlea Waves,a0
moveq #0,d2
ISmt1 btst d2,d1
beq.s ISmt2
move.w d0,(a0)
ISmt2 addq.l #2,a0
addq.w #1,d2
cmp.w #4,d2
bcs.s ISmt1
rts
******* SAM PLAY number
L_ISam1 equ 39
L39 move.l (a3)+,d0
Rbsr L_GetSam
moveq #%1111,d1
Rbra L_GoSam
******* SAM PLAY voix,number
L_ISam2 equ 40
L40 move.l (a3)+,d0
Rbsr L_GetSam
move.l (a3)+,d1
Rbra L_GoSam
******* SAM PLAY voix,number,frequence
L_ISam3 equ 41
L41 move.l 4(a3),d0
Rbsr L_GetSam
move.l (a3)+,d3
cmp.l #500,d3
Rble L_IFonc
addq.l #4,a3
move.l (a3)+,d1
Rbra L_GoSam
******* SAM RAW voice,ad,length,freq
L_ISamR equ 42
L42 move.l (a3)+,d3
cmp.l #500,d3
Rble L_IFonc
move.l (a3)+,d2
cmp.l #256,d2
Rble L_IFonc
move.l (a3)+,a1
move.l (a3)+,d1
Rbra L_GoSam
L_GoSam: equ 43
L43 move.l a3,-(sp)
Dload a3
move.w d1,d0
eor.w #$000F,d0
Rbsr L_StopDma
Rbsr L_VOnOf
lea Circuits,a2
move.w EnvOn-MB(a3),d7
clr.w EnvOn-MB(a3)
move.w #$8000,Sami_bits-MB(a3)
* Do all voices
moveq #0,d0
move.w d1,d4
moveq #3,d1
ISp2b btst d1,d4
beq.s ISp2c
Rbsr L_SPlay
ISp2c dbra d1,ISp2b
* Start!
ISpX
Rbsr L_DmaWait
bset #15,d0
move.w d0,DmaCon(a2)
move.w Sami_bits-MB(a3),IntEna(a2)
move.w d7,EnvOn-MB(a3)
move.l (sp)+,a3
rts
******* Find a sample -> A0
L_GetSam equ 44
L44 move.l d0,-(sp)
Dload a0
move.w SamBank-MB(a0),d0
ext.l d0
Rbeq L_IFonc
move.l d1,-(sp)
Rjsr L_Bnk.GetAdr
Rbeq L_BNSam
move.l (sp)+,d1
move.l -8(a0),d0
cmp.l #"Samp",d0
Rbne L_BNSam
* Get sample characteristics1
move.l (sp)+,d0
Rbls L_IFonc
cmp.w (a0),d0
Rbhi L_SNDef
lsl.w #2,d0
move.l 2-4(a0,d0.w),d0
Rbeq L_SNDef
add.l d0,a0
moveq #0,d3
move.w 8(a0),d3
move.l 10(a0),d2
lea 14(a0),a1
rts
*********************************************************************
* SLOAD fichier,adresse,longueur
L_Sload equ 45
L45 move.l (a3)+,d3 Length
RBmi L_IFonc
move.l (a3)+,d0 Adress (or bank)
RJsr L_Bnk.OrAdr
move.l d0,d2
move.l (a3)+,d0 File
cmp.l #10,d0
Rbcc L_IFonc
subq.l #1,d0
Rbmi L_IFonc
mulu #TFiche,d0
lea Fichiers(a5),a2
add.w d0,a2
move.l Fha(a2),d1
RBeq L_IFonc
btst #2,FhT(a2)
Rbne L_IFonc
* Load the data
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr -42(a6) DosRead
move.l (sp)+,a6
tst.l d0
RBmi L_IDError
rts
******* SAMPLAY routine
* A1= Sample
* D3= Freq
* D2= Long
* D1= Voice
L_SPlay: equ 46
L46 movem.l d0-d6/a0-a2,-(sp)
bclr d1,Noise-MB(a3)
moveq #0,d6
Rbra L_SPl0
L_SPl0 equ 47
L47
movem.l a4,-(sp)
moveq #0,d0
bset d1,d0 * Stop voice
move.w d0,DmaCon(a2)
lea Sami_int-MB(a3),a4
move.w #Sami_intl,d0
mulu d1,d0
add.w d0,a4 * a4-> Sami interrupts
move.w Sami_bit(a4),IntEna(a2) * No more interrupts
lea EnvBase-MB(a3),a0 * Enveloppe
move.w d1,d0
mulu #EnvLong,d0
add.w d0,a0
lea $a0(a2),a2
move.w d1,d4
lsl.w #4,d4
add.w d4,a2 * a2-> I/O
move.w #1,$4(a2)
move.l a1,Sami_adr(a4) * Adresse
move.l d2,Sami_long(a4) * Longueur
clr.l Sami_pos(a4) * Position
clr.l Sami_rpos(a4) * Sam loop on?
btst d1,SamLoops+1-MB(a3)
bne.s .skipa
subq.l #1,Sami_rpos(a4)
.skipa clr.l Sami_radr(a4) * Pas de double buffer
move.l d6,d5
move.l MusClock-MB(a3),d6
bsr Div32
cmp.l #124,d0
bcc.s .skip0
moveq #124,d0
.skip0 move.w d0,6(a2) * AudPer
bclr d1,d7
move.w EnvDVol(a0),Sami_dvol(a4) * Volume, sauf si
tst.l d5 une enveloppe est
beq.s .skip1 definie
clr.l Sami_rpos(a4)
bclr #0,d5
bne.s .skipb
subq.l #1,Sami_rpos(a4)
.skipb bset d1,d7
move.w #-1,Sami_dvol(a4)
move.l d5,EnvAd(a0)
move.l d5,EnvDeb(a0)
clr.w EnvVol(a0)
Rbsr L_MuIntE
.skip1 move.w Sami_bit(a4),d0
or.w d0,Sami_bits-MB(a3)
* Va demarrer le son...
lea Circuits,a0
move.l a4,a1
move.l Sami_Handad-MB(a3),a2
jsr (a2)
* Fini!
move.l (sp)+,a4
movem.l (sp)+,d0-d6/a0-a2
bset d1,d0
rts
* Division 32 bits
* D6/D3 -> D0
Div32 movem.l d1/d3/d4/d5/d6,-(sp)
moveq #31,d5
moveq #-1,d4
clr.l d1
dv2: lsl.l #1,d6
roxl.l #1,d1
cmp.l d3,d1
bcs.s dv1
sub.l d3,d1
lsr #1,d4
dv1: roxl.l #1,d0
dbra d5,dv2
movem.l (sp)+,d1/d3/d4/d5/d6
rts
***********************************************************
* WAVE INSTRUCTION SET
******* WAVE n TO n
L_IWave: equ 48
L48 move.l 4(a3),d1
Rbmi L_IFonc
Rbsr L_WaveAd
Rbeq L_WNDef
move.l (a3)+,d1
move.l (a3)+,d0
Rbra L_ISmt
******* SET WAVE n,a$
L_ISWave: equ 49
L49 move.l (a3)+,a1
move.w (a1)+,d1
cmp.w #256,d1
Rbcs L_STSho
move.l (a3)+,d1
Rbls L_IFonc
move.l a3,-(sp)
Dload a3
Rbsr L_NeWave
Rbne L_IOOMem
move.l (sp)+,a3
rts
******* DEL WAVE
L_IDWave1 equ 50
L50 move.l (a3)+,d1
Rbmi L_IFonc
Rbeq L_W0Res
cmp.l #1,d1
Rbeq L_W0Res
move.l a3,-(sp)
DLoad a3
moveq #%1111,d0
Rbsr L_EnvOff
Rbsr L_WaveAd
Rbeq L_WNDef
Rbsr L_WaveDel
Rbsr L_NoWave
move.l (sp)+,a3
rts
******* SET ENVEL n,n TO n,v
L_ISEnv equ 51
L51 move.l (a3)+,d4
cmp.l #64,d4
Rbcc L_IFonc
move.l (a3)+,d3
move.l (a3)+,d5
Rbmi L_IFonc
cmp.l #7,d5
Rbcc L_IFonc
move.l (a3)+,d1
Rbmi L_IFonc
tst.w d5
bne.s ISe1
tst.w d3
Rbls L_IFonc
ISe1 move.l a3,-(sp)
Dload a3
Rbsr L_WaveAd
Rbeq L_WNDef
lsl.w #2,d5
lea WaveEnv(a2,d5.w),a2
move.w d3,(a2)+
move.w d4,(a2)+
clr.w (a2)
move.l (sp)+,a3
rts
******* RAZ WAVES
L_RazWave equ 52
L52 movem.l a2/d0-d2,-(sp)
moveq #%1111,d0
Rbsr L_EnvOff * Stop all voices
lea WaveBase-MB(a3),a2 * Erase all instruments
move.l a2,d2
RzW1 move.l d2,a2
move.l (a2),d0
beq.s RzW2
move.l d0,a2
Rbsr L_WaveDel
bra.s RzW1
RzW2 Rbsr L_NoWave
movem.l (sp)+,a2/d0-d2
rts
* Plus de Waves speciales
L_NoWave equ 53
L53 Dlea Waves,a0 * Default waves
move.w #1,(a0)+
move.w #1,(a0)+
move.w #1,(a0)+
move.w #1,(a0)+
rts
******* NEW WAVES
* A1= Array address
* D1= # to create
L_NeWave: equ 54
L54 movem.l d1-d7/a1-a2,-(sp)
NeW0 Rbsr L_WaveAd
beq.s NeW1
moveq #%1111,d0
Rbsr L_EnvOff
Rbsr L_WaveDel
bra.s NeW0
NeW1 move.l #WaveLong,d0
RJsr L_RamChip
beq.s NeWE
move.l d0,(a2)
move.l d0,a2
move.w d1,WaveNb(a2)
* Copy default ADSR
move.l a1,-(sp)
lea EnvDef-MB(a3),a0
lea WaveEnv(a2),a1
NeW3 move.l (a0)+,(a1)+
bne.s NeW3
move.l (sp)+,a1
* Full wave: 256 bytes
lea WaveDeb(a2),a2
move.l a2,a0
moveq #256/4-1,d0
NeW2 move.l (a1)+,(a0)+
dbra d0,NeW2
* 1/2
move.l a2,a1
move.l a0,a2
moveq #127,d0
bsr NewRout
* 1/4
move.l a2,a1
move.l a0,a2
moveq #63,d0
bsr NewRout
* 1/8
move.l a2,a1
move.l a0,a2
moveq #31,d0
bsr NewRout
* 1/16
move.l a2,a1
move.l a0,a2
moveq #15,d0
bsr NewRout
* 1/32
move.l a2,a1
move.l a0,a2
moveq #7,d0
bsr NewRout
* 1/64
move.l a2,a1
move.l a0,a2
moveq #3,d0
bsr NewRout
******* No error
moveq #0,d0
NeWx movem.l (sp)+,d1-d7/a1-a2
rts
******* Out of mem
NeWE moveq #-1,d0
bra.s NeWx
******* Divide a sample by 2
NewRout move.b (a1)+,d1
ext.w d1
move.b (a1)+,d2
ext.w d2
add.w d2,d1
asr.w #1,d1
move.b d1,(a0)+
dbra d0,NewRout
rts
******* Get a wave address
L_WaveAd: equ 55
L55 moveq #0,d2
Dlea WaveBase,a2
move.l (a2),d0
beq.s WAd2
WAd1 move.l a2,d2
move.l d0,a2
cmp.w WaveNb(a2),d1
beq.s WAd3
move.l (a2),d0
bne.s WAd1
WAd2 moveq #0,d0
rts
WAd3 moveq #-1,d0
rts
******* Deletion of a WAVE (A2)-D2
L_WaveDel equ 56
L56 movem.l a0-a2/d0-d2,-(sp)
move.w WaveNb(a2),d1
move.l d2,a0
move.l (a2),(a0)
move.l #WaveLong,d0
move.l a2,a1
Rjsr L_RamFree
movem.l (sp)+,a0-a2/d0-d2
rts
***********************************************************
* STOP SAMPLES INTERRUPTS
L_Sami_stop equ 57
L57 move.w #%0000011110000000,d0
move.w d0,Circuits+IntEna
move.w d0,Circuits+IntReq
rts
***********************************************************
* ENVELOPPES
***********************************************************
* STOP ENVELOPPE D0
L_EnvOff equ 58
L58 movem.l d0-d3/a0,-(sp)
move.w EnvOn-MB(a3),d1
clr.w EnvOn-MB(a3)
moveq #0,d3
lea Circuits,a0
moveq #0,d2
EOf1 btst d2,d0
beq.s EOf2
bclr d2,d1
beq.s EOf2
bset d2,d3
move.w #2,$a4(a0)
clr.w $a8(a0)
EOf2 lea $10(a0),a0
addq.w #1,d2
cmp.w #4,d2
bcs.s EOf1
move.w d1,EnvOn-MB(a3)
move.w d3,MuReStart-MB(a3)
movem.l (sp)+,d0-d3/a0
rts
******* Next enveloppe
L_MuIntE equ 59
L59 move.l EnvAd(a0),a1
MuIe0 move.w (a1)+,d3
beq.s MuIntS
bmi.s MuIe1
move.w d3,EnvNb(a0)
move.w EnvDVol(a0),d4
mulu (a1)+,d4
lsr.w #6,d4
sub.w EnvVol(a0),d4
ext.l d4
lsl.w #8,d4
divs d3,d4
ext.l d4
lsl.l #8,d4
move.l d4,EnvDelta(a0)
clr.w EnvVol+2(a0)
move.l a1,EnvAd(a0)
rts
* Loop
MuIe1 move.l EnvDeb(a0),a1
bra.s MuIe0
* End of a voice
MuIntS bset d1,d5
bclr d1,d0
bclr d1,Noise-MB(a3)
* Restarts the music
bset d1,MuReStart+1-MB(a3)
rts
******************************************************************
* MUSIC
******* Music initialisation
L_MuInit: equ 60
L60 clr.l MuBase-MB(a3)
clr.w MuNumber-MB(a3)
move.l #$DFF0A0,MuChip0-MB(a3)
move.l #$DFF0B0,MuChip1-MB(a3)
move.l #$DFF0C0,MuChip2-MB(a3)
move.l #$DFF0D0,MuChip3-MB(a3)
move.w #$000F,MuDMAsk-MB(a3)
clr.w MuReStart-MB(a3)
Rbra L_MOff
******* MUSIC OFF-> Stops all musics
L_IMuSOff equ 61
L61 movem.l a0-a3/d0-d1,-(sp)
Dload a3
clr.l MuBase-MB(a3)
clr.w MuNumber-MB(a3)
Rbsr L_MOff
movem.l (sp)+,a0-a3/d0-d1
rts
******* MUSIC STOP-> Stops current music
L_IMuStop equ 62
L62 movem.l a0-a3/d0-d1,-(sp)
Dload a3
move.l MuBase-MB(a3),d0
beq.s IStp
clr.w MuBase-MB(a3)
move.l d0,a0
clr.w VoiCpt0(a0)
clr.w VoiCpt1(a0)
clr.w VoiCpt2(a0)
clr.w VoiCpt3(a0)
move.l d0,MuBase-MB(a3)
IStp movem.l (sp)+,a0-a3/d0-d1
rts
******* MUSIC VOLUME
L_IMVol equ 63
L63 move.l (a3)+,d0
cmp.l #64,d0
Rbcs L_MVol
Rbcc L_IFonc
* Set volume
L_MVol equ 64
L64 and.w #63,d0
Dload a0
move.w d0,MuVolume-MB(a0)
move.l MuBase-MB(a0),d4
beq.s MVol3
clr.l MuBase-MB(a0)
lea MuBuffer-MB(a0),a1
move.w MuNumber-MB(a0),d1
MVol0 move.l a1,a2
moveq #3,d2
MVol1 move.w VoiDVol(a2),d3
mulu d0,d3
lsr.w #6,d3
move.w d3,VoiVol(a2)
lea VoiLong(a2),a2
dbra d2,MVol1
MVol2 lea MuLong(a1),a1
subq.w #1,d1
bne.s MVol0
move.l d4,MuBase-MB(a0)
MVol3 rts
******* VOICE ON/OFF Voices
L_IVoice equ 65
L65 move.l (a3)+,d0
and.w #$000F,d0
move.l a3,-(sp)
Dload a3
Rbsr L_VOnOf
movem.l (sp)+,a3
rts
******* Start / Stop voices D0
L_VOnOf equ 66
L66 movem.l d0-d5/a0-a3,-(sp)
move.w d0,d4
Dload a3
move.l MuBase-MB(a3),d1
beq.s VooX
clr.l MuBase-MB(a3)
move.l d1,a1
move.l d1,a2
move.w MuDMAsk-MB(a3),d1
move.w d0,MuDMAsk-MB(a3)
move.l WaveBase-MB(a3),a0
lea WaveDeb(a0),a0
move.l a0,d3
lea MuChip0-MB(a3),a0
moveq #0,d2
moveq #0,d4
* Exploration loop
Voo1 btst d2,d0
bne.s Voo2
* Stop a voice!
btst d2,d1 * Already stopped?
beq.s VooN
bset d2,d4
move.l d3,(a0)
bclr d2,MuStart+1(a2)
bclr d2,MuStop+1(a2)
bra.s VooN
* Re start a voice
Voo2 btst d2,d1 * Already on?
bne.s VooN
bset d2,MuReStart+1-MB(a3)
* Next
VooN addq.l #4,a0
lea VoiLong(a1),a1
addq.w #1,d2
cmp.w #4,d2
bcs.s Voo1
* Stop them!
move.l a2,MuBase-MB(a3)
move.w d4,Circuits+DmaCon
VooX movem.l (sp)+,d0-d5/a0-a3
rts
******* MUSIC n
L_IMusic equ 67
L67 move.l (a3)+,d3
Rbls L_IFonc
* Points to the SONG
move.l a3,-(sp)
Dload a3
tst.l MusBank-MB(a3)
Rbeq L_MnRes
move.l BankSong-MB(a3),a1
cmp.w (a1),d3
Rbhi L_MNDef
lsl.w #2,d3
add.l 2-4(a1,d3.w),a1
* Still room?
cmp.w #3,MuNumber-MB(a3)
bcc IMusX
clr.l MuBase-MB(a3)
* Buffer address
move.w MuNumber-MB(a3),d0
move.w d0,d1
addq.w #1,MuNumber-MB(a3)
mulu #MuLong,d0
lea MuBuffer-MB(a3),a2
add.w d0,a2
* Init datas
moveq #(VoiLong*4)/2-1,d0
move.l a2,a0
IMus1 clr.w (a0)+
dbra d0,IMus1
clr.w MuStop(a2)
clr.w MuStart(a2)
* Init parameters
move.l a2,d2
move.w TempoBase-MB(a3),MuCpt(a2)
move.w #17,MuTempo(a2) *XXX
moveq #0,d0
IMus2 move.w #1,VoiCpt(a2)
lea FoEnd-MB(a3),a0
move.l a0,VoiAdr(a2)
move.l a1,a0
add.w 0(a0,d0.w),a0
move.l a0,VoiPat(a2)
move.l a0,VoiDPat(a2)
lea NoEffect2(pc),a0
move.l a0,VoiEffect(a2)
lea VoiLong(a2),a2
addq.w #2,d0
cmp.w #8,d0
bne.s IMus2
* No more samples
move.w #%0000011110000000,Circuits+IntEna
* Starts music
move.l d2,MuBase-MB(a3)
IMusX move.l (sp)+,a3
rts
NoEffect2
move.w VoiNote(a4),$06(a6)
rts
******* Tempo T
L_ITempo equ 68
L68 move.l (a3)+,d0
cmp.l #100,d0
Rbhi L_IFonc
Dload a0
move.l MuBase-MB(a0),d1
beq.s ITemp
move.l d1,a0
move.w d0,MuTempo(a0)
ITemp rts
***********************************************************
* =VU METRE(v)
L_FVu equ 69
L69 move.l (a3)+,d0
cmp.l #4,d0
Rbcc L_IFonc
Dload a0
moveq #0,d3
move.b 0(a0,d0.w),d3
clr.b 0(a0,d0.w)
moveq #0,d2
rts
***********************************************************
* =MU BASE
L_FMB equ 70
L70 Dload a0
move.l a0,d3
moveq #0,d2
rts
***********************************************************
* LED INSTRUCTION
L_LedOn equ 71
L71 bclr #1,$BFE001
rts
L_LedOf equ 72
L72 bset #1,$BFE001
rts
***********************************************************
* INSTALL THE SAMPLE HANDLER
L_Sami_install equ 73
L73 tst.w Sami_flag-MB(a3)
bne.s .skip
movem.l d0-d2/a0-a2/a6,-(sp)
move.l $4.w,a6
; Save state of interrupts
move.w Circuits+IntEnaR,d0
and.w #%0000011110000000,d0
move.w d0,Sami_OldEna-MB(a3)
Rbsr L_Sami_stop
; Install 4 voices
lea Sami_int-MB(a3),a1
moveq #7,d0
.loop bsr.s Sami_start
lea Sami_intl(a1),a1
addq.w #1,d0
cmp.w #11,d0
bne.s .loop
subq.w #1,Sami_flag-MB(a3)
movem.l (sp)+,d0-d2/a0-a2/a6
.skip rts
Sami_start
move.l a1,is_data(a1)
move.l Sami_handad-MB(a3),is_code(a1)
move.b #2,ln_type(a1)
move.b #0,ln_pri(a1)
move.l $4.w,a6
movem.l d0/a1,-(sp)
jsr -162(a6) SetIntVector
move.l d0,d1
movem.l (sp)+,d0/a1
move.l d1,Sami_old(a1)
rts
***********************************************************
* REMOVE THE SAMPLE HANDLER
L_Sami_remove equ 74
L74 tst.w Sami_flag-MB(a3)
beq.s .skip
movem.l a0-a2/a6/d0-d2,-(sp)
Rbsr L_Sami_Stop
move.l $4.w,a6
moveq #7,d2
lea Sami_Int-MB(a3),a2
.loop move.l Sami_old(a2),a1
move.l d2,d0
jsr -162(a6) SetIntVector
lea Sami_intl(a2),a2
addq.w #1,d2
cmp.w #11,d2
bne.s .loop
lea Circuits,a0
move.w #$000F,DmaCon(a0)
move.w Sami_oldena-MB(a3),IntEna(a0)
clr.w Sami_flag-MB(a3)
movem.l (sp)+,a0-a2/a6/d0-d2
.skip rts
***********************************************************
* Normal error messages
; This routines performs jump to the normal AMOS error messages:
; Load in D0 the number of the error, and do a RJmp to L_Error.
L_IOOMem equ 75
L75
moveq #24,d0
Rjmp L_Error
L_IFonc equ 76
L76 moveq #23,d0
Rjmp L_Error
***********************************************************
* Customized error messages
; This list of routines just load in D0 the number of the error message in
; the extension error-list, and call the error handling routine.
L_WNDef equ 77
L77 moveq #0,d0
Rbra L_Custom
L_SNDef equ 78
L78 moveq #1,d0
Rbra L_Custom
L_BNSam equ 79
L79 moveq #2,d0
Rbra L_Custom
L_STSho equ 80
L80 moveq #3,d0
Rbra L_Custom
L_W0Res equ 81
L81 moveq #4,d0
Rbra L_Custom
L_MnRes equ 82
L82 moveq #5,d0
Rbra L_Custom
L_MNDef equ 83
L83 moveq #6,d0
Rbra L_Custom
********************************************************************
* =SAM SWAPPED(V)
L_Samswapped equ 84
L84 move.l (a3)+,d0
moveq #0,d2
moveq #0,d3
cmp.l #3,d0
Rbhi L_IFonc
move.w Circuits+IntEnaR,d1
lsr.w #7,d1
btst d0,d1
beq.s .stop
Dlea Sami_int,a0
mulu #Sami_intl,d0
tst.l Sami_radr(a0,d0.l)
bne.s .skip
move.l Sami_pos(a0,d0.l),d1
cmp.l #Sami_lplay,d1
beq.s .skip
moveq #-1,d3
.skip rts
.stop moveq #1,d3
rts
*********************************************************************
* SAM SWAP
L_SamSwap equ 85
L85 move.l (a3)+,d4
Rbmi L_IFonc
move.l (a3)+,d0
Rjsr L_Bnk.OrAdr
move.l d0,d3
move.l (a3)+,d2
moveq #0,d1
Dlea Sami_int,a0
.loop btst d1,d2
beq.s .skip
move.l d3,Sami_radr(a0)
move.l d4,Sami_rlong(a0)
.skip lea Sami_intl(a0),a0
addq.w #1,d1
cmp.w #4,d1
bne.s .loop
rts
*********************************************************************
* SAM STOP
L_SamStop0 equ 86
L86 move.l #$f,-(a3)
RBra L_SamStop1
L_SamStop1 equ 87
L87 move.l (a3)+,d1
and.l #$F,d1
move.w d1,Circuits+DmaCon
lsl.w #7,d1
move.w d1,Circuits+IntEna
rts
*********************************************************************
* TRACKER instructions
******* TRACK LOAD "nom",banque
L_Trackload equ 88
L88
move.l (a3)+,d3
cmp.l #$10000,d3
Rbge L_IFonc
Dload a0
cmp.w Track_Bank-MB(a0),d3
bne.s .kkk
tst.b mt_on-MB(a0)
beq.s .kkk
RBsr L_TrackStop
.kkk move.w d3,Track_Bank-MB(a0) * Numero de la banque
move.l d3,-(sp)
; Get name to load
; ~~~~~~~~~~~~~~~~
move.l (a3)+,a0
move.w (a0)+,d0
subq.w #1,d0
cmp.w #128,d0
Rbcc L_IFonc
move.l Name1(a5),a1
.loop move.b (a0)+,(a1)+
dbra d0,.loop
clr.b (a1)
Rjsr L_Dsk.PathIt
; Open the file
; ~~~~~~~~~~~~~
move.l Name1(a5),d1
move.l #1005,d2
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr -30(a6) DosOpen, fichier sons
move.l (sp)+,a6
move.l d0,d7
Rbeq L_IDError
move.l d7,d1 Trouve la taille
bsr .taille
move.l d0,d6
; Reserve the bank
; ~~~~~~~~~~~~~~~~
move.l (sp)+,d0 Numero
moveq #(1<<Bnk_BitData+1<<Bnk_BitChip),d1 Flag
move.l d6,d2 Taille
lea BkTrack(pc),a0 Nom
Rjsr L_Bnk.Reserve
beq .mem
; Load the music
; ~~~~~~~~~~~~~~
move.l d7,d1
move.l a0,d2
move.l d6,d3
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr -42(a6) Read
move.l (sp)+,a6
move.l d0,d2
move.l d7,d1
bsr .clo
cmp.l d2,d3
Rbne L_IFonc
rts
* Close the file
.clo movem.l a6/a0/a1,-(sp)
move.l DosBase(a5),a6
jsr -36(a6) Close
movem.l (sp)+,a6/a0/a1
rts
* Out of memory
.mem move.l d7,d1
bsr.s .clo
RBra L_IOOMem
* Find the size of the file
.taille move.l a6,-(sp)
move.l d1,-(sp)
moveq #0,d2
moveq #1,d3
move.l DosBase(a5),a6
jsr -66(a6) DosSeek
move.l (sp)+,d1
move.l d0,d2
moveq #-1,d3
move.l DosBase(a5),a6
jsr -66(a6) DosSeek
move.l (sp)+,a6
rts
BkTrack dc.b "Tracker "
even
******* TRACK CHECK, arrete la musique si pas banque...
L_TrackCheck equ 89
L89 movem.l a0-a1,-(sp)
DLoad a1
tst.b mt_on-MB(a1)
beq.s .skip
move.l mt_data-MB(a1),a0
cmp.l #"ker ",-(a0)
bne.s .stop
cmp.l #"Trac",-(a0)
beq.s .skip
.stop RBsr L_TrackStop
.skip movem.l (sp)+,a0-a1
rts
******* TRACK STOP
L_TrackStop equ 90
L90 move.l a0,-(sp)
Dload a0
tst.b mt_on-MB(a0)
beq.s .Skip
clr.b mt_on-MB(a0)
moveq #0,d0
lea $dff000,a0
move.w d0,$a8(a0)
move.w d0,$b8(a0)
move.w d0,$c8(a0)
move.w d0,$d8(a0)
move.w #$f,$dff096
.Skip move.l (sp)+,a0
rts
******* TRACK LOOP ON/OFF
L_TrackLoopon equ 91
L91 rts
L_TrackLoopof equ 92
L92 rts
******* TRACK PLAY [Bank],[Pattern]
L_TrackPlay0 equ 93
L93
move.l #Entnul,-(a3)
Rbra 94
L_TrackPlay1 equ 94
L94
move.l #Entnul,-(a3)
Rbra 95
L_TrackPlay2 equ 95
L95
move.l (a3)+,d7
cmp.l #Entnul,(a3)
bne.s .skip
Dload a0
moveq #0,d0
move.w Track_Bank-MB(a0),d0
move.l d0,(a3)
.skip
move.l (a3)+,d0
Rjsr L_Bnk.OrAdr
move.l d0,a2
cmp.l #"Trac",-8(a2)
bne .nobank
cmp.l #"ker ",-4(a2)
bne .nobank
Rbsr L_SamStop0
Rbsr L_TrackStop
; Init music...
; ~~~~~~~~~~~~~
move.l a3,-(sp)
Dload a3
move.l a2,a0
move.l a0,mt_data-MB(a3)
lea mt_mulu-MB(a3),a1
moveq #$0c,d0
add.l a0,d0
moveq #$1f,d1
moveq #$1e,d3
.lop4 move.l d0,(a1)+
add.l d3,d0
dbf d1,.lop4
lea $3b8(a0),a1
moveq #$7f,d0
moveq #0,d1
moveq #0,d2
.lop2 move.b (a1)+,d1
cmp.b d2,d1
ble.s .lop
move.l d1,d2
.lop dbf d0,.lop2
addq.w #1,d2
asl.l #8,d2
asl.l #2,d2
lea 4(a1,d2.l),a2
lea mt_samplestarts-MB(a3),a1
add.w #$2a,a0
moveq #$1e,d0
.lop3 clr.l (a2)
move.l a2,(a1)+
moveq #0,d1
move.b d1,2(a0)
move.w (a0),d1
asl.l #1,d1
add.l d1,a2
add.l d3,a0
dbf d0,.lop3
move.b #6,mt_speed-mt_samplestarts-$7c(a1)
moveq #0,d0
lea $dff000,a0
move.w d0,$a8(a0)
move.w d0,$b8(a0)
move.w d0,$c8(a0)
move.w d0,$d8(a0)
move.b d0,mt_songpos-mt_samplestarts-$7c(a1)
move.b d0,mt_counter-mt_samplestarts-$7c(a1)
move.w d0,mt_pattpos-mt_samplestarts-$7c(a1)
; Demarage de la musique!
; ~~~~~~~~~~~~~~~~~~~~~~~
move.b #1,mt_on-MB(a3)
move.l (sp)+,a3
rts
* Pas un module tracker
.nobank moveq #8,d0
Rbra L_Custom
******* Erreur disque
L_IDError equ 96
L96 move.w #DEBase+15,d0
Rjmp L_Error
******* Routine, demande la bouche du narrator
L_Lips equ 97
L97 Dload a2
tst.l TranBase-MB(a2)
beq.s .Err
move.l WriteIo-MB(a2),d0
beq.s .Err
move.l d0,a0
tst.b 66(a0)
beq.s .Err
lea ReadIo-MB(a2),a1
move.w #2,28(a1) CMD_READ
move.l a6,-(sp)
move.l $4.w,a6
jsr DoIO(a6)
move.l (sp)+,a6
lea ReadIo-MB(a2),a1
cmp.b #-8,$1f(a1) ND_NOWRITE
beq.s .Err
rts
.Err lea ReadIo-MB(a2),a0
move.w #-1,88(a0)
rts
*********************************************************************
* AMIGA.LIB linked code.
* In order to make it relocatable, I have been
* obliged to disassemble the code and include it in this
* routine.
L_Amiga.Lib equ 98
L98 lsl.w #2,d0
lea JJJmp(pc),a0
jmp 0(a0,d0.w)
JJJmp bra _CreatePort
bra _DeletePort
bra _CreateExtIO
bra _DeleteExtIO
_CreatePort
MOVEM.L D2-7/A2,-(A7)
MOVE.L $20(A7),D4
MOVE.B $27(A7),D3
MOVE.L #$FFFFFFFF,-(A7)
BSR L7C7DB14
MOVE.L D0,D5
MOVE.L D5,D6
MOVEQ #-1,D2
CMP.L D5,D2
ADDQ.L #4,A7
BNE.S L7C7D97A
MOVEQ #0,D0
BRA L7C7D9E6
L7C7D97A MOVE.L #$10001,-(A7)
PEA $22.W
BSR L7C7DAD0
MOVEA.L D0,A2
EXG D7,A2
TST.L D7
EXG D7,A2
ADDQ.L #8,A7
BNE.S L7C7D9A4
MOVE.L D6,-(A7)
BSR L7C7DB28
MOVEQ #0,D0
ADDQ.L #4,A7
BRA.S L7C7D9E6
L7C7D9A4 MOVE.L D4,$A(A2)
MOVE.B D3,9(A2)
MOVE.B #4,8(A2)
CLR.B $E(A2)
MOVE.B D6,$F(A2)
CLR.L -(A7)
BSR L7C7DB00
MOVE.L D0,$10(A2)
TST.L D4
ADDQ.L #4,A7
BEQ.S L7C7D9D8
MOVE.L A2,-(A7)
BSR L7C7DB3C
ADDQ.L #4,A7
BRA.S L7C7D9E4
L7C7D9D8 PEA $14(A2)
BSR _NewList
ADDQ.L #4,A7
L7C7D9E4 MOVE.L A2,D0
L7C7D9E6 MOVEM.L (A7)+,D2-7/A2
RTS
_DeletePort
MOVEM.L D2/A2,-(A7)
MOVEA.L $C(A7),A2
TST.L $A(A2)
BEQ.S L7C7DA04
MOVE.L A2,-(A7)
BSR L7C7DB50
ADDQ.L #4,A7
L7C7DA04 MOVE.B #$FF,8(A2)
MOVEQ #-1,D2
MOVE.L D2,$14(A2)
MOVEQ #0,D2
MOVE.B $F(A2),D2
MOVE.L D2,-(A7)
BSR L7C7DB28
PEA $22.W
MOVE.L A2,-(A7)
BSR L7C7DAE8
LEA $C(A7),A7
MOVEM.L (A7)+,D2/A2
RTS
_CreateExtIO
MOVEM.L D2-4,-(A7)
MOVE.L $10(A7),D2
MOVE.L $14(A7),D3
TST.L D2
BNE.S L7C7DA54
MOVEQ #0,D0
BRA.S L7C7DA82
L7C7DA54 MOVE.L #$10001,-(A7)
MOVE.L D3,-(A7)
BSR L7C7DAD0
MOVEA.L D0,A0
EXG D4,A0
TST.L D4
EXG D4,A0
ADDQ.L #8,A7
BNE.S L7C7DA72
MOVEQ #0,D0
BRA.S L7C7DA82
L7C7DA72 MOVE.B #5,8(A0)
MOVE.W D3,$12(A0)
MOVE.L D2,$E(A0)
MOVE.L A0,D0
L7C7DA82 MOVEM.L (A7)+,D2-4
RTS
_DeleteExtIO
MOVEM.L D2-3,-(A7)
MOVEA.L $C(A7),A0
EXG D3,A0
TST.L D3
EXG D3,A0
BEQ L7C7DABE
MOVE.B #$FF,8(A0)
MOVEQ #-1,D2
MOVE.L D2,$14(A0)
MOVEQ #-1,D2
MOVE.L D2,$18(A0)
MOVEQ #0,D2
MOVE.W $12(A0),D2
MOVE.L D2,-(A7)
MOVE.L A0,-(A7)
BSR L7C7DAE8
ADDQ.L #8,A7
L7C7DABE MOVEM.L (A7)+,D2-3
RTS
L7C7DAD0
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVEM.L 8(A7),D0-1
JSR -$C6(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DAE8
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVEA.L 8(A7),A1
MOVE.L $C(A7),D0
JSR -$D2(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DB00
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVEA.L 8(A7),A1
JSR -$126(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DB14
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVE.L 8(A7),D0
JSR -$14A(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DB28
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVE.L 8(A7),D0
JSR -$150(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DB3C
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVEA.L 8(A7),A1
JSR -$162(A6)
MOVEA.L (A7)+,A6
RTS
L7C7DB50
MOVE.L A6,-(A7)
MOVEA.L $4.w,A6
MOVEA.L 8(A7),A1
JSR -$168(A6)
MOVEA.L (A7)+,A6
RTS
_NewList
move.l 4(a7),a0
move.l a0,(a0)
addq.l #4,(a0)
clr.l 4(a0)
move.l a0,8(a0)
rts
******* TALK MISC volume,freq
L_TalkMisc equ 99
L99 Rbsr L_OpNar
move.l #EntNul,d0
Dload a1
move.l WriteIo-MB(a1),a1
move.l (a3)+,d1
cmp.l d0,d1
beq.s .IRd0
cmp.w #5000,d1
Rbcs L_IFonc
cmp.w #25000,d1
Rbhi L_IFonc
move.w d1,64(a1)
.IRd0
move.l (a3)+,d1
cmp.l d0,d1
beq.s .IRd1
tst.l d1
RBmi L_IFonc
cmp.w #64,d1
Rbhi L_IFonc
move.w d1,62(a1)
.IRd1
rts
*********************************************************************
* SSAVE fichier,adresse To fin
L_SSave equ 100
L100 move.l (a3)+,d3 End adress
move.l (a3)+,d2 Start Adress
sub.l d2,d3
RBle L_IFonc
move.l (a3)+,d0 File
cmp.l #10,d0
Rbcc L_IFonc
subq.l #1,d0
Rbmi L_IFonc
mulu #TFiche,d0
lea Fichiers(a5),a2
add.w d0,a2
move.l Fha(a2),d1
Rbeq L_IFonc
btst #2,FhT(a2)
Rbne L_IFonc
* Save the data
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr _LVOWrite(a6)
move.l (sp)+,a6
tst.l d0
RBmi L_IDError
rts
; ___________________________________________________________________
;
; MED instructions
; ___________________________________________________________________
; MED LOAD "nom",banque
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedLoad equ 101
L101 Rbsr L_MedOpen
move.l (a3)+,d3
cmp.l #$10000,d3
Rbge L_IFonc
Dload a2
cmp.w Med_Bank-MB(a2),d3
bne.s .k
Rbsr L_MedStop
.k move.w d3,Med_Bank-MB(a2) * Numero de la banque
; Get name to load
; ~~~~~~~~~~~~~~~~
move.l (a3)+,a0
move.w (a0)+,d0
subq.w #1,d0
cmp.w #128,d0
Rbcc L_IFonc
move.l Name1(a5),a1
.loop move.b (a0)+,(a1)+
dbra d0,.loop
clr.b (a1)
Rjsr L_Dsk.PathIt
; Trouve la taille
; ~~~~~~~~~~~~~~~~
move.l Name1(a5),d1
move.l #1005,d2
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr -30(a6) DosOpen,
move.l (sp)+,a6
move.l d0,d7
Rbeq L_IDError
move.l d7,d1 Trouve la taille
bsr .taille
move.l d0,d6
; Reserve la banque
; ~~~~~~~~~~~~~~~~~
move.w Med_Bank-MB(a2),d0 Numero de la banque
ext.l d0
moveq #(1<<Bnk_BitChip),d1 Flag CHIP
move.l d6,d2
addq.l #8,d2 Taille
lea .BkMed(pc),a0 Nom
Rjsr L_Bnk.Reserve
beq .mem
move.l a0,a2
; Charge la musique
; ~~~~~~~~~~~~~~~~~
move.l d7,d1
move.l a2,d2
move.l d6,d3
move.l a6,-(sp)
move.l DosBase(a5),a6
jsr -42(a6) Read
move.l (sp)+,a6
move.l d0,d2
move.l d7,d1
bsr .clo
cmp.l d2,d3
Rbne L_IFonc
cmp.l #"MMD0",(a2)
beq.s .ok
cmp.l #"MMD1",(a2)
bne.s .med
; Relocation du module
; ~~~~~~~~~~~~~~~~~~~~
.ok move.l a6,-(sp)
Dload a0
move.l Med_Base-MB(a0),a6
move.l a2,a0
jsr _MEDRelocModule(a6)
move.l (sp)+,a6
rts
* Ferme le fichier
.clo movem.l a6/a0/a1,-(sp)
move.l DosBase(a5),a6
jsr -36(a6) Close
movem.l (sp)+,a6/a0/a1
rts
* Out of memory
.mem move.l d7,d1
beq.s .xx
bsr.s .clo
.xx Rbra L_IOOMem
* Not a MED file
.med Dlea Med_Bank,a0
move.w (a0),d0
ext.l d0
Rjsr L_Bnk.Eff
move.w #189,d0
Rjmp L_Error
* Routine, trouve la taille d'un fichier
.taille move.l a6,-(sp)
move.l d1,-(sp)
moveq #0,d2
moveq #1,d3
move.l DosBase(a5),a6
jsr -66(a6) DosSeek
move.l (sp)+,d1
move.l d0,d2
moveq #-1,d3
move.l DosBase(a5),a6
jsr -66(a6) DosSeek
move.l (sp)+,a6
rts
.BkMed dc.b "Med "
even
; MED CHECK, arrete la musique si pas banque...
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedCheck equ 102
L102 movem.l d0/a0-a1,-(sp)
DLoad a1
tst.b Med_On-MB(a1)
beq.s .skip
move.l Med_Adr-MB(a1),d0
beq.s .skip
move.l d0,a0
cmp.l #"Med ",-(a0)
bne.s .stop
cmp.l #" ",-(a0)
beq.s .skip
.stop Rbsr L_MedStop
clr.l Med_Adr-MB(a1)
.skip movem.l (sp)+,d0/a0-a1
rts
; MED STOP
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedStop equ 103
L103 movem.l a0-a2/a6/d0-d2,-(sp)
Dload a0
tst.b Med_On-MB(a0)
beq.s .NoMed
clr.b Med_On-MB(a0)
move.l Med_Base-MB(a0),a6
jsr _MEDStopPlayer(a6)
.NoMed movem.l (sp)+,a0-a2/a6/d0-d2
rts
; MED PLAY [Bank],[Song]
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedPlay0 equ 104
L104 move.l #EntNul,-(a3)
Rbra L_MedPlay1
L_MedPlay1 equ 105
L105 move.l #EntNul,-(a3)
Rbra L_MedPlay2
L_MedPlay2 equ 106
L106 Dload a2 Arret d'une eventuelle musique
Rbsr L_MedOpen Ouvre la librairie, s'il faut
Rbsr L_MedStop
clr.l Med_Adr-MB(a2)
; Verification de la banque
; ~~~~~~~~~~~~~~~~~~~~~~~~~
move.l (a3)+,d7
cmp.l #Entnul,(a3)
bne.s .skip
moveq #0,d0
move.w Med_Bank-MB(a2),d0
move.l d0,(a3)
.skip move.l (a3)+,d0
Rjsr L_Bnk.OrAdr
move.l d0,a2
cmp.l #"Med ",-8(a2)
bne .nobank
cmp.l #" ",-4(a2)
bne .nobank
; Arret de tous les sons...
; ~~~~~~~~~~~~~~~~~~~~~~~~~
Rbsr L_SamStop0
Rbsr L_TrackStop
Rbsr L_MedStop
; Pointe la chanson
; ~~~~~~~~~~~~~~~~~
movem.l a3/a6,-(sp)
Dload a3
moveq #0,d0
cmp.l #Entnul,d7
beq.s .skp
move.l d7,d0
.skp move.l Med_Base-MB(a3),a6
jsr _MEDSetModnum(a6)
; Demarre la chanson
; ~~~~~~~~~~~~~~~~~~
move.l a2,a0
jsr _MEDPlayModule(a6)
move.l a2,Med_Adr-MB(a3)
move.b #1,Med_On-MB(a3)
; Termin<69>
; ~~~~~~~
movem.l (sp)+,a3/a6
rts
; Pas une banque MED
; ~~~~~~~~~~~~~~~~~~
.nobank moveq #8,d0
Rbra L_Custom
; Ouvre la librairie MED
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedOpen equ 107
L107 movem.l a0-a2/d0-d2,-(sp)
Dload a2
tst.l Med_Base-MB(a2)
bne.s .Open
lea Med_Name-MB(a2),a1
moveq #2,d0 2 et pas 3!!!!!!!!!!!!!!!!!!!!
move.l a6,-(sp)
move.l $4.w,a6
jsr _LVOOpenLibrary(a6)
move.l (sp)+,a6
move.l d0,Med_Base-MB(a2)
beq.s .Err1
moveq #0,d0
move.b Med_Midi-MB(a2),d0
move.l a6,-(sp)
move.l Med_Base-MB(a2),a6
jsr _MEDGetPlayer(a6)
move.l (sp)+,a6
tst.l d0
bne .Err2
.Open movem.l (sp)+,a0-a2/d0-d2
rts
.Err1 move.w #187,d0 Cannot load med.lib
Rjmp L_Error
.Err2 Rbsr L_MedClose Cannot initialise med.lib
move.w #188,d0
Rjmp L_Error
; MED MIDI ON / OFF
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedMidiOn equ 108
L108 Dlea Med_Midi,a0
move.b #1,(a0)
rts
L109
; MED CLOSE
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedClose equ 110
L110 movem.l a0-a2/a6/d0-d2,-(sp)
Rbsr L_MedStop
Dload a2
clr.b Med_Midi-MB(a2)
clr.l Med_Adr-MB(a2)
move.l Med_Base-MB(a2),d0
beq.s .Skip
move.l d0,a6
jsr _MEDFreePlayer(a6)
move.l Med_Base-MB(a2),a1
clr.l Med_Base-MB(a2)
move.l $4.w,a6
jsr _LVOCloseLibrary(a6)
.Skip movem.l (sp)+,a0-a2/a6/d0-d2
rts
; MED CONT
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L_MedCont equ 111
L111 movem.l a0-a2/a6/d0-d2,-(sp)
Dload a0
move.l Med_Adr-MB(a0),d0
beq.s .Skip
tst.b Med_On-MB(a0)
bne.s .Skip
move.b #1,Med_On-MB(a0)
move.l Med_Base-MB(a0),a6
move.l d0,a0
jsr _MEDContModule(a6)
.Skip movem.l (sp)+,a0-a2/a6/d0-d2
rts
*********************************************************************
* ERROR MESSAGES...
;
; You know that the compiler have a -E1 option (with errors) and a
; a -E0 (without errors). To achieve that, the compiler copies one of
; the two next routines, depending on the -E flag. If errors are to be
; copied along with the program, then the next next routine is used. If not,
; then the next one is copied.
; The compiler assumes that the two last routines in the library handles
; the errors: the previous last is WITH errors, the last is WITHOUT. So,
; remember:
;
; THESE ROUTINES MUST BE THE LAST ONES IN THE LIBRARY
;
; The AMOS interpretor always needs errors. So make all your custom errors
; calls point to the L_Custom routine, and everything will work fine...
;
******* "With messages" routine.
; The following routine is the one your program must call to output
; a extension error message. It will be used under interpretor and under
; compiled program with -E1
L_Custom equ 112
L112 lea ErrMess(pc),a0
moveq #0,d1 * Can be trapped
moveq #ExtNb,d2 * Number of extension
moveq #0,d3 * IMPORTANT!!!
RJmp L_ErrorExt * Jump to routine...
* Messages...
ErrMess dc.b "Wave not defined",0 *0
dc.b "Sample not defined",0 *1
dc.b "Sample bank not found",0 *2
dc.b "256 characters for a wave",0 *3
dc.b "Wave 0 and 1 are reserved",0 *4
dc.b "Music bank not found",0 *5
dc.b "Music not defined",0 *6
dc.b "Can't open narrator",0 *7
dc.b "Not a tracker module",0 *8
* IMPORTANT! Always EVEN!
even
******* "No errors" routine
; If you compile with -E0, the compiler will replace the previous
; routine by this one. This one just sets D3 to -1, and does not
; load messages in A0. Anyway, values in D1 and D2 must be valid.
;
; THIS ROUTINE MUST BE THE LAST ONE IN THE LIBRARY!
;
L113 moveq #0,d1
moveq #ExtNb,d2
moveq #-1,d3
RJmp L_ErrorExt
; Do not forget the last label to delimit the last library routine!
L114
; ---------------------------------------------------------------------
; Now the title of the extension, just the string.
;
; TITLE MESSAGE
C_Title dc.b "AMOSPro Music extension V "
Version
dc.b 0,"$VER: "
Version
dc.b 0
Even
;
; Note : magic title!
; ~~~~~~~~~~~~~~~~~~~
; If your extension begins with "MAGIC***", AMOSPro will call the
; address located after the string (even of course!). You can do whatever
; you want to the editor screen (the current at the moment), but
; restore it.
; You also handle the user key press, and the PREVIOUS/NEXT/CANCEL
; selection, buy returning a number in D0:
; D0=-1 Cancel
; D0=0 Previous extension
; D0=1 Next extension
; Example of magic title:
; C_Title dc.b "MAGIC***"
; bra Magic_Title
; END OF THE EXTENSION
C_End dc.w 0
even