-
Notifications
You must be signed in to change notification settings - Fork 1
/
modplayer.txt
264 lines (205 loc) · 9.47 KB
/
modplayer.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
Instructions for using "modplayer.a", the stand-alone playroutine
of OctaMED V2.0
"modplayer" is a piece of code (about 3 - 5 KBytes, depending on your needs)
which is linked with your program and plays modules made in OctaMED.
"modplayer" 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 etc. etc.
ARGUMENTS: none
RETURNS: nothing
--------------------------------------------------------------------------
PlayModule -- start playing a module
When you want to start playing call this.
ARGUMENTS: a0 = pointer to the module. Where to get that pointer?
Don't panic, it's explained later....
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
ARGUMENTS: d0 = new tempo (1 - 240)
RETURNS: nothing
--------------------------------------------------------------------------
"modplayer.a" is the source code of the music routine. It contains stuff
that may be unnecessary for your purposes, that just takes 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 the song(s) use(s) only the Amiga audio channels, 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 the song(s) doesn't use synth/hybrid sounds, then 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.
IFF53 If the song doesn't contain IFF 3- or 5-octave samples,
this can be zero.
HOLD This turns off the hold/decay features.
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. Then 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. This option also replaces the 'easyplayer.a' from the previous
release of OctaMED and MED.
"modplayer.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 "modplayer.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).
Assembling
==========
"modplayer.a" can be assembled by using A68k V2.61 (or later) or 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). The freely distributable assembler, A68k is
available e.g. on Fish disk #314. If you've working on a linker environment
(e.g. programming in C), you've to include the resulted "modplayer.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 (MED 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 "modplayer.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 arguments 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 in stack
jsr _RelocModule(pc)
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 the Objconv. Relocation is required
in any case.
And the second method (loading modules from disk):
--------------------------------------------------------------------------
File "loadmod.a" contains three routines:
LoadModule
UnLoadModule
RelocModule (not external)
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, nothing and nothing
--------------------------------------------------------------------------
Just call LoadModule to load the module and send the returned pointer to
PlayModule. Easy??
==========================================================================
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.xx, this is done automatically if you include
"modplayer.h" in all your code modules which call modplayer. If you
have a compiler which doesn't support argument passing in registers,
then you have to write the stub routines in assembler.
That was it. See also the small example sources.
==========================================================================
==========================================================================
mod8player.a
~~~~~~~~~~~~
"mod8player.a" is the play-routine for OctaMED 5 - 8 channel songs. This
can be used exactly in the same way as "modplayer.a". The functions just
have slightly different names:
InitPlayer8
RemPlayer8
PlayModule8
ContModule8
StopPlayer8
modnum8
Note that this player have some restrictions, as opposed to "modplayer.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.
Note that you need an assembler with REPT or equivalent directive (e.g.
Devpac 2) to assemble this file.
A reminder that this is copyrighted so if you intend using it for commercial
purposes,you must contact RBF Software before doing so.