/* Warning! This C source contains extended characters! */ #include #include #include #include #include #include #include #include #include #include #include void bellit(void) /* short bell */ { sound(SNDFREQ); delay(SNDLENGTH); nosound(); } void myresetmode(PARAMETERTYPE *parameter) /* Turbo-C doesn't like extended or non-text modes */ /* resets the video mode iff necessary */ /* does not rely on knowing the screen size since no clear screen done */ /* some incomplete BIOSes may force complete reset all the time */ { union REGS regs; regs.h.ah=(unsigned)'\xF'; /* get current video mode */ int86(0x10,®s,®s); if (regs.h.al!=(unsigned char)parameter->videomode) { regs.h.ah=(unsigned)'\x0'; /* reset video mode */ regs.h.al=(unsigned char)parameter->videomode; int86(0x10,®s,®s); } } void setborder(int color) /* sets the border color */ /* color is in high 4 nibbles */ { union REGS regs; /* CGA EGA VGA */ regs.h.bl=(unsigned char)(color>>4); regs.h.bh=(unsigned)'\x0'; regs.x.ax=(unsigned)0xB00; int86(0x10,®s,®s); } void highbackground(void) /* disables blinking/enables high intensity background */ { union REGS regs; int addr; unsigned char data; /* MDA CGA */ addr=peek((unsigned)0x40,(unsigned)0x63)+0x4; data=(unsigned)(peekb((unsigned)0x40,(unsigned)0x65) & '\xDF'); outportb(addr,data); /* MCGA EGA VGA */ regs.h.bl=(unsigned)'\x0'; regs.x.ax=(unsigned)0x1003; int86(0x10,®s,®s); } void myclrscr(PARAMETERTYPE *parameter, int color) /* Turbo-C doesn't like extended or non-text modes */ /* clear screen, sets border, and enables high intensity background */ /* color is is high 4 nibbles */ { union REGS regs; regs.x.ax=(unsigned)0x700; /* scroll whole screen */ regs.h.bh=(unsigned char)color; regs.x.cx=(unsigned)0x0; regs.h.dl=(unsigned char)(parameter->maxcolumn-1); regs.h.dh=(unsigned char)(parameter->maxline-1); int86(0x10,®s,®s); regs.h.ah=(unsigned)'\x2'; /* cursor in upper-left corner */ regs.h.bh=(unsigned)'\x0'; regs.x.dx=(unsigned)0x0; int86(0x10,®s,®s); highbackground(); setborder(color); } void mysetmode(PARAMETERTYPE *parameter) /* Turbo-C doesn't like extended or non-text modes */ /* sets the video mode and border, enables high intensity background */ /* avoids a complete video mode reset when possible */ /* some incomplete BIOSes may force complete reset all the time */ { union REGS regs; regs.h.ah=(unsigned)'\xF'; /* get current video mode */ int86(0x10,®s,®s); if (regs.h.al!=(unsigned char)parameter->videomode) { regs.h.ah=(unsigned)'\x0'; /* reset video mode */ regs.h.al=(unsigned char)parameter->videomode; int86(0x10,®s,®s); } myclrscr(parameter,colorborder); /* always set screen attributes to border */ } void blankstring(char target[], int targetlength) /* creates a string full of spaces */ { int ptr; for (ptr=0 ; ptrsongnumber=0; songs->songcorner=songs->songcurrent=1; songs->songpath[0]='\0'; songs->songpathoffset=1; /* used for overwriting items to erase them on the screen */ blankstring(songs->song[0].diskname,DISKNAMELENGTH); blankstring(songs->song[0].score,SCORELENGTH); blankstring(songs->song[0].DOSname,DOSNAMELENGTH); blankstring(songs->song[0].songname,SONGNAMELENGTH); songs->song[0].picked=0; songs->song[0].DOSpath=songs->songpath; strcpy(menuname,DEFAULTMENU); strcpy(parameter->speed,DEFAULTSPEED); parameter->tempdrive=ODDDRIVE; parameter->ports[0]=ODDPORTS; parameter->videomode=ODDMODE; parameter->A=parameter->B=parameter->C=FALSE; parameter->verbose=FALSE; parameter->DOS=FALSE; parameter->pause=FALSE; parameter->mouse=FALSE; parameter->rawvideo=TRUE; switch (peek((unsigned)0x40,(unsigned)0x63)) { case 0x3B4:parameter->videosegment=0xB000; break; case 0x3D4:parameter->videosegment=0xB800; break; default:error(34); } } void busyfloppy(void) /* waits until floppy shuts off */ { while ((0xF & (int)peekb((unsigned)0x40,(unsigned)0x3F))!=0) ; } void cuttail(char text[]) /* cuts the tail of spaces */ { int scanner; scanner=strlen(text); while ((text[--scanner]==' ') && (scanner>=0)) text[scanner]='\0'; } int locateasong(SONGTYPE *song, PARAMETERTYPE *parameter) /* checks that a module exists and maybe asks for the correct floppy */ /* looks for .MOD first, then for .ZIP (iff PKUNZIP.EXE located) */ /* returns -1 if not found, 0-1-2 for .MOD, and 3-4-5 for .ZIP */ /* looks in: temporary drive-path supplied(if not .)-current drive */ /* uses normal, read-only, hidden, system, archive bits for looking */ { struct ffblk fff; char filename[LINELENGTH+LINELENGTH]; /* path could be long */ int notfound; char currenttext[3]; strcpy(currenttext,"A:"); currenttext[0]+=(char)parameter->currentdrive; /* look on temporary drive for .MOD */ strcpy(filename,(*song).DOSname); cuttail(filename); strcat(filename,MPENDING); notfound=findfirst(filename,&fff,39); if (notfound) { if (parameter->pkunzipfound) { /* look on temporary drive for .ZIP */ strcpy(filename,(*song).DOSname); cuttail(filename); strcat(filename,PKENDING); notfound=findfirst(filename,&fff,39); } if (notfound) { if (strcmp((*song).DOSpath,ODDPATH)!=0) { /* look on menu path for .MOD */ strcpy(filename,(*song).DOSpath); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,MPENDING); notfound=findfirst(filename,&fff,39); } if (notfound) { if (parameter->pkunzipfound) if (strcmp((*song).DOSpath,ODDPATH)!=0) { /* look on menu path for .ZIP */ strcpy(filename,(*song).DOSpath); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,PKENDING); notfound=findfirst(filename,&fff,39); } if (notfound) do { /* look on current drive for .MOD */ strcpy(filename,currenttext); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,MPENDING); notfound=findfirst(filename,&fff,39); if (notfound) { if (parameter->pkunzipfound) { /* look on current drive for .ZIP */ strcpy(filename,currenttext); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,PKENDING); notfound=findfirst(filename,&fff,39); } if (notfound) if (parameter->currentdrive<=1) { /* song on floppy; ask user */ bellit(); message(23); printf("%s\n",(*song).diskname); message(22); switch (bioskey(0)) { case KEYESC:return(-1); /* aborted */ default:break; } } else { /* song not on floppy; give up */ printf("<%s>\n",(*song).songname); message(24); if (parameter->pause) { message(25); bellit(); bioskey(0); } else { bellit(); delay(NOTFOUNDDELAY); bellit(); delay(NOTFOUNDDELAY); bellit(); delay(NOTFOUNDDELAY); bellit(); delay(NOTFOUNDDELAY); bellit(); } return(-1); /* not found */ } else { message(35); return(5); /* .ZIP under current drive */ } } else { message(32); return(2); /* .MOD under current drive */ } } while (TRUE); else { message(34); return(4); /* .ZIP under path */ } } else { message(31); return(1); /* .MOD under path */ } } else { message(33); return(3); /* .ZIP under temporary drive */ } } else { message(36); return(0); /* .MOD under temporary drive */ } } void checkasong(char DOSname[]) /* checks that a module exists */ { struct ffblk fff; char filename[LINELENGTH]; strcpy(filename,DOSname); cuttail(filename); strcat(filename,MPENDING); /* normal, read-only, hidden, system, archive */ if (findfirst(filename,&fff,39)) error(18); } void deleteasong(char DOSname[]) /* deletes a song */ { char filename[LINELENGTH]; int errorint; message(40); strcpy(filename,DOSname); cuttail(filename); strcat(filename,MPENDING); errorint=unlink(filename); if (errorint==-1) error(19); } void shutup(int port) /* turns off gradually a parallel port */ { int value; value=(int)inportb(port); while (value>0) { value--; outportb(port,(unsigned char)value); delay(SHUTUPDELAY); } } void movemodule(SONGTYPE *song, int found, PARAMETERTYPE *parameter) /* moves a module onto the temporary drive */ /* because the module must be in the current directory for ModPlay */ /* this is simpler than to look at DOSpath and to be clever with logged drive */ /* found=1 is from path, found=2 is from current drive */ { char buffer[BUFFERSIZE]; char filename[LINELENGTH+LINELENGTH]; /* path could be long */ FILE *source,*target; int errorint,tomove,moved; char temporarytext[3]; char currenttext[3]; message(38); strcpy(temporarytext,"A:"); strcpy(currenttext,"A:"); temporarytext[0]+=(char)parameter->tempdrive; currenttext[0]+=(char)parameter->currentdrive; if (found==1) strcpy(filename,(*song).DOSpath); else strcpy(filename,currenttext); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,MPENDING); source=fopen(filename,"rb"); if (source==NULL) error(25); strcpy(filename,temporarytext); strcat(filename,(*song).DOSname); cuttail(filename); strcat(filename,MPENDING); target=fopen(filename,"wb"); if (target==NULL) error(26); tomove=(int)fread(buffer,(unsigned)1,(unsigned)BUFFERSIZE,source); while (tomove!=0) { moved=(int)fwrite(buffer,(unsigned)1,(unsigned)tomove,target); if (moved!=tomove) error(27); tomove=(int)fread(buffer,(unsigned)1,(unsigned)BUFFERSIZE,source); } errorint=fclose(source); if (errorint==EOF) error(28); errorint=fclose(target); if (errorint==EOF) error(29); } void playasong(SONGTYPE *song, PARAMETERTYPE *parameter) /*finds, maybe decompresses, waits, plays, shuts off, and maybe deletes a song*/ { char command[LINELENGTH+LINELENGTH]; /* path could be long */ char currenttext[3]; int found,errorint; strcpy(currenttext,"A:"); currenttext[0]+=(char)parameter->currentdrive; /* look for MOD or ZIP under temporary drive, menu path, and current drive */ found=locateasong(song,parameter); if (found>=0) { /* song found */ if (found>=3) { /* must be decompressed on the temporary drive known clear */ message(37); /* known on the temporary drive */ strcpy(command,PKUNZIP0); strcat(command," "); if (found==4) strcat(command,(*song).DOSpath); else if (found==5) strcat(command,currenttext); strcat(command,(*song).DOSname); cuttail(command); message(43); printf("%s\n",command); if (parameter->pause) { bellit(); message(22); switch (bioskey(0)) { case KEYESC:error(9); /* aborted */ default:break; } } errorint=system(command); printf("\n"); if (errorint==-1) error(20); checkasong((*song).DOSname); } else /* if temporary drive is clear, move module there */ if (found>=1) movemodule(song,found,parameter); message(39); /* known on the temporary drive */ strcpy(command,MODPLAY0); strcat(command," "); strcat(command,parameter->ports); strcat(command," "); strcat(command,parameter->speed); strcat(command," "); strcat(command,(*song).DOSname); cuttail(command); message(43); printf("%s\n",command); if (parameter->pause) { bellit(); message(22); switch (bioskey(0)) { case KEYESC:error(9); /* aborted */ default:break; } } busyfloppy(); errorint=system(command); if (errorint==-1) error(20); if (parameter->A) { message(29); shutup(PORT1); } if (parameter->B) { message(29); shutup(PORT2); } if (parameter->C) { message(29); shutup(PORT3); } /* if .MOD was copied/created, it must be deleted since not there before */ if (found>=1) deleteasong((*song).DOSname); } } void cleanup(PARAMETERTYPE *parameter) /* deletes temporary programs on the temporary drive */ { int errorint; if (parameter->pkunzipcopied || parameter->modplaycopied) { message(6); if (parameter->modplaycopied) { errorint=unlink(MODPLAY1); if (errorint==-1) { errorint=unlink(MODPLAY2); if (errorint==-1) { errorint=unlink(MODPLAY3); if (errorint==-1) error(21); } } } if (parameter->pkunzipcopied) { errorint=unlink(PKUNZIP1); if (errorint==-1) error(21); } } } void playbatch(SONGSTYPE *songs, PARAMETERTYPE *parameter) /* plays the current batch of modules and Escape aborts */ { int songptr; int priority; int songcancel; songcancel=FALSE; for (priority=1 ; priority<=songs->songpriority ; priority++) if (!songcancel) { for (songptr=1 ; songptr<=songs->songnumber ; songptr++) if (songs->song[songptr].picked==priority) { songs->song[songptr].picked=0; playasong(&(songs->song[songptr]),parameter); break; } while (bioskey(1)) if (bioskey(0)==KEYESC) songcancel=TRUE; else bellit(); } if (songcancel) for (songptr=1 ; songptr<=songs->songnumber ; songptr++) songs->song[songptr].picked=0; } int main(int argc, char *argv[]) { char menuname[LINELENGTH]; FILE *menufile; SONGSTYPE songs; PARAMETERTYPE parameter; MOUSETYPE mousedata; int errorint; int songabort; /* TRUE indicates terminate MUSIQUE */ directvideo=0; /* safety for extended color text modes */ delay(1); /* solves initial delay() bug(?) */ srand((unsigned)time(NULL)); initialize(&songs,¶meter,menuname); scanarguments(argc,argv,menuname,¶meter); if (parameter.videomode!=ODDMODE) myresetmode(¶meter); /* Copyright notice so Borland is happy */ message(1); message(2); printf("%s\n",menuname); menufile=fopen(menuname,"rt"); if (menufile==NULL) { strcat(menuname,MENUENDING); message(2); printf("%s\n",menuname); menufile=fopen(menuname,"rt"); if (menufile==NULL) error(2); } message(3); readmenu(menufile,&songs); message(4); printf("%s\n",menuname); errorint=fclose(menufile); if (errorint==EOF) error(3); message(5); readparameter(¶meter,&mousedata,songs.songnumber); myclrscr(¶meter,colorborder); /* clear screen, set border & high stuff */ setdisk(parameter.tempdrive); if (getdisk()!=parameter.tempdrive) error(32); do { /* screen already cleared here */ printoutline(¶meter); if (parameter.mouse) mouseshow(mousedata.x,mousedata.y,&(mousedata.c),&(mousedata.color)); printsongs(&songs,¶meter,&mousedata); songabort=picksongs(&songs,¶meter,&mousedata); if (parameter.mouse) mousehide(mousedata.x,mousedata.y,mousedata.c,mousedata.color); myclrscr(¶meter,7); if (!songabort) { playbatch(&songs,¶meter); mysetmode(¶meter); /* reset mode/clear screen, border & high stuff */ } } while (!songabort); /* screen already cleared here */ cleanup(¶meter); setdisk(parameter.currentdrive); if (getdisk()!=parameter.currentdrive) error(33); return(0); }