home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
m
/
mtracker.zip
/
MTRACKER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-28
|
72KB
|
2,398 lines
/* NOTE! Remember to LZEXE after compilation! It will reduce EXE size by
more than half... */
#ifndef __COMPACT__
#error Compile with COMPACT memory model!
#endif
#include <alloc.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <dir.h>
#define MAXFILES 200
#define MAXDIRS 100
struct STMHeader {
char name[20];
char tnam[8];
char d1a;
char typ; /* 1 = STS, 2 = STM, 5 = MTS, 6 = MTM */
unsigned int ver;
unsigned char tempo;
unsigned char patnum;
unsigned char volume;
char reserved[13];
struct {
char name[13];
char disk;
char ch; /* Reserved in STM/STS */
unsigned char prg; /* Reserved in STM/STS */
unsigned int length;
unsigned int loops;
unsigned int loope;
unsigned char volume;
unsigned char pan; /* Reserved in STM/STS */
unsigned int rate;
unsigned char nt; /* Reserved in STM/STS */
char reserved[5];
} inst[31];
} stm;
struct BPMHeader {
char name[32];
char typ; /* File type: bit 0-5 = file version
bit 6 = note display
bit 7 = song (0) / module (1) */
char tnam[8];
unsigned int tempo_hi;
unsigned int tempo_lo;
unsigned ihertz;
unsigned int signature; /* high byte / low byte */
struct {
char name[12];
unsigned int length;
unsigned char volume;
unsigned int loops;
unsigned int loope;
unsigned int dummy;
} inst[32];
char dummy[16];
unsigned char patnum;
} bpm;
struct MODHeader {
char name[20];
struct {
char name[22];
unsigned int length; /* Number of words, not bytes */
char finetune;
unsigned char volume; /* 0 .. 64 */
unsigned int loops; /* Start pos in words from start */
unsigned int loopl; /* Loop length in words */
} inst[31];
unsigned char songlength; /* Number of patterns in song
unsigned char dummy; /* Restart byte */
} mod;
unsigned char systemarea[] = { 0xF0, 65, 16, 22, 18,
0x10, 0, 1, /* System Area address */
2, /* [8] Reverb Mode (0,1,2,3) */
5, /* [9] Reverb Time (0..7) */
4, /* [10] Reverb Level (0..7) */
9, 1, 8, 3, 2, 0, 0, 0, 9, /* Partial Resrv */
1, 2, 3, 4, 5, 6, 7, 8, 9, /* MIDI channels */
90, /* [29] Master Volume */
0, /* [30] Checksum */
0xF7 };
unsigned char sampleheader[19] = { 0xF0,0x7E,1,
0, /* [3] = sample number */
0,12, /* 12 bits per word */
0x31,0x63,0x7, /* sampling period in nS */
0,0,0, /* [9] = total words in sample */
0,0,0, /* [12] = loop start */
0,0,0, /* [15] = loop end */
0 }; /* 0 = looping mode */
unsigned char sampleblock[122];
unsigned char sampledata[319] = { 0xF0,0x47,0,10,65,0,0,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
24,0,0,0,0,0,60,1,
0,0, /* undefined */
1,0, /* [265] = loop mode */
0,0,0,0, /* start point */
0,0,0,0, /* undefined */
0,0,0,0, /* [275] = endpoint */
0,0,0,0, /* [279] = loop point */
0,0,0,0, /* undefined */
0,0, /* LFO speed, 0 = 2 Hz */
0,0, /* LFO depth */
0,0, /* LFO delay */
99,0, /* filter */
30,0, /* release */
99,0, /* loudness */
0,0, /* [299] fine tuning */
60,0, /* nominal rec pitch */
60,0, /* [303] rec bandwidth */
0,0, /* forward */
0,0, /* velocity/filter */
50,0, /* velocity/loudness */
0,0, /* velocity/release */
0,0,0,0, /* undefined */
0,0xF7 }; /* [317] = checksum of 7-316 */
unsigned char sampleparam[319];
unsigned samplerates[42] = { 3920,4160,4400,4670,4940,5240,
5550,5880,6230,6600,6990,7410,
7849,8315,8810,9330,9890,10480,
11100,11760,12460,13200,13990,
14820,15697,16630,17620,18670,
19780,20950,22200,23520,24920,
26400,27970,29630,31400,33260,
35240,37340,39560,41900 };
char notes[12][3] = { " C","C#"," D","D#"," E"," F",
"F#"," G","G#"," A","A#"," B" };
typedef unsigned char PA[1024];
PA *pattern[128];
unsigned char orders[256];
unsigned char MIDIch[31]; /* MIDI channels, values 1..16 (0=undefined) */
unsigned char MIDInt[31]; /* MIDI fixed notes (0=original, >128 = transpose) */
unsigned char MIDIprg[31]; /* MIDI programs (0..127) or samples (130-145) */
typedef char *P;
P sample[31];
unsigned int j,urpo;
char defnam[13], apu[80];
char defdir[64] = "C:\\SOUNDS\\ST224\\SONG\\";
char defext[6] = "*.mt?";
char lmode='M';
char allfiles[MAXFILES][13];
char alldirs[MAXDIRS][13];
FILE *f;
int i,MPUok,AKAIok,FILEok,FILE1st,FILElkm,mx,my,mode;
struct text_info tinfo;
char scrbuf[2048];
unsigned char overalldata[33];
/* ---------------------------- Common routines -------------------------- */
void ShowError(viesti)
char *viesti;
{
gotoxy(3,47);
textcolor(YELLOW);
textbackground(RED);
cprintf(" %-75s",viesti);
textcolor(WHITE);
textbackground(BLUE);
return;
}
/* ---------------------------- Midi routines ---------------------------- */
#define COMDPORT 0x331
#define STATPORT 0x331
#define DATAPORT 0x330
#define DRR 0x40
#define DSR 0x80
#define CMD_UART 0x3F
#define CMD_RESET 0xFF
#define MPU_ACK 0xFE
#define GET_VERS 0xAC
unsigned ticktest;
void SetTick()
{
ticktest=(unsigned)peek(0x0040,0x006C);
return;
}
int GoneTicks(tk)
unsigned tk;
{
if (ticktest+tk<(unsigned)peek(0x0040,0x006C))
return 1;
else
return 0;
}
int ResetMPU()
{
outportb(COMDPORT,CMD_RESET);
/* Wait until MPU acknowledges command or 220 ms gone... */
SetTick();
while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
if (inportb(DATAPORT) != MPU_ACK)
{
ShowError("MPU does not acknowledge Reset, starting in demo mode!");
return 0;
}
return 1;
}
int InitMPU()
{
int i,vers=0;
gotoxy(3,47);
cprintf(" %-75s","Initializing MPU-compatible midi interface...");
if (!ResetMPU()) return 0;
SetTick();
if (inportb(STATPORT) & DRR) /* If MPU is not ready to receive yet.. */
{
ShowError("MPU does not respond, starting in demo mode!");
return 0; /* MPU error */
}
/* --- Try to get firmware version --- */
outportb(COMDPORT,GET_VERS);
do {
SetTick();
while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
if (GoneTicks(4))
{
ShowError("MPU does not respond, starting in demo mode!");
return 0; /* MPU error */
}
} while ((vers=inportb(DATAPORT))==MPU_ACK);
/* --- Command MPU to Dumb UART mode --- */
outportb(COMDPORT,CMD_UART);
SetTick();
while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
if (GoneTicks(4) || inportb(DATAPORT) != MPU_ACK)
{
ShowError("MPU does not respond, starting in demo mode!");
return 0; /* MPU error */
}
gotoxy(3,47);
cprintf(" %-75s","MPU-interface initialized OK.");
return vers; /* MPU OK, return firmware version number. */
}
void SendData(dat)
unsigned char dat;
{
if (!MPUok) return;
while ((inportb(STATPORT) & DRR)) /* Wait until MPU ready */ ;
outportb(DATAPORT,dat);
return;
}
int ReceiveData()
{
register int i=20;
while (--i && (inportb(STATPORT) & DSR)) /* Wait until char ready */ ;
if (i) return (inportb(DATAPORT));
else return(256);
}
void ClearMPU() /* Clear MPU data buffer */
{
if (!MPUok) return;
while (!(inportb(STATPORT) & DSR)) inportb(DATAPORT);
return;
}
void SendACK() /* Sends ACK to Akai X7000 */
{
SendData( 0xF0 ); /* Start of SYSEX */
SendData( 0x7E ); /* Common non-realtime code */
SendData( 0x7F ); /* ACKS */
SendData( 0xF7 ); /* End Of SYSEX */
}
int WaitACK()
{
unsigned char handshake[3];
register int i=0,apu;
while ((apu=ReceiveData()) != 0xF0) /* Wait for SYSEX */ ;
while (i<3)
if ((apu=ReceiveData())<256) handshake[i++]=apu;
return (handshake[1]);
}
void SendAkaiEx(fun) /* Sends Akai Exclusive to X7000 */
char fun;
{
SendData( 0xF0 );
SendData( 0x47 ); /* Akai identifier */
SendData( 0 ); /* Midi Channel, 0..15 */
SendData( fun ); /* 1 = Request overall settings,
5 = System Exclusive Common Enable */
SendData( 65 ); /* S700 and X7000 identifier */
SendData( 0 ); /* Sample number */
SendData( 0 );
SendData( 0xF7 );
}
/* ---------------------------- Midi Interrupt Handler ------------------- */
#define INTR 0x08
void interrupt ( *oldhandler)(void);
char INTord,INTpat,INTcount,INTrow,oldrow,oldord;
unsigned char INTtempo, oldtempo;
long INTtime,oldtime;
unsigned char INTnote,INTvol,INTch,INTins,INTstop,INTloop,INTvols,
INTplaying=0,INTi,INTj,INTnotes[4][4];
unsigned char INTvolumes[16]; /* Controller 7 value for each midi ch */
unsigned char *INTp;
void interrupt PlayInt()
{
INTtempo++;
INTcount++;
if (INTcount == 42)
{
if (!INTstop) INTtime+=55; /* 55 ms per original tick */
oldhandler(); /* Go to original if about 55 ms gone */
INTcount=0;
}
else
outportb(0x20,0x20); /* End-of-interrupt */
if (INTtempo == stm.tempo && !INTstop) /* Time to play a quarternote */
{
INTtempo=0;
INTp = (char *)pattern[INTpat]+((unsigned)INTrow << 4);
for (INTi=0;INTi<4;INTi++,INTp+=4) /* Handle all 4 tracks in a loop */
{
/* Check if a command */
switch(*(INTp+2) & 15)
{
case 1: /* Set timebase to [INFO] */
stm.tempo = *(INTp+3);
break;
case 2: /* B?? = Break pattern and jump to order [INFO] */
INTord=*(INTp+3);
INTrow=-1;
INTpat=orders[INTord];
break;
case 3: /* C00 = Break pattern */
INTrow=63;
break;
default:break; /* No command */
}
/* Get the note volume = velocity */
INTvol=((*(INTp+1) & 7) << 1) + (*(INTp+2) & 0xF0);
if (INTvol==128) INTvol=127;
/* INTch = currently playing midich on this track */
INTch=INTnotes[INTi][1];
/* Play a new note */
if (*INTp<251)
{
INTins=*(INTp+1) >> 3; /* Instrument number */
if (!INTins) /* Instrument == 0 -> use previus instrument */
{
INTins=INTnotes[INTi][2]; /* Instrument # */
}
else /* Instrument > 0 -> normal case */
{
if (!(INTch=MIDIch[INTins-1])) continue; /* No MIDI ch */
INTch+=0x8F;
}
if (INTvol==130) INTvol=stm.inst[INTins-1].volume;
/* Check if a fixed note */
if ((INTnote=MIDInt[INTins-1])==0)
INTnote=36+(*INTp & 15)+12*(*INTp >> 4);
/* Check if transposed note */
else if (INTnote>128)
INTnote=36+(*INTp & 15)+12*(*INTp >> 4) + (INTnote - 192);
/* Turn off previous note on this channel (1..4) */
if (INTnotes[INTi][1])
{
switch (INTi)
{
case 0:
if ( (INTnotes[0][1]==INTnotes[1][1] &&
INTnotes[0][0]==INTnotes[1][0]) ||
(INTnotes[0][1]==INTnotes[2][1] &&
INTnotes[0][0]==INTnotes[2][0]) ||
(INTnotes[0][1]==INTnotes[3][1] &&
INTnotes[0][0]==INTnotes[3][0]) )
goto no_off;
break;
case 1:
if ( (INTnotes[1][1]==INTnotes[0][1] &&
INTnotes[1][0]==INTnotes[0][0]) ||
(INTnotes[1][1]==INTnotes[2][1] &&
INTnotes[1][0]==INTnotes[2][0]) ||
(INTnotes[1][1]==INTnotes[3][1] &&
INTnotes[1][0]==INTnotes[3][0]) )
goto no_off;
break;
case 2:
if ( (INTnotes[2][1]==INTnotes[1][1] &&
INTnotes[2][0]==INTnotes[1][0]) ||
(INTnotes[2][1]==INTnotes[0][1] &&
INTnotes[2][0]==INTnotes[0][0]) ||
(INTnotes[2][1]==INTnotes[3][1] &&
INTnotes[2][0]==INTnotes[3][0]) )
goto no_off;
break;
case 3:
if ( (INTnotes[3][1]==INTnotes[1][1] &&
INTnotes[3][0]==INTnotes[1][0]) ||
(INTnotes[3][1]==INTnotes[2][1] &&
INTnotes[3][0]==INTnotes[2][0]) ||
(INTnotes[3][1]==INTnotes[0][1] &&
INTnotes[3][0]==INTnotes[0][0]) )
goto no_off;
break;
}
/* Clear a note off the screen */
pokeb(0xB800,1610+160*(unsigned)INTnotes[INTi][2],' ');
SendData( INTnotes[INTi][1] ); /* Note On */
SendData( INTnotes[INTi][0] );
SendData( 0 ); /* Velocity=0 -> Note Off */
}
no_off:
/* Show a note on the screen */
pokeb(0xB800,1610+160*(unsigned)INTins,14);
if (INTvols && INTvolumes[INTch & 15] != INTvol)
{
SendData( INTch + 0x20 ); /* Bx = Controller */
SendData( 7 ); /* 7 = Main Volume */
SendData( (INTvol >> 1) + 64 ); /* New Volume */
INTvolumes[INTch & 15]=INTvol; /* Remember volume */
}
INTnotes[INTi][0]=INTnote; /* Remember which note */
INTnotes[INTi][1]=INTch; /* Remember which MIDI ch */
INTnotes[INTi][2]=INTins; /* Remember which instrument */
INTnotes[INTi][3]=INTvol; /* Remember what volume */
SendData( INTch ); /* Note On */
SendData( INTnote ); /* Note value */
if (INTvols)
SendData( 127 ); /* Velocity */
else
SendData( INTvol ); /* Velocity */
}
/* Check for other than note on - commands. Can be note off, */
/* volume change or no change */
else if (INTch) /* If there was a note on this track */
{
/* Turn a note off? */
if (*INTp==254)
{
SendData( INTch ); /* Note On */
SendData( INTnotes[INTi][0] ); /* Note value */
SendData( 0 ); /* Velocity -> Note Off */
INTnotes[INTi][1]=0; /* Tell we play nothing */
}
/* Volume change? */
else if (INTvols && INTvol != INTnotes[INTi][3])
{
if (INTvol==130) /* Default instrument volume */
INTvol=stm.inst[INTnotes[INTi][2]-1].volume;
SendData( INTch + 0x20 ); /* Bx = Controller */
SendData( 7 ); /* 7 = Main Volume */
SendData( (INTvol >> 1) + 64 ); /* New Volume */
INTvolumes[INTch & 15]=INTvol; /* Save midich-vol */
INTnotes[INTi][3]=INTvol; /* Save track-volume */
}
}
}
if (INTrow++ == 63) /* If next pattern... */
{
INTrow=0;
INTpat=orders[++INTord];
if (INTpat>=stm.patnum) /* If all patterns done... */
{
INTord=0;
INTpat=orders[0];
if (!INTloop)
INTstop=1;
else
INTtime=0L;
}
}
}
}
void Silent()
{
int i;
for (i=0;i<4;i++)
{
if (INTnotes[i][0]) /* If there was a note on this channel... */
{
SendData( INTnotes[i][1] ); /* Note Off */
SendData( INTnotes[i][0] );
SendData( 0 );
INTnotes[i][0]=0;
}
}
return;
}
void ShowTime(tim)
long tim;
{
gotoxy(24,6);
cprintf("%2d:%02d:%02d",
(int)(tim/60000L),
((int)(tim/1000L)) % 60,
(int)(tim % 100L));
return;
}
void ShowPat(pat,row)
int pat,row;
{
int i;
unsigned char *p = (char *)pattern[pat] + (row << 4);
unsigned char vol;
if (!FILEok) return;
gotoxy(4,45);
cprintf("%3d:%2d",pat,row);
for (i=0;i<4;i++)
{
/* Note, 255 = no change, 254 = off */
gotoxy(13+i*17,45);
if (*p<251)
cprintf("%2.2s%d",notes[*p & 15],(*p >> 4)+3);
else if (*p==254)
cprintf(" ");
/* Instrument, 0 = no change */
if (*(p+1) & 0xF8)
{
gotoxy(17+i*17,45);
cprintf("%2d",*(p+1) >> 3);
}
/* Volume, 130 = use default for this instrument */
vol=((*(p+1) & 7) << 1) + (*(p+2) & 0xF0);
if (vol==128)
vol=127;
gotoxy(20+i*17,45);
if (*p<251 || stm.ver < 15)
if (vol==130)
cprintf("max");
else
cprintf("%3d",vol);
/* Command */
gotoxy(24+i*17,45);
if (*(p+2) & 15)
cprintf("%c%02X",(*(p+2) & 15)+64,*(p+3));
else
cprintf(" ");
p += 4;
}
return;
}
void ShowOrd(cnt)
unsigned char cnt;
{
int i,j,k;
if (!FILEok) return;
if (cnt<5)
{
j=0;
k=cnt+5;
}
else if (cnt>122)
{
j=116;
k=cnt-111;
}
else
{
j=cnt-5;
k=10;
}
for (i=0;i<12;i++,j++)
{
gotoxy(52,i+5);
if (orders[j] < 99)
cprintf("%3d ",orders[j]);
else
cprintf(" ");
}
gotoxy(55,k);
putch(17);
return;
}
void Play()
{
unsigned i;
if (!FILEok) return;
INTcount=41;
INTtempo=stm.tempo-1;
INTstop=0;
for (i=0;i<4;i++) INTnotes[i][0]=0;
gotoxy(3,47);
cprintf(" %-75s","Playing song...");
oldrow=INTrow;
ShowPat(INTpat,INTrow);
ShowOrd(INTord);
ShowTime(INTtime);
gotoxy(63,16);
if (INTloop)
putch(2);
else
putch(1);
gotoxy(63,14);
if (INTvols)
putch(2);
else
putch(1);
for (i=11+160*11;i<11+42*160;i+=160)
pokeb(0xB800,i,YELLOW+16*BLUE);
for (i=0;i<31;i++) /* Go through all the MIDI tracks... */
{
if (i<16) INTvolumes[i]=0;
if (!INTvols && MIDIch[i])
{
/* --- Send Volume values --- */
SendData ( 0xB0 + MIDIch[i] - 1 ); /* Controller */
SendData ( 0x07 ); /* Main Volume */
SendData ( stm.inst[i].volume ); /* Send Volume value */
}
}
if (!INTplaying)
{
oldhandler = getvect(INTR);
disable(); /* Disable interrupts */
outportb(0x43,0x34);
outportb(0x40,15);
outportb(0x40,6); /* Frequency = 1191564/1551 ≈ 768 Hz ≈ 128 BPM */
outportb(0x43,0x90);
setvect(INTR, PlayInt);
enable(); /* Enable interrupts */
}
INTplaying=1;
return;
}
void Stop()
{
unsigned i;
if (!FILEok) return;
if (INTplaying)
{
disable(); /* Disable interrupts */
outportb(0x43,0x34);
outportb(0x40,0);
outportb(0x40,0); /* Frequency = 1191564/65536 = 18.18 Hz */
enable(); /* Enable interrupts */
setvect(INTR, oldhandler);
}
for (i=10+160*11;i<10+42*160;i+=160)
pokeb(0xB800,i,' ');
gotoxy(3,47);
cprintf(" %-75s","Play stopped.");
INTrow=0;
INTord=0;
INTpat=orders[INTord];
INTtime=0L;
INTplaying=0;
Silent();
stm.tempo=96;
textcolor(WHITE);
gotoxy(12,5);
cprintf("%3d",stm.tempo);
ShowPat(INTpat,INTrow);
ShowOrd(INTord);
return;
}
void Pause()
{
if (!FILEok) return;
if (INTplaying)
{
disable(); /* Disable interrupts */
outportb(0x43,0x34);
outportb(0x40,0);
outportb(0x40,0); /* Frequency = 1191564/65536 = 18.18 Hz */
enable(); /* Enable interrupts */
setvect(INTR, oldhandler);
}
gotoxy(3,47);
cprintf(" %-75s","Play paused.");
INTplaying=0;
Silent();
ShowPat(INTpat,INTrow);
ShowOrd(INTord);
ShowTime(INTtime);
return;
}
void ShowPlay()
{
int i;
if (!INTplaying || !FILEok) return;
if (INTstop)
Stop();
else if (INTtime != oldtime)
{
if (stm.tempo != oldtempo)
{
oldtempo = stm.tempo;
textcolor(WHITE);
gotoxy(12,5);
cprintf("%3d",stm.tempo);
}
ShowTime(INTtime);
oldtime = INTtime;
if (INTrow != oldrow)
{
ShowPat(INTpat,oldrow);
oldrow=INTrow;
if (INTord != oldord)
{
ShowOrd(INTord);
oldord=INTord;
}
}
}
return;
}
/* ---------------------------- Mouse routines --------------------------- */
void MoveMouse(x,y)
int x,y;
{
struct REGPACK reg;
reg.r_ax=4;
reg.r_cx=x;
reg.r_dx=y;
intr(0x33,®);
return;
}
int InitMouse()
{
struct REGPACK reg;
reg.r_ax = 0;
intr(0x33,®);
if (reg.r_ax==0xffff)
{
unsigned buttons=reg.r_bx;
reg.r_ax=8;
reg.r_cx=0;
reg.r_dx=399;
intr(0x33,®); /* Vertical area 0..49 */
reg.r_ax=10;
reg.r_bx=0;
reg.r_cx=0x00FF;
reg.r_dx=0x0E00;
intr(0x33,®); /* Define software text cursor masks */
MoveMouse(0,0);
return buttons;
}
else
return 0;
}
void MouseOn()
{
struct REGPACK reg;
reg.r_ax=1;
intr(0x33,®);
return;
}
void MouseOff()
{
struct REGPACK reg;
reg.r_ax=2;
intr(0x33,®);
return;
}
int GetClick(mx,my)
int *mx,*my;
{
static int bdown;
struct REGPACK reg;
reg.r_ax = 6;
reg.r_bx = 0;
intr(0x33,®);
if (!(reg.r_ax & 1)) bdown=0;
if (bdown) return 0; /* Don't check presses until released, too */
reg.r_ax = 5;
reg.r_bx = 0;
intr(0x33,®);
*mx = (reg.r_cx >> 3)+1;
*my = (reg.r_dx >> 3)+1;
if (reg.r_ax & 1) bdown=1;
return (reg.r_ax & 1);
}
void GetMouse(mx,my)
int *mx,*my;
{
struct REGPACK reg;
reg.r_ax = 3;
reg.r_bx = 0;
intr(0x33,®);
*mx = (reg.r_cx >> 3)+1;
*my = (reg.r_dx >> 3)+1;
ShowPlay();
gotoxy(*mx,*my);
return;
}
/* ---------------------------- Special routines ------------------------- */
void CalcChecksum(dat,pos)
unsigned char *dat;
int pos;
{
unsigned int checksum=0,i;
for (i=5;i<pos;i++) checksum+=dat[i];
checksum = (128 - (checksum % 128)) % 128;
dat[pos]=(unsigned char)checksum;
return;
}
int InitLAPC(mode)
char mode;
{
int i;
if (!AKAIok) return 0;
if (mode)
for (i=20;i<28;i++) systemarea[i]=16; /* Part OFF */
else
for (i=20;i<28;i++) systemarea[i]=i-19; /* Part ON */
CalcChecksum(systemarea,30);
gotoxy(3,47);
cprintf(" %-75s","Initializing LAPC-I synth module...");
for (i=0;i<100;i++) ReceiveData();
for (i=0;i<32;i++) SendData(systemarea[i]);
gotoxy(3,47);
cprintf(" %-75s","LAPC-I synth initialized OK.");
return 1;
}
int InitAkai() /* Request and send overall parameters from/to Akai X7000 */
{
int apu,i=0;
if (!MPUok) return 0;
gotoxy(3,47);
cprintf(" %-75s","Initializing Akai X7000 sampler...");
SendAkaiEx(5); /* Enable system common reception */
ClearMPU(); /* Empty the MPU buffer */
SendAkaiEx(1); /* Request overall parameters */
SetTick();
do {
if ((apu=ReceiveData())<256)
{
overalldata[i++]=apu;
SetTick();
}
} while (!GoneTicks(6) && i<33); /* Until EOX */
if (GoneTicks(6) || apu != 247)
{
ShowError("AKAI X7000 does not respond, using plain synth mode!");
return 0;
}
/* Change parameters the way we want them... */
overalldata[7]=0; /* Midi Reception Channel = 1 */
overalldata[2]=0; /* MIDI Channel no. (in header) = 1 */
overalldata[11]=0; /* Midi Transmission Channel = 1 */
overalldata[9]=3; /* Polyphonic */
overalldata[13]=64; /* Multi Program */
overalldata[14]=0; /* - // - */
overalldata[15]=12; /* Pitch Wheel Range = 1 octave */
overalldata[17]=127; /* Program Change Off */
overalldata[18]=1; /* - // - */
/* Clear and calculate XOR checksum... */
for (overalldata[31]=0,i=7;i<31;i++) overalldata[31] ^= overalldata[i];
/* Send Overall Settings to Akai */
for (i=0;i<33;i++) SendData(overalldata[i]);
gotoxy(3,47);
cprintf(" %-75s","Akai X7000 sampler initialized OK.");
return 1;
}
void DoParams(endp,loopp)
unsigned endp,loopp;
{
if (loopp<endp) sampleparam[265]=2; /* Looping Mode */
sampleparam[275]=endp & 127;
sampleparam[276]=(endp >> 7) & 1;
sampleparam[277]=(endp >> 8) & 127;
sampleparam[278]=endp >> 15;
sampleparam[279]=loopp & 127;
sampleparam[280]=(loopp >> 7) & 1;
sampleparam[281]=(loopp >> 8) & 127;
sampleparam[282]=loopp >> 15;
sampleheader[9] = endp & 127;
sampleheader[10]=(endp >> 7) & 127;
sampleheader[11]=(endp >> 14) & 127;
sampleheader[12]= loopp & 127;
sampleheader[13]=(loopp >> 7) & 127;
sampleheader[14]=(loopp >> 14) & 127;
sampleheader[15]=endp & 127;
sampleheader[16]=(endp >> 7) & 127;
sampleheader[17]=(endp >> 14) & 127;
return;
}
void SendInit() /* Sending Program/Sample, Volume and Pan data to synths. */
{
int i,j,semitone,apui,trk;
char sfntun;
unsigned char smpl,rate;
unsigned char *p;
unsigned k,blk,apuw;
long drate,apul;
if (!FILEok) return;
gotoxy(3,47);
cprintf(" %-75s","Sending Program, Sample, Volume and Pan data...");
for (trk=0;trk<31;trk++) /* Go through all the MIDI tracks... */
if (MIDIch[trk]) /* Handle only tracks that have channel assigned... */
{
/* --- Send Pan values --- */
SendData ( 0xB0 + MIDIch[trk] - 1 ); /* Controller */
SendData ( 0x0A ); /* Pan Position */
SendData ( stm.inst[trk].pan ); /* Send Pan value */
/* --- Send Volume values --- */
SendData ( 0xB0 + MIDIch[trk] - 1 ); /* Controller */
SendData ( 0x07 ); /* Main Volume */
SendData ( stm.inst[trk].volume ); /* Send Volume value */
/* --- Send Program / Sample information --- */
if (MIDIprg[trk]<128) /* Send just program data, no samples */
{
SendData ( 0xC0 + MIDIch[trk] - 1 ); /* Program Change */
SendData ( MIDIprg[trk] ); /* Send new patch number */
}
else if (MIDIprg[trk]>129 && AKAIok && stm.inst[trk].length>=200 &&
(p=sample[trk])!=NULL) /* Test if OK to send sample data. */
{
gotoxy(3,47);
cprintf(" %-75s"," ");
smpl=MIDIprg[trk]-130; /* smpl = sample number */
sampleheader[3]=smpl; /* Set header sample number */
memcpy(sampleparam,sampledata,319); /* Make parameter work area */
sampleparam[5]=smpl; /* Set sample parameter sample number */
if (stm.inst[trk].loope != 65535) /* Looped sample */
{
if (stm.inst[trk].loope<stm.inst[trk].length)
stm.inst[trk].length=stm.inst[trk].loope;
else if (stm.inst[trk].loope>stm.inst[trk].length)
stm.inst[trk].loope=stm.inst[trk].length;
DoParams(stm.inst[trk].loope,stm.inst[trk].loops);
}
else
DoParams(stm.inst[trk].length,stm.inst[trk].length);
/* --- Send Raw Sample --- */
ClearMPU(); /* Empty the MPU buffer */
for (i=0;i<19;i++) SendData(sampleheader[i]);
if (WaitACK() != 0x7F)
{
ShowError("Akai does not acknowledge sample header!");
return;
}
k=0; blk=0;
do {
sampleblock[0]=blk++ & 127;
for (sampleblock[121]=0,j=1;j<61;j++,k++)
{
sampleblock[121] ^=
(sampleblock[j+j-1]=((*p ^ 0x80) >> 5) + 60);
sampleblock[121] ^=
(sampleblock[j+j]=(*(p++) & 31) << 2);
}
for (i=0;i<122;i++) SendData(sampleblock[i]);
if ((WaitACK()) != 0x7F)
{
ShowError("Akai does not acknowledge sample block!");
continue;
}
gotoxy(3,47);
cprintf(" Sending sample %d point %d... ",smpl+1,k);
} while (k < stm.inst[trk].length);
SendData(0xF7); /* Send EOX */
/* --- Send sample parameters --- */
drate=(long)stm.inst[trk].rate;
apuw=65000;
for (i=0;i<41;i++)
{
apul=samplerates[i];
if ((unsigned)abs(apul-drate) < apuw)
{
rate=i+36;
apuw=(unsigned)abs(apul-drate);
apui=(int)(drate-apul);
}
}
semitone = (int)(drate/24);
apui = apui % semitone;
sfntun = 16 * apui / semitone;
sampleparam[299]=sfntun & 127;
sampleparam[300]=(sfntun >> 7) & 1;
sampleparam[303]=rate;
sampleparam[1+8*MIDIch[trk]]=99; /* Keyrange for AKAI program */
for (sampleparam[317]=0,i=7;i<317;i++)
sampleparam[317] ^= sampleparam[i];
for (i=0;i<319;i++) SendData(sampleparam[i]);
}
}
gotoxy(3,47);
cprintf(" %-75s","Initialization data sent OK.");
return;
}
int ShowFiles()
{
int done,lkm=0;
char haku[80];
struct ffblk ffb;
strcpy(haku,defdir);
strcat(haku,defext);
textcolor(WHITE);
gotoxy(53,18);
cprintf("%-25.25s",defdir);
window(52,22,77,40);
clrscr();
window(52,22,77,41);
done = findfirst(haku,&ffb,0);
while (!done)
{
if (lkm<38) cprintf(" %-12s",ffb.ff_name);
if (lkm<MAXFILES) strcpy(allfiles[lkm],ffb.ff_name);
lkm++;
done=findnext(&ffb);
}
for(;lkm<MAXFILES;lkm++) allfiles[lkm][0]='\0';
window(1,1,80,50);
return (lkm);
}
int ShowDirs(haku)
char *haku;
{
int done,lkm=0;
char apu[80];
struct ffblk ffb;
strcpy(apu,haku);
strcat(apu,"*");
textcolor(WHITE);
gotoxy(53,18);
cprintf("%-25.25s",haku);
window(52,22,77,40);
clrscr();
done = findfirst(apu,&ffb,FA_DIREC);
while (!done)
{
if (ffb.ff_attrib==FA_DIREC)
{
if (lkm<38) cprintf(" %-12s",ffb.ff_name);
if (lkm<MAXDIRS) strcpy(alldirs[lkm],ffb.ff_name);
lkm++;
}
done=findnext(&ffb);
}
for(;lkm<MAXDIRS;lkm++) alldirs[lkm][0]='\0';
window(1,1,80,50);
return (lkm);
}
void ChangeDir(nam)
char *nam;
{
int i;
if (!strcmp(nam,"..")) /* If one directory up.. */
{
i=strlen(defdir)-2;
while (defdir[i] != '\\') defdir[i--]='\0';
}
else if (!strcmp(nam,".")) return; /* Nothing to do, if current dir */
else
{
strcat(defdir,nam);
strcat(defdir,"\\");
}
gotoxy(53,18);
cprintf("%-25.25s",defdir);
return;
}
int ChangeDrive(nam)
char nam;
{
strcpy(defdir,"X:\\");
defdir[0]=nam+'A';
if (getcurdir(nam+1,defdir+3))
{
ShowError("Error: Drive not valid!");
return 0;
}
if (defdir[strlen(defdir)-1] != '\\') strcat(defdir,"\\");
gotoxy(53,18);
cprintf("%-25.25s",defdir);
gotoxy(3,47);
cprintf(" %-75s","New default drive selected.");
return 1;
}
int SelectDrive()
{
int i;
gettext(51,20,56,29,scrbuf);
window(51,20,56,29);
textcolor(LIGHTGRAY);
clrscr();
cprintf("╔════╗║ ║║ ║║ ║║ ║║ ║║ ║║ ║║ ║╚════");
window(1,1,80,50);
gotoxy(56,29);putch('╝');
textcolor(WHITE);
for (i=0;i<8;i++)
{
gotoxy(53,21+i);
putch(i+'C');putch(':');
}
gotoxy(2,49);
cprintf("Select drive to make current.\r");
do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
if (mx>51 && mx<56 && my>20 && my<29) /* If selected a drive... */
i=ChangeDrive(my-19);
else
i=0;
MouseOff();
puttext(51,20,56,29,scrbuf);
MouseOn();
return i;
}
void SelectCh(trk)
unsigned char trk;
{
int i;
gettext(24,12,29,30,scrbuf);
window(24,12,29,30);
textcolor(LIGHTGRAY);
clrscr();
cprintf("╔════╗║ ║║ ║║ ║║ ║║ ║║ ║║ ║║ ║");
cprintf("║ ║║ ║║ ║║ ║║ ║║ ║║ ║║ ║║ ║╚════");
window(1,1,80,50);
gotoxy(29,30);putch('╝');
textcolor(WHITE);
gotoxy(26,13);
cprintf("--");
for (i=1;i<17;i++)
{
gotoxy(26,13+i);
cprintf("%2d",i);
}
gotoxy(2,49);
cprintf("Select MIDI channel for track %d.\r",trk);
do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
if (mx>25 && mx<28 && my>12 && my<30) /* If selected a channel... */
MIDIch[trk]=my-13;
MouseOff();
puttext(24,12,29,30,scrbuf);
for (i=0;i<31;i++)
{
gotoxy(32,12+i);
if (MIDIch[i]) { textcolor(WHITE); cprintf("%2d",MIDIch[i]); }
else { textcolor(LIGHTGRAY); cprintf("__"); }
}
textcolor(WHITE);
MouseOn();
return;
}
void SelectNote(trk)
unsigned char trk;
{
int i,oct,not;
MouseOff();
gettext(16,12,65,29,scrbuf);
textcolor(LIGHTGRAY);
gotoxy(16,12);
cprintf("╔════════════════════════════════════════════════╗");
for (not=13;not<29;not++)
{
gotoxy(16,not);putch('║');
gotoxy(65,not);putch('║');
}
gotoxy(16,29);
cprintf("╚════════════════════════════════════════════════╝");
window(17,13,64,28);
textcolor(WHITE);
clrscr();
window(17,13,64,29);
/* Fixed notes */
for (oct=0;oct<10;oct++)
for (not=0;not<12;not++)
cprintf("%2s%d ",notes[not],oct);
/* Transposed notes */
for (not=-36;not<0;not++)
cprintf("%02d ",not);
for (not=0;not<36;not++)
cprintf("+%02d ",not);
gotoxy(1,1);cprintf(" --");
window(1,1,80,50);
MouseOn();
do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
if (mx>16 && mx<65 && my>12 && my<23) /* If selected a fixed note... */
MIDInt[trk]=(my-13)*12+(mx-17)/4;
else if (mx>16 && mx<65 && my>22 && my<29) /* If selected a fixed note... */
MIDInt[trk]=192 + (my-26)*12 + (mx-17)/4;
MouseOff();
puttext(16,12,65,29,scrbuf);
for (i=0;i<31;i++)
{
gotoxy(47,12+i);
if ( MIDInt[i] > 0 && MIDInt[i] < 128 )
{
textcolor(WHITE);
cprintf("%2s%d",notes[MIDInt[i] % 12],MIDInt[i] / 12);
}
else if ( MIDInt[i] > 191 )
{
textcolor(WHITE);
cprintf("+%02d",MIDInt[i] - 192);
}
else if ( MIDInt[i] > 127 )
{
textcolor(WHITE);
cprintf("%02d",MIDInt[i] - 192);
}
else
{
textcolor(LIGHTGRAY);
cprintf("___");
}
}
MouseOn();
textcolor(WHITE);
return;
}
void SelectPrg(trk)
unsigned char trk;
{
int i;
MouseOff();
gettext(23,11,56,30,scrbuf);
textcolor(LIGHTGRAY);
gotoxy(23,11);
cprintf("╔════════════════════════════════╗");
for (i=12;i<30;i++)
{
gotoxy(23,i);putch('║');
gotoxy(56,i);putch('║');
}
gotoxy(23,30);
cprintf("╚════════════════════════════════╝");
window(24,12,55,29);
clrscr();
window(24,12,55,30);
textcolor(WHITE);
cprintf("S01 S02 S03 S04 S05 S06 S07 S08 ");
cprintf("S09 S10 S11 S12 S13 S14 S15 S16 ");
for (i=1;i<129;i++) cprintf("%3d ",i);
window(1,1,80,50);
MouseOn();
do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
if (mx>23 && mx<56 && my>13 && my<30) /* If selected a program... */
MIDIprg[trk]=(my-14)*8+(mx-24)/4;
else if (mx>23 && mx<56 && my>11 && my<14) /* If selected a sample... */
MIDIprg[trk]=130+(my-12)*8+(mx-24)/4;
else
MIDIprg[trk]=128;
MouseOff();
puttext(23,11,56,30,scrbuf);
for (i=0;i<31;i++)
{
gotoxy(35,12+i);
if (MIDIprg[i] < 128) /* Programs = 0..127 */
{
textcolor(WHITE);
cprintf("%3d",MIDIprg[i]+1); /* Show them as 1..128 */
}
else if (MIDIprg[i] > 129) /* Samples = 130-135 */
{
textcolor(WHITE);
cprintf("S%02d",MIDIprg[i]-129);
}
else /* Undefined = 128 */
{
MIDIprg[i]=128;
textcolor(LIGHTGRAY);
cprintf("___");
}
}
MouseOn();
textcolor(WHITE);
return;
}
void ToggleDisp()
{
static int mode;
int i;
if (!FILEok) return;
mode ^= 1;
gotoxy(20,11);
textcolor(LIGHTGRAY);
if (mode)
cprintf("LoopS LoopE");
else
cprintf("Bytes Hz");
textcolor(WHITE);
MouseOff();
for (i=0;i<31;i++)
{
if (stm.inst[i].length)
{
gotoxy(20,12+i);
if (mode)
{
if (stm.inst[i].loope != 65535)
{
cprintf("%5u",stm.inst[i].loops);
gotoxy(26,12+i);
cprintf("%5u",stm.inst[i].loope);
}
else
{
textcolor(LIGHTGRAY);
cprintf("_____ _____");
textcolor(WHITE);
}
}
else
{
cprintf("%5u",stm.inst[i].length);
gotoxy(26,12+i);
cprintf("%5d",stm.inst[i].rate);
}
}
}
MouseOn();
return;
}
void ClearSong()
{
int i;
textcolor(LIGHTGRAY);
gotoxy(12,4);
cprintf("____________________");
gotoxy(12,8);
cprintf("________");
gotoxy(23,8);
cprintf(" ");
gotoxy(12,5);
cprintf("___");
gotoxy(12,6);
cprintf("___");
gotoxy(12,7);
cprintf("___");
for (i=0;i<31;i++)
{
MIDInt[i]=0; /* Undefined note */
gotoxy(47,12+i);
cprintf("___");
MIDIch[i]=0; /* Undefined channel */
gotoxy(32,12+i);
cprintf("__");
MIDIprg[i]=128; /* Undefined program */
gotoxy(35,12+i);
cprintf("___");
gotoxy(7,12+i);
cprintf("____________");
gotoxy(20,12+i);
cprintf("_____");
gotoxy(26,12+i);
cprintf("_____");
gotoxy(39,12+i);
cprintf("___");
gotoxy(43,12+i);
cprintf("___");
}
gotoxy(4,45);
cprintf("___:__");
for (i=0;i<4;i++)
{
gotoxy(13+i*17,45);
cprintf("___ __ ___ ___");
}
for (i=0;i<12;i++)
{
gotoxy(52,i+5);
cprintf(" ");
}
textcolor(WHITE);
return;
}
void ShowSong()
{
int i;
textcolor(WHITE);
gotoxy(12,4);
cprintf("%-20.20s",stm.name);
gotoxy(12,8);
cprintf("%8.8s",stm.tnam);
gotoxy(23,8);
cprintf("%d.%d ", stm.ver & 255, stm.ver >> 8);
gotoxy(12,5);
cprintf("%3d",stm.tempo);
gotoxy(12,6);
cprintf("%3d",stm.volume);
gotoxy(12,7);
cprintf("%3d",stm.patnum);
for (i=0;i<31;i++)
{
if (!stm.inst[i].length)
{
textcolor(LIGHTGRAY);
gotoxy(7,12+i);
cprintf("____________");
gotoxy(20,12+i);
cprintf("_____");
gotoxy(26,12+i);
cprintf("_____");
gotoxy(39,12+i);
cprintf("___");
gotoxy(43,12+i);
cprintf("___");
MIDInt[i]=0; /* Undefined note */
gotoxy(47,12+i);
cprintf("___");
MIDIch[i]=0; /* Undefined channel */
gotoxy(32,12+i);
cprintf("__");
MIDIprg[i]=128; /* Undefined program */
gotoxy(35,12+i);
cprintf("___");
continue;
}
if (stm.typ & 4) /* MidiTracker modules */
{
MIDInt[i]=stm.inst[i].nt;
gotoxy(47,12+i);
if ( MIDInt[i] > 0 && MIDInt[i] < 128 )
{
textcolor(WHITE);
cprintf("%2s%d",notes[MIDInt[i] % 12],MIDInt[i] / 12);
}
else if ( MIDInt[i] > 191 )
{
textcolor(WHITE);
cprintf("+%02d",MIDInt[i] - 192);
}
else if ( MIDInt[i] > 127 )
{
textcolor(WHITE);
cprintf("%02d",MIDInt[i] - 192);
}
else
{
textcolor(LIGHTGRAY);
cprintf("___");
}
MIDIch[i]=stm.inst[i].ch;
gotoxy(32,12+i);
if (MIDIch[i]) { textcolor(WHITE); cprintf("%2d",MIDIch[i]); }
else { textcolor(LIGHTGRAY); cprintf("__"); }
MIDIprg[i]=stm.inst[i].prg;
gotoxy(35,12+i);
if (MIDIprg[i] < 128) /* Programs = 0..127 */
{
textcolor(WHITE);
cprintf("%3d",MIDIprg[i]+1); /* Show them as 1..128 */
}
else if (MIDIprg[i] > 129) /* Samples = 130-145 */
{
textcolor(WHITE);
cprintf("S%02d",MIDIprg[i]-129);
}
else /* Undefined = 128 */
{
MIDIprg[i]=128;
textcolor(LIGHTGRAY);
cprintf("___");
}
}
else /* STM modules */
{
textcolor(LIGHTGRAY);
MIDInt[i]=0; /* Undefined note */
gotoxy(47,12+i);
cprintf("___");
MIDIch[i]=0; /* Undefined channel */
gotoxy(32,12+i);
cprintf("__");
MIDIprg[i]=128; /* Undefined program */
gotoxy(35,12+i);
cprintf("___");
stm.inst[i].volume=stm.inst[i].volume+63; /* 64 -> 127 */
stm.inst[i].pan=64; /* Pan to middle */
}
textcolor(WHITE);
gotoxy(7,12+i);
cprintf("%-12s",stm.inst[i].name);
gotoxy(20,12+i);
cprintf("%5u",stm.inst[i].length);
gotoxy(26,12+i);
cprintf("%5d",stm.inst[i].rate);
gotoxy(39,12+i);
cprintf("%3d",stm.inst[i].volume);
gotoxy(43,12+i);
cprintf("%3d",stm.inst[i].pan);
}
textcolor(WHITE);
INTord=0;
ShowOrd(INTord);
INTpat=orders[0];
ShowPat(INTpat,0);
return;
}
void ConvertPattern()
{
unsigned int w2;
unsigned char b1, b2, b3, b4, b5, b6;
unsigned char *p = (unsigned char *)pattern[i];
for (j=0;j<256;j++) /* Handle 256 notes = 4 ch * 64 rows */
{
w2 = *p & 0x0F;
w2 = (w2 << 8) + *(p+1);
if ( ! w2 )
{
b1 = 0x0F;
b2 = 0x0F;
b3 = 0;
}
else
{
b2 = 2;
do {
if (w2<220)
{
b2++;
w2 = w2 << 1;
}
if (w2>440)
{
b2--;
w2 = w2 >> 1;
}
} while (w2<220 || w2>440);
if ( w2>424 && w2<431) b1=0;
else if ( w2>399 && w2<411) b1=1;
else if ( w2>378 && w2<385) b1=2;
else if ( w2>356 && w2<366) b1=3;
else if ( w2>334 && w2<343) b1=4;
else if ( w2>316 && w2<325) b1=5;
else if ( w2>298 && w2<306) b1=6;
else if ( w2>280 && w2<290) b1=7;
else if ( w2>264 && w2<275) b1=8;
else if ( w2>249 && w2<260) b1=9;
else if ( w2>236 && w2<244) b1=10;
else if ( w2>223 && w2<231) b1=11;
b3 = (*(p+2) >> 4) + (*p & 0x10); /* Instrument */
}
b4 = 65;
b5 = *(p+2) & 15; /* Command */
b6 = *(p+3); /* Command byte */
switch (b5) /* Commands */
{
case 0: b5=0;break; /* $A */
case 1: b5=6;break;
case 2: b5=5;break;
case 3: b5=7;break;
case 4: b5=8;break;
case 0x0A: b5=4;break;
case 0x0B: b5=2;break;
case 0x0C:
b4=b6;
b5=0;
b6=0;
if (b4>64) b4=64;
break;
case 0x0D: b5=3;break;
case 0x0F:
b5=1;
b6=b6*16;
break;
default: b5=0;
}
if (b5==0) b6=0;
*(p) = b1 + (b2 << 4);
*(p+1) = (b3 << 3) + (b4 & 7);
*(p+2) = b5 + (b4 & 0xF8) * 2;
*(p+3) = b6;
p += 4; /* Next note */
}
}
int ReadModule(nam)
char *nam;
{
char fnam[100];
size_t loadsize;
unsigned apusana;
unsigned int bpmpat[6];
unsigned char *p;
FILEok=0;
gotoxy(66,20);
cprintf(" ");
gotoxy(3,47);
cprintf(" %-75s","Loading module...");
/* Free the memory previously allocated for samples */
for (i=30;i>=0;i--) { free(sample[i]); sample[i] = NULL; }
/* Free the memory allocated for patterns */
for (i=0;i<stm.patnum;i++) { free(pattern[i]); pattern[i] = NULL; }
strcpy(fnam,defdir);
strcat(fnam,nam);
if (!(f = fopen(fnam,"rb")))
{
sprintf(apu,"Error: %s!",sys_errlist[errno]);
ShowError(apu);
return -1;
}
if (lmode=='S' || lmode=='M') /* STM and MTM modules */
{
urpo = fread(&stm,sizeof(stm),1,f);
if (stm.typ > 6)
{
ShowError("Not a recognized module!");
fclose(f);
return -2;
}
urpo = fread(&orders,128,1,f);
gotoxy(3,47);
cprintf("Loading patterns...");
for (i=0;i<stm.patnum;i++)
{
if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
{
sprintf(apu,"Not enough memory to load pattern %d !",i);
ShowError(apu);
fclose(f);
return -4;
}
if (!fread(pattern[i],sizeof(PA),1,f))
{
sprintf(apu,"Disk read error loading pattern %d !",i);
ShowError(apu);
fclose(f);
return -5;
}
}
}
else if (lmode=='B') /* BPM modules */
{
urpo = fread(&bpm,sizeof(bpm),1,f);
if ((bpm.typ & 63) != 1)
{
ShowError("Not a recognized module!");
fclose(f);
return -2;
}
/* Now copy all needed info to STM struct */
memcpy(stm.name,bpm.name,20);
memcpy(stm.tnam,bpm.tnam,8);
if (bpm.typ & 0x80)
stm.typ=2;
else
stm.typ=1;
stm.ver=(bpm.typ & 63);
stm.tempo= 12000 / (bpm.tempo_hi & 255);
stm.patnum=bpm.patnum;
stm.volume=127;
for (i=0;i<31;i++)
{
memcpy(stm.inst[i].name,bpm.inst[i].name,12);
stm.inst[i].name[12]=' ';
stm.inst[i].length=bpm.inst[i].length;
stm.inst[i].volume=(bpm.inst[i].volume * 64 / 100);
stm.inst[i].loops=bpm.inst[i].loops;
stm.inst[i].loope=bpm.inst[i].loope;
stm.inst[i].rate=bpm.ihertz;
}
urpo = fread(&orders,256,1,f);
/* Go over extra info bytes */
fseek(f,10L,SEEK_CUR);
gotoxy(3,47);
cprintf("Loading patterns...");
for (i=0;i<stm.patnum;i++)
{
urpo = fread(&bpmpat,sizeof(bpmpat),1,f); /* Read pattern header */
if (bpmpat[5] != 64)
{
sprintf(apu,"Invalid pattern %d size (%d bytes) !",i,bpmpat[5]);
ShowError(apu);
fclose(f);
return -8;
}
if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
{
sprintf(apu,"Not enough memory to load pattern %d !",i);
ShowError(apu);
fclose(f);
return -4;
}
if (!fread(pattern[i],sizeof(PA),1,f))
{
sprintf(apu,"Disk read error loading pattern %d !",i);
ShowError(apu);
fclose(f);
return -5;
}
for (j=0;j<1024;j+=4)
{
p = (unsigned char *)pattern[i] + j;
if (*p < 0xFC) *p -= 32; /* Transpose 2 octaves down */
*(p+1)=(*(p+1) << 3) + 8; /* Instrument, bits 0-5 -> BYTE1/8 */
*(p+2)=(*(p+2) & 127 | 112); /* Volume to BYTE2/2 */
}
}
}
else if (lmode=='A') /* MOD modules */
{
urpo = fread(&mod,sizeof(mod),1,f);
fseek(f,1080L,SEEK_SET);
urpo = fread(&bpmpat,4,1,f);
fseek(f,952L,SEEK_SET);
if ( memcmp(&bpmpat,"M.K.",4) ) /* Check if this is 31-inst module */
{
fseek(f,472L,SEEK_SET);
stm.ver = 15; /* 15-instrument module */
mod.songlength=mod.inst[15].name[0];
}
else
stm.ver = 31; /* 31-instrument module */
/* Now copy all needed info to STM struct */
memcpy(stm.name,mod.name,20);
memcpy(stm.tnam,"Amiga NT",8);
stm.typ = 2; /* Must be a module */
stm.tempo = 96; /* Tempo? */
stm.patnum = mod.songlength;
stm.volume = 127;
for (i=0;i<31;i++)
{
if (i>14 && stm.ver==15)
stm.inst[i].length=0;
else
{
if ( (! memcmp(mod.inst[i].name,"st-",3) ||
! memcmp(mod.inst[i].name,"ST-",3) ) &&
mod.inst[i].name[5]==':')
memcpy(stm.inst[i].name,mod.inst[i].name+6,12);
else
memcpy(stm.inst[i].name,mod.inst[i].name,12);
stm.inst[i].name[12] = 0;
_AX = mod.inst[i].length;
asm xchg ah,al
asm shl ax,1
stm.inst[i].length = _AX;
stm.inst[i].volume = mod.inst[i].volume;
_AX = mod.inst[i].loops;
asm xchg ah,al
asm shl ax,1
stm.inst[i].loops = _AX;
_AX = mod.inst[i].loopl;
if (_AX == 256)
stm.inst[i].loope = 65535;
else
{
asm xchg ah,al
asm shl ax,1
stm.inst[i].loope = _AX + stm.inst[i].loops;
}
stm.inst[i].rate = 8448; /* Sample hertz? */
}
}
urpo = fread(&orders,128,1,f);
if (stm.ver==31)
urpo = fread(&bpmpat,4,1,f); /* Read over the M.K. signum */
for (i=stm.patnum;i<128;i++)
orders[i]=99;
stm.patnum = 0;
for (i=0;i<128;i++)
if (orders[i]>stm.patnum && orders[i]<99)
stm.patnum = orders[i];
stm.patnum++;
for (i=0;i<stm.patnum;i++)
{
gotoxy(3,47);
cprintf("Converting pattern %d ...",i);
if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
{
sprintf(apu,"Not enough memory to load pattern %d !",i);
ShowError(apu);
fclose(f);
return -4;
}
if (!fread(pattern[i],sizeof(PA),1,f))
{
sprintf(apu,"Disk read error loading pattern %d !",i);
ShowError(apu);
fclose(f);
return -5;
}
ConvertPattern();
}
}
else if (!urpo)
{
ShowError("Module Header Read Error!");
fclose(f);
return -3;
}
/* Load samples, if Akai initialized OK and we are reading a module. */
if (AKAIok && (stm.typ & 2))
{
/* Load the samples */
for (i=0;i<31;i++)
{
if (!stm.inst[i].length) continue; /* Don't load if 0 length */
gotoxy(3,47);
cprintf("Loading sample %d (%5u bytes)... ",i,stm.inst[i].length);
loadsize = (size_t)stm.inst[i].length;
if (stm.inst[i].length > 32752) stm.inst[i].length=32752;
/* If loading STM samples, use 16 byte boundaries. */
if ((loadsize & 0x0F) && (lmode=='S'))
loadsize = (loadsize & 0xFFF0) + 0x10;
if ((sample[i] = (char *)malloc(loadsize))==NULL)
{
sprintf(apu,"Not enough memory to load sample %d !",i+1);
ShowError(apu);
fclose(f);
return -4;
}
/* If we hit the end of file, end the for-loop here. */
if ((urpo=fread(sample[i],1,loadsize,f)) < loadsize-16)
{
if (loadsize > 16)
{
sprintf(apu,
"Error loading sample %d (expected %d, read %d bytes) !",
i+1,(unsigned int)loadsize,urpo);
ShowError(apu);
fclose(f);
return -4;
}
}
if (lmode=='B')
{
for (j=0;j<stm.inst[i].length;j++)
*((char *)sample[i] + j) ^= 0x80;
}
}
}
fclose(f);
gotoxy(66,20);
cprintf("%-12s",nam);
strcpy(defnam,nam);
gotoxy(3,47);
sprintf(apu,"Loaded OK, %ld bytes memory free.",coreleft());
cprintf(" %-75s",apu);
FILEok=1;
return 0;
}
int SaveModule()
{
int i;
char fnam[100];
size_t savesize;
char *p;
gotoxy(3,47);
cprintf(" %-75s","Saving module...");
strcpy(fnam,defdir);
p=strchr(defnam,'.');
if (stm.typ==1 || !AKAIok)
{
stm.typ = 5; /* MidiTracker type, 5=song, 6=module */
if (p)
strcpy(p,".MTS");
else
strcat(defnam,".MTS");
}
else if (stm.typ==2)
{
stm.typ = 6; /* MidiTracker type, 5=song, 6=module */
if (p)
strcpy(p,".MTM");
else
strcat(defnam,".MTM");
}
strcat(fnam,defnam);
gotoxy(66,20);
cprintf("%-12s",defnam);
if (!(f = fopen(fnam,"wb")))
{
sprintf(apu,"Error: %s!",sys_errlist[errno]);
ShowError(apu);
return -1;
}
for (i=0;i<31;i++)
{
stm.inst[i].nt=MIDInt[i];
stm.inst[i].ch=MIDIch[i];
stm.inst[i].prg=MIDIprg[i];
}
urpo = fwrite(&stm,sizeof(stm),1,f);
if (!urpo)
{
ShowError("Disk write error saving module header!");
fclose(f);
return -3;
}
urpo = fwrite(&orders,128,1,f);
gotoxy(3,47);
cprintf("Saving patterns...");
for (i=0;i<stm.patnum;i++)
{
if (!fwrite(pattern[i],sizeof(PA),1,f))
{
sprintf(apu,"Disk write error saving pattern %d !",i);
ShowError(apu);
fclose(f);
return -5;
}
}
/* Saving samples, if Akai initialized OK. */
if (AKAIok && (stm.typ & 2))
{
/* Save the samples */
for (i=0;i<31;i++)
{
if (!stm.inst[i].length) continue; /* Don't save if 0 length */
gotoxy(3,47);
cprintf("Saving sample %d (%5u bytes)... ",i,stm.inst[i].length);
savesize = (size_t)stm.inst[i].length;
if (!fwrite(sample[i],savesize,1,f))
{
sprintf(apu,"Disk write error saving sample %d !",i+1);
ShowError(apu);
fclose(f);
return -5;
}
}
}
fclose(f);
gotoxy(3,47);
cprintf(" %-75s","Module saved OK.");
return 0;
}
int Screen()
{
int i;
textmode(C4350);
textbackground(BLUE);
clrscr();
cprintf("\n");
textcolor(LIGHTGRAY);
cprintf(" ╔═════════╗ ╔═════════╗\r\n");
textcolor(YELLOW);
gotoxy(14,2);
cprintf("MidiTracker v0.9 Made in Finland by Patrick Aalto 1991\r\n");
textcolor(LIGHTGRAY);
cprintf(" ║ ╚════════════════════╦═════════════════╦════╦════════════╝ ║\r\n");
cprintf(" ║ Module: ___________________ ║ ┌───┐┌───┐┌───┐ ║ ║ ║\r\n");
cprintf(" ║ Tempo : ___ ╔════════════════╣ │ « ││ > ││ » │ ║ ║ ║\r\n");
cprintf(" ║ Volume: ___ ║ 00:00:00 ║ └───┘└───┘└───┘ ║ ║ ║\r\n");
cprintf(" ║ PatCnt: ___ ╚════════════════╣ ┌────────┐┌───┐ ║ ║ ║\r\n");
cprintf(" ║ Trackr: ________ v ║ │ STOP ││ ║ │ ║ ║ ║\r\n");
cprintf(" ╠══════════════════════════════╣ └────────┘└───┘ ║ ║ ║\r\n");
cprintf(" ║ ╚═════════════════╣ ║ ║\r\n");
cprintf(" ║ Nr Name Bytes Hz Ch P/S Vol Pan Not ║ ║ ║\r\n");
cprintf(" ║ 1 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║ ║\r\n");
cprintf(" ║ 2 ____________ _____ _____ __ ___ ___ ___ ___ ║ ╟────────┬──────┬──────╢\r\n");
cprintf(" ║ 3 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║ VOLS │ SAVE │ ║\r\n");
cprintf(" ║ 4 ____________ _____ _____ __ ___ ___ ___ ___ ║ ╟────────┼──────┼──────╢\r\n");
cprintf(" ║ 5 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║ LOOP │ INIT │ EXIT ║\r\n");
cprintf(" ║ 6 ____________ _____ _____ __ ___ ___ ___ ___ ╠════╩════════╧══════╧══════╣\r\n");
cprintf(" ║ 7 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 8 ____________ _____ _____ __ ___ ___ ___ ___ ║ ┌──────────────╢\r\n");
cprintf(" ║ 9 ____________ _____ _____ __ ___ ___ ___ ___ ╟────────────┤ ║\r\n");
cprintf(" ║ 10 ____________ _____ _____ __ ___ ___ ___ ___ ║ └──────────────╢\r\n");
cprintf(" ║ 11 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 12 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 13 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 14 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 15 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 16 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 17 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 18 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 19 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 20 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 21 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 22 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 23 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 24 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 25 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 26 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 27 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 28 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 29 ____________ _____ _____ __ ___ ___ ___ ___ ║ ║\r\n");
cprintf(" ║ 30 ____________ _____ _____ __ ___ ___ ___ ___ ╟─────┬─────┬─────┬─────┬───╢\r\n");
cprintf(" ║ 31 ____________ _____ _____ __ ___ ___ ___ ___ ║ MTM │ STM │ BPM │ MOD │ D ║\r\n");
cprintf(" ╠════════╤════════════════╤════════════════╤═════╩═════╧════╤╧═════╧═════╧═══╣\r\n");
cprintf(" ║ │ Not I# Vol Cmd │ Not I# Vol Cmd │ Not I# Vol Cmd │ Not I# Vol Cmd ║\r\n");
cprintf(" ║ ___:__ │ ___ __ ___ ___ │ ___ __ ___ ___ │ ___ __ ___ ___ │ ___ __ ___ ___ ║\r\n");
cprintf(" ╠════════╧════════════════╧════════════════╧════════════════╧════════════════╣\r\n");
cprintf(" ║ ║\r\n");
cprintf(" ╚════════════════════════════════════════════════════════════════════════════╝\r\n");
gotoxy(42,5);putch(16);
gotoxy(79,22);putch(24);
gotoxy(79,40);putch(25);
gotoxy(56,5);putch(24);
gotoxy(56,16);putch(25);
textcolor(BLACK);
gotoxy(4,3);cprintf("OVERALL");
gotoxy(52,4);cprintf("LINK");
gotoxy(18,6);cprintf("TIME:");
gotoxy(71,3);cprintf("COMMAND");
gotoxy(4,10);cprintf("INSTRUMENTS AND MIDI TRACKS");
gotoxy(4,44);cprintf("PATTERN");
gotoxy(53,21);cprintf("MT MODULES");
gotoxy(53,19);cprintf("DIRECTORY");
return 0;
}
void HandleMouse(mode)
int *mode;
{
int oldmode = *mode;
int x,y,done=0;
do {
if (!INTplaying) ClearMPU(); /* Keep incoming midi buffer clear */
GetMouse(&mx,&my);
if (mx==53 && my==18) *mode = 1; /* Drive */
else if (mx>52 && my>21 && mx<77 && my<41 && mx!=65) *mode = 2; /* File */
else if (mx>51 && my==42)
{
if (mx<57) *mode = 3; /* STM */
else if (mx>57 && mx<63) *mode = 4; /* STS */
else if (mx>63 && mx<69) *mode = 5; /* BPM */
else if (mx>69 && mx<75) *mode = 6; /* MOD */
else if (mx>75 && mx<79) *mode = 7; /* Dir */
else *mode = 0;
}
else if (mx<72 && mx>65 && my==16) *mode=8; /* Send Init */
else if (mx>72 && my==16) *mode=9; /* Exit */
else if (mx>39 && my>3 && mx<45 && my<7) *mode=10; /* Play */
else if (mx>34 && my>6 && mx<45 && my<10) *mode=11; /* Stop */
else if (mx<34 && mx>31 && my>11 && my<43) *mode=12; /* Select Ch */
else if (mx<50 && mx>46 && my>11 && my<43) *mode=13; /* Select Note */
else if (mx<38 && mx>34 && my>11 && my<43) *mode=14; /* Select Prg */
else if (mx<65 && mx>56 && my==16) *mode=15; /* LOOP ON/OFF */
else if (mx>44 && my>6 && mx<50 && my<10) *mode=16; /* Pause */
else if (mx>19 && mx<31 && my>11 && my<43) *mode=17; /* Display Toggle */
else if (mx==56 && (my==5 || my==16)) *mode=18; /* Scroll links */
else if (my>3 && my<7 && ((mx>34 && mx<40) ||
(mx>44 && mx<50))) *mode=19; /* Search */
else if (mx<72 && mx>65 && my==14) *mode=20; /* Save */
else if (mx==79 && (my==22 || my==40)) *mode=21; /* Scroll files */
else if (mx<65 && mx>56 && my==14) *mode=22; /* VOLS ON/OFF */
else
*mode = 0;
if (*mode != oldmode)
{
gotoxy(2,49);
oldmode = *mode;
switch(*mode)
{
case 0: cprintf("Move mouse to select option. \r");break;
case 1: cprintf("Click to change current drive. \r");break;
case 2: if (lmode=='D')
cprintf("Click on directory to make current. \r");
else
cprintf("Click on filename to load. \r");
break;
case 3: cprintf("Click to handle MidiTracker modules. \r");break;
case 4: cprintf("Click to handle ScreamTracker modules. \r");break;
case 5: cprintf("Click to handle B's ProTracker modules.\r");break;
case 6: cprintf("Click to handle Amiga modules. \r");break;
case 7: cprintf("Click to select search directory. \r");break;
case 8: cprintf("Click to initialize synth(s). \r");break;
case 9: cprintf("Click to Exit MidiTracker. \r");break;
case 10:cprintf("Click to Play song. \r");break;
case 11:cprintf("Click to Stop (and rewind) song. \r");break;
case 12:cprintf("Click to select MIDI channel. \r");break;
case 13:cprintf("Click to select fixed/transposed note. \r");break;
case 14:cprintf("Click to select MIDI program / sample#.\r");break;
case 15:cprintf("Click to toggle Looping Mode. \r");break;
case 16:cprintf("Click to Pause song. \r");break;
case 17:cprintf("Click to toggle displayed data. \r");break;
case 18:cprintf("Click to scroll links. \r");break;
case 19:cprintf("Click to search in pattern. \r");break;
case 20:cprintf("Click to save song/module. \r");break;
case 21:cprintf("Click to scroll files. \r");break;
case 22:cprintf("Click to toggle Volume Mode. \r");break;
}
}
else if (GetClick(&mx,&my) && *mode)
{
gotoxy(2,49);
cprintf("Working... \r");
switch(*mode)
{
/* -- Clicked on a new drive -- */
case 1:
if (SelectDrive())
if (lmode == 'D')
ShowDirs(defdir);
else
ShowFiles();
break;
/* -- Clicked on a file/directory -- */
case 2:
if (mx>65) x=1; else x=0;
y = (my-22)*2+FILE1st;
switch(lmode)
{
case 'M': case 'S': case 'B': case 'A':
if (INTplaying)
{
ShowError("Cannot load while playing!");
break;
}
if (allfiles[x+y][0])
{
ClearSong();
ReadModule(allfiles[x+y]);
if (FILEok) ShowSong();
}
break;
case 'D':
if (alldirs[x+y][0])
{
MouseOff();
ChangeDir(alldirs[x+y]);
ShowDirs(defdir);
MouseOn();
}
break;
}
break;
/* -- Selection of input file types -- */
case 3:
strcpy(defext,"*.mt?");
lmode='M';
textcolor(BLACK);gotoxy(53,21);cprintf("MT MODULES ");
FILElkm=ShowFiles();
break;
case 4:
strcpy(defext,"*.st?");
lmode='S';
textcolor(BLACK);gotoxy(53,21);cprintf("ST MODULES ");
FILElkm=ShowFiles();
break;
case 5:
strcpy(defext,"*.bpm");
lmode='B';
textcolor(BLACK);gotoxy(53,21);cprintf("BP MODULES ");
FILElkm=ShowFiles();
break;
case 6:
strcpy(defext,"*.mod");
lmode='A';
textcolor(BLACK);gotoxy(53,21);cprintf("AMIGA MODS ");
FILElkm=ShowFiles();
break;
case 7:
lmode='D';
textcolor(BLACK);gotoxy(53,21);cprintf("DIRECTORIES");
FILElkm=ShowDirs(defdir);
break;
case 8:
if (!INTplaying)
SendInit();
else
ShowError("Cannot initialize while playing!");
break;
case 9:
if (!INTplaying)
done=1;
else
ShowError("Cannot exit while playing!");
break;
case 10:
if (!INTplaying) Play();
break;
case 11:
Stop();
ShowTime(INTtime);
break;
case 12:
SelectCh(my-12);
break;
case 13:
SelectNote(my-12);
break;
case 14:
SelectPrg(my-12);
break;
case 15:
INTloop ^= 1;
gotoxy(63,16);
MouseOff();
if (INTloop) putch(2); else putch(1);
MouseOn();
break;
case 16:
Pause();
break;
case 17:
ToggleDisp();
break;
case 18:
if (my==5 && INTord>0)
INTord-=1;
else if (my==16 && orders[INTord+1]<stm.patnum)
INTord+=1;
ShowOrd(INTord);
INTpat=orders[INTord];
ShowPat(INTpat,INTrow);
break;
case 19:
if (mx<42 && (INTord>0 || INTrow>0))
{
if (!INTrow) { INTord-=1; INTrow=63; }
else INTrow-=1;
}
else if (mx>42 && (orders[INTord+1]<stm.patnum ||
INTrow<63))
{
if (INTrow==63) { INTord+=1; INTrow=0; }
else INTrow+=1;
}
ShowOrd(INTord);
INTpat=orders[INTord];
ShowPat(INTpat,INTrow);
break;
case 20:
if (FILEok)
SaveModule();
else
ShowError("No module loaded, cannot save!");
break;
case 21:
if (my==22 && FILE1st>0)
{
FILE1st-=2;
movetext(52,22,77,39,52,23);
gotoxy(52,22);
cprintf(" %-12s %-12s",
allfiles[FILE1st],allfiles[FILE1st+1]);
}
else if (my==40 && FILE1st+36<FILElkm)
{
FILE1st+=2;
movetext(52,23,77,40,52,22);
gotoxy(52,40);
cprintf(" %-12s %-12s",
allfiles[FILE1st+36],allfiles[FILE1st+37]);
}
break;
case 22:
INTvols ^= 1;
gotoxy(63,14);
MouseOff();
if (INTvols) putch(2); else putch(1);
MouseOn();
break;
default: break;
}
oldmode = -1;
}
} while (!done);
}
main()
{
for (i=30;i>=0;i--) sample[i]=NULL;
for (i=0;i<128;i++) orders[i]=99;
for (i=0;i<31;i++) MIDIprg[i]=128;
if (!InitMouse())
{
cprintf("Sorry, but MidiTracker requires a mouse!\r\n");
exit(1);
}
gettextinfo(&tinfo);
Screen();
textcolor(WHITE);
FILEok = 0;
MPUok = InitMPU();
MouseOn();
getcwd(defdir,64);
if (defdir[strlen(defdir)-1] != '\\') strcat(defdir,"\\");
ShowFiles();
if (MPUok) AKAIok = InitAkai();
InitLAPC(1);
mode = -1;
HandleMouse(&mode);
MouseOff();
InitLAPC(0);
if (MPUok) ResetMPU();
for (i=30;i>=0;i--) free(sample[i]);
textattr(tinfo.attribute);
textmode(tinfo.currmode);
clrscr();
return 0;
}