#include #include #include #include #include #include #include #include "midas.h" #include "mconfig.h" #include "vu.h" #include "vga.h" #include "midp.h" #ifndef NOTIMER #define SCRSYNC #endif int numChannels = 0; /* number of channels in module */ int activeChannel = 0; /* active channel number */ uchar attrDispTop = 0x4F; /* display top message */ uchar attrMainBg = 0x70; /* main window background */ uchar attrMainLit = 0x7F; /* main window lit areas */ uchar attrMainShadow = 0x78; /* main window shadow areas */ uchar attrMainBorderLit = 0x0F; /* main window lit border */ uchar attrMainBorderSh = 0x08; /* main window shadow border */ uchar attrChanInfoSep = 0x70; /* channel information separator */ uchar attrChanInfo = 0x70; /* channel information */ uchar attrSongInfoLabel = 0x7F; /* song information label */ uchar attrSongInfo = 0x70; /* song information */ uchar attrUsedInstName = 0x70; /* used instrument name */ uchar attrUnusedInstName = 0x78; /* unused instrument name */ uchar attrInstNameSeparator = 0x70; /* instrument name separator */ uchar attrInstIndicator = 0x7E; /* instrument used indicator */ uchar attrActChanMarker = 0x07; /* active channel marker */ uchar attrVUMeters = 0x7A; /* VU meters */ uchar attrVUBlank = 0x70; /* Blank VU meters */ int msgWindowHeight = 8; /* message window height */ time_t startTime; /* total playing time */ time_t pauseTime = 0; /* time spent paused */ time_t pauseStart; /* start time for current pause */ int paused = 0; /* is playing paused? */ unsigned masterVolume = 64; /* master volume */ int instNameMode = 0; /* instrument name display mode */ int firstInstName = 1; /* first instrument name on screen */ int realVU = 1; /* are real VU meters active? */ gmpModule *module; /* current playing module */ gmpInformation *info; /* current module playing info */ int callMP; uchar chMuted[32]; /* channel muted flags */ unsigned scrSync; /* timer screen sync value */ volatile ulong frameCount; /* frame counter */ void DumpHeap(void) { static struct _heapinfo hinfo; int hstatus; hinfo._pentry = NULL; while ( 1 ) { hstatus = _heapwalk(&hinfo); if ( hstatus != _HEAPOK ) break; if ( hinfo._useflag == _USEDENTRY ) printf("USED block at %FP of size %4.4X\n", hinfo._pentry, hinfo._size); else printf("FREE block at %FP of size %4.4X\n", hinfo._pentry, hinfo._size); } switch ( hstatus ) { case _HEAPEND: printf("OK - end of heap\n\n"); break; case _HEAPEMPTY: printf("OK - heap is empty\n\n"); break; default: printf("ERROR - heap corrupted\n\n"); } } void CommandChecksum(void) { ulong sum = 0; int i; for ( i = 0; i < gmpNumCommands; i++ ) sum += (ulong) gmpTick0CommandsPT[i]; printf("%08X, ", sum); for ( i = 0; i < gmpNumCommands; i++ ) sum += (ulong) gmpContCommandsPT[i]; printf("%08X\n", sum); fflush(stdout); } void CALLING PreVR(void) { frameCount++; } void WaitFrame(void) { #ifdef SCRSYNC ulong oldFrameCount = frameCount; return; while ( oldFrameCount == frameCount ); #else vgaWaitVR(); vgaWaitDE(); #endif } int CALLING MakeMeter(sdSample *sdsmp, gmpSample *gmpsmp) { return vuPrepare(sdsmp, gmpsmp->sdHandle - 1); } int main(int argc, char *argv[]) { int error; int quit = 0; int key, i; int doConfig = 0; static fileHandle f; static uchar buf[48]; static int panning; // puts("Press any"); // getch(); setvbuf(stdout, NULL, _IONBF, 0); midasSetDefaults(); if ( argc < 2 ) { puts("Usage: MIDP [options]\n"); puts("Options: -c Manual sound card configuration"); exit(EXIT_SUCCESS); } if ( argc > 2 ) { if ( ((argv[2][0] == '-') || (argv[2][0] == '/')) && ((argv[2][1] == 'c') || (argv[2][1] == 'C')) ) doConfig = 1; } midasSetDefaults(); if ( doConfig ) midasConfig(); midasDisableEMS = 1; // midasOutputMode |= sdMono; // midasOutputMode &= (~sdStereo); // midasSDNumber = 2; InitDisplay(); DrawScreen(); #ifdef SCRSYNC if ( (error = tmrGetScrSync(&scrSync)) != OK ) midasError(error); #endif midasInit(); if ( realVU ) if ( (error = vuInit()) != OK ) midasError(error); //#ifdef SCRSYNC // if ( (error = tmrSyncScr(scrSync, &PreVR, NULL, NULL)) != OK ) // midasError(error); //#endif printf("%P\n", dsmMixBuffer); printf("Using %s\n%s, using port %X, IRQ %i and DMA %i\n", midasSD->name, midasSD->cardNames[midasSD->cardType-1], midasSD->port, midasSD->IRQ, midasSD->DMA); /* Read first 48 bytes of module: */ if ( (error = fileOpen(argv[1], fileOpenRead, &f)) != OK ) midasError(error); if ( (error = fileRead(f, buf, 48)) != OK ) midasError(error); if ( (error = fileClose(f)) != OK ) midasError(error); if ( mMemEqual(buf, "Extended Module:", 16) ) { puts("Loading Fasttracker 2 module"); if ( realVU ) { if ( (error = gmpLoadXM(argv[1], 1, &MakeMeter, &module)) != OK ) midasError(error); } else { if ( (error = gmpLoadXM(argv[1], 1, NULL, &module)) != OK ) midasError(error); } } else { if ( mMemEqual(buf+44, "SCRM", 4) ) { puts("Loading Screamtracker 3 module"); if ( realVU ) { if ( (error = gmpLoadS3M(argv[1], 1, &MakeMeter, &module)) != OK ) midasError(error); } else { if ( (error = gmpLoadS3M(argv[1], 1, NULL, &module)) != OK ) midasError(error); } } else { puts("Loading Protracker module"); if ( realVU ) { if ( (error = gmpLoadMOD(argv[1], 1, &MakeMeter, &module)) != OK ) midasError(error); } else { if ( (error = gmpLoadMOD(argv[1], 1, NULL, &module)) != OK ) midasError(error); } } } numChannels = dispChannels = module->numChannels; puts("Playing"); midasPlayModule(module, 0); DrawScreen(); DrawSongInfo(); startTime = time(NULL); #ifdef SCRSYNC if ( (error = tmrSyncScr(scrSync, &PreVR, NULL, NULL)) != OK ) midasError(error); #endif /* Clear channel muted flags: */ for ( i = 0; i < 32; i++ ) chMuted[i] = 0; while ( !quit ) { WaitFrame(); #ifdef BORDERS vgaSetBorder(15); #endif #ifdef NOTIMER if ( (error = midasSD->StartPlay()) != OK ) midasError(error); do { #ifdef BORDERS vgaSetBorder(3); #endif if ( (error = midasSD->Play(&callMP)) != OK ) midasError(error); #ifdef BORDERS vgaSetBorder(13); #endif if ( callMP ) { // CommandChecksum(); if ( (error = gmpPlay()) != OK ) midasError(error); } } while ( callMP && (midasSD->tempoPoll == 0) ); // gmpPlay(); #endif #ifdef BORDERS vgaSetBorder(1); #endif if ( (error = gmpGetInformation(midasPlayHandle, &info)) != OK ) midasError(error); UpdateScreen(); #ifdef BORDERS vgaSetBorder(0); #endif if ( kbhit() ) { key = mGetKey(); /* read keypress */ if ( key < 0x100 ) key = toupper ( (char) key ); switch ( key ) { case 27: quit = 1; break; case 9: instNameMode ^= 1; DrawScreen(); DrawSongInfo(); break; case 'D': #ifdef SCRSYNC if ( (error = tmrStopScrSync()) != OK ) midasError(error); #endif spawnl(P_WAIT, mGetEnv("COMSPEC"), NULL); InitDisplay(); DrawScreen(); DrawSongInfo(); #ifdef SCRSYNC if ( (error = tmrSyncScr(scrSync, &PreVR, NULL, NULL)) != OK ) midasError(error); #endif break; case '-': if ( masterVolume > 0 ) masterVolume--; if ( (error = midasSD->SetMasterVolume(masterVolume)) != OK ) midasError(error); break; case '+': if ( masterVolume < 64 ) masterVolume++; if ( (error = midasSD->SetMasterVolume(masterVolume)) != OK ) midasError(error); break; case 0x14d: /* Right arrow */ incPosition: gmpHandle->position++; /* Check if we reached song length, and if so, jump to restart position: */ if (gmpHandle->position > gmpHandle->songEnd) { gmpHandle->position = gmpHandle->restartPos; } /* Get the pattern number for new position: */ if (( gmpCurModule->songData[gmpHandle->position] == 0xfffe ) || (gmpCurModule-> songData[gmpHandle->position] == 0xffff)) goto incPosition; gmpHandle->pattern = gmpCurModule-> songData[gmpHandle->position]; gmpHandle->row = 0; gmpHandle->playPtr = NULL; break; case 0x14b: /* Left arrow */ decPosition: gmpHandle->position--; if ( gmpHandle->position >= gmpCurModule->songLength ) gmpHandle->position = gmpCurModule->songLength-1; if ( (gmpCurModule->songData[gmpHandle->position] == 0xfffe ) || ( gmpCurModule-> songData[gmpHandle->position] == 0xffff ) ) goto decPosition; gmpHandle->pattern = gmpCurModule-> songData[gmpHandle->position]; gmpHandle->row = 0; gmpHandle->playPtr = NULL; break; case 0x151: /* Page down */ if ( firstInstName < gmpHandle->module->numInsts ) { firstInstName++; DrawInstNames(); } break; case 0x149: /* Page up */ if ( firstInstName > 1 ) { firstInstName--; DrawInstNames(); } break; case 0x148: /* Up arrow */ if ( activeChannel > 0 ) activeChannel--; break; case 0x150: /* Down arrow */ if ( activeChannel < (numChannels-1) ) activeChannel++; break; case 'T': /* T - toggle channel mute on/off */ chMuted[activeChannel] ^= 1; if ( (error = midasSD->MuteChannel(activeChannel, chMuted[activeChannel])) != OK ) midasError(error); break; case 'M': if ( (error = midasSD->SetPanning(activeChannel, panMiddle)) != OK ) midasError(error); break; case 'L': if ( (error = midasSD->SetPanning(activeChannel, panLeft)) != OK ) midasError(error); break; case 'R': if ( (error = midasSD->SetPanning(activeChannel, panRight)) != OK ) midasError(error); break; case 'U': if ( (error = midasSD->SetPanning(activeChannel, panSurround)) != OK ) midasError(error); break; case ',': if ( (error = midasSD->GetPanning(activeChannel, &panning)) != OK ) midasError(error); if ( panning > panLeft ) { panning--; if ( (error = midasSD->SetPanning(activeChannel, panning)) != OK ) midasError(error); } break; case '.': if ( (error = midasSD->GetPanning(activeChannel, &panning)) != OK ) midasError(error); if ( panning < panRight ) { panning++; if ( (error = midasSD->SetPanning(activeChannel, panning)) != OK ) midasError(error); } break; } } } printf("\n"); puts("0"); midasStopModule(module); puts("0.5"); if ( realVU ) { for ( i = 0; i < MAXSAMPLES; i++ ) if ( (error = vuRemove(i)) != OK ) midasError(error); } puts("1"); if ( (error = gmpFreeModule(module)) != OK ) midasError(error); puts("1.5"); if ( realVU ) { if ( (error = vuClose()) != OK ) midasError(error); } puts("2"); midasClose(); DumpHeap(); #ifdef DEBUG errPrintList(); #endif return 0; }