home *** CD-ROM | disk | FTP | other *** search
/ AMOS PD CD / amospdcd.iso / 551-575 / apd560 / amoner5 / editor / amos_&_asm.txt < prev    next >
Text File  |  1993-11-29  |  21KB  |  625 lines

  1. .                              AMOS & ASSEMBLER
  2. .                                     by
  3. .                               Michael D. Cox
  4. --------------------------------------------------------------------------
  5.     Before we begin, you need to have either a commercial or PD assembler.
  6. For PD, there is A68k.  For commercial, there are several.  DevPac II/III,
  7. CAPE 68k, ASSEMPRO (don't go near this one), and even the AMOS Assembler.
  8. I use DevPac II (hope to have III soon) as it is easy and fast.  Besides,
  9. all the great programmers use it!!!
  10.     A68k is a good assembler also.  Heck, it's free!  It is available on the
  11. Fish disks and probably many bulletin board systems.  I will even try and
  12. have it included on this issue of the AMONER disk.  If not and you don't mind
  13. spending a few bucks for postage, mail me a disk or two and I will send it
  14. to you without charging return postage.
  15.     You'll also need a good Amiga Programmer's book.  Something like the
  16. RKMs, Amiga Programmer's Handbook Vol. I & II (SYBEX), or Amiga System
  17. Programmer's Guide (ABACUS).  You will need one of these because they
  18. explain the libraries and how the work.  They also tell you what the offset
  19. is for each function in a library.  You need these offsets for use with
  20. the EXECALL, DOSCALL, etc. commands.
  21.     Next, you need to become familiar with some of the AMOS commands that
  22. deal with the assembler routines.  They are on pages 285 to 287 in the AMOS
  23. manual.
  24.  
  25.     -   PLOAD "fielname",bank
  26.         This will load your compiled assembler program into bank.  No need
  27.         to reserve the bank first, but make sure you don't use a reserved
  28.         one (like 1 to 4).  Once loaded with PLOAD, the assembler routines
  29.         will be saved with your program!
  30.  
  31.     -   CALL bank[,params]
  32.         This executes your program at bank.  Params
  33.         are the arguments passed to your routines.  Thoroughly read the
  34.         manual and what it says about Params and the registers.
  35.  
  36.     -   =AREG= and =DREG=
  37.         These arrays let you set the registers used in your routines.
  38.         However, for the AREG, only 0, 1, and 2 are passed when you
  39.         CALL your routine.  All of the DREGs are passed when CALL is
  40.         executed.
  41.  
  42. Timeout for a little assembler lesson:
  43.  
  44. You have two types of registers:  ADDRESS and DATA.  ADDRESS registers hold
  45. addresses of certain things.  They can hold the address of a variable, a
  46. buffer, a library, and so on.  They 'point' to where the data begins.
  47. When they point to a string variable, the string must end in a NULL or
  48. CHR$(0).
  49. DATA registers hold things like values.  Results of certain commands are
  50. returned in the DATA registers.  For instance, when you Open a Library,
  51. using the OpenLibrary function in exec.library, D0 will either contain
  52. a 0 if the OpenLibrary failed, or the starting address of where the
  53. library is located in memory.
  54.  
  55. As an example:  Let's open the medplayer.library.  First, we need to know
  56. what the OpenLibrary function requires in order to work.  I look in my RKMs
  57. or any of the Amiga programming manuals available that discuss the
  58. EXEC library for OpenLibrary.  Okay, here is the format:
  59.  
  60.     address = OpenLibrary(LibName,version)
  61.       D0    =               A1       D0
  62.  
  63. This tells me that when the OpenLibrary function is finished, it will return
  64. the results in D0.  And, I need to set A1 to where (an address) the
  65. name of the library is stored (a string variable).  In D0, I say which
  66. version of the library I want to use (We set it to 0, which means we will
  67. use any version).
  68.  
  69. Now, in AMOS, we would do this:
  70.  
  71. _OPENLIBRARY = -$228 : Rem             Offset of OpenLibrary function in EXEC
  72. A$="medplayer.library"+Chr$(0) : Rem   Null terminate the string
  73. NAME_POINTER = Varptr(A$) : Rem        Varptr tells me the address of A$
  74. Areg(1) = NAME_POINTER : Rem           Set A1 to address of the library name
  75. Dreg(0) = 0 : Rem                      Set D0 to 0 for any version
  76. R=Execall(_OPENLIBRARY)
  77.  
  78. Now, if R = 0, then it failed.  Otherwise, save R to a variable like
  79. MED_LIB_POINTER as it contains the address of where medplayer.library
  80. is located in memory.
  81.  
  82. Okay, enough rambling....
  83.  
  84.     You need to also become familiar with the DOSCALL, EXECALL, GFXCALL,
  85. and INTCALL functions.  And, on page 281, VARPTR is explained.
  86.  
  87.  
  88.     Okay, we are ready to continue once you are familiar with the above
  89. commands.  If not, keep your manual nearby (who doesn't?).
  90.  
  91.     So, we know how to open a library.  How do we close it?  Just as simple!
  92. We lookup CloseLibrary and find:
  93.  
  94.     CloseLibrary(library)
  95.                     A1
  96.  
  97. Which tells us??  Anyone, anyone?  Right, Johnny!  We put the address of
  98. where the library is located in A1.  No return value is expected, so nothing
  99. else needs to be done.  So, if we opened the library as above, we would do
  100. the following to close it:
  101.  
  102. Rem Use _CLOSELIBRARY as AMOS reserves Close
  103. _CLOSELIBRARY = -$19E : Rem          Offset of CloseLibrary in EXEC
  104. Areg(1)=MED_LIB_POINTER : Rem        Set A1 to address of library
  105. R=Execall(_CLOSELIBRARY) : Rem       Call the CloseLibrary function
  106. End
  107.  
  108. Now, if you typed the above segments into AMOS, make sure medplayer.library
  109. is in you LIBS: directory.  It is included on this AMONER disk and also disk
  110. 4.
  111.     So, what does this have to do with assembler?  Well, a lot, but it has
  112. nothing to do with our assembler.  So, first, we need to write a little
  113. assembler routine that will get the medplayer ready and one routine to
  114. get rid of the player.  The following routines were taken from the
  115. documentation for medplayer.library and have been subtly modified to work
  116. with AMOS.
  117.     Load up your assembler, type in each routine below and assemble it as an
  118. executable and re-locatable.
  119.  
  120. GetPlayer:
  121.     move.l  a6,-(sp) ; Save pointer to program on the stack pointer (SP)
  122.     movea.l a2,a6    ; Move address in A2 (MED_LIB_POINTER) into A6
  123.     jsr     -$1e(a6) ; Jump to the GetPlayer routine in medplayer.library
  124.     movea.l (sp)+,a6 ; Return program pointer back to A6
  125.     rts              ; Return control back to AMOS
  126.  
  127. FreePlayer:
  128.     move.l  a6,-(sp) ; Save pointer to program on the stack pointer (SP)
  129.     movea.l a2,a6    ; Move address in A2 (MED_LIB_POINTER) into A6
  130.     jsr     -$24(a6) ; Jump to the FreePlayer routine in medplayer.library
  131.     movea.l (sp)+,a6 ; Return program pointer back to A6
  132.     rts              ; Return control back to AMOS
  133.  
  134.  
  135. Okay, have you assembled these routines into seperate executables?  Good,
  136. let's load up AMOS.
  137.  
  138. Load in the _OPENLIBRARY and _CLOSELIBRARY program.  ESCape to Direct mode
  139. and load your two assembler routines into two separate banks.  I used Bank 9
  140. for GetPlayer and Bank 12 for FreePlayer.
  141.  
  142. For example:
  143.  
  144. AMOS> pload "ram:getplayer",9
  145. AMOS> pload "ram:freeplayer",12
  146.  
  147. Go back to the editor and save the program!  Remember, when dealing with
  148. unfamiliar territory, save before doing anything.
  149.  
  150. Now, we need to look at what the two medplayer.library functions need in
  151. order to work.
  152.  
  153. error = GetPlayer (midi)        Freeplayer()
  154. D0                 D0
  155.  
  156. So, GetPlayer returns a 0 to D0 if everything works fine.  Before CALLing
  157. GetPlayer, we set D0 to a 0 since we don't want any MIDI.
  158.  
  159. FreePlayer requires no arguments to work.
  160.  
  161. Make a mental note:  Even though the functions do not say they need the
  162. MED_LIB_POINTER, they always do.
  163.  
  164. Since A0 to A2 registers are passed when you CALL a routine, we will put
  165. MED_LIB_POINTER into A2.  You could use A0 or A1, but some functions will
  166. need to use those also.
  167.  
  168. Alright, we are ready to enter our AMOS Procedures to GetPlayer then
  169. FreePlayer.
  170.  
  171. Procedure _GET_PLAYER [LIB_POINTER,MIDI]
  172.     Dreg(0) = MIDI
  173.     Areg(2) = LIB_POINTER
  174.     Call 9
  175.     FLUBBED = Dreg(0)
  176.     If FLUBBED = 0
  177.         Print "Unable to GetPlayer.  Press any key to exit"
  178.         Wait Key
  179.         End
  180.     End If
  181. End Proc
  182.  
  183. Procedure _FREE_PLAYER [LIB_POINTER]
  184.     Areg(2) = LIB_POINTER
  185.     Call 12
  186.     Print "Player Freed.  Press any key to exit."
  187.     Wait Key
  188.     End
  189. End Proc
  190.  
  191.  
  192.  
  193. Now, when we call the procedures, we do:
  194.  
  195. _GETPLAYER[MIDI,MED_LIB_POINTER]
  196. ? "Press Any key to FreePlayer"
  197. Wait key
  198. _FREE_PLAYER [MED_LIB_POINTER]
  199.  
  200.  
  201. That's all there is to it, folks!  What's that, Bubba?  You want to load
  202. and play a MED Module?  Well, just go back to the menu and select the MED
  203. player!  If there is room, there should be a MED module on the disk.  You
  204. readers should write a player too.  Mail me the completed program and
  205. I will include them all on the next disk.
  206.  
  207. Below is all the MEDPlayer docs and assembler routines.  It contains all you
  208. need to know to write the routines and is the original that came with
  209. the original archive.
  210.  
  211.  
  212. So, mail me with your comments (good or bad)!!!
  213.  
  214.  
  215. Michael D. Cox
  216. 13600 EDS Drive
  217. MS A5N-B51
  218. Herndon, VA 22071
  219.  
  220. Email:  aj639@Cleveland.freenet.edu
  221. (Next issue, look for my review of Stephen Hill's book AMIGA GAME MAKER'S
  222. MANUAL (WITH AMOS BASIC) from SIGMA press.)
  223. ++++++++++++++++++++++++++++END+++++++++++++++++++++++++++++++++++++++++
  224. ; medplrlib_stub.a:     stub routines for calling medplayer.library from
  225. ;                       C-compilers which don't support direct library
  226. ;                       calling
  227.  
  228.         XREF    _MEDPlayerBase
  229.         XDEF    _GetPlayer
  230.         XDEF    _FreePlayer
  231.         XDEF    _PlayModule
  232.         XDEF    _ContModule
  233.         XDEF    _StopPlayer
  234.         XDEF    _DimOffPlayer
  235.         XDEF    _SetTempo
  236.         XDEF    _LoadModule
  237.         XDEF    _UnLoadModule
  238.         XDEF    _GetCurrentModule
  239.         XDEF    _ResetMIDI
  240.  
  241.         CODE
  242.  
  243. _GetPlayer:
  244.         MOVE.L  4(SP),D0
  245.         MOVE.L  A6,-(SP)
  246.         MOVEA.L _MEDPlayerBase,A6
  247.         JSR     -$1E(A6)
  248.         MOVEA.L (SP)+,A6
  249.         RTS
  250.  
  251. _FreePlayer:
  252.         MOVE.L  A6,-(SP)
  253.         MOVEA.L _MEDPlayerBase,A6
  254.         JSR     -$24(A6)
  255.         MOVEA.L (SP)+,A6
  256.         RTS
  257.  
  258. _PlayModule:
  259.         MOVEA.L 4(SP),A0
  260.         MOVE.L  A6,-(SP)
  261.         MOVEA.L _MEDPlayerBase,A6
  262.         JSR     -$2A(A6)
  263.         MOVEA.L (SP)+,A6
  264.         RTS
  265.  
  266. _ContModule:
  267.         MOVEA.L 4(SP),A0
  268.         MOVE.L  A6,-(SP)
  269.         MOVEA.L _MEDPlayerBase,A6
  270.         JSR     -$30(A6)
  271.         MOVEA.L (SP)+,A6
  272.         RTS
  273.  
  274. _StopPlayer:
  275.         MOVE.L  A6,-(SP)
  276.         MOVEA.L _MEDPlayerBase,A6
  277.         JSR     -$36(A6)
  278.         MOVEA.L (SP)+,A6
  279.         RTS
  280.  
  281. _DimOffPlayer:
  282.         MOVE.L  4(SP),D0
  283.         MOVE.L  A6,-(SP)
  284.         MOVEA.L _MEDPlayerBase,A6
  285.         JSR     -$3C(A6)
  286.         MOVEA.L (SP)+,A6
  287.         RTS
  288.  
  289. _SetTempo:
  290.         MOVE.L  4(SP),D0
  291.         MOVE.L  A6,-(SP)
  292.         MOVEA.L _MEDPlayerBase,A6
  293.         JSR     -$42(A6)
  294.         MOVEA.L (SP)+,A6
  295.         RTS
  296.  
  297. _LoadModule:
  298.         MOVEA.L 4(SP),A0
  299.         MOVE.L  A6,-(SP)
  300.         MOVEA.L _MEDPlayerBase,A6
  301.         JSR     -$48(A6)
  302.         MOVEA.L (SP)+,A6
  303.         RTS
  304.  
  305. _UnLoadModule:
  306.         MOVEA.L 4(SP),A0
  307.         MOVE.L  A6,-(SP)
  308.         MOVEA.L _MEDPlayerBase,A6
  309.         JSR     -$4E(A6)
  310.         MOVEA.L (SP)+,A6
  311.         RTS
  312.  
  313. _GetCurrentModule:
  314.         MOVE.L  A6,-(SP)
  315.         MOVEA.L _MEDPlayerBase,A6
  316.         JSR     -$54(A6)
  317.         MOVEA.L (SP)+,A6
  318.         RTS
  319.  
  320. _ResetMIDI:
  321.         MOVE.L  A6,-(SP)
  322.         MOVEA.L _MEDPlayerBase,A6
  323.         JSR     -$5A(A6)
  324.         MOVEA.L (SP)+,A6
  325.         RTS
  326.  
  327.         END
  328. +++++++++++++++++++++++++++END+++++++++++++++++++++++++++++++++++++++++++++
  329. Instructions for using "medplayer.library" V1.11, by Teijo Kinnunen.
  330. --------------------------------------------------------------------
  331.  
  332. "medplayer.library" is a shared library, which can be used to load
  333. and play MED modules. You can call its functions from any language
  334. which supports library calls (C, Assembler, Basic...)
  335.  
  336. First you must install "medplayer.library" to your LIBS: drawer.
  337. You can also load it with ARP's "loadlib" command.
  338.  
  339. The current version number of medplayer.library is V1.11. It's similar
  340. to V1.10 released with MED V3.00 (only one bug fix).
  341.  
  342. "medplayer.library" supports only 4-channel MED songs!!
  343.  
  344. Here's the complete list of the functions of "medplayer.library" (in
  345. RKM autodoc-style):
  346.  
  347. ---------------------------------------------------------------------------
  348. ---------------------------------------------------------------------------
  349.  
  350. GetPlayer
  351.  
  352. NAME
  353.         GetPlayer -- get and initialize the player routine
  354.  
  355. SYNOPSIS
  356.         error = GetPlayer(midi)
  357.         D0                D0
  358.  
  359. FUNCTION
  360.         This routine allocates the audio channels and CIAB timer A/B
  361.         and prepares the interrupt. If "midi" is nonzero, serial
  362.         port is allocated and initialized. You should call this
  363.         routine when your programs starts up.
  364.  
  365. INPUTS
  366.         midi = 0 no midi, 1 set up midi. When you use a song that
  367.                has only Amiga samples, there's no reason to allocate
  368.                 the serial port. Then set midi to 0.
  369.  
  370. RESULT
  371.         If everything is OK, GetPlayer() returns zero. If initialization
  372.         failed or somebody else is currently using the library, then
  373.         GetPlayer() returns nonzero value.
  374.         NOTE: Even if GetPlayer() returned an error, you can still call
  375.               the library functions without making harm. They just won't
  376.               work (except LoadModule(), UnLoadModule() and GetCurrent-
  377.               Module(), which always work).
  378.  
  379. SEE ALSO
  380.         FreePlayer
  381.  
  382. ---------------------------------------------------------------------------
  383. ---------------------------------------------------------------------------
  384.  
  385. FreePlayer
  386.  
  387. NAME
  388.         FreePlayer -- free the resources allocated by GetPlayer()
  389.  
  390. SYNOPSIS
  391.         FreePlayer()
  392.  
  393. FUNCTION
  394.         This routine frees all resources allocated by GetPlayer().
  395.         Remember always call this routine before your program
  396.         exits. It doesn't harm to call this if GetPlayer() failed.
  397.         If you don't call this function during exit, audio channels,
  398.         timer etc. will remain allocated until reboot.
  399.  
  400. SEE ALSO
  401.         GetPlayer
  402.  
  403. ---------------------------------------------------------------------------
  404. ---------------------------------------------------------------------------
  405.  
  406. PlayModule
  407.  
  408. NAME
  409.         PlayModule -- play module from the beginning
  410.  
  411. SYNOPSIS
  412.         PlayModule(module)
  413.                    A0
  414.  
  415. FUNCTION
  416.         This routine starts to play the module from the beginning.
  417.         The module can be obtained by calling LoadModule() or it can
  418.         be part of your program (when saved as an object file and
  419.         linked with it or included with some assemblers "binary
  420.         include" option).
  421.  
  422. INPUTS
  423.         module = pointer to module. If zero, then play the current
  424.                  module (module which was played last).
  425.  
  426. SEE ALSO
  427.         ContModule, StopPlayer, DimOffPlayer
  428.  
  429. ---------------------------------------------------------------------------
  430. ---------------------------------------------------------------------------
  431.  
  432. ContModule
  433.  
  434. NAME
  435.         ContModule -- continue playing the module from where it stopped
  436.  
  437. SYNOPSIS
  438.         ContModule(module)
  439.                    A0
  440.  
  441. FUNCTION
  442.         ContModule() functions just like PlayModule() except if you
  443.         have stopped playing with StopPlayer(), the playing will
  444.         continue where it stopped. When you play the module first
  445.         time, you should use PlayModule(), because ContModule() doesn't
  446.         initialize the filter.
  447.  
  448. INPUTS
  449.         module = pointer to module. If zero, use the current module.
  450.  
  451. SEE ALSO
  452.         PlayModule, StopPlayer, DimOffPlayer
  453.  
  454. ---------------------------------------------------------------------------
  455. ---------------------------------------------------------------------------
  456.  
  457. StopPlayer
  458.  
  459. NAME
  460.         StopPlayer -- stops playing immediately
  461.  
  462. SYNOPSIS
  463.         StopPlayer()
  464.  
  465. FUNCTION
  466.         Stop.
  467.  
  468. SEE ALSO
  469.         PlayModule, ContModule, DimOffPlayer
  470.  
  471. ---------------------------------------------------------------------------
  472. ---------------------------------------------------------------------------
  473.  
  474. DimOffPlayer
  475.  
  476. NAME
  477.         DimOffPlayer -- fade out the volume and stop playing
  478.  
  479. SYNOPSIS
  480.         DimOffPlayer(dimlength)
  481.  
  482. FUNCTION
  483.         Fades out the volume and stops the playing. The routine
  484.         returns immediately after you've called it. Then the
  485.         sound will start fading. If you want to know when the
  486.         player has stopped, you can examine the playstate-field
  487.         of the current module.
  488.  
  489. INPUTS
  490.         dimlength = how slowly should the sound fade, in lines
  491.                     e.g. DimOffPlayer(60) fades the sound in 60
  492.                      lines
  493.  
  494. SEE ALSO
  495.         PlayModule, ContModule, StopPlayer
  496.  
  497. ---------------------------------------------------------------------------
  498. ---------------------------------------------------------------------------
  499.  
  500. SetTempo
  501.  
  502. NAME
  503.         SetTempo -- modify the playing speed
  504.  
  505. SYNOPSIS
  506.         SetTempo(tempo)
  507.                  D0
  508.  
  509. FUNCTION
  510.         If you want to modify the playback speed, you can call this one.
  511.         This number should be 1 - 240. Note that tempos 1 - 10 are
  512.         recognized as SoundTracker tempos.
  513.  
  514. INPUTS
  515.         tempo = new tempo
  516.  
  517. ---------------------------------------------------------------------------
  518. ---------------------------------------------------------------------------
  519.  
  520. LoadModule
  521.  
  522. NAME
  523.         LoadModule -- load a MED module from disk and relocate it
  524.  
  525. SYNOPSIS
  526.         module = LoadModule(name)
  527.         D0                  A0
  528.  
  529. FUNCTION
  530.         When you want to load a module from disk, call this function.
  531.         The function loads only MED modules (MMD0). It doesn't load
  532.         Tracker-modules, MED songs or object files. Only MMD0's
  533.         (MMD0 is the identification word at the beginning of the file).
  534.         Because the module contains many pointers, they must be
  535.         relocated. This function relocates the module automatically.
  536.         If you link songs saved as object files, they will be relocated
  537.         by the AmigaDOS. Only if you include the module as a binary file,
  538.         then YOU must relocate it. This is an easy thing to do. You can
  539.         use the "relocmod" function from "loadmod.a".
  540.  
  541. INPUTS
  542.         name = pointer to file name (null-terminated)
  543.  
  544. RESULT
  545.         module = pointer to module. If failed to load for some reason
  546.                  (disk error, out of memory, not a module), zero will
  547.                   be returned.
  548.  
  549. SEE ALSO
  550.         UnLoadModule
  551.  
  552. ---------------------------------------------------------------------------
  553. ---------------------------------------------------------------------------
  554.  
  555. UnLoadModule
  556.  
  557. NAME
  558.         UnLoadModule -- frees the module from memory
  559.  
  560. SYNOPSIS
  561.         UnLoadModule(module)
  562.                      A0
  563. FUNCTION
  564.         When you don't need the module anymore, you MUST free the
  565.         memory it has used. Use this routine for it. Remember to
  566.         stop the player before unloading the module it is playing.
  567.  
  568.         NOTE: unload only those modules which are loaded with
  569.         LoadModule(). If you attempt to free module which is a part
  570.         of the program, you will cause guru 81000009/81000005.
  571.  
  572. INPUTS
  573.         module = pointer to module. If zero, nothing happens.
  574.  
  575. SEE ALSO
  576.         LoadModule
  577.  
  578. ---------------------------------------------------------------------------
  579. ---------------------------------------------------------------------------
  580.  
  581. GetCurrentModule
  582.  
  583. NAME
  584.         GetCurrentModule -- returns the address of module currently playing
  585.  
  586. SYNOPSIS
  587.         module = GetCurrentModule()
  588.         D0
  589.  
  590. FUNCTION
  591.         Simply returns the pointer of the module, which is currently
  592.         playing (or if player is stopped, which was played last). This
  593.         works also if some other task is currently playing. In this case,
  594.         because of multitasking, you should have no use for the value
  595.         (the module can be already unloaded). You may ask what use this
  596.         function has. Well, I'm not sure, but because this function
  597.         takes only 2 machine language instructions (8 bytes of memory)
  598.         there's no much harm of it.
  599.  
  600. RESULT
  601.         module = pointer to current module
  602.  
  603. ---------------------------------------------------------------------------
  604. ---------------------------------------------------------------------------
  605.  
  606. ResetMIDI
  607.  
  608. NAME
  609.         ResetMIDI -- reset all pitchbenders and modulation wheels and
  610.                      ask player to resend the preset values
  611.  
  612. SYNOPSIS
  613.         ResetMIDI()
  614.  
  615. FUNCTION
  616.         This function resets pitchbenders and modulation wheels on all
  617.         MIDI channels. It also asks the player to send again the
  618.         preset change requests for all instruments, so that the presets
  619.         will be correct if the user has changed them. It performs the
  620.         same function as MED's Ctrl-Space.
  621.  
  622. ---------------------------------------------------------------------------
  623. ---------------------------------------------------------------------------
  624.  
  625.