Note to Authors:  © Fully Copyrighted  RBF Software

Use of these library functions is heartily encouraged IF you intend using
them within a Public Domain Program.
If you intend using them within a program written for gain ie: Commercial
or one of the many low charge libraries,(even if you will only be receiving
a SMALL share per sale),then you MUST by law obtain a licence from
RBF Software. The address is given in the ReadMe file.
You are welcome to alter anything that you feel may be required for your
own personal usage, however, please send any altered routines to RBF Software
along with a note of explanition for the alterations.
Also, if you require a specific routine to be writen, then provided you
are registered with RBF Software, send them your EXACT requirements/needs
and we shall do our best to assist you.

    Instructions for using "proplayer.a", the stand-alone playroutine.
==========================================================================

"proplayer" is a piece of code which is linked with your program and plays
MED and OctaMED modules.

"proplayer" contains the following routines:
    InitPlayer
    RemPlayer
    PlayModule
    ContModule
    StopPlayer
    SetTempo

The arguments are passed in registers, and return values are returned in d0.
These routines will trash registers d0-d1 and a0-a1.

And now the descriptions of each one:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InitPlayer -- initialize everything

Before you can call the other functions, you must call this function.
It allocates the audio channels, timer, serial port (if MIDI) etc...

ARGUMENTS:  none

RETURNS:    0 if everything is ok, otherwise something failed.
        If something failed, you can still call the other
        routines - they just don't do anything.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RemPlayer -- return everything back

Call this when your program exits. It frees the audio channels, timer,
serial port etc.

ARGUMENTS:  none

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PlayModule -- start playing a module

When you want to start playing, call this routine.

ARGUMENTS:  a0 = pointer to the module. See below for instructions
        how to obtain the pointer.

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StopPlayer -- stop playing

ARGUMENTS:  no arguments

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ContModule -- continue playing

This routine continues playing the module from the point it was stopped.

ARGUMENTS:  a0 = pointer to the module

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SetTempo -- set the playback tempo

(This routine has not much use.)

ARGUMENTS:  d0 = new tempo (1 - 240)

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

"proplayer.a" is the source code of the music routine. It contains stuff
that may be unnecessary for your purposes, just taking time and memory.
There are some "switches" at the beginning of the source, that allow you
to turn off features you don't need. They are:

MIDI        If only the Amiga audio channels are used, set this to 0.
AUDDEV      For some purposes, you may want to disable the code that
        allocates the audio channels using "audio.device", e.g.
        in a non-multitasking environment. Normally this should
        be 1.
SYNTH       If synth/hybrid sounds are not in use, this can be set to
        zero.
CHECK       This does some checkings to ensure that several values are
        correct (e.g. is the sample in memory, no Amiga effects on
        MIDI-tracks etc..). If you know that the song is correct,
        you can safely turn the checks off.
RELVOL      If you don't need the "relative volume", this can be zero.
IFFMOCT     If the song doesn't contain multi-octave IFF samples
        this can be zero.
HOLD        This turns off the hold/decay features.
PLAYMMD0    If set, the play routine will also handle old MMD0 type
        modules. Useful for player programs. MMD1/MMD2 type
        modules are always supported by the current play routine.


There's an additional flag, EASY. If set, the usage of the player routines
is even more simplified, and you enter the module name into an INCBIN
statement. There are two routines (_startmusic, _endmusic) you call
to start and stop the music (the music can be started ONLY ONCE). The
EASY option is suitable for demos etc. where only a single tune is
required.

"proplayer.a" also supports multi-modules. It defines a UWORD modnum
(in assembler: _modnum). Set this variable to the number of the song
you want to play before calling PlayModule (0 is the first, 1 is the
second song etc..). For example:
    #include "proplayer.h" /* defines 'modnum' */
    ...
    modnum = 1; /* Play the second module */
    PlayModule(module);
    ...
Assembler:
    xref    _modnum
    xref    _PlayModule
    ...
    move.w  #1,_modnum
    lea _module,a0
    jsr _PlayModule(pc)
    ...

