// only for stand-alone version // VOID _cdecl main(INT argc, LPSTR argv[]) { UINT idxFnames; if (argc < 3) { I_OutputMsg("Format is mid2strm [-c] infile outfile\n"); I_OutputMsg("-c\tNo-stream-id compression\n"); exit(1); } idxFnames = 1; if (argv[1][0] == '-') { ++idxFnames; if (argv[1][1] == 'c') fCompress = TRUE; } if (!Init(argv[idxFnames], argv[idxFnames+1])) exit(1); if (!BuildNewTracks()) exit(1); if (!WriteStreamBuffers()) exit(1); // Add cleanup code!!! // Cleanup(); exit(0); }
// -------------- // BuildNewTracks // // This is where the actual work gets done. // // Until all tracks are done, // Scan the tracks to find the next due event // Figure out where the event belongs in the new mapping // Put it there // Add end of track metas to all new tracks that now have any data // // Return TRUE on success // Prints its own error message if something goes wrong // -------------- static BOOL BuildNewTracks(VOID) { LPINTRACKSTATE pInTrack; LPINTRACKSTATE pInTrackFound; UINT idx; DWORD tkNext; TEMPEVENT me; for (;;) { // Find nearest event due // pInTrackFound = NULL; tkNext = 0xFFFFFFFFL; for (idx = 0, pInTrack = ifs.pTracks; idx < ifs.nTracks; ++idx, ++pInTrack) { if ((!(pInTrack->fdwTrack & ITS_F_ENDOFTRK)) && (pInTrack->tkNextEventDue < tkNext)) { tkNext = pInTrack->tkNextEventDue; pInTrackFound = pInTrack; } } // None found? We must be done // if (!pInTrackFound) break; // Ok, get the event header from that track // if (!GetTrackEvent(pInTrackFound, &me)) { I_OutputMsg("MIDI file is corrupt!\n"); return FALSE; } // Don't add end of track event 'til we're done // if (me.abEvent[0] == MIDI_META && me.abEvent[1] == MIDI_META_EOT) continue; if (!AddEventToStream(&me)) { I_OutputMsg("Out of memory building tracks.\n"); return FALSE; } } return TRUE; }
boolean LoadGL(void) { const char *OGLLibname = NULL; const char *GLULibname = NULL; if (M_CheckParm ("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); if (SDL_GL_LoadLibrary(OGLLibname) != 0) { I_OutputMsg("Could not load OpenGL Library: %s\n", SDL_GetError()); I_OutputMsg("falling back to Software mode\n"); if (!M_CheckParm ("-OGLlib")) I_OutputMsg("if you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } #if 0 GLULibname = "/proc/self/exe"; #elif defined (_WIN32) GLULibname = "GLU32.DLL"; #elif defined (__MACH__) GLULibname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; #elif defined (macintos) GLULibname = "OpenGLLibrary"; #elif defined (__unix__) || defined (__HAIKU__) GLULibname = "libGLU.so"; #else GLULibname = NULL; #endif if (M_CheckParm ("-GLUlib") && M_IsNextParm()) GLULibname = M_GetNextParm(); if (GLULibname) { GLUhandle = hwOpen(GLULibname); if (GLUhandle) return SetupGLfunc(); else { I_OutputMsg("Could not load GLU Library: %s\n", GLULibname); I_OutputMsg("falling back to Software mode\n"); if (!M_CheckParm ("-GLUlib")) I_OutputMsg("if you know what is the GLU library's name, use -GLUlib\n"); } } else { I_OutputMsg("Please fill a bug report to tell SRB2 where to find the default GLU library for this unknown OS\n"); I_OutputMsg("falling back to Software mode\n"); I_OutputMsg("if you know what is the GLU library's name, use -GLUlib\n"); } return 0; }
static VOID ShowTrackError(LPINTRACKSTATE pInTrack, LPSTR szErr) { LPBYTE data; int i; I_OutputMsg("Track %u: %s\n", pInTrack->nTrack, szErr); I_OutputMsg("Track offset %lu\n", pInTrack->pTrackPointer - pInTrack->pTrackData); I_OutputMsg("Track total %lu Track left %lu\n", pInTrack->iTrackLen, pInTrack->iBytesLeft); I_OutputMsg(" Midi header: "); data = ifs.pFile; for (i = 0; i < 6; i++) { I_OutputMsg("%02x ", data[i]); } I_OutputMsg("\nTrack data: "); data = pInTrack->pTrackData; for (i = 0; i < 512; i++) { I_OutputMsg("%02x ", data[i]); } I_OutputMsg("\n"); }
// ------------------- // MCIErrorMessageBox // Retrieve error message corresponding to return value from // mciSendCommand() or mciSenString() // ------------------- static VOID MCIErrorMessageBox (MCIERROR iErrorCode) { char szErrorText[128]; if (!mciGetErrorStringA (iErrorCode, szErrorText, sizeof (szErrorText))) wsprintfA(szErrorText,"MCI CD Audio Unknown Error #%d\n", iErrorCode); I_OutputMsg("%s", szErrorText); /*MessageBox (GetActiveWindow(), szTemp+1, "LEGACY", MB_OK | MB_ICONSTOP);*/ }
// return a free acknum and copy netbuffer in the ackpak table static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) { node_t *node = &nodes[doomcom->remotenode]; INT32 i, numfreeslote = 0; if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0) { DEBFILE(va("too fast %d %d\n",node->remotefirstack,node->nextacknum)); return false; } for (i = 0; i < MAXACKPACKETS; i++) if (!ackpak[i].acknum) { // for low priority packet, make sure let freeslotes so urgents packets can be sent numfreeslote++; if (netbuffer->packettype >= PT_CANFAIL && numfreeslote < URGENTFREESLOTENUM) continue; ackpak[i].acknum = node->nextacknum; ackpak[i].nextacknum = node->nextacknum; node->nextacknum++; if (!node->nextacknum) node->nextacknum++; ackpak[i].destinationnode = (UINT8)(node - nodes); ackpak[i].length = doomcom->datalength; if (lowtimer) { // lowtime mean can't be sent now so try it soon as possible ackpak[i].senttime = 0; ackpak[i].resentnum = 1; } else { ackpak[i].senttime = I_GetTime(); ackpak[i].resentnum = 0; } M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length); *freeack = ackpak[i].acknum; sendackpacket++; // for stat return true; } #ifdef PARANOIA if (devparm) I_OutputMsg("No more free ackpacket\n"); #endif if (netbuffer->packettype < PT_CANFAIL) I_Error("Connection lost\n"); return false; }
boolean LoadGL(void) { #ifndef STATIC_OPENGL const char *OGLLibname = NULL; const char *GLULibname = NULL; if (M_CheckParm ("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); if (SDL_GL_LoadLibrary(OGLLibname) != 0) { I_OutputMsg("Could not load OpenGL Library: %s\n" "Falling back to Software mode.\n", SDL_GetError()); if (!M_CheckParm ("-OGLlib")) I_OutputMsg("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } #if 0 GLULibname = "/proc/self/exe"; #elif defined (_WIN32) GLULibname = "GLU32.DLL"; #elif defined (__MACH__) GLULibname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; #elif defined (macintos) GLULibname = "OpenGLLibrary"; #elif defined (__unix__) GLULibname = "libGLU.so.1"; #elif defined (__HAIKU__) GLULibname = "libGLU.so"; #else GLULibname = NULL; #endif if (M_CheckParm ("-GLUlib") && M_IsNextParm()) GLULibname = M_GetNextParm(); if (GLULibname) { GLUhandle = hwOpen(GLULibname); if (GLUhandle) return SetupGLfunc(); else { I_OutputMsg("Could not load GLU Library: %s\n", GLULibname); if (!M_CheckParm ("-GLUlib")) I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); } } else { I_OutputMsg("Could not load GLU Library\n"); I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); } #endif return SetupGLfunc(); }
/************************************************************************** * * function: PauseCD * * description: * * **************************************************************************/ void I_PauseCD (void) { #ifndef NOSDLCD if (!cdrom || !cdEnabled) return; if (!cdPlaying) return; if (SDL_CDPause(cdrom)) I_OutputMsg("cdrompause failed\n"); wasPlaying = cdPlaying; cdPlaying = SDL_FALSE; #endif }
/************************************************************************** * * function: StopCD * * description: * * **************************************************************************/ void I_StopCD(void) { #ifndef NOSDLCD if (!cdrom || !cdEnabled) return; if (!(cdPlaying || wasPlaying)) return; if (SDL_CDStop(cdrom)) I_OutputMsg("cdromstop failed\n"); wasPlaying = SDL_FALSE; cdPlaying = SDL_FALSE; #endif }
// ------------------------- // Mid2StreamRewindConverter // This little function is an adaptation of the ConverterInit() code which // resets the tracks without closing and opening the file, thus reducing the // time it takes to loop back to the beginning when looping. // ------------------------- static BOOL Mid2StreamRewindConverter(VOID) { DWORD iTrack; LPINTRACKSTATE pInTrack; tkCurrentTime = 0; // reset to start of midi file ifs.iBytesLeft = ifs.FileSize; ifs.pFilePointer = ifs.pFile; for (iTrack = 0, pInTrack = ifs.pTracks; iTrack < ifs.nTracks; ++iTrack, ++pInTrack) { pInTrack->iBytesLeft = pInTrack->iTrackLen; // Setup pointer to the current position in the track pInTrack->pTrackPointer = pInTrack->pTrackData; pInTrack->fdwTrack = 0; pInTrack->bRunningStatus = BAD_MIDI_FIX; pInTrack->tkNextEventDue = 0; // Handle bozo MIDI files which contain empty track chunks if (!pInTrack->iBytesLeft) { pInTrack->fdwTrack |= ITS_F_ENDOFTRK; continue; } // We always preread the time from each track so the mixer code can // determine which track has the next event with a minimum of work if (!GetTrackVDWord(pInTrack, &pInTrack->tkNextEventDue)) { I_OutputMsg("Read error while reading first delta time of track.\n"); return TRUE; } } // End of track initialization code return FALSE; }
// continue after a pause void I_ResumeCD (void) { #ifndef NOSDLCD if (!cdrom || !cdEnabled) return; if (!cdValid) return; if (!wasPlaying) return; if (cd_volume.value == 0) return; if (SDL_CDResume(cdrom)) I_OutputMsg("cdromresume failed\n"); cdPlaying = SDL_TRUE; wasPlaying = SDL_FALSE; #endif }
// ------------- // GetTrackEvent // // Fills in the event struct with the next event from the track // // pMe->tkEvent will contain the absolute tick time of the event // pMe->abEvent[0] will contain // MIDI_META if the event is a meta event; // in this case pMe->abEvent[1] will contain the meta class // MIDI_SYSEX or MIDI_SYSEXEND if the event is a SysEx event // Otherwise, the event is a channel message and pMe->abEvent[1] // and pMe->abEvent[2] will contain the rest of the event. // // pMe->dwEventLength will contain // The total length of the channel message in pMe->abEvent if // the event is a channel message // The total length of the paramter data pointed to by // pMe->pEvent otherwise // // pMe->pEvent will point at any additional paramters if the // event is a SysEx or meta event with non-zero length; else // it will contain NULL // // Returns TRUE on success or FALSE on any kind of parse error // Prints its own error message ONLY in the debug version // // Maintains the state of the input track (i.e. pInTrack->iBytesLeft, // pInTrack->pTrackPointers, and pInTrack->bRunningStatus). // ------------- static BOOL GetTrackEvent(LPINTRACKSTATE pInTrack, LPTEMPEVENT pMe) { BYTE b; UINT32 dwEventLength; // Clear out the temporary event structure to get rid of old data... ZeroMemory(pMe, sizeof (TEMPEVENT)); // Already at end of track? There's nothing to read. // if ((pInTrack->fdwTrack & ITS_F_ENDOFTRK) || !pInTrack->iBytesLeft) return FALSE; // Get the first BYTE, which determines the type of event. // b = *pInTrack->pTrackPointer++; --pInTrack->iBytesLeft; // If the high bit is not set, then this is a channel message // which uses the status BYTE from the last channel message // we saw. NOTE: We do not clear running status across SysEx or // meta events even though the spec says to because there are // actually files out there which contain that sequence of data. // if (!(b & 0x80)) { // No previous status BYTE? We're hosed. // if (!pInTrack->bRunningStatus) { TRACKERR(pInTrack, gteBadRunStat); return FALSE; } //faB: the last midi command issued on that track pMe->abEvent[0] = pInTrack->bRunningStatus; pMe->abEvent[1] = b; // the data ! b = (BYTE)(pMe->abEvent[0] & 0xF0); pMe->dwEventLength = 2; //2 data bytes // Only program change and channel pressure events are 2 BYTEs long; // the rest are 3 and need another BYTE // if ((b != MIDI_PRGMCHANGE) && (b != MIDI_CHANPRESS)) { if (!pInTrack->iBytesLeft) { TRACKERR(pInTrack, gteRunStatMsgTrunc); pInTrack->fdwTrack |= ITS_F_ENDOFTRK; return FALSE; } pMe->abEvent[2] = *pInTrack->pTrackPointer++; --pInTrack->iBytesLeft; ++pMe->dwEventLength; } } else if ((b & 0xF0) != MIDI_SYSEX) { // Not running status, not in SysEx range - must be // normal channel message (0x80-0xEF) pMe->abEvent[0] = b; pInTrack->bRunningStatus = b; // Strip off channel and just keep message type // b &= 0xF0; dwEventLength = (b == MIDI_PRGMCHANGE || b == MIDI_CHANPRESS) ? 1 : 2; pMe->dwEventLength = dwEventLength + 1; if (pInTrack->iBytesLeft < dwEventLength) { TRACKERR(pInTrack, gteChanMsgTrunc); pInTrack->fdwTrack |= ITS_F_ENDOFTRK; return FALSE; } pMe->abEvent[1] = *pInTrack->pTrackPointer++; if (dwEventLength == 2) pMe->abEvent[2] = *pInTrack->pTrackPointer++; pInTrack->iBytesLeft -= dwEventLength; } else if (b == MIDI_SYSEX || b == MIDI_SYSEXEND) { // One of the SysEx types. (They are the same as far as we're concerned; // there is only a semantic difference in how the data would actually // get sent when the file is played. We must take care to put the correct // event type back on the output track, however.) // // Parse the general format of: // BYTE bEvent (MIDI_SYSEX or MIDI_SYSEXEND) // VLONG cbParms // BYTE abParms[cbParms] // pMe->abEvent[0] = b; if (!GetTrackVDWord(pInTrack, &pMe->dwEventLength)) { TRACKERR(pInTrack, gteSysExLenTrunc); return FALSE; } if (pInTrack->iBytesLeft < pMe->dwEventLength) { TRACKERR(pInTrack, gteSysExTrunc); pInTrack->fdwTrack |= ITS_F_ENDOFTRK; return FALSE; } pMe->pEvent = pInTrack->pTrackPointer; pInTrack->pTrackPointer += pMe->dwEventLength; pInTrack->iBytesLeft -= pMe->dwEventLength; } else if (b == MIDI_META) { // It's a meta event. Parse the general form: // BYTE bEvent (MIDI_META) // BYTE bClass // VLONG cbParms // BYTE abParms[cbParms] // pMe->abEvent[0] = b; if (!pInTrack->iBytesLeft) { TRACKERR(pInTrack, gteMetaNoClass); pInTrack->fdwTrack |= ITS_F_ENDOFTRK; return FALSE; } pMe->abEvent[1] = *pInTrack->pTrackPointer++; --pInTrack->iBytesLeft; if (!GetTrackVDWord(pInTrack, &pMe->dwEventLength)) { TRACKERR(pInTrack, gteMetaLenTrunc); return FALSE; } // NOTE: Perfectly valid to have a meta with no data // In this case, dwEventLength == 0 and pEvent == NULL // if (pMe->dwEventLength) { if (pInTrack->iBytesLeft < pMe->dwEventLength) { TRACKERR(pInTrack, gteMetaTrunc); pInTrack->fdwTrack |= ITS_F_ENDOFTRK; return FALSE; } pMe->pEvent = pInTrack->pTrackPointer; pInTrack->pTrackPointer += pMe->dwEventLength; pInTrack->iBytesLeft -= pMe->dwEventLength; } if (pMe->abEvent[1] == MIDI_META_EOT) pInTrack->fdwTrack |= ITS_F_ENDOFTRK; } else { // Messages in this range are system messages and aren't supposed to // be in a normal MIDI file. If they are, we've misparsed or the // authoring software is stpuid. #ifdef DEBUGMIDISTREAM I_OutputMsg("System message not supposed to be in MIDI file..\n"); #endif return FALSE; } // Event time was already stored as the current track time // pMe->tkEvent = pInTrack->tkNextEventDue; // Now update to the next event time. The code above MUST properly // maintain the end of track flag in case the end of track meta is // missing. if (!(pInTrack->fdwTrack & ITS_F_ENDOFTRK)) { DWORD tkDelta; if (!GetTrackVDWord(pInTrack, &tkDelta)) return FALSE; pInTrack->tkNextEventDue += tkDelta; } return TRUE; }
// ---- // Init (stand-alone version) // // Open the input and output files // Allocate and read the entire input file into memory // Validate the input file structure // Allocate the input track structures and initialize them // Initialize the output track structures // // Return TRUE on success // Prints its own error message if something goes wrong // // ---- static BOOL Init(LPSTR szInFile, LPSTR szOutFile) { BOOL fRet = FALSE; LONG cbRead; UINT32 *pChunkID; UINT32 *pChunkSize; LONG iChunkSize; LPMIDIFILEHDR pHeader; LPINTRACKSTATE pInTrack; UINT iTrack; // Initialize things we'll try to free later if we fail // ifs.FileSize = 0; ifs.pFile = NULL; //ifs.pTracks = NULL; // Attempt to open the input and output files // hInFile = CreateFileA(szInFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hInFile) { I_OutputMsg("Could not open \"%s\" for read.\n", szInFile); goto Init_Cleanup; } hOutFile = CreateFileA(szOutFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hOutFile) { I_OutputMsg("Could not open \"%s\" for write.\n", szOutFile); goto Init_Cleanup; } // Figure out how big the input file is and allocate a chunk of memory big enough // to hold the whole thing. Read the whole file in at once. // if (INVALID_FILE_SIZE == (ifs.FileSize = GetFileSize(hInFile, NULL))) { I_OutputMsg("File system error on input file.\n"); goto Init_Cleanup; } if (NULL == (ifs.pFile = GlobalAllocPtr(GPTR, ifs.FileSize))) { I_OutputMsg("Out of memory.\n"); goto Init_Cleanup; } if ((!ReadFile(hInFile, ifs.pFile, ifs.FileSize, &cbRead, NULL)) || cbRead != ifs.FileSize) { I_OutputMsg("Read error on input file.\n"); goto Init_Cleanup; } // Set up to read from the memory buffer. Read and validate // - MThd header // - size of file header chunk // - file header itself // ifs.iBytesLeft = ifs.FileSize; ifs.pFilePointer = ifs.pFile; // note: midi header size should always be 6 if ((pChunkID = (UINT32*)GetInFileData(sizeof (*pChunkID))) == NULL || *pChunkID != MThd || (pChunkSize = (UINT32*)GetInFileData(sizeof (*pChunkSize))) == NULL || (iChunkSize = LONGSWAP(*pChunkSize)) < sizeof (MIDIFILEHDR) || (pHeader = (LPMIDIFILEHDR)GetInFileData(iChunkSize)) == NULL) { I_OutputMsg("Read error on MIDI header.\n"); goto Init_Cleanup; } // File header is stored in hi-lo order. Swap this into Intel order and save // parameters in our native int size (32 bits) // ifs.dwFormat = (LONG)WORDSWAP(pHeader->wFormat); ifs.nTracks = (LONG)WORDSWAP(pHeader->nTracks); ifs.dwTimeDivision = (LONG)WORDSWAP(pHeader->wTimeDivision); #ifdef DEBUGMIDISTREAM I_OutputMsg("MIDI Header:\n" "------------\n" "format: %d\n" "number of tracks: %d\n" "time division: %d\n", ifs.dwFormat, ifs.nTracks, ifs.dwTimeDivision); #endif // We know how many tracks there are; allocate the structures for them and parse // them. The parse merely looks at the MTrk signature and track chunk length // in order to skip to the next track header. // faB: now static // ifs.pTracks = (INTRACKSTATE *)GlobalAllocPtr(GPTR, ifs.nTracks*sizeof (INTRACKSTATE)); // if (ifs.pTracks == NULL) // { // I_OutputMsg("Out of memory.\n"); // goto Init_Cleanup; // } // faB: made it static, but don't quit if there are more tracks, just skip'em // (this isn't really a limit, since 32 tracks are really the maximum for MIDI files) if (ifs.nTracks > MAX_MIDI_IN_TRACKS) ifs.nTracks = MAX_MIDI_IN_TRACKS; for (iTrack = 0, pInTrack = ifs.pTracks; iTrack < ifs.nTracks; ++iTrack, ++pInTrack) { if ((pChunkID = (UINT32*)GetInFileData(sizeof (*pChunkID))) == NULL || *pChunkID!= MTrk || (pChunkSize = (UINT32*)GetInFileData(sizeof (*pChunkSize))) == NULL) { I_OutputMsg("Read error on track header.\n"); goto Init_Cleanup; } iChunkSize = LONGSWAP(*pChunkSize); pInTrack->iTrackLen = iChunkSize; pInTrack->iBytesLeft = iChunkSize; pInTrack->pTrackData = GetInFileData(iChunkSize); if (pInTrack->pTrackData == NULL) { I_OutputMsg("Read error while reading track data.\n"); goto Init_Cleanup; } #ifdef DEBUGMIDISTREAM I_OutputMsg("Track %d : length %d bytes\n", iTrack, iChunkSize); pInTrack->nTrack = iTrack; #endif pInTrack->pTrackPointer = pInTrack->pTrackData; pInTrack->fdwTrack = 0; pInTrack->bRunningStatus = 0; // Handle bozo MIDI files which contain empty track chunks // if (!pInTrack->iBytesLeft) { pInTrack->fdwTrack |= ITS_F_ENDOFTRK; continue; } // We always preread the time from each track so the mixer code can // determine which track has the next event with a minimum of work // if (!GetTrackVDWord(pInTrack, &pInTrack->tkNextEventDue)) { I_OutputMsg("Read error while reading first delta time of track.\n"); goto Init_Cleanup; } } ots.tkTrack = 0; ots.pFirst = NULL; ots.pLast = NULL; fRet = TRUE; Init_Cleanup: if (!fRet) Cleanup(); return fRet; }
// // calculate bounds for minimum angle // void phiBounds(double phi1, double phi2, double *phiMin, double *phiMax) { double phi1Tmp, phi2Tmp; double psi1, psi2, psi3, psi4, psi5, psi6, psi7; // for optimization sortPhi(phi1, phi2, &phi1Tmp, &phi2Tmp); phi1 = phi1Tmp; phi2 = phi2Tmp; // check start condition if(*phiMin > M_PI || *phiMax > M_PI) { *phiMin = phi1; *phiMax = phi2; return; } // 6 cases: // new angles inbetween phiMin, phiMax -> forget it // new angles enclose phiMin -> set phiMin // new angles enclose phiMax -> set phiMax // new angles completely outside phiMin, phiMax -> leave largest area free // new angles close the range completely! // new angles enlarges range on both sides psi1 = phiDiff(*phiMin, phi1); psi2 = phiDiff(*phiMin, phi2); psi3 = phiDiff(*phiMax, phi1); psi4 = phiDiff(*phiMax, phi2); psi5 = phiDiff(*phiMin, *phiMax); psi6 = 2.0*M_PI - psi5; // phiDiff(*phiMax, *phiMin); psi7 = 2.0*M_PI - psi2; // phiDiff(phi2, *phiMin); // case 1 & 5! if((psi1 <= psi5) && (psi2 <= psi5)) { if(psi1 <= psi2) // case 1 { return; } else // case 5 { // create some artificial interval here not to get into numerical trouble // in fact we know now the sector is completely enclosed -> base for computational optimization *phiMax = 0.0; *phiMin = DELTAPHI; return; } } // case 2 if((psi1 >= psi5) && (psi2 <= psi5)) { *phiMin = phi1; return; } // case 3 if((psi3 >= psi6) && (psi4 <= psi6)) { *phiMax = phi2; return; } // case 4 & 6 #ifdef PARANOIA if((psi3 <= psi6) && (psi4 <= psi6)) // FIXME: isn't this case implicitly true anyway?? #endif { if(psi3 <= psi4) //case 4 { if(psi3 >= psi7) { *phiMin = phi1; return; } else { *phiMax = phi2; return; } } else // case 6 { *phiMin = phi1; *phiMax = phi2; return; } } I_OutputMsg("phiMin = %f, phiMax = %f, phi1 = %f, phi2 = %f\n", *phiMin, *phiMax, phi1, phi2); I_Error("Holy shit, phiBounds() freaked out\n"); }
// allocate a socket static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen) { SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP); int opt; socklen_t opts; #ifdef FIONBIO #ifdef WATTCP char trueval = true; #else unsigned long trueval = true; #endif #endif mysockaddr_t straddr; if (s == (SOCKET_TYPE)ERRSOCKET || s == BADSOCKET) return (SOCKET_TYPE)ERRSOCKET; #ifdef USE_WINSOCK { // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up #ifdef USE_WINSOCK2 DWORD dwBytesReturned = 0; BOOL bfalse = FALSE; WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse), NULL, 0, &dwBytesReturned, NULL, NULL); #else unsigned long falseval = false; ioctl(s, SIO_UDP_CONNRESET, &falseval); #endif } #endif straddr.any = *addr; I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr)); if (family == AF_INET) { mysockaddr_t tmpaddr; tmpaddr.any = *addr ; if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) { opt = true; opts = (socklen_t)sizeof(opt); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts); } // make it broadcastable opt = true; opts = (socklen_t)sizeof(opt); if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore } } #ifdef HAVE_IPV6 else if (family == AF_INET6) { if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL { opt = true; opts = (socklen_t)sizeof(opt); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts); } #ifdef IPV6_V6ONLY // make it IPv6 ony opt = true; opts = (socklen_t)sizeof(opt); if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore } #endif } #endif if (bind(s, addr, addrlen) == ERRSOCKET) { close(s); I_OutputMsg("Binding failed\n"); return (SOCKET_TYPE)ERRSOCKET; } #ifdef FIONBIO // make it non blocking opt = true; if (ioctl(s, FIONBIO, &trueval) != 0) { close(s); I_OutputMsg("Seting FIOBIO on failed\n"); return (SOCKET_TYPE)ERRSOCKET; } #endif opts = (socklen_t)sizeof(opt); getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts); CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10); if (opt < 64<<10) // 64k { opt = 64<<10; opts = (socklen_t)sizeof(opt); setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts); getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts); if (opt < 64<<10) CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n")); else CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); }
static BOOL AddEventToStream(LPTEMPEVENT pMe) { PLONG pdw; LONG tkNow, tkDelta; UINT cdw; tkNow = ots.tkTrack; // Delta time is absolute event time minus absolute time // already gone by on this track tkDelta = pMe->tkEvent - ots.tkTrack; // Event time is now current time on this track ots.tkTrack = pMe->tkEvent; if (pMe->abEvent[0] < MIDI_SYSEX) { // Channel message. We know how long it is, just copy it. Need 3 LONG's: delta-t, // stream-ID, event /// \todo Compress with running status cdw = (fCompress ? 2 : 3); if (NULL == (pdw = (PLONG)GetOutStreamBytes(tkNow, cdw * sizeof (LONG), 3 * sizeof (LONG)))) return FALSE; *pdw++ = tkDelta; if (!fCompress) *pdw++ = 0; *pdw = (pMe->abEvent[0]) | (((LONG)pMe->abEvent[1]) << 8) | (((LONG)pMe->abEvent[2]) << 16) | MIDS_SHORTMSG; } else if (pMe->abEvent[0] == MIDI_SYSEX || pMe->abEvent[0] == MIDI_SYSEXEND) { if (devparm) // Tails I_OutputMsg("NOTE: Ignoring SysEx for now.\n"); } else { // Better be a meta event. // BYTE bEvent // BYTE bClass // VLONG cbParms // BYTE abParms[cbParms] // if (!(pMe->abEvent[0] == MIDI_META)) { I_OutputMsg("Mid2Stream: error1\n"); return FALSE; } // The only meta-event we care about is change tempo if (pMe->abEvent[1] != MIDI_META_TEMPO) return TRUE; if (!(pMe->dwEventLength == 3)) { I_OutputMsg("Mid2Stream: error2\n"); return FALSE; } cdw = (fCompress ? 2 : 3); pdw = (PLONG)GetOutStreamBytes(tkNow, cdw * sizeof (LONG), 3 * sizeof (LONG)); if (NULL == pdw) return FALSE; *pdw++ = tkDelta; if (!fCompress) *pdw++ = (LONG)-1; *pdw = (pMe->pEvent[2]) | (((LONG)pMe->pEvent[1]) << 8) | (((LONG)pMe->pEvent[0]) << 16) | MIDS_TEMPO; } return TRUE; }
// ----------------- // GetOutStreamBytes // // This function performs the memory management and pseudo-file I/O for output // tracks. // // We build a linked list of stream buffers as they would exist if they were // about to be played. Each buffer is CB_STREAMBUF BYTEs long maximum. They are // filled as full as possible; events are not allowed to cross buffers. // // Returns a pointer to the number of requested BYTEs or NULL if we're out of memory // ----------------- static LPBYTE GetOutStreamBytes(LONG tkNow, LONG cbNeeded, LONG cbUncompressed) { LPBYTE pb; // Round request up to the next LONG boundry. This aligns the final output buffer correctly // and allows the above routines to deal with BYTE-aligned data cbNeeded = (cbNeeded + 3) & ~3; cbUncompressed = (cbUncompressed + 3) & ~3; if (!(cbUncompressed >= cbNeeded)) { I_OutputMsg("GetOutStreamBytes: error\n"); return NULL; } if (NULL == ots.pLast || cbUncompressed > ots.pLast->iBytesLeftUncompressed) { PSTREAMBUF pNew; pNew = GlobalAllocPtr(GHND, sizeof (*pNew) + CB_STREAMBUF); if (NULL == pNew) return NULL; pNew->pBuffer = (LPBYTE)(pNew + 1); //skip PSTRAMBUF struct header.. pNew->tkStart = tkNow; pNew->pbNextEvent = pNew->pBuffer; pNew->iBytesLeft = CB_STREAMBUF; pNew->iBytesLeftUncompressed = CB_STREAMBUF; pNew->pNext = NULL; if (!ots.pLast) { ots.pFirst = pNew; ots.pLast = pNew; } else { ots.pLast->pNext = pNew; ots.pLast = pNew; } } // If there's STILL not enough room for the requested block, then an event is bigger than // the buffer size -- this is unacceptable. // if (cbNeeded > ots.pLast->iBytesLeft) { I_OutputMsg("NOTE: An event requested %lu BYTEs of memory; the\n", cbNeeded); I_OutputMsg(" maximum configured buffer size is %lu.\n", CB_STREAMBUF); return NULL; } pb = ots.pLast->pbNextEvent; ots.pLast->pbNextEvent += cbNeeded; ots.pLast->iBytesLeft -= cbNeeded; ots.pLast->iBytesLeftUncompressed -= cbUncompressed; return pb; }
// ----------------------- // Mid2StreamConverterInit // // Validate the input file structure // Allocate the input track structures and initialize them (faB: now STATIC) // Initialize the output track structures // // Return TRUE on success // ----------------------- BOOL Mid2StreamConverterInit(LPBYTE pMidiData, size_t iMidiSize) { BOOL fRet = TRUE; UINT32 *pChunkID; UINT32 *pChunkSize; UINT32 iChunkSize; LPMIDIFILEHDR pHeader; LPINTRACKSTATE pInTrack; UINT iTrack; tkCurrentTime = 0; // Initialize things we'll try to free later if we fail ZeroMemory(&ifs, sizeof (INFILESTATE)); //ifs.pTracks = NULL; //faB: now static // Set up to read from the memory buffer. Read and validate // - MThd header // - size of file header chunk // - file header itself // ifs.FileSize = iMidiSize; ifs.pFile = pMidiData; ifs.iBytesLeft = ifs.FileSize; ifs.pFilePointer = ifs.pFile; #ifdef DEBUGMIDISTREAM I_OutputMsg("Midi file size: %d\n", iMidiSize); #endif // note: midi header size should always be 6 if ((pChunkID = (UINT32*)GetInFileData(sizeof (*pChunkID))) == NULL || *pChunkID != MThd || (pChunkSize = (UINT32*)GetInFileData(sizeof (*pChunkSize))) == NULL || (iChunkSize = LONGSWAP(*pChunkSize)) < sizeof (MIDIFILEHDR) || (pHeader = (LPMIDIFILEHDR)GetInFileData(iChunkSize)) == NULL) { I_OutputMsg("Read error on MIDI header.\n"); goto Init_Cleanup; } ifs.dwFormat = (LONG)WORDSWAP(pHeader->wFormat); ifs.nTracks = (LONG)WORDSWAP(pHeader->nTracks); ifs.dwTimeDivision = (LONG)WORDSWAP(pHeader->wTimeDivision); #ifdef DEBUGMIDISTREAM I_OutputMsg("MIDI Header:\n" "------------\n" "format: %d\n" "number of tracks: %d\n" "time division: %d\n", ifs.dwFormat, ifs.nTracks, ifs.dwTimeDivision); #endif /* faB: made static ifs.pTracks = (INTRACKSTATE *)GlobalAllocPtr(GPTR, ifs.nTracks*sizeof (INTRACKSTATE)); if (ifs.pTracks == NULL) { I_OutputMsg("Out of memory.\n"); goto Init_Cleanup; } */ // faB: made it static, but don't quit if there are more tracks, just skip'em if (ifs.nTracks > MAX_MIDI_IN_TRACKS) ifs.nTracks = MAX_MIDI_IN_TRACKS; for (iTrack = 0, pInTrack = ifs.pTracks; iTrack < ifs.nTracks; ++iTrack, ++pInTrack) { if ((pChunkID = (UINT32*)GetInFileData(sizeof (*pChunkID))) == NULL || *pChunkID!= MTrk || (pChunkSize = (UINT32*)GetInFileData(sizeof (*pChunkSize))) == NULL) { I_OutputMsg("Read error on track header.\n"); goto Init_Cleanup; } iChunkSize = LONGSWAP(*pChunkSize); pInTrack->iTrackLen = iChunkSize; // Total track length pInTrack->iBytesLeft = iChunkSize; pInTrack->pTrackData = GetInFileData(iChunkSize); if (pInTrack->pTrackData == NULL) { I_OutputMsg("Read error while reading track data.\n"); goto Init_Cleanup; } #ifdef DEBUGMIDISTREAM I_OutputMsg("Track %d : length %d bytes\n", iTrack, iChunkSize); pInTrack->nTrack = iTrack; #endif // Setup pointer to the current position in the track pInTrack->pTrackPointer = pInTrack->pTrackData; pInTrack->fdwTrack = 0; pInTrack->bRunningStatus = BAD_MIDI_FIX; pInTrack->tkNextEventDue = 0; // Handle bozo MIDI files which contain empty track chunks if (!pInTrack->iBytesLeft) { pInTrack->fdwTrack |= ITS_F_ENDOFTRK; continue; } // We always preread the time from each track so the mixer code can // determine which track has the next event with a minimum of work if (!GetTrackVDWord(pInTrack, &pInTrack->tkNextEventDue)) { I_OutputMsg("Read error while reading first delta time of track.\n"); goto Init_Cleanup; } } // End of track initialization code fRet = FALSE; Init_Cleanup: if (fRet) Mid2StreamConverterCleanup(); return fRet; }
// // D_SRB2Main // void D_SRB2Main(void) { INT32 p; char srb2[82]; // srb2 title banner char title[82]; INT32 pstartmap = 1; boolean autostart = false; // keep error messages until the final flush(stderr) #if !defined (PC_DOS) && !defined (_WIN32_WCE) && !defined(NOTERMIOS) if (setvbuf(stderr, NULL, _IOFBF, 1000)) I_OutputMsg("setvbuf didnt work\n"); #endif #ifdef GETTEXT // initialise locale code M_StartupLocale(); #endif // get parameters from a response file (eg: srb2 @parms.txt) M_FindResponseFile(); // MAINCFG is now taken care of where "OBJCTCFG" is handled G_LoadGameSettings(); // Test Dehacked lists DEH_Check(); // identify the main IWAD file to use IdentifyVersion(); #if !defined (_WIN32_WCE) && !defined(NOTERMIOS) setbuf(stdout, NULL); // non-buffered output #endif #if defined (_WIN32_WCE) //|| defined (_DEBUG) || defined (GP2X) devparm = !M_CheckParm("-nodebug"); #else devparm = M_CheckParm("-debug"); #endif // for dedicated server #if !defined (_WINDOWS) //already check in win_main.c dedicated = M_CheckParm("-dedicated") != 0; #endif strcpy(title, "Sonic Robo Blast 2"); strcpy(srb2, "Sonic Robo Blast 2"); D_MakeTitleString(srb2); #ifdef PC_DOS D_Titlebar(srb2, title); #endif #if defined (__OS2__) && !defined (SDL) // set PM window title snprintf(pmData->title, sizeof (pmData->title), "Sonic Robo Blast 2" VERSIONSTRING ": %s", title); pmData->title[sizeof (pmData->title) - 1] = '\0'; #endif if (devparm) CONS_Printf(M_GetText("Development mode ON.\n")); // default savegame strcpy(savegamename, SAVEGAMENAME"%u.ssg"); { const char *userhome = D_Home(); //Alam: path to home if (!userhome) { #if ((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__) && !defined (DC) && !defined (PSP) && !defined(GP2X) I_Error("Please set $HOME to your home directory\n"); #elif defined (_WIN32_WCE) && 0 if (dedicated) snprintf(configfile, sizeof configfile, "/Storage Card/SRB2DEMO/d"CONFIGFILENAME); else snprintf(configfile, sizeof configfile, "/Storage Card/SRB2DEMO/"CONFIGFILENAME); #else if (dedicated) snprintf(configfile, sizeof configfile, "d"CONFIGFILENAME); else snprintf(configfile, sizeof configfile, CONFIGFILENAME); #endif } else { // use user specific config file #ifdef DEFAULTDIR snprintf(srb2home, sizeof srb2home, "%s" PATHSEP DEFAULTDIR, userhome); snprintf(downloaddir, sizeof downloaddir, "%s" PATHSEP "DOWNLOAD", srb2home); if (dedicated) snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, srb2home); else snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2home); // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); I_mkdir(srb2home, 0700); #else snprintf(srb2home, sizeof srb2home, "%s", userhome); snprintf(downloaddir, sizeof downloaddir, "%s", userhome); if (dedicated) snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, userhome); else snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, userhome); // can't use sprintf since there is %u in savegamename strcatbf(savegamename, userhome, PATHSEP); #endif } configfile[sizeof configfile - 1] = '\0'; #ifdef _arch_dreamcast strcpy(downloaddir, "/ram"); // the dreamcast's TMP #endif } // rand() needs seeded regardless of password srand((unsigned int)time(NULL)); if (M_CheckParm("-password") && M_IsNextParm()) D_SetPassword(M_GetNextParm()); else { size_t z; char junkpw[25]; for (z = 0; z < 24; z++) junkpw[z] = (char)(rand() & 64)+32; junkpw[24] = '\0'; D_SetPassword(junkpw); } // add any files specified on the command line with -file wadfile // to the wad list if (!(M_CheckParm("-connect"))) { if (M_CheckParm("-file")) { // the parms after p are wadfile/lump names, // until end of parms or another - preceded parm while (M_IsNextParm()) { const char *s = M_GetNextParm(); if (s) // Check for NULL? { if (!W_VerifyNMUSlumps(s)) G_SetGameModified(true); D_AddFile(s); } } } } // get map from parms if (M_CheckParm("-server") || dedicated) netgame = server = true; if (M_CheckParm("-warp") && M_IsNextParm()) { const char *word = M_GetNextParm(); if (fastncmp(word, "MAP", 3)) pstartmap = M_MapNumber(word[3], word[4]); else pstartmap = atoi(word); // Don't check if lump exists just yet because the wads haven't been loaded! // Just do a basic range check here. if (pstartmap < 1 || pstartmap > NUMMAPS) I_Error("Cannot warp to map %d (out of range)\n", pstartmap); else { if (!M_CheckParm("-server")) G_SetGameModified(true); autostart = true; } } CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n"); Z_Init(); // adapt tables to SRB2's needs, including extra slots for dehacked file support P_PatchInfoTables(); //---------------------------------------------------- READY TIME // we need to check for dedicated before initialization of some subsystems CONS_Printf("I_StartupTimer()...\n"); I_StartupTimer(); // Make backups of some SOCcable tables. P_BackupTables(); // Setup default unlockable conditions M_SetupDefaultConditionSets(); // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); if (!W_InitMultipleFiles(startupwadfiles)) #ifdef _DEBUG CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #else I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #endif D_CleanFile(); #if 1 // md5s last updated 3/15/14 // Yes, you read that right, that's the day of release. // Aren't we batshit insane? // Check MD5s of autoloaded files W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta W_VerifyFileMD5(4, "c529930ee5aed6dbe33625dc8075520b"); // patch.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif mainwads = 5; // there are 5 wads not to unload cht_Init(); //---------------------------------------------------- READY SCREEN // we need to check for dedicated before initialization of some subsystems CONS_Printf("I_StartupGraphics()...\n"); I_StartupGraphics(); //--------------------------------------------------------- CONSOLE // setup loading screen SCR_Startup(); // we need the font of the console CONS_Printf("HU_Init(): Setting up heads up display.\n"); HU_Init(); COM_Init(); // libogc has a CON_Init function, we must rename SRB2's CON_Init in WII/libogc #ifndef _WII CON_Init(); #else CON_InitWii(); #endif D_RegisterServerCommands(); D_RegisterClientCommands(); // be sure that this is called before D_CheckNetGame R_RegisterEngineStuff(); S_RegisterSoundStuff(); I_RegisterSysCommands(); //--------------------------------------------------------- CONFIG.CFG M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()" G_LoadGameData(); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen #endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); wipegamestate = gamestate; P_InitMapHeaders(); savedata.lives = 0; // flag this as not-used //------------------------------------------------ COMMAND LINE PARAMS // Initialize CD-Audio if (M_CheckParm("-usecd") && !dedicated) I_InitCD(); if (M_CheckParm("-noupload")) COM_BufAddText("downloading 0\n"); CONS_Printf("M_Init(): Init miscellaneous info.\n"); M_Init(); CONS_Printf("R_Init(): Init SRB2 refresh daemon.\n"); R_Init(); // setting up sound CONS_Printf("S_Init(): Setting up sound.\n"); if (M_CheckParm("-nosound")) nosound = true; if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic nomidimusic = nodigimusic = true; else { if (M_CheckParm("-nomidimusic")) nomidimusic = true; ; // WARNING: DOS version initmusic in I_StartupSound if (M_CheckParm("-nodigmusic")) nodigimusic = true; // WARNING: DOS version initmusic in I_StartupSound } I_StartupSound(); I_InitMusic(); S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); CONS_Printf("ST_Init(): Init status bar.\n"); ST_Init(); if (M_CheckParm("-room")) { if (!M_IsNextParm()) I_Error("usage: -room <room_id>\nCheck the Master Server's webpage for room ID numbers.\n"); #ifdef UPDATE_ALERT GetMODVersion_Console(); #endif ms_RoomId = atoi(M_GetNextParm()); } // init all NETWORK CONS_Printf("D_CheckNetGame(): Checking network game status.\n"); if (D_CheckNetGame()) autostart = true; // check for a driver that wants intermission stats // start the apropriate game based on parms if (M_CheckParm("-metal")) { G_RecordMetal(); autostart = true; } else if (M_CheckParm("-record") && M_IsNextParm()) { G_RecordDemo(M_GetNextParm()); autostart = true; } // user settings come before "+" parameters. if (dedicated) COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home)); else COM_ImmedExecute(va("exec \"%s"PATHSEP"autoexec.cfg\" -noerror\n", srb2home)); if (!autostart) M_PushSpecialParameters(); // push all "+" parameters at the command buffer // demo doesn't need anymore to be added with D_AddFile() p = M_CheckParm("-playdemo"); if (!p) p = M_CheckParm("-timedemo"); if (p && M_IsNextParm()) { char tmp[MAX_WADPATH]; // add .lmp to identify the EXTERNAL demo file // it is NOT possible to play an internal demo using -playdemo, // rather push a playdemo command.. to do. strcpy(tmp, M_GetNextParm()); // get spaced filename or directory while (M_IsNextParm()) { strcat(tmp, " "); strcat(tmp, M_GetNextParm()); } FIL_DefaultExtension(tmp, ".lmp"); CONS_Printf(M_GetText("Playing demo %s.\n"), tmp); if (M_CheckParm("-playdemo")) { singledemo = true; // quit after one demo G_DeferedPlayDemo(tmp); } else G_TimeDemo(tmp); G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; return; } if (M_CheckParm("-ultimatemode")) { autostart = true; ultimatemode = true; } if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect")) { gameaction = ga_nothing; CV_ClearChangedFlags(); // Do this here so if you run SRB2 with eg +timelimit 5, the time limit counts // as having been modified for the first game. M_PushSpecialParameters(); // push all "+" parameter at the command buffer if (M_CheckParm("-gametype") && M_IsNextParm()) { // from Command_Map_f INT32 j; INT16 newgametype = -1; const char *sgametype = M_GetNextParm(); for (j = 0; gametype_cons_t[j].strvalue; j++) if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype)) { newgametype = (INT16)gametype_cons_t[j].value; break; } if (!gametype_cons_t[j].strvalue) // reached end of the list with no match { j = atoi(sgametype); // assume they gave us a gametype number, which is okay too if (j >= 0 && j < NUMGAMETYPES) newgametype = (INT16)j; } if (newgametype != -1) { j = gametype; gametype = newgametype; D_GameTypeChanged(j); } } if (server && !M_CheckParm("+map") && !M_CheckParm("+connect") && !M_CheckParm("-connect")) { // Prevent warping to nonexistent levels if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) I_Error("Could not warp to %s (map not found)\n", G_BuildMapName(pstartmap)); // Prevent warping to locked levels // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. else if (!dedicated && M_MapLocked(pstartmap)) I_Error("You need to unlock this level before you can warp to it!\n"); else D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false); } } else if (M_CheckParm("-skipintro")) { CON_ToggleOff(); CON_ClearHUD(); F_StartTitleScreen(); } else F_StartIntro(); // Tails 03-03-2002 if (dedicated && server) { pagename = "TITLESKY"; levelstarttic = gametic; G_SetGamestate(GS_LEVEL); if (!P_SetupLevel(false)) I_Quit(); // fail so reset game stuff } }
// ---------------------- // AddEventToStreamBuffer // // Put the given event into the given stream buffer at the given location // pMe must point to an event filled out in accordance with the // description given in GetTrackEvent // // Returns FALSE on sucess or TRUE on an error condition // Handles its own error notification by displaying to the appropriate // output device (either our debugging window, or the screen). // ---------------------- static int AddEventToStreamBuffer(LPTEMPEVENT pMe, LPCONVERTINFO lpciInfo) { DWORD tkNow, tkDelta; MIDIEVENT *pmeEvent; pmeEvent = (MIDIEVENT *)(lpciInfo->mhBuffer.lpData + lpciInfo->dwStartOffset + lpciInfo->dwBytesRecorded); // When we see a new, empty buffer, set the start time on it... if (!lpciInfo->dwBytesRecorded) lpciInfo->tkStart = tkCurrentTime; // Use the above set start time to figure out how much longer we should fill // this buffer before officially declaring it as "full" if (tkCurrentTime - lpciInfo->tkStart > dwBufferTickLength) { if (lpciInfo->bTimesUp) { lpciInfo->bTimesUp = FALSE; return CONVERTERR_BUFFERFULL; } else lpciInfo->bTimesUp = TRUE; } tkNow = tkCurrentTime; // Delta time is absolute event time minus absolute time // already gone by on this track tkDelta = pMe->tkEvent - tkCurrentTime; // Event time is now current time on this track tkCurrentTime = pMe->tkEvent; if (pMe->abEvent[0] < MIDI_SYSEX) { // Channel message. We know how long it is, just copy it. // Need 3 DWORD's: delta-t, stream-ID, event if (lpciInfo->dwMaxLength-lpciInfo->dwBytesRecorded < 3*sizeof (DWORD)) { // Cleanup from our write operation return CONVERTERR_BUFFERFULL; } pmeEvent->dwDeltaTime = tkDelta; pmeEvent->dwStreamID = 0; pmeEvent->dwEvent = (pMe->abEvent[0]) | (((DWORD)pMe->abEvent[1]) << 8) | (((DWORD)pMe->abEvent[2]) << 16) | MEVT_F_SHORT; //faB: control the volume with our own volume percentage if (((pMe->abEvent[0] & 0xF0) == MIDI_CTRLCHANGE) && (pMe->abEvent[1] == MIDICTRL_VOLUME)) { // If this is a volume change, generate a callback so we can grab // the new volume for our cache // BP: this seems like this is useless and cause many many many bugs ! //pmeEvent->dwEvent |= MEVT_F_CALLBACK; } lpciInfo->dwBytesRecorded += 3 *sizeof (DWORD); } else if ((pMe->abEvent[0] == MIDI_SYSEX) || (pMe->abEvent[0] == MIDI_SYSEXEND)) { if (devparm) // Tails I_OutputMsg("NOTE: Ignoring SysEx for now.\n"); } else { DWORD dwCurrentTempo; // Better be a meta event. // BYTE byEvent // BYTE byEventType // VDWORD dwEventLength // BYTE pLongEventData[dwEventLength] // if (!(pMe->abEvent[0] == MIDI_META)) { I_Error("AddEventToStreamBuffer: not a META event\n"); } // The only meta-event we care about is change tempo // if (pMe->abEvent[1] != MIDI_META_TEMPO) return CONVERTERR_METASKIP; // We should have three bytes of parameter data... if (!(pMe->dwEventLength == 3)) { I_Error("AddEventToStreamBuffer: dwEventLength <> 3\n"); } // Need 3 DWORD's: delta-t, stream-ID, event data if (lpciInfo->dwMaxLength - lpciInfo->dwBytesRecorded < 3 *sizeof (DWORD)) { return CONVERTERR_BUFFERFULL; } pmeEvent->dwDeltaTime = tkDelta; pmeEvent->dwStreamID = 0; // Note: this is backwards from above because we're converting a single // data value from hi-lo to lo-hi format... pmeEvent->dwEvent = (pMe->pEvent[2]) | (((DWORD)pMe->pEvent[1]) << 8) | (((DWORD)pMe->pEvent[0]) << 16); dwCurrentTempo = pmeEvent->dwEvent; pmeEvent->dwEvent |= (((DWORD)MEVT_TEMPO) << 24) | MEVT_F_SHORT; dwBufferTickLength = (ifs.dwTimeDivision * 1000 * BUFFER_TIME_LENGTH) / dwCurrentTempo; #ifdef DEBUGMIDISTREAM I_OutputMsg("dwBufferTickLength = %lu", dwBufferTickLength); #endif lpciInfo->dwBytesRecorded += 3 *sizeof (DWORD); } return FALSE; }