home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMOS PD CD
/
amospdcd.iso
/
551-575
/
apd560
/
amoner5
/
editor
/
amos_&_asm.txt
< prev
next >
Wrap
Text File
|
1993-11-29
|
21KB
|
625 lines
. AMOS & ASSEMBLER
. by
. Michael D. Cox
--------------------------------------------------------------------------
Before we begin, you need to have either a commercial or PD assembler.
For PD, there is A68k. For commercial, there are several. DevPac II/III,
CAPE 68k, ASSEMPRO (don't go near this one), and even the AMOS Assembler.
I use DevPac II (hope to have III soon) as it is easy and fast. Besides,
all the great programmers use it!!!
A68k is a good assembler also. Heck, it's free! It is available on the
Fish disks and probably many bulletin board systems. I will even try and
have it included on this issue of the AMONER disk. If not and you don't mind
spending a few bucks for postage, mail me a disk or two and I will send it
to you without charging return postage.
You'll also need a good Amiga Programmer's book. Something like the
RKMs, Amiga Programmer's Handbook Vol. I & II (SYBEX), or Amiga System
Programmer's Guide (ABACUS). You will need one of these because they
explain the libraries and how the work. They also tell you what the offset
is for each function in a library. You need these offsets for use with
the EXECALL, DOSCALL, etc. commands.
Next, you need to become familiar with some of the AMOS commands that
deal with the assembler routines. They are on pages 285 to 287 in the AMOS
manual.
- PLOAD "fielname",bank
This will load your compiled assembler program into bank. No need
to reserve the bank first, but make sure you don't use a reserved
one (like 1 to 4). Once loaded with PLOAD, the assembler routines
will be saved with your program!
- CALL bank[,params]
This executes your program at bank. Params
are the arguments passed to your routines. Thoroughly read the
manual and what it says about Params and the registers.
- =AREG= and =DREG=
These arrays let you set the registers used in your routines.
However, for the AREG, only 0, 1, and 2 are passed when you
CALL your routine. All of the DREGs are passed when CALL is
executed.
Timeout for a little assembler lesson:
You have two types of registers: ADDRESS and DATA. ADDRESS registers hold
addresses of certain things. They can hold the address of a variable, a
buffer, a library, and so on. They 'point' to where the data begins.
When they point to a string variable, the string must end in a NULL or
CHR$(0).
DATA registers hold things like values. Results of certain commands are
returned in the DATA registers. For instance, when you Open a Library,
using the OpenLibrary function in exec.library, D0 will either contain
a 0 if the OpenLibrary failed, or the starting address of where the
library is located in memory.
As an example: Let's open the medplayer.library. First, we need to know
what the OpenLibrary function requires in order to work. I look in my RKMs
or any of the Amiga programming manuals available that discuss the
EXEC library for OpenLibrary. Okay, here is the format:
address = OpenLibrary(LibName,version)
D0 = A1 D0
This tells me that when the OpenLibrary function is finished, it will return
the results in D0. And, I need to set A1 to where (an address) the
name of the library is stored (a string variable). In D0, I say which
version of the library I want to use (We set it to 0, which means we will
use any version).
Now, in AMOS, we would do this:
_OPENLIBRARY = -$228 : Rem Offset of OpenLibrary function in EXEC
A$="medplayer.library"+Chr$(0) : Rem Null terminate the string
NAME_POINTER = Varptr(A$) : Rem Varptr tells me the address of A$
Areg(1) = NAME_POINTER : Rem Set A1 to address of the library name
Dreg(0) = 0 : Rem Set D0 to 0 for any version
R=Execall(_OPENLIBRARY)
Now, if R = 0, then it failed. Otherwise, save R to a variable like
MED_LIB_POINTER as it contains the address of where medplayer.library
is located in memory.
Okay, enough rambling....
You need to also become familiar with the DOSCALL, EXECALL, GFXCALL,
and INTCALL functions. And, on page 281, VARPTR is explained.
Okay, we are ready to continue once you are familiar with the above
commands. If not, keep your manual nearby (who doesn't?).
So, we know how to open a library. How do we close it? Just as simple!
We lookup CloseLibrary and find:
CloseLibrary(library)
A1
Which tells us?? Anyone, anyone? Right, Johnny! We put the address of
where the library is located in A1. No return value is expected, so nothing
else needs to be done. So, if we opened the library as above, we would do
the following to close it:
Rem Use _CLOSELIBRARY as AMOS reserves Close
_CLOSELIBRARY = -$19E : Rem Offset of CloseLibrary in EXEC
Areg(1)=MED_LIB_POINTER : Rem Set A1 to address of library
R=Execall(_CLOSELIBRARY) : Rem Call the CloseLibrary function
End
Now, if you typed the above segments into AMOS, make sure medplayer.library
is in you LIBS: directory. It is included on this AMONER disk and also disk
4.
So, what does this have to do with assembler? Well, a lot, but it has
nothing to do with our assembler. So, first, we need to write a little
assembler routine that will get the medplayer ready and one routine to
get rid of the player. The following routines were taken from the
documentation for medplayer.library and have been subtly modified to work
with AMOS.
Load up your assembler, type in each routine below and assemble it as an
executable and re-locatable.
GetPlayer:
move.l a6,-(sp) ; Save pointer to program on the stack pointer (SP)
movea.l a2,a6 ; Move address in A2 (MED_LIB_POINTER) into A6
jsr -$1e(a6) ; Jump to the GetPlayer routine in medplayer.library
movea.l (sp)+,a6 ; Return program pointer back to A6
rts ; Return control back to AMOS
FreePlayer:
move.l a6,-(sp) ; Save pointer to program on the stack pointer (SP)
movea.l a2,a6 ; Move address in A2 (MED_LIB_POINTER) into A6
jsr -$24(a6) ; Jump to the FreePlayer routine in medplayer.library
movea.l (sp)+,a6 ; Return program pointer back to A6
rts ; Return control back to AMOS
Okay, have you assembled these routines into seperate executables? Good,
let's load up AMOS.
Load in the _OPENLIBRARY and _CLOSELIBRARY program. ESCape to Direct mode
and load your two assembler routines into two separate banks. I used Bank 9
for GetPlayer and Bank 12 for FreePlayer.
For example:
AMOS> pload "ram:getplayer",9
AMOS> pload "ram:freeplayer",12
Go back to the editor and save the program! Remember, when dealing with
unfamiliar territory, save before doing anything.
Now, we need to look at what the two medplayer.library functions need in
order to work.
error = GetPlayer (midi) Freeplayer()
D0 D0
So, GetPlayer returns a 0 to D0 if everything works fine. Before CALLing
GetPlayer, we set D0 to a 0 since we don't want any MIDI.
FreePlayer requires no arguments to work.
Make a mental note: Even though the functions do not say they need the
MED_LIB_POINTER, they always do.
Since A0 to A2 registers are passed when you CALL a routine, we will put
MED_LIB_POINTER into A2. You could use A0 or A1, but some functions will
need to use those also.
Alright, we are ready to enter our AMOS Procedures to GetPlayer then
FreePlayer.
Procedure _GET_PLAYER [LIB_POINTER,MIDI]
Dreg(0) = MIDI
Areg(2) = LIB_POINTER
Call 9
FLUBBED = Dreg(0)
If FLUBBED = 0
Print "Unable to GetPlayer. Press any key to exit"
Wait Key
End
End If
End Proc
Procedure _FREE_PLAYER [LIB_POINTER]
Areg(2) = LIB_POINTER
Call 12
Print "Player Freed. Press any key to exit."
Wait Key
End
End Proc
Now, when we call the procedures, we do:
_GETPLAYER[MIDI,MED_LIB_POINTER]
? "Press Any key to FreePlayer"
Wait key
_FREE_PLAYER [MED_LIB_POINTER]
That's all there is to it, folks! What's that, Bubba? You want to load
and play a MED Module? Well, just go back to the menu and select the MED
player! If there is room, there should be a MED module on the disk. You
readers should write a player too. Mail me the completed program and
I will include them all on the next disk.
Below is all the MEDPlayer docs and assembler routines. It contains all you
need to know to write the routines and is the original that came with
the original archive.
So, mail me with your comments (good or bad)!!!
Michael D. Cox
13600 EDS Drive
MS A5N-B51
Herndon, VA 22071
Email: aj639@Cleveland.freenet.edu
(Next issue, look for my review of Stephen Hill's book AMIGA GAME MAKER'S
MANUAL (WITH AMOS BASIC) from SIGMA press.)
++++++++++++++++++++++++++++END+++++++++++++++++++++++++++++++++++++++++
; medplrlib_stub.a: stub routines for calling medplayer.library from
; C-compilers which don't support direct library
; calling
XREF _MEDPlayerBase
XDEF _GetPlayer
XDEF _FreePlayer
XDEF _PlayModule
XDEF _ContModule
XDEF _StopPlayer
XDEF _DimOffPlayer
XDEF _SetTempo
XDEF _LoadModule
XDEF _UnLoadModule
XDEF _GetCurrentModule
XDEF _ResetMIDI
CODE
_GetPlayer:
MOVE.L 4(SP),D0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$1E(A6)
MOVEA.L (SP)+,A6
RTS
_FreePlayer:
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$24(A6)
MOVEA.L (SP)+,A6
RTS
_PlayModule:
MOVEA.L 4(SP),A0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$2A(A6)
MOVEA.L (SP)+,A6
RTS
_ContModule:
MOVEA.L 4(SP),A0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$30(A6)
MOVEA.L (SP)+,A6
RTS
_StopPlayer:
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$36(A6)
MOVEA.L (SP)+,A6
RTS
_DimOffPlayer:
MOVE.L 4(SP),D0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$3C(A6)
MOVEA.L (SP)+,A6
RTS
_SetTempo:
MOVE.L 4(SP),D0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$42(A6)
MOVEA.L (SP)+,A6
RTS
_LoadModule:
MOVEA.L 4(SP),A0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$48(A6)
MOVEA.L (SP)+,A6
RTS
_UnLoadModule:
MOVEA.L 4(SP),A0
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$4E(A6)
MOVEA.L (SP)+,A6
RTS
_GetCurrentModule:
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$54(A6)
MOVEA.L (SP)+,A6
RTS
_ResetMIDI:
MOVE.L A6,-(SP)
MOVEA.L _MEDPlayerBase,A6
JSR -$5A(A6)
MOVEA.L (SP)+,A6
RTS
END
+++++++++++++++++++++++++++END+++++++++++++++++++++++++++++++++++++++++++++
Instructions for using "medplayer.library" V1.11, by Teijo Kinnunen.
--------------------------------------------------------------------
"medplayer.library" is a shared library, which can be used to load
and play MED modules. You can call its functions from any language
which supports library calls (C, Assembler, Basic...)
First you must install "medplayer.library" to your LIBS: drawer.
You can also load it with ARP's "loadlib" command.
The current version number of medplayer.library is V1.11. It's similar
to V1.10 released with MED V3.00 (only one bug fix).
"medplayer.library" supports only 4-channel MED songs!!
Here's the complete list of the functions of "medplayer.library" (in
RKM autodoc-style):
---------------------------------------------------------------------------
---------------------------------------------------------------------------
GetPlayer
NAME
GetPlayer -- get and initialize the player routine
SYNOPSIS
error = GetPlayer(midi)
D0 D0
FUNCTION
This routine allocates the audio channels and CIAB timer A/B
and prepares the interrupt. If "midi" is nonzero, serial
port is allocated and initialized. You should call this
routine when your programs starts up.
INPUTS
midi = 0 no midi, 1 set up midi. When you use a song that
has only Amiga samples, there's no reason to allocate
the serial port. Then set midi to 0.
RESULT
If everything is OK, GetPlayer() returns zero. If initialization
failed or somebody else is currently using the library, then
GetPlayer() returns nonzero value.
NOTE: Even if GetPlayer() returned an error, you can still call
the library functions without making harm. They just won't
work (except LoadModule(), UnLoadModule() and GetCurrent-
Module(), which always work).
SEE ALSO
FreePlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
FreePlayer
NAME
FreePlayer -- free the resources allocated by GetPlayer()
SYNOPSIS
FreePlayer()
FUNCTION
This routine frees all resources allocated by GetPlayer().
Remember always call this routine before your program
exits. It doesn't harm to call this if GetPlayer() failed.
If you don't call this function during exit, audio channels,
timer etc. will remain allocated until reboot.
SEE ALSO
GetPlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
PlayModule
NAME
PlayModule -- play module from the beginning
SYNOPSIS
PlayModule(module)
A0
FUNCTION
This routine starts to play the module from the beginning.
The module can be obtained by calling LoadModule() or it can
be part of your program (when saved as an object file and
linked with it or included with some assemblers "binary
include" option).
INPUTS
module = pointer to module. If zero, then play the current
module (module which was played last).
SEE ALSO
ContModule, StopPlayer, DimOffPlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
ContModule
NAME
ContModule -- continue playing the module from where it stopped
SYNOPSIS
ContModule(module)
A0
FUNCTION
ContModule() functions just like PlayModule() except if you
have stopped playing with StopPlayer(), the playing will
continue where it stopped. When you play the module first
time, you should use PlayModule(), because ContModule() doesn't
initialize the filter.
INPUTS
module = pointer to module. If zero, use the current module.
SEE ALSO
PlayModule, StopPlayer, DimOffPlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
StopPlayer
NAME
StopPlayer -- stops playing immediately
SYNOPSIS
StopPlayer()
FUNCTION
Stop.
SEE ALSO
PlayModule, ContModule, DimOffPlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
DimOffPlayer
NAME
DimOffPlayer -- fade out the volume and stop playing
SYNOPSIS
DimOffPlayer(dimlength)
FUNCTION
Fades out the volume and stops the playing. The routine
returns immediately after you've called it. Then the
sound will start fading. If you want to know when the
player has stopped, you can examine the playstate-field
of the current module.
INPUTS
dimlength = how slowly should the sound fade, in lines
e.g. DimOffPlayer(60) fades the sound in 60
lines
SEE ALSO
PlayModule, ContModule, StopPlayer
---------------------------------------------------------------------------
---------------------------------------------------------------------------
SetTempo
NAME
SetTempo -- modify the playing speed
SYNOPSIS
SetTempo(tempo)
D0
FUNCTION
If you want to modify the playback speed, you can call this one.
This number should be 1 - 240. Note that tempos 1 - 10 are
recognized as SoundTracker tempos.
INPUTS
tempo = new tempo
---------------------------------------------------------------------------
---------------------------------------------------------------------------
LoadModule
NAME
LoadModule -- load a MED module from disk and relocate it
SYNOPSIS
module = LoadModule(name)
D0 A0
FUNCTION
When you want to load a module from disk, call this function.
The function loads only MED modules (MMD0). It doesn't load
Tracker-modules, MED songs or object files. Only MMD0's
(MMD0 is the identification word at the beginning of the file).
Because the module contains many pointers, they must be
relocated. This function relocates the module automatically.
If you link songs saved as object files, they will be relocated
by the AmigaDOS. Only if you include the module as a binary file,
then YOU must relocate it. This is an easy thing to do. You can
use the "relocmod" function from "loadmod.a".
INPUTS
name = pointer to file name (null-terminated)
RESULT
module = pointer to module. If failed to load for some reason
(disk error, out of memory, not a module), zero will
be returned.
SEE ALSO
UnLoadModule
---------------------------------------------------------------------------
---------------------------------------------------------------------------
UnLoadModule
NAME
UnLoadModule -- frees the module from memory
SYNOPSIS
UnLoadModule(module)
A0
FUNCTION
When you don't need the module anymore, you MUST free the
memory it has used. Use this routine for it. Remember to
stop the player before unloading the module it is playing.
NOTE: unload only those modules which are loaded with
LoadModule(). If you attempt to free module which is a part
of the program, you will cause guru 81000009/81000005.
INPUTS
module = pointer to module. If zero, nothing happens.
SEE ALSO
LoadModule
---------------------------------------------------------------------------
---------------------------------------------------------------------------
GetCurrentModule
NAME
GetCurrentModule -- returns the address of module currently playing
SYNOPSIS
module = GetCurrentModule()
D0
FUNCTION
Simply returns the pointer of the module, which is currently
playing (or if player is stopped, which was played last). This
works also if some other task is currently playing. In this case,
because of multitasking, you should have no use for the value
(the module can be already unloaded). You may ask what use this
function has. Well, I'm not sure, but because this function
takes only 2 machine language instructions (8 bytes of memory)
there's no much harm of it.
RESULT
module = pointer to current module
---------------------------------------------------------------------------
---------------------------------------------------------------------------
ResetMIDI
NAME
ResetMIDI -- reset all pitchbenders and modulation wheels and
ask player to resend the preset values
SYNOPSIS
ResetMIDI()
FUNCTION
This function resets pitchbenders and modulation wheels on all
MIDI channels. It also asks the player to send again the
preset change requests for all instruments, so that the presets
will be correct if the user has changed them. It performs the
same function as MED's Ctrl-Space.
---------------------------------------------------------------------------
---------------------------------------------------------------------------