Timing
======
If you need vertical blanking timing, you can set VBLANK to 1 and CIAB to 0.
In normal use this is not recommended (because of the 16 % difference in
playing speed with NTSC and PAL Amigas), but if tight synchronization to
vertical blanking (e.g. in most demos/games) is required, VBLANK could be
used.

For VBlank timing, the song has to be composed with primary tempo of about
33. The primary tempo cannot be changed with command F. Only the secondary
tempo control can be used (command 9).

Assembling
==========
"proplayer.a" can be assembled by using HiSoft Devpac 2 without need to
make changes. Other assemblers may need some small changes to work
correctly (mostly because the directives they support may be slightly
different). If you're working on a linker environment (e.g. programming
in C), you need to include the resulted "proplayer.o" in your .lnk-file.

==========================================================================

And how to get some music?

You have two ways to get the music:
1. Include the module in your final executable.
2. Save the module as a separate disk file and load it when needed
   (this is probably the best way if you have more than one song, and
    you don't want to use multi-modules).

First I cover the first method:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Including the module in your final executable:

The direct object file saving is removed now (you can still use the previous
versions which support it, if you want). There's now another way to convert
the song to an object file.

There's a new utility, Objconv, which loads the module and dumps it into an
object file. Here's an example how to use it:

- Save the song as a module
- Use Objconv e.g. objconv medmodule mod.o
- Objconv requests the symbol name, enter "song" (without "'s), for example.
- Now there's a file 'mod.o'. Link this file, and the file 'reloc.o'
  with your program.
- In your program, you define the module:
    #include "proplayer.h"
    ...
    extern struct MMD0 far song;
  You must relocate the module before it's used. Do this only once!
  This is done by
    RelocModule(&song);
  RelocModule expects the argument in stack, so use __stdargs, if you've
  turned registerized parameters on.

In assembler, you'd do exactly in the same way, except:
    xref    _song
    xref    _RelocModule
    xref    _PlayModule

    ... (assuming all init stuff is here)

    lea _song,a0
    move.l  a0,-(sp)    ;push into stack
    jsr _RelocModule(pc)
    addq.l  #4,sp       ;reset stack pointer
    lea _song,a0    ;this is passed in register a0
    jsr _PlayModule
    ...

Note: if you've got an assembler that supports 'incbin' directive or
equivalent, you can use it instead of Objconv. Relocation is required
in any case.

And the second method (loading modules from disk):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
File "loadmod.a" contains three routines:
    LoadModule
    UnLoadModule
    RelocModule

You usually need only the first two of them. RelocModule is used by
LoadModule.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LoadModule -- loads a module from disk

This function loads a module from disk. Note that relocation is done
automatically, so you must not RelocModule() a module obtained by using
this routine.

ARGUMENTS:  a0 = pointer to file name

RETURNS:    d0 = pointer to the module, if something failed: 0

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UnLoadModule -- free the module from memory

Frees the module. Remember to StopPlayer() before you unload the module
that is currently playing. Also remember to free all modules you've loaded
before you exit the program.

ARGUMENTS:  a0 = pointer to the module (may be 0)

RETURNS:    nothing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

==========================================================================

REMEMBER:   All functions expect the arguments in registers (except
        RelocModule() from reloc.o). This is automatically (??)
        handled by you when you program in assembler, but it is
        not automatically handled when you're programming in C.

If you have Lattice/SAS C V5/6, this is done automatically if you include
"proplayer.h" in all your code modules which call proplayer. If you
have a compiler which doesn't support argument passing in registers,
then you have to write the stub routines in assembler.

See also the small example sources.

==========================================================================

    pro8player.a
    ~~~~~~~~~~~~

"pro8player.a" is the play-routine for OctaMED 5 - 8 channel songs. This
can be used exactly in the same way as "proplayer.a". The functions just
have slightly different names:
    InitPlayer8
    RemPlayer8
    PlayModule8
    ContModule8
    StopPlayer8
    modnum8

Note that this player have some restrictions, as opposed to "proplayer.a".
They're listed in OctaMED documents. It also takes LOTS of processor time,
depending on how many splitted channels there are.

You can use the same RelocModule() and (Un)LoadModule() routines with
5 - 8 channel songs.

This routine does not support the HQ mode, but if there's demand, it will
be added.

              Ray.
==========================================================================