home *** CD-ROM | disk | FTP | other *** search
- /* MIDP.C
- *
- * MIDAS Module Player v0.42
- *
- * Copyright 1994 Petteri Kangaslampi and Jarno Paananen
- *
- * This file is part of the MIDAS Sound System, and may only be
- * used, modified and distributed under the terms of the MIDAS
- * Sound System license, LICENSE.TXT. By continuing to use,
- * modify or distribute this file you indicate that you have
- * read the license and understand and accept it fully.
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dir.h>
- #include <conio.h>
- #include <dos.h>
- #include <alloc.h>
- #include <string.h>
- #include <process.h>
- #include <ctype.h>
- #include <time.h>
-
- #include "midas.h"
- #include "vgatext.h"
-
- char *title =
- "MIDAS Module Player v0.42, Copyright 1994 Petteri Kangaslampi & "
- "Jarno Paananen\n";
-
- char *usage =
- "Usage:\tMIDP\t[options] <filename> [options]\n\n"
- "Options:\n"
- "\t-sx\tForce Sound Device x (1 = GUS, 2 = PAS, 3 = WSS, 4 = SB,\n"
- "\t\t5 = No Sound)\n"
- "\t-pxxx\tForce I/O port xxx (hex) for Sound Device\n"
- "\t-ix\tForce IRQ x for Sound Device\n"
- "\t-dx\tForce DMA channel x for Sound Device\n"
- "\t-mxxxxx\tSet mixing rate to xxxxx Hz\n"
- "\t-e\tDisable EMS usage\n"
- "\t-t\tDisable ProTracker BPM tempos\n"
- "\t-S\tJump immediately to DOS shell\n"
- "\t-u\tEnable Surround\n"
- "\t-oxxx\tForce output mode (8 = 8-bit, 1 = 16-bit, s = stereo, m = mono)\n"
- "\t-v\tDisable real VU-meters\n"
- "\t-c\tDisable screen synchronization\n"
- "\t-C\tEnable screen synchronization also in DOS shell\n"
- "\t-Lx\tNumber of song loops before next song / restart\n"
- "\t-O\tScramble module order\n"
- "\t-nxx\tDefault panning";
-
- char *scrtop =
- "\xFF\x4FMIDAS Module Player v0.42, Copyright 1994 Petteri Kangaslampi and "
- "Jarno Paananen"
- "\xFF\x0F▐\xFF\x7F\x7F\x4E▀\xFF\x08▌"
- "\xFF\x0F▐\xFF\x78┌\x7F\x4C─\xFF\x7F┐\xFF\x08▌"
- "\xFF\x0F▐\xFF\x78│\xFF\x7FModule:\x7F\x1F Type:\x7F\x21 │\xFF\x08▌"
- "\xFF\x0F▐\xFF\x78│\xFF\x7FMixing Rate:\x7F\x0C Mixing Mode:\x7F\x1B Time:"
- "\x7F\x08 │\xFF\x08▌"
- "\xFF\x0F▐\xFF\x78│\xFF\x7FLength: Position: Pattern: Row: Tempo:"
- " Speed: Vol: │\xFF\x08▌"
- "\xFF\x0F▐\xFF\x78└\xFF\x7F\x7F\x4C─┘\xFF\x08▌";
-
-
- #define MAXNAMES 256 /* maximum number of file names */
-
-
- ulong free1, free2;
- mpModule *mod;
- int numChans;
- ushort scrSync;
- int immShell = 0;
- int sync = 1, shellSync = 0;
- volatile ulong frameCnt;
- mpInformation *info;
- ushort actch = 0;
- char masterVol = 64;
- char exitFlag = 0;
- char fadeOut;
- short loopCnt = 0;
- ushort defPanning;
- int useDefPanning = 0;
- char *fNames[MAXNAMES];
- time_t startTime, pauseTime = 0, pauseStart;
- int muted = 0, paused = 0;
- int numFNames;
- int fileNumber;
- int noNext;
- int isArchive; /* is file archive */
- int arcType; /* archive type */
- int decompressed; /* 1 if already decompressed */
- char *decompName = NULL; /* name of decompressed module file */
-
- char *tempDir; /* temporary directory for
- decompression */
- int scrambleOrder = 0;
-
- char *modTypes[2] = { /* module type strings */
- { "Scream Tracker ]I[" },
- { "Protracker" } };
-
- char *notes[13] = { /* note strings */
- "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-"};
-
- #define DECOMPMEM 350000 /* number of bytes of memory required
- for decompression */
- #define NUMARCEXTS 3
- char *arcExtensions[NUMARCEXTS] =
- { ".ZIP", ".MDZ", ".S3Z" };
-
- char Channels[32]; /* channel mute flags */
- uchar oldInsts[32]; /* old instrument values for all
- channels */
- struct text_info textInfo; /* text mode information */
-
-
- /****************************************************************************\
- *
- * Function: void Error(char *msg)
- *
- * Description: Prints an error message to stderr, uninitializes MIDAS and
- * exits to DOS
- *
- * Input: char *msg error message
- *
- \****************************************************************************/
-
- void Error(char *msg)
- {
- textmode(C80);
- fprintf(stderr, "Error: %s\n", msg);
- midasClose();
- exit(EXIT_FAILURE);
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void toggleChannel(char channel)
- *
- * Description: Toggles a channel mute on/off
- *
- * Input: char channel channel number
- *
- \****************************************************************************/
-
- void toggleChannel(char channel)
- {
- if ( channel < numChans )
- {
- Channels[channel] ^= 1;
- SD->MuteChannel(channel, Channels[channel]);
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void prevr(void)
- *
- * Description: preVR() routine for Timer, increments frame counter
- *
- \****************************************************************************/
-
- void prevr(void)
- {
- frameCnt++;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void showheap(void)
- *
- * Description: Displays amount of free memory and amount of memory used,
- * and checks for heap corruption.
- *
- \****************************************************************************/
-
- void showheap(void)
- {
- struct heapinfo hinfo;
-
-
- free2 = coreleft();
- cprintf("%lu bytes memory free - %lu bytes used.\r\n",
- free2, free1-free2);
-
- if ( heapcheck() != _HEAPOK )
- cputs("HEAP CORRUPTED - PREPARE FOR SYSTEM CRASH!\r\n");
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void dumpheap(void)
- *
- * Description: Lists all blocks in heap
- *
- \****************************************************************************/
-
- void dumpheap(void)
- {
- struct heapinfo hinfo;
-
- if ( heapcheck() == _HEAPOK )
- cputs("Heap OK\r\n");
- else
- cputs("HEAP CORRUPTED!\r\n");
-
- hinfo.ptr = NULL;
-
- while ( heapwalk(&hinfo) == _HEAPOK )
- {
- cprintf("%p: %06u - ", hinfo.ptr, hinfo.size);
- if ( hinfo.in_use == 1 )
- cprintf("USED\r\n");
- else
- cprintf("FREE\r\n");
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void dumpfree(void)
- *
- * Description: Lists all free blocks in heap
- *
- \****************************************************************************/
-
- void dumpfree(void)
- {
- struct heapinfo hinfo;
-
- if ( heapcheck() == _HEAPOK )
- cputs("Heap OK\r\n");
- else
- cputs("HEAP CORRUPTED!\r\n");
-
- hinfo.ptr = NULL;
-
- while ( heapwalk(&hinfo) == _HEAPOK )
- {
- if ( hinfo.in_use != 1 )
- cprintf("%p: %06u\r\n", hinfo.ptr, hinfo.size);
- }
- }
-
-
-
- /****************************************************************************\
- *
- * Function: void ParseCmdLine(int argc, char *argv[])
- *
- * Description: Parses command line options
- *
- * Input: int argc argc from main()
- * char *argv[] argv from main()
- *
- \****************************************************************************/
-
- void ParseCmdLine(int argc, char *argv[])
- {
- int i, error;
-
- numFNames = 0;
-
- for ( i = 1; i < argc; i++ )
- {
- if ( argv[i][0] == '-' )
- {
- switch ( argv[i][1] )
- {
- case 'S':
- immShell = 1;
- break;
-
- case 'C':
- shellSync = 1;
- break;
-
- case 'c':
- sync = 0;
- break;
-
- case 'L':
- loopCnt = atoi(&argv[i][2]);
- if ( loopCnt == 0 )
- loopCnt = 1;
- break;
-
- case 'O':
- scrambleOrder = 1;
- break;
-
- case 'n':
- defPanning = atoi(&argv[i][2]);
- useDefPanning = 1;
- break;
-
- default:
- midasParseOption(&argv[i][1]);
- break;
- }
- }
- else
- {
- if ( numFNames >= MAXNAMES )
- Error("Too many file names");
-
- fNames[numFNames] = argv[i];
- numFNames++;
- }
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void InitMIDAS(void)
- *
- * Description: Initializes MIDAS Sound System
- *
- \****************************************************************************/
-
- void InitMIDAS(void)
- {
- int error;
-
- /* Get screen synchronization value if Timer should be synchronized to
- screen: */
- if ( sync )
- {
- if ( (error = tmrGetScrSync(&scrSync)) != OK )
- midasError(errorMsg[error]);
- }
-
- midasInit();
-
- /* Synchronize timer to screen, if synchronization is used. prevr() will
- be called before each retrace */
- if ( sync )
- {
- if ( (error = tmrSyncScr(scrSync, &prevr, NULL, NULL)) != OK )
- midasError(errorMsg[error]);
- }
-
- cprintf("MIDAS Sound System succesfully initialized.\r\n"
- "Playing through %s,\r\nusing port %Xh, IRQ %i and DMA %i\r\n",
- SD->ID, (unsigned) SD->port, (int) SD->IRQ, (int) SD->DMA);
- showheap();
- }
-
-
-
-
-
- /****************************************************************************\
- *
- * Function: void CloseMIDAS(void)
- *
- * Description: Uninitializes MIDAS Sound System
- *
- \****************************************************************************/
-
- void CloseMIDAS(void)
- {
- int error;
-
- /* Remove screen synchronization if used: */
- if ( sync )
- {
- if ( (error = tmrStopScrSync()) != OK )
- midasError(errorMsg[error]);
- }
-
- midasClose();
-
- cprintf("MIDAS Sound System succesfully uninitialized\r\n");
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void WaitVR(void)
- *
- * Description: Waits for Vertical Retrace
- *
- \****************************************************************************/
-
- void WaitVR(void)
- {
- asm mov dx,03DAh
- wvr:
- asm { in al,dx
- test al,8
- jz wvr
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void WaitDE(void)
- *
- * Description: Waits for Display Enable
- *
- \****************************************************************************/
-
- void WaitDE(void)
- {
- asm mov dx,03DAh
- wde:
- asm { in al,dx
- test al,1
- jnz wde
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void SetBorder(uchar color)
- *
- * Description: Sets display border color
- *
- * Input: uchar color new border color
- *
- \****************************************************************************/
-
- void SetBorder(uchar color)
- {
- asm { mov dx,03C0h
- mov al,31h
- out dx,al
- mov al,color
- out dx,al
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void InitScreen(void)
- *
- * Description: Initializes MIDAS Module Player screen
- *
- \****************************************************************************/
-
- void InitScreen(void)
- {
- frameCnt = 0;
- textmode(C4350);
- clrscr();
- vgaWriteText(1, 1, scrtop);
- vgaWriteText(1, 8, "\xFF\x0F▐\xFF\x78\x7F\x4E▄\xFF\x08▌");
- window(1, 42, 80, 50);
- gotoxy(1, 1);
- textattr(0x07);
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void DrawScreen(void)
- *
- * Description: Draws MIDAS Module Player screen. Used after module has
- * been loaded.
- *
- \****************************************************************************/
-
- void DrawScreen(void)
- {
- int i, x, y, len;
- char c;
- char str[32];
- char chstr[18];
- ushort mode, mixRate;
- int error;
-
- vgaWriteText(1, 1, scrtop);
- vgaWriteText(1, 8, "\xFF\x0F▐\xFF\x78┌\x7F\x4C─\xFF\x7F┐\xFF\x08▌");
- for ( i = 0; i < numChans; i++ )
- vgaWriteText(1, 9+i, "\xFF\x0F▐\xFF\x78│\xFF\x70 │\x7F\x11 │ │ │"
- "\x7F\x0E │\x7F\x20■\xFF\x7F│\xFF\x08▌");
- y = 9+numChans;
- vgaWriteText(1, y, "\xFF\x0F▐\xFF\x78└\xFF\x7F\x7F\x4C─┘\xFF\x08▌");
- vgaWriteText(1, y+1, "\xFF\x0F▐\xFF\x78┌\x7F\x4C─\xFF\x7F┐\xFF\x08▌");
- y+=2;
- for ( ; y < 40; y++ )
- vgaWriteText(1, y, "\xFF\x0F▐\xFF\x78│\xFF\x70\x7F\x25 │\x7F\x26 "
- "\xFF\x7F│\xFF\x08▌");
- vgaWriteText(1, 40, "\xFF\x0F▐\xFF\x78└\xFF\x7F\x7F\x4C─┘\xFF\x08▌");
- vgaWriteText(1, 41, "\xFF\x0F▐\xFF\x78\x7F\x4E▄\xFF\x08▌");
-
- for ( i = 0; i < numChans; i++ )
- {
- if ( i < 9 )
- c = i + '1';
- else
- c = i + 'A' - 9;
- chstr[i] = c;
- }
- chstr[numChans] = 0;
-
- sprintf(&str[0], "%s Module", modTypes[mod->IDnum]);
- vgaWriteStr(46, 4, str, 0x70, 33);
-
- vgaWriteStr(10, 4, &mod->songName[0], 0x70, 31);
-
- for ( i = 0; i < mod->numInsts; i++ )
- {
- x = 3;
- y = 11 + numChans + i;
- len = 33-numChans;
- if ( y >= 40 )
- {
- x += 38;
- y -= (29 - numChans);
- len++;
- }
- if ( y < 40 )
- {
- vgaWriteStr(x, y, &chstr[0], 0x70, numChans);
- x += numChans+1;
- if(mod->instsUsed[i] == 1)
- {
- vgaWriteByte(x, y, i+1, 0x70);
- vgaWriteStr(x+3, y, &mod->insts[i].iname[0], 0x70, len);
- }
- else
- {
- vgaWriteByte(x, y, i+1, 0x78);
- vgaWriteStr(x+3, y, &mod->insts[i].iname[0], 0x78, len);
- }
- }
- }
-
- vgaWriteByte(10, 6, mod->songLength, 0x70);
-
- if ( (error = SD->GetMixRate(&mixRate)) != OK )
- midasError(errorMsg[error]);
- sprintf(&str[0], "%uHz", mixRate);
- vgaWriteStr(15, 5, str, 0x70, 7);
-
- if ( (error = SD->GetMode(&mode)) != OK )
- midasError(errorMsg[error]);
-
- if ( mode & sd16bit )
- strcpy(&str[0], "16-bit ");
- else
- strcpy(&str[0], "8-bit ");
-
- if ( mode & sdStereo )
- strcat(&str[0], "Stereo ");
- else
- strcat(&str[0], "Mono ");
-
- if ( mode & sdHighQ )
- strcat(&str[0], "High");
- else
- strcat(&str[0], "Normal");
-
- vgaWriteStr(39, 5, str, 0x70, 26);
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void UpdScreen(void)
- *
- * Description: Updates MIDAS Module Player screen
- *
- \****************************************************************************/
-
- void UpdScreen(void)
- {
- char str[32];
- int i, x, y;
- char *iname;
- mpChanInfo *chan;
- int numInsts;
- short pan;
- ulong rate;
- int error;
- ushort meter, pos;
- time_t currTime;
- int hour, min, sec;
-
- vgaWriteByte(23, 6, info->pos, 0x70);
- vgaWriteByte(35, 6, info->pattern, 0x70);
- vgaWriteByte(43, 6, info->row, 0x70);
- sprintf(&str[0], "%3u", (unsigned) info->BPM);
- vgaWriteStr(53, 6, &str[0], 0x70, 3);
- vgaWriteByte(64, 6, info->speed, 0x70);
- sprintf(&str[0], "%2u", masterVol);
- vgaWriteStr(72, 6, &str[0], 0x70, 3);
-
- if ( !paused )
- {
- currTime = time(NULL) - startTime - pauseTime;
- hour = currTime / 3600;
- min = ((currTime - 3600*hour) / 60) % 60;
- sec = currTime % 60;
- sprintf(&str[0], "%2i:%02i:%02i", hour, min, sec);
- vgaWriteStr(71, 5, &str[0], 0x70, 8);
- }
- else
- vgaWriteStr(71, 5, "-PAUSED-", 0x70, 8);
-
- numInsts = mod->numInsts;
-
- for ( i = 0; i < numChans; i++ )
- {
- chan = &info->chans[i];
-
- if ( oldInsts[i] != 0 )
- {
- x = 3+i;
- y = 11 + numChans + (oldInsts[i]-1);
- if ( y >= 40 )
- {
- x += 38;
- y -= (29 - numChans);
- }
- if ( y < 40 )
- {
- str[1] = 0;
- if ( i < 9 )
- str[0] = i + '1';
- else
- str[0] = (i-9) + 'A';
- vgaWriteStr(x, y, &str[0], 0x70, 1);
- }
- }
-
- if ( (Channels[i] == 0) && (!muted) && (!paused) )
- {
- if ( (chan->instrument != 0) && (chan->instrument <= numInsts) )
- {
- x = 3+i;
- y = 11 + numChans + (chan->instrument-1);
- if ( y >= 40 )
- {
- x += 38;
- y -= (29 - numChans);
- }
- if ( y < 40 )
- {
- str[1] = 0;
- if ( i < 9 )
- str[0] = i + '1';
- else
- str[0] = (i-9) + 'A';
- vgaWriteStr(x, y, &str[0], 0x7E, 1);
- }
-
- vgaWriteByte(7, 9+i, chan->instrument, 0x70);
-
- iname = &mod->insts[chan->instrument-1].iname[0];
-
- vgaWriteStr(10, 9+i, iname, 0x70, 14);
-
- oldInsts[i] = chan->instrument;
-
- if ( realVU )
- {
- if ( (error = SD->GetRate(i, &rate)) != OK )
- midasError(errorMsg[error]);
-
- if ( (error = SD->GetPosition(i, &pos)) != OK )
- midasError(errorMsg[error]);
-
- if ( rate != 0 )
- {
- error = vuMeter(
- mod->insts[chan->instrument - 1].sdInstHandle,
- rate, pos, (chan->volume * masterVol) / 64,
- &meter);
- if ( error != OK )
- midasError(errorMsg[error]);
- }
- else
- meter = 0;
- }
- else
- meter = chan->volumebar;
-
- if ( (chan->note < 254) && ( (chan->note & 15) < 12) )
- {
- strcpy(&str[0], notes[chan->note & 15]);
- str[2] = (chan->note >> 4) + '0';
- str[3] = 0;
- vgaWriteStr(25, 9+i, &str[0], 0x70, 3);
- }
- else
- vgaWriteStr(25, 9+i, "", 0x70, 3);
- }
- else
- meter = 0;
-
- vgaWriteByte(29, 9+i, chan->volume, 0x70);
- if ( chan->commandname[0] != 0 )
- {
- sprintf(&str[0], "%s %02X", chan->commandname,
- (int) chan->infobyte);
- vgaWriteStr(32, 9+i, &str[0], 0x70, 14);
- }
- else
- vgaWriteStr(32, 9+i, "", 0x70, 14);
-
- vgaDrawMeter(47, 9+i, meter >> 1, 32, '■', 0x7A, 0x70);
- }
- else
- vgaWriteText(7, 9+i,
- "\xFF\x70\x7F\x11 │ │ │\x7F\x0E │\x7F\x20■");
-
- if ( (error = SD->GetPanning(i, &pan)) != OK )
- midasError(errorMsg[error]);
-
- switch ( pan )
- {
- case panLeft:
- strcpy(&str[0], "LFT");
- break;
-
- case panRight:
- strcpy(&str[0], "RGT");
- break;
-
- case panMiddle:
- strcpy(&str[0], "MID");
- break;
-
- case panSurround:
- strcpy(&str[0], "SUR");
- break;
-
- default:
- sprintf(&str[0], "%3i", pan);
- }
- if ( i != actch )
- vgaWriteStr(3, i+9, &str[0], 0x70, 3);
- else
- vgaWriteStr(3, i+9, &str[0], 0x07, 3);
- }
- }
-
-
-
- /****************************************************************************\
- *
- * Function: void WaitFrame(void)
- *
- * Description: Waits for next frame, either by using VGA hardware or by
- * waiting for the frame counter to change, depending on
- * whether screen synchronization is used or not
- *
- \****************************************************************************/
-
- void WaitFrame(void)
- {
- ulong oldcnt = frameCnt;
-
- if ( sync )
- while ( frameCnt == oldcnt );
- else
- {
- WaitDE();
- WaitVR();
- }
- }
-
-
-
- /****************************************************************************\
- *
- * Function: void DOSshell(void)
- *
- * Description: Jumps to DOS shell
- *
- \****************************************************************************/
-
- void DOSshell(void)
- {
- char *comspec;
- char *dir;
- int disk, error;
-
- if ( (!shellSync) && sync )
- tmrStopScrSync();
-
- /* restore old text mode: */
- textmode(textInfo.currmode);
-
- if ( (error = memAlloc(MAXDIR, (void**) &dir)) != OK )
- Error(errorMsg[error]);
-
- disk = getdisk();
- getcurdir(0, dir);
-
- comspec=getenv("COMSPEC");
- spawnl(P_WAIT, comspec, NULL);
-
- /* save text mode information, including mode: */
- gettextinfo(&textInfo);
-
- InitScreen();
- DrawScreen();
-
- setdisk(disk);
- chdir("\\");
- chdir(dir);
-
- if ( (error = memFree(dir)) != OK )
- Error(errorMsg[error]);
-
- if ( (!shellSync) && sync )
- tmrSyncScr(scrSync, &prevr, NULL, NULL);
- showheap();
-
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void prepare(int fNum)
- *
- * Description: Prepares for playing a module file, setting variables
- * isArchive and decompressed as necessary.
- *
- * Input: int fNum number of file name
- *
- \****************************************************************************/
-
- void prepare(int fNum)
- {
- int i;
- char ext[_MAX_EXT];
-
- /* get file name extension: */
- fnsplit(fNames[fNum], NULL, NULL, NULL, &ext[0]);
-
- isArchive = 0;
-
- /* Search through known archive extensions. If a match is found, the file
- is an archive. */
- for ( i = 0; i < NUMARCEXTS; i++ )
- if ( stricmp(&ext[0], arcExtensions[i]) == 0 )
- isArchive = 1;
-
- decompressed = 0;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void decompress(char *fileName)
- *
- * Description: Decompresses a file and sets decompName to decompressed file
- * name. The archive is assumed to contain a single file, with
- * the same name as the archive and any extension.
- *
- * Input: char *fileName pointer to archive file name
- *
- \****************************************************************************/
-
- void decompress(char *fileName)
- {
- int error;
- char name[_MAX_FNAME];
- struct ffblk ffb;
-
- fnsplit(fileName, NULL, NULL, &name[0], NULL);
-
- if ( decompName == NULL )
- {
- if ( (error = memAlloc(_MAX_PATH, (void**) &decompName)) != OK )
- Error(errorMsg[error]);
- }
-
- if ( spawnlp(P_WAIT, "PKUNZIP", "", fileName, tempDir, NULL) != OK )
- Error("PKUNZIP failed");
-
- strcpy(decompName, tempDir);
- strcat(decompName, &name[0]);
- strcat(decompName, ".*");
-
- if ( findfirst(decompName, &ffb, 0) != 0 )
- Error("Unable to find decompressed file");
-
- strcpy(decompName, tempDir);
- strcat(decompName, &ffb.ff_name[0]);
- decompressed = 1;
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void HandleKeys(void)
- *
- * Description: Handles the keypresses
- *
- \****************************************************************************/
-
- void HandleKeys(void)
- {
- char key;
- short panning;
- int error;
- FILE *sf;
-
- key = getch();
-
- if ( !key )
- {
- switch ( getch() )
- {
- case 45: /* Alt-X */
- exitFlag = 1;
- break;
-
- case 77: /* Right arrow */
- MP->SetPosition(info->pos + 1);
- break;
-
- case 75: /* Left arrow */
- MP->SetPosition(info->pos - 1);
- break;
-
- case 72: /* Up arrow */
- if ( actch > 0 )
- actch--;
- break;
-
- case 80: /* Down arrow */
- if ( actch < (numChans-1) )
- actch++;
- break;
- }
- }
- else
- {
- switch ( toupper(key) )
- {
- case 27:
- fadeOut = 1;
- noNext = 1;
- break;
-
- case '+':
- if ( masterVol != 64 )
- {
- masterVol++;
- MP->SetMasterVolume(masterVol);
- }
- break;
-
- case '-':
- if ( masterVol != 0 )
- {
- masterVol--;
- MP->SetMasterVolume(masterVol);
- }
- break;
-
- case 'D':
- DOSshell();
- break;
-
- case '0': toggleChannel(9); break;
- case '1': toggleChannel(0); break;
- case '2': toggleChannel(1); break;
- case '3': toggleChannel(2); break;
- case '4': toggleChannel(3); break;
- case '5': toggleChannel(4); break;
- case '6': toggleChannel(5); break;
- case '7': toggleChannel(6); break;
- case '8': toggleChannel(7); break;
- case '9': toggleChannel(8); break;
-
- case 'T': toggleChannel(actch); break;
-
- case ',':
- if ( (error = SD->GetPanning(actch, &panning)) != OK )
- midasError(errorMsg[error]);
- if ( (panning > -64) && (panning <= 64) )
- if ( (error = SD->SetPanning(actch, panning-1)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case '.':
- if ( (error = SD->GetPanning(actch, &panning)) != OK )
- midasError(errorMsg[error]);
- if ( (panning < 64) && (panning >= -64) )
- if ( (error = SD->SetPanning(actch, panning+1)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case 'M':
- if ( (error = SD->SetPanning(actch, panMiddle)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case 'U':
- if ( (error = SD->SetPanning(actch, panSurround)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case 'L':
- if ( (error = SD->SetPanning(actch, panLeft)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case 'R':
- if ( (error = SD->SetPanning(actch, panRight)) != OK )
- midasError(errorMsg[error]);
- break;
-
- case 'F':
- dumpfree();
- break;
-
- case 'H':
- dumpheap();
- break;
-
- case 'N':
- fadeOut = 1;
- break;
-
- #ifdef DEBUG
- /*
- case 'B':
- sf = fopen("MIDPSCR.BIN", "wb");
- fwrite(MK_FP(0xB800, 0), 8000, 1, sf);
- fclose(sf);
- break;
- */
- #endif
- case 'P':
- paused ^= 1;
- SD->Pause(paused);
- if ( paused == 1 )
- pauseStart = time(NULL);
- else
- pauseTime += time(NULL) - pauseStart;
- break;
-
- case ' ':
- muted ^= 1;
- SD->Mute(muted);
- break;
- }
- }
- }
-
-
-
-
- /****************************************************************************\
- *
- * Function: void PlayModule(char *fName)
- *
- * Description: Plays a module file
- *
- * Input: char *fName
- *
- \****************************************************************************/
-
- void PlayModule(char *fName)
- {
- int stop, i, error, nextf;
-
- cprintf("Loading \"%s\"\r\n", fName);
-
- /* load module: */
- mod = midasPlayModule(fName, 0);
- startTime = time(NULL);
-
- numChans = mod->numChans;
-
- if ( (useDefPanning) && ((defPanning < 64) || (defPanning == 100)) )
- {
- for ( i = 0; i < numChans; i++ )
- {
- /* Default panning is used. If 100, set channel to surround: */
- if ( defPanning == 100 )
- {
- if ( (error = SD->SetPanning(i, panSurround)) != OK )
- midasError(errorMsg[error]);
- }
- else
- {
- /* If channel is panned to left, set it to -defPanning,
- otherwise set it to right */
- if ( mod->chanSettings[i] < 0 )
- {
- if ( (error = SD->SetPanning(i, -defPanning)) != OK )
- midasError(errorMsg[error]);
- }
- else
- {
- if ( (error = SD->SetPanning(i, defPanning)) != OK )
- midasError(errorMsg[error]);
- }
- }
- }
- }
-
- /* Prepare screen display: */
- DrawScreen();
- showheap();
-
- for ( i = 0; i < 32; i++ )
- {
- oldInsts[i] = 0;
- Channels[i] = 0;
- }
-
- /* Allocate memory for Module Player information structure and prepare
- it for use: */
- if ( (error = memAlloc(sizeof(mpInformation), (void**) &info)) != OK )
- Error(errorMsg[error]);
- info->numChannels = numChans;
- if ( (error = memAlloc(numChans * sizeof(mpChanInfo), (void**)
- &info->chans)) != OK )
- Error(errorMsg[error]);
-
- stop = 0;
- fadeOut = 0;
- masterVol = 64;
- if ( (error = MP->SetMasterVolume(64)) != OK )
- midasError(errorMsg[error]);
-
- if ( (loopCnt == 0) && (numFNames != 1) )
- loopCnt = 1;
-
- if ( isArchive )
- {
- if ( remove(fName) != 0 )
- Error("Unable to delete file");
- decompressed = 0;
- }
-
- if ( numFNames != 1 )
- {
- if ( fileNumber < (numFNames-1) )
- nextf = fileNumber + 1;
- else
- nextf = 0;
-
- prepare(nextf);
-
- if ( isArchive )
- {
- if ( coreleft() >= DECOMPMEM )
- {
- decompress(fNames[nextf]);
- InitScreen();
- DrawScreen();
- cprintf("Next module file decompressed\r\n");
- }
- else
- cprintf("Not enough free memory to decompress next module "
- "file while playing\r\n");
- }
- }
-
- cprintf ("Playing %d-channel %s Module \"%s\"\r\n", numChans,
- modTypes[mod->IDnum], &mod->songName[0]);
- showheap();
-
- while ( (!stop) && (!exitFlag) )
- {
- WaitFrame(); /* wait for next frame */
-
- /* Read Module Player information: */
- if ( (error = MP->GetInformation(info)) != OK )
- midasError(errorMsg[error]);
-
- if ( loopCnt != 0 )
- {
- if ( info->loopCnt >= loopCnt )
- fadeOut = 1;
- }
-
- UpdScreen(); /* update screen */
-
- if ( fadeOut )
- {
- if ( masterVol > 0 )
- {
- masterVol--;
- if ( (error = MP->SetMasterVolume(masterVol)) != OK )
- midasError(errorMsg[error]);
- }
- else
- {
- stop = 1;
- if ( (error = MP->SetMasterVolume(0)) != OK )
- midasError(errorMsg[error]);
- }
- }
-
- if( kbhit() )
- HandleKeys();
- }
-
- /* stop playing: */
- midasStopModule(mod);
-
- /* deallocate info structure: */
- if ( (error = memFree(info->chans)) != OK )
- Error(errorMsg[error]);
- if ( (error = memFree(info)) != OK )
- Error(errorMsg[error]);
-
- showheap();
-
- if ( noNext )
- exitFlag = 1;
- }
-
-
-
-
-
- int main(int argc, char *argv[])
- {
- int error, i, n;
- char *temp;
-
- /* save text mode information, including mode: */
- gettextinfo(&textInfo);
-
- puts(title);
- if ( argc < 2 )
- {
- puts(usage);
- exit(EXIT_SUCCESS);
- }
-
- printf("Free memory: %lu\n", free1 = coreleft());
- startTime = time(NULL);
-
- midasSetDefaults();
- midasParseEnvironment();
- ParseCmdLine(argc, argv);
- if ( numFNames == 0 )
- {
- puts(usage);
- exit(EXIT_SUCCESS);
- }
-
- if ( scrambleOrder )
- {
- randomize();
- for ( i = 0; i < numFNames; i++ )
- {
- n = random(numFNames);
- temp = fNames[i];
- fNames[i] = fNames[n];
- fNames[n] = temp;
- }
- }
-
- /* allocate memory for decompression directory name string: */
- if ( (error = memAlloc(MAXPATH, (void*) &tempDir)) != OK )
- Error(errorMsg[error]);
-
- /* if environment variable "TEMP" is set, use it, otherwise use "C:\" */
- temp = getenv("TEMP");
- if ( temp != NULL )
- {
- /* "TEMP" environment string found. Copy it to tempDir, and if the
- last character is not '\', append one to the end. */
- strcpy(tempDir, temp);
- if ( tempDir[strlen(tempDir)-1] != '\\' )
- strcat(tempDir, "\\");
- }
- else
- {
- /* No "TEMP" environment string found - use "C:\" */
- strcpy(tempDir, "C:\\");
- }
-
-
- if ( !immShell )
- InitScreen();
- InitMIDAS();
-
- if ( immShell )
- {
- mod = midasPlayModule(fNames[0], 0);
- DOSshell();
- midasStopModule(mod);
- exitFlag = 1;
- }
-
- if ( numFNames == 1 )
- noNext = 1;
-
- fileNumber = 0;
- prepare(fileNumber);
-
- while( !exitFlag )
- {
- pauseTime = 0;
- paused = 0;
- muted = 0;
-
- if ( isArchive )
- {
- if ( decompressed )
- PlayModule(decompName);
- else
- {
- decompress(fNames[fileNumber]);
- InitScreen();
- cprintf("Module file decompressed.\r\n");
- showheap();
- PlayModule(decompName);
- }
- }
- else
- PlayModule(fNames[fileNumber]);
-
- fileNumber++;
- if ( fileNumber >= numFNames )
- fileNumber = 0;
- }
-
- if ( (decompressed) && (decompName != NULL) )
- if ( remove(decompName) != 0 )
- Error("Unable to delete file");
-
- if ( decompName != NULL )
- if ( (error = memFree(decompName)) != OK )
- Error(errorMsg[error]);
-
- midasClose();
-
- if ( (error = memFree(tempDir)) != OK )
- Error(errorMsg[error]);
-
- /* restore old text mode: */
- textmode(textInfo.currmode);
-
- showheap();
-
- #ifdef DEBUG
- errPrintList();
- #endif
-
- return 0;
- }
-