home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 15
/
CD_ASCQ_15_070894.iso
/
vrac
/
mikmod43.zip
/
MIKMOD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-30
|
9KB
|
432 lines
/*
MIKMOD.C Programmed by MikMak of Unicorn Design
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <alloc.h>
#include <conio.h>
#include <ctype.h>
#include "modload.h"
#include "modplay.h"
#include "mytypes.h"
#include "forte.h"
#include "gf1proto.h"
#include "extern.h"
#include "ultraerr.h"
#include "ultraext.h"
#include "wildfile.h"
#include "getopt.h"
extern ULTRA_CFG config;
#define MAXHANDLE 31
/* this example only loads 1 module
at a time, so 31 handles are enough */
ULONG Ultra[MAXHANDLE];
/* Ultra[] holds the sample dram adresses
of the 31 samples of a module */
void SetBPM(int bpm)
{
/* The player routine has to be called (bpm*50)/125 times a second,
so the interval between calls takes 125/(bpm*50) seconds (amazing!).
The Timer1 handler has a resolution of 160 microseconds.
So the timer value to program:
(125/(bpm*50)) / 1.6e-4 = 15625/bpm
*/
UltraStartTimer(1,15625/bpm);
}
#pragma argsused
void GusPlay(int voice,AUDTMP *aud,MODFILE *mf)
/*
Callback routine for playing the samples on a GUS. (this routine is
called each tick, for each voice)
*/
{
UWORD period,vol,frq;
ULONG base;
/* get sample period and volume */
period=aud->period;
if(period<50) period=50; // limit the period value
if(period>1814) period=1814;
vol=((UWORD)mp_mainvol*aud->volume)/0xd;
frq=3579546UL/period;
// Check if the sample has to be restarted
if(aud->kick){
// Get sample dram address
base=Ultra[aud->handle];
/* When the previous sample still is active, ramp down the volume
and wait until the ramping is done */
if (!UltraVoiceStopped(voice)) {
UltraVectorLinearVolume(voice,0,0x3f,0);
while (!UltraVolumeStopped(voice)) ;
UltraStopVoice(voice);
}
UltraSetFrequency(voice,frq);
if(aud->loop<aud->size){
// Start a looping sample
UltraStartVoice(voice,
base+aud->start,
base+aud->loop,
base+aud->size,0x8);
}
else{
// Start a one-shot sample
UltraStartVoice(voice,
base+aud->start,
base+aud->start,
base+aud->size,0);
}
aud->kick=0;
}
else{
/* Voice doesn't have to be restarted, so
just update the period */
UltraSetFrequency(voice,frq);
}
// and update volume
UltraVectorLinearVolume(voice,vol,0x3f,0);
}
void HandleTimer1()
{
static int odd=0;
/* Do not service the odd calls to this handler .. This
effectively makes this a 2*80=160 microsecond handler */
if(odd^=1) return;
MP_HandleTick(); // Call the player routine
SetBPM(mp_bpm); // Update beats-per-minute
}
int GusLoad(FILE *fp,SAMPLEINFO *smp)
/*
callback routine for the MODLOAD module.
fp :file ptr to that sample
smp :Sampleinfo of the sample that is being loaded.
returns: -1 on error
or
>=0 samplehandle
*/
{
int handle;
// Find empty slot to put sample address in
for(handle=0;handle<MAXHANDLE;handle++){
if(Ultra[handle]==0) break;
}
if(handle==MAXHANDLE) return -1;
// Allocate GUS dram and store the address in Ultra[handle]
// Alloc 1 byte more for anticlick measures. see below.
if(UltraMemAlloc(smp->length+1,&Ultra[handle])!=ULTRA_OK)
return -1;
// Load the sample
if(UltraFileload(fp,DMA_8|DMA_NO_CVT,Ultra[handle],smp->length)==0) return -1;
if(smp->replen>2){ // looping sample ?
/* Anticlick for looping samples:
Copy the first byte in the loop
one place beyond the end of the loop */
UltraPoke(Ultra[handle]+smp->reppos+smp->replen,
UltraPeek(Ultra[handle]+smp->reppos));
}
else{
/* Anticlick for one-shot samples:
Zero the byte beyond the end of the sample.
*/
UltraPoke(Ultra[handle]+smp->length,0);
}
return handle;
}
void GusUnLoad(int handle,SAMPLEINFO *smp)
/*
callback routine to unload samples
handle :Sample-handle that is being freed
smp :sampleinfo of sample that is being freed
*/
{
UltraMemFree(smp->length+1,Ultra[handle]);
Ultra[handle]=0;
}
int PlayModule(char *file)
{
char c;
int t;
MODFILE *mf;
printf("\nFile : %s\n",file);
if((mf=ML_Open(file,NULL))==NULL){
printf("MikMod Error: %s\n",ML_Error());
return 0;
}
printf("Title : %s\n"
"ModType : %s %d channels\n"
"Patterns : %d\n"
"Songlength: %d\n",
mf->songname,
mf->modtype,
mf->numchn,
mf->numpat,
mf->songlength);
if(!ML_Load(mf)){
printf("MikMod Error: %s\n",ML_Error());
ML_Free(mf);
return 0;
}
MP_Init(mf);
for(t=0;t<mf->numchn;t++) UltraSetBalance(t,7+t-(mf->numchn>>1));
// Let's make some noise !
UltraEnableOutput();
delay(30);
SetBPM(125); // Kickstart the timer
puts("Press space to continue, ESC to quit..");
// You might want to do something more useful here
do c=getch(); while(c!=' ' && c!=0x1b);
UltraStopTimer(1);
for(t=0;t<mf->numchn;t++) UltraVoiceOff(t,0);
UltraDisableOutput();
ML_Free(mf);
return(c!=0x1b);
}
int PlayWildModule(char *wildname)
/*
Plays all modules that correspond to the wildcard filename 'wildname'
*/
{
int ok;
char *name;
if((name=GetFirstName(wildname))==NULL){
printf("Could not find %s\n",wildname);
return 0;
}
do{
ok=PlayModule(name);
} while(ok && (name=GetNextName())!=NULL);
return ok;
}
int breakhandler(void)
{
return 1;
}
int main(int argc,char *argv[])
{
int t;
char opt,*arg;
int argcount=0; // counts number of 'real' arguments
int cmderr=0; // error in commandline flag
int morehelp=0; // set if user wants more help
printf("MIKMOD v0.43 or how to make a modplayer using the GUS SDK Toolkit v2.10\n"
"Programmed by MikMak of Unicorn Design. This is SOURCEWARE/PUBLIC DOMAIN\n"
"So you may use my routines as long as you mention my name :)\n"
"E-Mail: mikmak@stack.urc.tue.nl\n\n");
/* init the option scanner to look
for the options /? /H /L /X and /V */
InitOpt(argc,argv,"?hHlLxXv:V:");
while((t=GetOpt(&opt,&arg))!=GO_EOF && !cmderr){
switch(t){
case GO_OPT:
switch(tolower(opt)){
case 'l':
ML_Load15(1);
break;
case 'x':
MP_ExtSpd(0);
break;
case 'v':
MP_MainVol(atoi(arg));
break;
case '?':
case 'h':
morehelp=1;
cmderr=1;
break;
}
break;
case GO_ARG:
argcount++; // count the number of "real" arguments
break;
case GO_UNKNOWN_SWITCH:
printf("\07Unknown switch - '%c'\n\n",opt);
cmderr=1;
break;
case GO_SWITCH_NEEDS_ARG:
printf("\07Switch needs an argument - '%c'\n\n",opt);
cmderr=1;
break;
}
}
if(cmderr || argcount==0){
puts("Usage: MIKMOD <fletch.mod> [spacedb.mod] ... [/X] [/L] [/Vxx] [/?] [/H]\n");
if(morehelp)
puts("- /L enables loading old 15-instrument modules\n"
"- /X disables protracker extended speed\n"
"- /Vxx Sets volume from 0 (silence) to 100 (mayhem). Default=80\n"
"- Wildcards are allowed\n"
"- Options can be placed anywhere on the commandline\n"
"- Options can be combined behind a single switch char: /XV 100\n\n"
"Examples:\n\n"
"MIKMOD teardrop.mod /L /V50\tPlays 15-instr. module at 50% volume\n"
"MIKMOD /X klisjepa.mod /V100\tPlays klisjepa.mod without ext. spd at max vol.\n"
"MIKMOD x*.mod y*.mod \t\tPlays all modules starting with 'x' and 'y'\n");
else
puts("Type MIKMOD /? or MIKMOD /h for more help.");
return -1;
}
/* disable control-break by
installing a custom handler */
ctrlbrk(breakhandler);
/* Get the ULTRASND environment string parameters */
if(!UltraGetCfg(&config)){
puts("Ultrasound env. string not found..");
return -1;
}
/* Set up 14 channels */
if(UltraOpen(&config,14)==NO_ULTRA){
puts("No ultrasound card found");
return -1;
}
/* Report size of GUS DRAM */
printf("This GUS has %dK of Dram\n",UltraSizeDram());
/* Grab the 80 microsecond timer handler */
UltraTimer1Handler(HandleTimer1);
/* Make MODLOAD and MODPLAY use the gus-
specific load,unload and play routines */
ML_RegisterLoader(GusLoad);
ML_RegisterUnLoader(GusUnLoad);
MP_RegisterPlayer(GusPlay);
/* Then try to load and play each module yeah */
InitOpt(argc,argv,"?hHlLxXv:V:");
while((t=GetOpt(&opt,&arg))!=GO_EOF){
if(t==GO_ARG){
if(!PlayWildModule(arg)) break;
}
}
/* Shut sound down & re-init hardware ... */
UltraClose();
return 0;
}