;--------------------------------------------------------------------- ; ** ** ** *** *** **** ** *** ** **** ; **** *** *** ** ** ** ** ** **** ** ** ** ** ; ** ** ** * ** ** ** *** ***** ** ** *** ** ** ; ****** ** ** ** ** ** ** ** ****** ** ** ** ; ** ** ** ** ** ** * ** ** ** ** ** * ** ** ** ** ; ** ** ** ** *** *** ***** ** ** *** ** **** ;--------------------------------------------------------------------- ; 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écé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<