// Find the intersection with another rect and fill in the intersect rect // if requested (not NULL) // bool TClipRect::Intersect(Rectangle* pTargetRect, Rectangle* pIntRect) { coord l; coord t; coord r; coord b; bool ret = FALSE; if (IsEmpty() == FALSE) { // we have a rect to check l = AMax(x1, pTargetRect->x1); t = AMin(x2 - 1, pTargetRect->x2); r = AMax(y1, pTargetRect->y1); b = AMin(y2 - 1, pTargetRect->y2); if (r >= l && b >= t) { if (pIntRect) { pIntRect->x1 = l; pIntRect->y1 = t; pIntRect->x2 = r; pIntRect->y2 = b; } ret = TRUE; } } return ret; }
// Clip this rectangle to be within the passed clipRect // void Rectangle::Clip(Rectangle* clipRect) { x1 = AMax(x1, clipRect->x1); y1 = AMax(y1, clipRect->y1); x2 = AMax(AMin(x2, clipRect->x2), x1); y2 = AMax(AMin(y2, clipRect->y2), y1); }
// Clip this rectangle to be within the passed TClipRect // void TClipRect::Clip(TClipRect* pClipRect) { x1 = AMax(x1, pClipRect->x1); y1 = AMax(y1, pClipRect->y1); x2 = AMax(AMin(x2, pClipRect->x2), x1); y2 = AMax(AMin(y2, pClipRect->y2), y1); }
// Clip this rectangle to be within the passed TClipRect // void TClipRect::Clip(Rectangle* pClipRect) { x1 = AMax(x1, pClipRect->x1); y1 = AMax(y1, pClipRect->y1); x2 = AMax(AMin(x2, pClipRect->x2 + 1), x1); y2 = AMax(AMin(y2, pClipRect->y2 + 1), y1); }
// Enlarge to bound second rect void Rectangle::Unite(Rectangle* pRect2) { x1 = AMin(x1, pRect2->x1); y1 = AMin(y1, pRect2->y1); x2 = AMax(x2, pRect2->x2); y2 = AMax(y2, pRect2->y2); area = CalcArea(); }
// Enlarge to bound second rect void TClipRect::Unite(TClipRect* pRect2) { x1 = AMin(x1, pRect2->x1); y1 = AMin(y1, pRect2->y1); x2 = AMax(x2, pRect2->x2); y2 = AMax(y2, pRect2->y2); area = CalcArea(); }
// Calculate the area of a rect large enough to contain this rect // and another rect. uint Rectangle::AreaBounds(Rectangle* pRect2) { coord t, l, b, r; l = AMin(x1, pRect2->x1); t = AMin(y1, pRect2->y1); r = AMax(x2, pRect2->x2); b = AMax(y2, pRect2->y2); return ((b - t + 1) * (r - l + 1)); }
// Calculate the area of a rect large enough to contain this rect // and another rect. uint TClipRect::AreaBounds(TClipRect* pRect2) { coord t, l, b, r; l = AMin(x1, pRect2->x1); t = AMin(y1, pRect2->y1); r = AMax(x2, pRect2->x2); b = AMax(y2, pRect2->y2); return ((b - t) * (r - l)); }
// Find the intersection with another rect and fill in the intersect rect // if requested (not NULL) // bool Rectangle::Intersect(Rectangle* pTargetRect, Rectangle* pIntRect) { coord l = AMax(x1, pTargetRect->x1); coord t = AMin(x2, pTargetRect->x2); coord r = AMax(y1, pTargetRect->y1); coord b = AMin(y2, pTargetRect->y2); bool ret = FALSE; if (r >= l && b >= t) { if (pIntRect) { pIntRect->x1 = l; pIntRect->y1 = t; pIntRect->x2 = r; pIntRect->y2 = b; } ret = TRUE; } return ret; }
int main(int argc, char** argv) { char mess[100], *string1; uint16 saverResult; int loop1, loop2, framesRun, framesPerSec = 0; bool fWaitToSend; BAM_WorldEnderPopup *pWEPop; FILE *pFile; // Nothing *pNothing1 = new Nothing; // NothingMore *pNothingMore1 = new NothingMore; // Dummy *pDummy1 = new Dummy(0x1234); // pNothing1->SetValue(0x1234); // pNothingMore1->SetValue(0x5678); // pDummy1->SetValue(0x90ab); // Unit *pUnit = new Unit(TRUE); // Unit unit1(TRUE); /* Jay - here's the code for the test case you said you wanted to try next: pFile = fopen("unit1.dat", "wb"); fwrite(&unit1, 1, sizeof(unit1), pFile); fclose(pFile); */ /* pFile = fopen("unit1.dat", "rb"); fread(&unit1, 1, sizeof(unit1), pFile); fclose(pFile); */ time_t startTime, timeDif, lastTime; time(&startTime); lastTime = startTime; // disable critical error handler _harderr(critical_error_handler); AInitializePlatform(); #ifndef NDEBUG printf("\n\n&ReportFreeMem==0x%08X\n", (int)ReportFreeMem); #endif #ifdef OS_DOS printf("\nBLOOD & MAGIC Copyright (C) 1996 by Tachyon Studios Inc..\n"); printf("Developed by Tachyon Studios for Interplay Productions.\n"); printf("BLOOD & MAGIC, FORGOTTEN REALMS and the TSR LOGO are Trademarks\n"); printf("owned by TSR, Inc and are used under license.\n"); printf("\nCompiled %s %s\n", __DATE__, __TIME__); printf("%dk free after platform initialization\n", AAvailMem() / 1024); if(AAvailMem() < MIN_MEM_REQ) { printf("\nWARNING: Free XMS memory is low (<%dk)!\nBAM may not run reliably\n", MIN_MEM_REQ / 1000); sleep(4); } #endif // short-circuit any command line args // argc = 1; if(argc > 1 && (!memcmp(argv[1], "?", 2) || !memcmp(argv[1], "-HELP", 6))) { // printf("Format: BAM [mapNum] [-NOINTRO] [-NOFOG] [-SIDEx] [-NOWIN] [-NET] [-SHOWOFF]\n"); return(0); } // if the seed is the same, the sequence will repeat. cool! // ASeedRandom(41); // for repeatability of bugs // ASeedRandom2(41); // for repeatability of bugs ASeedRandom(startTime); // for genuine randomness ASeedRandom2(startTime); // for genuine randomness // If you ever don't want to see unfreed memory, like for demos, // then uncomment this. // extern bool fPrintUnfreedPtrs; // fPrintUnfreedPtrs = FALSE; TRACK_MEM("Mono"); pMono = new Mono; // if we really must allocate this on the fly instead of // having it global, then we must tell the memmgr not to save it. ASetSaveStatus(AGetGrip(pMono), FALSE); // also, we don't want this to be purged on a restore. ASetPurgeStatus(AGetGrip(pMono), FALSE); pMono->SetWindow(0, 7, 79, 12); pMono->Clear(); pMono->Out("Monochrome output initialized\n"); #ifndef NDBEUG pMono->Out("&ReportFreeMem==0x%08X\n", (int)ReportFreeMem); sleep(4); #endif pMono->Out("EventMgr initializing\n"); TRACK_MEM("EventMgr"); new EventMgr; // we are going to update ticks when we want to. AAutoUpdateTicks(FALSE); pMono->Out("ContextMgr initializing\n"); TRACK_MEM("ContextMgr"); new ContextMgr; pMono->Out("ResMgr initializing\n"); TRACK_MEM("ResMgr"); new ResourceMgr(TRUE); // NOTE - IT IS HIGHLY RECOMMENDED THAT YOU INIT THE SOUND MANAGER // BEFORE THE GRAPH MANAGER. If you don't, streamed sounds will // stop and start during restore because of the busy loop in graph // manager that happens when the palette fades up. pMono->Out("SoundMgr initializing\n"); TRACK_MEM("SndMgr"); new SoundMgr; pSoundMgr->Init(); // BUGBUG! If we bind w/ DOS4GW/Pro we will crash here! //setup smacker sound stuff SmackSoundUseSOS3((u16)pSoundMgr->hDigiDriverHandle,0); pMono->Out("GraphMgr initializing\n"); TRACK_MEM("GraphMgr"); pGraphMgr = new GraphicsMgr(MODEX_320X400); pMono->Out("%dk free after platform initialization\n", AAvailMem() / 1024); // Debugger debug1, debug2; // debug1.OpenWindow(0, 0, 79, 10); // debug2.OpenWindow(40, 11, 79, 21); // for(loop1 = 0; loop1 < 25; loop1++) // { // pMono->Out("\n%d", loop1); // } // sleep(2); TRACK_MEM("FontMgr"); pFontMgr = new FontMgr; // default font pFontMgr->SetRes(9050); // default font color pFontMgr->ForeColor(TEXT_DEFAULT); pFontMgr->colors[FNT_BACK_COLOR] = CI_SKIP; #ifdef OS_MAC // #include "menubar.hpp" // DS9MenuBar* pMenuBar; // TRACK_MEM("menuBar"); pMenuBar = new DS9MenuBar; TRACK_MEM("Mouse"); new Mouse; #else TRACK_MEM("Mouse"); new MouseInt; #endif if(pMouse->hideCount == 999) { // init error ShutDownSoundMgr(); APrintUnfreedPtrs(FALSE); exit(1); } pMouse->Init(0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1); pMouse->SetRes(RES_ANIM, POINTER_RES, 1); pMouse->Hide(); //let bamroom show it at room change time. // this is our global data saver AtSave(GlobalSave); // create the application instance TRACK_MEM("BAM App"); pBam = new BAM_Application; bGlobal.gBam = pBam->gSelf; pBam->msgMask = E_MOUSE_DOWN | E_MOUSE_UP | E_KEY_DOWN; // command-line options parsed here memcpy(pBam->scenarioName, "9110", 5); // default scenario pBam->fNoIntro = FALSE; pBam->fDefaultScenario = FALSE; pBam->fUseFog = TRUE; pBam->fUseWinLose = TRUE; pBam->playerSide = SIDE1; pBam->fMapEdit = FALSE; pBam->playerTypes[SIDE0] = PLAYER_NONE; pBam->playerTypes[SIDE1] = PLAYER_LOCAL; pBam->playerTypes[SIDE2] = PLAYER_NONE; pBam->playerTypes[SIDE3] = PLAYER_NONE; pBam->playerTypes[SIDE4] = PLAYER_NONE; { FILE *pPentiumFile; pPentiumFile = fopen("PENTIUM.VAN", "rb"); if(pPentiumFile) { fclose(pPentiumFile); fPentium = TRUE; } } for(loop1 = 1; loop1 < argc; loop1++) { strcpy(mess, argv[loop1]); string1 = mess; do { *string1 = (char) toupper(*string1); string1++; } while(*string1); if(mess[0] == '-') { // #ifdef ENABLE_EDITOR // if(!memcmp(mess, "-EDIT", 5)) // turn on edit mode // pBam->fMapEdit = TRUE; // #endif if(!memcmp(mess, "-NOINTRO", 9)) // turn off opening cinematic pBam->fNoIntro = TRUE; else if(!memcmp(mess, "-NOWIN", 6)) // turn on win/lose conditions pBam->fUseWinLose = FALSE; else if(!memcmp(mess, "-NOFOG", 6)) // turn off fog pBam->fUseFog = FALSE; else if(!memcmp(mess, "-NET", 4)) // network play { pBam->fNetworkTest = TRUE; bGlobal.storyLine = NETGAME; ASeedRandom(42); // need sync'ed RNGs } else if(!memcmp(mess, "-PENTIUM", 8)) { fPentium = TRUE; } else if(!memcmp(mess, "-MUSIC", 6)) { bGlobal.altMusicNum = atoi(mess + 6); } else if(!memcmp(mess, "-AIUNITS", 8)) { bGlobal.aiUnitMultiplier = atoi(mess + 8); } else if(!memcmp(mess, "-AI", 3)) { bGlobal.aiOveride = atoi(mess + 3); } else if(!memcmp(mess, "-FRENCH", 7)) { SetLanguage(LANG_FRENCH); } else if(!memcmp(mess, "-GERMAN", 7)) { SetLanguage(LANG_GERMAN); } else if(!memcmp(mess, "-ENGLISH", 8)) { SetLanguage(LANG_ENGLISH); } else if(!memcmp(mess, "-SHOWOFF", 8)) // storefront demo mode { bGlobal.storyLine = SHOW_OFF; } else if(!memcmp(mess, "-HACKRES", 8)) // allow single resource replacement { pResMgr->fSearchStuffsFirst = FALSE; } else if(!memcmp(mess, "-SIDE", 5)) // set player side (1 or 2) { switch(mess[5]) { case '0': pBam->playerSide = SIDE0; pBam->playerTypes[SIDE1] = PLAYER_NONE; pBam->playerTypes[SIDE2] = PLAYER_NONE; break; case '1': pBam->playerSide = SIDE1; pBam->playerTypes[SIDE1] = PLAYER_LOCAL; pBam->playerTypes[SIDE2] = PLAYER_NONE; break; case '2': pBam->playerSide = SIDE2; pBam->playerTypes[SIDE1] = PLAYER_NONE; pBam->playerTypes[SIDE2] = PLAYER_LOCAL; break; default: pMono->Out("Invalid option to command line arg -SIDEx\n"); break; } } } else if(atoi(argv[loop1])) { memcpy(pBam->scenarioName, argv[loop1], 8); pBam->fDefaultScenario = TRUE; } } #ifdef ENABLE_EDITOR if(pBam->fMapEdit) // if editor mode, then turn off fog pBam->fUseFog = FALSE; pBam->fShowTileNums = TRUE; #endif // initialize game start, pBam->Activate(TRUE); pContextMgr->msgMask = E_MOUSE_DOWN | E_MOUSE_UP | E_KEY_DOWN; #ifdef COUNT_FRAMES FrameCounter fps; #endif // COUNT_FRAMES TRACK_MEM("TCommMgr"); new TCommMgr; if(pBam->fNetworkTest) // if set up network from command line { // TNetwork *pComm; // TModem *pComm; TComm::ERROR errVal; int int1; // pMono->Out("New TCommMgr\n"); // TRACK_MEM("TCommMgr"); pCommMgr = new TCommMgr; //it isn't an object -no gSelf TRACK_MEM("TNetwork"); pComm = new TNetwork; // pComm = new TModem; // ((TModem*) pComm)->SetPort(3); // ((TModem*) pComm)->SetBaud(19200); #ifdef OS_MAC int commInitArg = 0; // ignored by DOS/TIGRE // player 1 is caller, player two is listener // at least for now, using command line args to specify direction if (pBam->playerTypes[SIDE1] == PLAYER_LOCAL) { commInitArg = TCommMacintosh::kATalkCaller; } else { commInitArg = TCommMacintosh::kATalkListener; } pCommMgr->Init(pComm, commInitArg); #else pCommMgr->SetUserAbortFn ((pIntFnInt) CycleConnection); pCommMgr->Init(pComm); #endif pMono->Out("Attempting connection...\n"); int1 = (int)pCommMgr->Connect(); errVal = (TComm::ERROR)int1; if(errVal != TComm::ALL_OK) { pMono->Out("Main() - error, commMgr->Connect() failed\n"); sleep(1); pBam->fNetworkTest = FALSE; } else { pMono->Out("Main() - connection established\n"); pBam->playerTypes[(pBam->playerSide == SIDE1)? SIDE2: SIDE1] = pCommMgr->GetUserID(); pMono->Out("User ID==%d\n", pCommMgr->GetUserID()); // sleep(2); } } pMono->Out("TIGRE engine initialized\n"); ReportFreeMem(); // side1 and side2 MUST have a player setting of some kind if(pBam->playerTypes[SIDE1] == PLAYER_NONE) pBam->playerTypes[SIDE1] = PLAYER_COMPUTER; if(pBam->playerTypes[SIDE2] == PLAYER_NONE) pBam->playerTypes[SIDE2] = PLAYER_COMPUTER; // initial room if(pBam->fDefaultScenario) { SetDefaults(pBam->scenarioName); bGlobal.roomMgr.NewRoom(BR_WORLD); // skip everything, go to game } else if(bGlobal.storyLine == SHOW_OFF) { bGlobal.roomMgr.NewRoom(BR_WORLD); // skip everything, go to game } else if(pBam->fNoIntro) bGlobal.roomMgr.NewRoom(BR_MENU); // skip intro, go to story selector else bGlobal.roomMgr.NewRoom(BR_CINE); // skip nothing bGlobal.roomMgr.CheckRoomChange(); #ifdef OS_MAC #include "menubar.hpp" DS9MenuBar *pMenuBar; TRACK_MEM("menuBar"); MenuBar.Init(); #endif ticks_t currTicks = ATicks(); int snapShot = 0; // anti-piracy stuff pFile = fopen("HMICARDS.386", "rb"); if(!pFile) bGlobal.antiPiracyCrashFlag &= 0xFFFFF0FF; else { for(loop1 = 0; loop1 < 5; loop1++) { char string1[128]; unsigned long lineCheck1, lineCheck2; fread(string1, 32, 1, pFile); // camoflage string fread(string1, 128, 1, pFile); // encrypted string fread(&lineCheck1, sizeof(lineCheck1), 1, pFile); // line checksum // verify checksum for(lineCheck2 = 0, loop2 = 0; loop2 < 128; loop2++) lineCheck2 = lineCheck2 + string1[loop2]; lineCheck2 ^= 0xF61E22C9; if(lineCheck1 != lineCheck2) { // failure - set the delayed crash flag fclose(pFile); bGlobal.antiPiracyCrashFlag &= 0xFFFFF0FF; } } fclose(pFile); } //======================================================================= //MAIN GAME LOOP //======================================================================= ReportFreeMem(); enum timerTags {TIMER_CYC_PER_FRAME = 0, TIMER_UPDATE_TICKS, TIMER_CONTEXT_CYCLE, TIMER_ANIMATE, TIMER_SYNC_SEND, TIMER_SYNC_RECV, TIMER_MAX}; DebugTimer timers[TIMER_MAX]; while (!pContextMgr->fQuitting) { #ifndef NDEBUG timers[TIMER_CYC_PER_FRAME].Start(); #endif #ifdef DEBUG_BIG_NET pMono->Out("main loop().."); #endif // our own exceptional ptrs pBam = ADerefAs(BAM_Application, bGlobal.gBam); if (bGlobal.gWorld) { pWorld = ADerefAs(World, bGlobal.gWorld); } else { pWorld = NULL; } #ifdef DEBUG_BIG_NET pMono->Out("roomMgr.cycle().."); #endif bGlobal.roomMgr.Cycle(); //fps.Count(); #ifdef DEBUG_BIG_NET pMono->Out("memMgr.cycle().."); #endif pMemMgr->Cycle(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER // // MDB - Modified the mouse interrupt handler. // MouseHandler( FALSE ); #endif #ifndef NDEBUG //mem_check(); #endif #ifdef DEBUG_BIG_NET pMono->Out("roomMgr.CheckRoomChange().."); #endif bGlobal.roomMgr.CheckRoomChange(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER // // MDB - Modified the mouse interrupt handler. // MouseHandler( FALSE ); #endif //if snap is on lets handle tick updates ourself if(bGlobal.gSnap && pSnap->snapOn) { //if snap just toggled on if(!snapShot) { snapShot++; currTicks = ATicks(); } else { currTicks += 2; } ASetTicks(currTicks); } else { snapShot = 0; //reset #ifdef DEBUG_BIG_NET pMono->Out("EventMgr->Publish().."); #endif // add local actions to actionPool2 pEventMgr->PublishNext(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER // // MDB - Modified the mouse interrupt handler. // MouseHandler( FALSE ); #endif if(pWorld) { // wait for next tick to occur, because otherwise there's no point. // note: UpdateTicks() cannot be trusted to change, in case of Pause() currTicks = ATicks(); // #ifndef NDEBUG // BamDebug.Out("main() - update tick counter (curr=%d)\n", // currTicks); // #endif #ifndef NDEBUG timers[TIMER_UPDATE_TICKS].Start(); #endif UpdateTicks(); // did the tick counter fail to increment? if(ATicks() == currTicks) { // loop on clock() delta, then resume. A tick will have changed by // then or else we're in Pause() mode, so who cares. clock_t currClock = clock(); while(currClock == clock()) { #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif }; // try again - if it fails again, assume Pause() and don't worry UpdateTicks(); } // if we skipped over a tick somehow.. if(ATicks() > currTicks + 1) { // #ifndef NDEBUG // BamDebug.Out("main() WARNING: ATicks() advanced by %d! - retarding\n", // ATicks() - currTicks); // #endif // dont allow the tick counter to increment by more than 1 // tick per frame, or we may get out of sync with the // remote machine ASetTicks(currTicks + 1); } #ifndef NDEBUG timers[TIMER_UPDATE_TICKS].Stop(); #endif // #ifndef NDEBUG // BamDebug.Out("ATicks() == %d\n", ATicks()); // #endif // sync1 - send actionPool2 to remote #ifndef NDEBUG timers[TIMER_SYNC_SEND].Start(); #endif fWaitToSend = FALSE; if(pCommMgr && pCommMgr->totalPacketsWaiting) fWaitToSend = TRUE; if(!pWorld->SyncSend()) { #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif //pWorld->AITakeOver(); if(!pBam->fWorldEnderPopupExists) { TRACK_MEM("BAM_WorldEnderPopup"); pWEPop = new BAM_WorldEnderPopup; pWEPop->Setup(); pBam->fWorldEnderPopupExists = TRUE; } } #ifndef NDEBUG timers[TIMER_SYNC_SEND].Stop(); #endif // process actionPool1 pWorld->ProcessActions(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } else { #ifndef NDEBUG timers[TIMER_UPDATE_TICKS].Start(); #endif UpdateTicks(); #ifndef NDEBUG timers[TIMER_UPDATE_TICKS].Stop(); #endif } if(bGlobal.storyLine == NETGAME && !bGlobal.netDisconnect) { pCommMgr->EnQueueData(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } } #ifdef DEBUG_BIG_NET pMono->Out("contextMgr.cycle().."); #endif #ifndef NDEBUG timers[TIMER_CONTEXT_CYCLE].Start(); #endif pContextMgr->Cycle(); #ifndef NDEBUG timers[TIMER_CONTEXT_CYCLE].Stop(); #endif #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif if(bGlobal.storyLine == NETGAME && !bGlobal.netDisconnect) { pCommMgr->EnQueueData(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } #ifdef DEBUG_BIG_NET pMono->Out("GraphMgr->Animate().."); #endif #ifndef NDEBUG timers[TIMER_ANIMATE].Start(); #endif pGraphMgr->Animate(); #ifndef NDEBUG timers[TIMER_ANIMATE].Stop(); #endif #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif if(bGlobal.storyLine == NETGAME && !bGlobal.netDisconnect) { pCommMgr->EnQueueData(); #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } #ifdef DEBUG_BIG_NET pMono->Out("soundMgr.cycle().."); #endif pSoundMgr->Cycle(); // current frame now done // gather cmds from remote for next frame, then prepare to run it if(pWorld) { pWorld->currFrame++; // sync2 - add remote actions to local actions in actionPool2 #ifndef NDEBUG timers[TIMER_SYNC_RECV].Start(); #endif if(!pWorld->SyncReceive()) { #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif //pWorld->AITakeOver(); if(!pBam->fWorldEnderPopupExists) { TRACK_MEM("BAM_WorldEnderPopup"); pWEPop = new BAM_WorldEnderPopup; pWEPop->Setup(); pBam->fWorldEnderPopupExists = TRUE; } } // sync3 - swap action pools pWorld->SwapActionPools(); #ifndef NDEBUG timers[TIMER_SYNC_RECV].Stop(); #endif } if(bGlobal.gSnap && pSnap->snapOn) { pSnap->SnapScreen(); } if(netRestoreNum || netSaveNum) { //this means we're in a netgame save or restore //we don't run the eventmgr to keep both sides in sync //and we set the restore number here, after the context cycle, //to insure the otherside has had time to be notified of this if(netRestoreNum) restoreNum = netRestoreNum; //our one net save game if(netSaveNum) { saveNum = netSaveNum; netSerialNum = ARandom(99999); sprintf(saveMessage,"%d",netSerialNum); } } if (saveNum) { pMemMgr->Dump((uint16) (100 + saveNum), "Save Dump", TRUE); saverResult = saveMgr.Save((uint16) saveNum, bGlobal.versionNum, bGlobal.versionSubNum, bGlobal.buildID, saveMessage); if (saverResult) { sprintf(mess, "save failed. error #%d", saverResult); APanic(mess); } netSaveNum = 0; //reset this after save saveNum = 0; } if (restoreNum) { saverResult = saveMgr.Restore((uint16) restoreNum, bGlobal.versionNum, bGlobal.versionSubNum, bGlobal.buildID); if (saverResult) { // sprintf(mess, "restore failed. error #%d", saverResult); BamDebug.Out("Restore failed! Error %d\n", saverResult); // APanic(mess); } pMemMgr->Dump((uint16) (200 + restoreNum), "Restore Dump", TRUE); netRestoreNum = 0; //reset this after restore restoreNum = 0; bGlobal.roomMgr.Cycle(); // frantic temporary debugging measure pBam = ADerefAs(BAM_Application, bGlobal.gBam); if (bGlobal.gWorld) { pWorld = ADerefAs(World, bGlobal.gWorld); pWorld->Save(AFTER_RESTORE); } else { pWorld = NULL; } bGlobal.roomMgr.Cycle(); pMemMgr->Cycle(); pSoundMgr->Cycle(); if(pWorld) { pBam->fPauseWorld = TRUE; //force ResumeTicks() to be called in PauseWorld pWorld->Pause(FALSE, TRUE); pBam->PauseWorld(); } else bGlobal.roomMgr.curRoom->Pause(FALSE, TRUE); #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } if(pWorld) if(pBam->fPauseWorld != pWorld->fIsPaused) pBam->PauseWorld(); #ifdef DEBUG_BIG_NET pMono->Out("main loop() done\n"); #endif #ifndef NDEBUG timers[TIMER_CYC_PER_FRAME].Stop(); #endif #ifndef NDEBUG pMono->SaveWindow(); pMono->Goto(24, 1); pMono->Out("CpF%5d UTick%5d CmC%5d GmA%5d Tx%4d:%dp@%4db]%c Rx[%4d]", timers[TIMER_CYC_PER_FRAME].duration, timers[TIMER_UPDATE_TICKS].duration, timers[TIMER_CONTEXT_CYCLE].duration, timers[TIMER_ANIMATE].duration, timers[TIMER_SYNC_SEND].duration, pCommMgr->pComm->totalPacketsSent, pCommMgr->pComm->totalBytesSent, fWaitToSend? 'W': 'w', timers[TIMER_SYNC_RECV].duration); pMono->Goto(25, 1); time(&timeDif); if(timeDif != lastTime) { lastTime = timeDif; framesPerSec = AMin(framesRun, 99); framesRun = 0; } else framesRun++; timeDif -= startTime; pMono->Out("%05dkt %05dkl %02d:%02d:%02d %2dFPS", pMemMgr->AvailMem() / 1024, pMemMgr->LargestAlloc() / 1024, timeDif / 3600, (timeDif / 60) % 60, timeDif % 60, framesPerSec); if(pWorld) { pMono->Goto(25, 32); pMono->Out("r%d g%d 0x%08x", pWorld->tileResNum, ALoad(RES_TILELIB, pWorld->tileResNum), AGetResData(ALoad(RES_TILELIB, pWorld->tileResNum))); } pCommMgr->pComm->totalBytesSent = 0; pCommMgr->pComm->totalPacketsSent = 0; pMono->RestoreWindow(); #endif #ifndef OLD_MOUSE_INTERRUPT_HANDLER MouseHandler( FALSE ); #endif } //=================================== LoadExitQuote(); //=================================== // get rid of our current room bGlobal.roomMgr.DeleteCurRoom(); // shut down communications if(pCommMgr) { pCommMgr->Disconnect(); pCommMgr->DiscardData(); delete pCommMgr; //its destructor will delete pComm pCommMgr = NULL; } if(bGlobal.gSnap) ADelete(bGlobal.gSnap); ADelete(bGlobal.gBam); // all actors should be removed from graphmgr, do one more // animate to clear lists. pGraphMgr->Animate(); ADelete(pContextMgr->gSelf); // TSound exitSound; // exitSound.Play(667); // while(exitSound.IsPlaying()) // pSoundMgr->Cycle(); // storm the office! kill all managers! ADelete(pGraphMgr->gSelf); ADelete(pFontMgr->gSelf); ADelete(pSoundMgr->gSelf); ADelete(pResMgr->gSelf); ADelete(pEventMgr->gSelf); ADelete(pMouse->gSelf); delete pMono; // DESTROY_MGR_CAREFUL(GraphicsMgr, pGraphMgr); // DESTROY_MGR_CAREFUL(Mono, pMono); // DESTROY_MGR_CAREFUL(FontMgr, pFontMgr); // DESTROY_MGR_CAREFUL(SoundMgr, pSoundMgr); // DESTROY_MGR(pResMgr); // DESTROY_MGR(pContextMgr); // DESTROY_MGR_CAREFUL(EventMgr, pEventMgr); #ifdef INTERACTIVE_DEMO DPMI dpmi; char *pScreen = (char *)dpmi.RealToProtected(0xB8000000); // kludge - remove "Installer" from data for(loop1 = 0; loop1 < 9; loop1++) MSG_DEMO_ENGL[86 + loop1 * 2] = ' '; memcpy(pScreen, (char *)MSG_DEMO_ENGL, 4000); while(!kbhit()); getch(); #endif system("mode co80"); // yeah, mega-cheesy I know. It's a bug patch. -Van printf("\n%s\n",exitMessage); printf("%s\n",exitAuthor); return 0; }
long TEightTrack::ReadTrack (char* pDst, int trackNum, long size) { int curSeg; int curOff; int lenToCopy; int lenToBound; sector_t sector; char* pSrc; STrack* pTrack; long countDistributed = 0; pTrack = &aTracks[trackNum]; // don't attempt to read any more than is in the original file size = AMin (size, pTrack->bytesToRead); while (size) { // real-mode-like addressing in scrambled sectors // get src ptr, segment, offset curSeg = pTrack->bytesDistributed / SECTOR_SIZE; curOff = pTrack->bytesDistributed % SECTOR_SIZE; lenToBound = SECTOR_SIZE - curOff; // Note that MakePtr() may force a load from disk if idling // has not preloaded the needed segment. pSrc = MakePtr (curSeg, curOff, trackNum, §or); if (pSrc == NULL) { // we were unable to get any more. // we are probably trying to read from disk during an interrupt, // which is a no-no. // let's get out of here break; } else { // read to sector boundary, size, or bytesToRead (which ever smallest) lenToCopy = AMin (lenToBound, size); // "distribute" bytes to reader memcpy (pDst, pSrc, lenToCopy); // updates countDistributed += lenToCopy; pTrack->bytesDistributed += lenToCopy; curOff += lenToCopy; pDst += lenToCopy; pTrack->bytesToRead -= lenToCopy; size -= lenToCopy; ASSERT (curOff <= SECTOR_SIZE); if (curOff == SECTOR_SIZE) { // free sector that has been distributed FreeSector (sector); // wrap to next sector curSeg++; curOff = 0; } } } return countDistributed; }
/* Parse a run of simple and parenthised regular expressions concatenated together. Plain characters, dots and character classes (optionally followed by a repetition specifier) are considered simple. IDEA: \< and friends */ static void ParseConcat(ParseInfo *info) { int litLen; ABool isPrevLit; litLen = 0; isPrevLit = FALSE; while (info->str < info->strEnd) { if (!isPrevLit) litLen = 0; isPrevLit = FALSE; switch (*info->str) { case '(': ParseParen(info); break; case ')': case '|': return; case '^': /* Beginning of line */ Emit(info, A_BOL_MULTI); info->str++; break; case '$': /* End of line */ Emit(info, A_EOL_MULTI); info->str++; break; case '.': /* Any character */ if (info->minLen == 0) memset(info->startChar, 0xff, sizeof(info->startChar)); info->str++; /* IDEA: Perhaps ANY_ALL (i.e. match newlines)? */ ParseSimpleRepetition(info, A_ANY); break; case '[': { /* Character class */ ABool complement = FALSE; AReOpcode set[A_SET_SIZE]; AWideChar ch; int i; WideCharSet wset; int flags = 0; InitWideSet(&wset); info->str++; /* Complement set? */ if (info->str < info->strEnd && *info->str == '^') { info->str++; complement = TRUE; } /* End of expression? */ if (info->str == info->strEnd) AGenerateError(info, ErrUnmatchedLbracket); memset(set, 0, sizeof(set)); do { AReOpcode code; ch = ParseChar(info, &code); if (info->str == info->strEnd) break; if (code >= CC) { int i; const AReOpcode *chClass = ACharClass[(code - CC) & ~CC_COMP]; for (i = 0; i < A_SET_SIZE; i++) { if (code & CC_COMP) set[i] |= ~chClass[i]; else set[i] |= chClass[i]; } if (code == CC_W) flags |= A_WS_WORD_CHAR; else if (code == (CC_W | CC_COMP)) flags |= A_WS_NOT_WORD_CHAR; /* Underline character is part of the \w set. */ if (code == CC_W || code == (CC_W | CC_COMP)) AToggleInSet(set, '_'); if (*info->str == '-') AGenerateError(info, ErrInvalidCharacterSet); } else { /* Character range? */ if (*info->str == '-') { AWideChar hiChar = ch; /* Skip '-', check end of expression. */ if (++info->str == info->strEnd) break; if (*info->str == ']') AAddToSet(set, '-'); else { hiChar = ParseChar(info, &code); if (code >= CC) AGenerateError(info, ErrInvalidCharacterSet); } AddToWideSet(info, &wset, ch, hiChar); for (; ch <= AMin(hiChar, 255); ch++) AAddToSet(set, ch); } else { AAddWideToSet(set, ch); AddToWideSet(info, &wset, ch, ch); } } } while (info->str < info->strEnd && *info->str != ']'); if (info->str == info->strEnd) AGenerateError(info, ErrUnmatchedLbracket); /* Skip ']'. */ info->str++; if (info->flags & A_RE_NOCASE) { for (i = 0; i < 256; i++) if (AIsInSet(set, i)) { AAddToSet(set, ALower(i)); AAddToSet(set, AUpper(i)); } } AddStartSet(info, set, complement); ParseSimpleRepetition(info, A_SET); EmitCharSet(info, set, &wset, complement, flags); FreeWideSet(&wset); break; } case '*': case '+': case '?': case '{': AGenerateError(info, ErrInvalidRepeat); info->str = info->strEnd; break; default: { AReOpcode code; AWideChar ch; ch = ParseChar(info, &code); /* Special character? */ if (code != A_EMPTY) { if (code < CC) { Emit(info, code); if (code == A_BACKREF || code == A_BACKREF_I) { int num = ch & ~48; int oldMaxLen = info->maxLen; if (!(info->parenFlags & (1 << num))) AGenerateError(info, ErrInvalidBackReference); Emit(info, num); info->maxLen *= 2; ParseRepetition(info, info->minLen, oldMaxLen, 2, info->mustStr, info->mustStrBack); } } else { AReOpcode set[A_SET_SIZE]; int flags = 0; memcpy(set, ACharClass[(code - CC) & ~CC_COMP], 32); /* Underline character is part of the \w set. */ if (code == CC_W || code == (CC_W | CC_COMP)) AToggleInSet(set, '_'); AddStartSet(info, set, code & CC_COMP); ParseSimpleRepetition(info, A_SET); if (code == CC_W || code == (CC_W | CC_COMP)) flags = A_WS_WORD_CHAR; EmitCharSet(info, set, NULL, code & CC_COMP, flags); } break; } if (info->flags & A_RE_NOCASE) { code = A_LITERAL_I; ch = ALower(ch); if (info->minLen == 0) { AAddWideToSet(info->startChar, ch); AAddWideToSet(info->startChar, AUpper(ch)); } } else { code = A_LITERAL; if (info->minLen == 0) AAddWideToSet(info->startChar, ch); } if (info->str == info->strEnd || (*info->str != '*' && *info->str != '+' && *info->str != '?' && *info->str != '{')) { info->minLen++; info->maxLen++; litLen++; isPrevLit = TRUE; if (litLen == 2) { /* Convert a single character to literal string. */ AWideChar prevCh; prevCh = info->buf[info->bufInd - 1]; info->buf[info->bufInd - 2] += A_STRING; info->buf[info->bufInd - 1] = 2; Emit(info, prevCh); Emit(info, ch); if (info->mustStr == 0) { info->mustStr = info->bufInd - litLen; info->mustStrBack = info->maxLen - 2; /* FIX? */ } } else if (litLen > 2) { /* Add a character to a literal string. */ Emit(info, ch); if (info->buf[info->mustStr - 1] <= litLen) { info->mustStr = info->bufInd - litLen; info->mustStrBack = info->maxLen - litLen; /* FIX? */ } info->buf[info->bufInd - litLen - 1] = litLen; } else { Emit(info, code); Emit(info, ch); } } else { ParseSimpleRepetition(info, code); Emit(info, ch); } break; } } } }
int test_linearRand() { int Error = 0; glm::int32 const Min = 16; glm::int32 const Max = 32; { glm::u8vec2 AMin(std::numeric_limits<glm::u8>::max()); glm::u8vec2 AMax(std::numeric_limits<glm::u8>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::u8vec2 A = glm::linearRand(glm::u8vec2(Min), glm::u8vec2(Max)); AMin = glm::min(AMin, A); AMax = glm::max(AMax, A); if(!glm::all(glm::lessThanEqual(A, glm::u8vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(A, glm::u8vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(AMin, glm::u8vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(AMax, glm::u8vec2(Max))) ? 0 : 1; assert(!Error); } glm::u16vec2 BMin(std::numeric_limits<glm::u16>::max()); glm::u16vec2 BMax(std::numeric_limits<glm::u16>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::u16vec2 B = glm::linearRand(glm::u16vec2(Min), glm::u16vec2(Max)); BMin = glm::min(BMin, B); BMax = glm::max(BMax, B); if(!glm::all(glm::lessThanEqual(B, glm::u16vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(B, glm::u16vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(BMin, glm::u16vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(BMax, glm::u16vec2(Max))) ? 0 : 1; assert(!Error); } glm::u32vec2 CMin(std::numeric_limits<glm::u32>::max()); glm::u32vec2 CMax(std::numeric_limits<glm::u32>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::u32vec2 C = glm::linearRand(glm::u32vec2(Min), glm::u32vec2(Max)); CMin = glm::min(CMin, C); CMax = glm::max(CMax, C); if(!glm::all(glm::lessThanEqual(C, glm::u32vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(C, glm::u32vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(CMin, glm::u32vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(CMax, glm::u32vec2(Max))) ? 0 : 1; assert(!Error); } glm::u64vec2 DMin(std::numeric_limits<glm::u64>::max()); glm::u64vec2 DMax(std::numeric_limits<glm::u64>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::u64vec2 D = glm::linearRand(glm::u64vec2(Min), glm::u64vec2(Max)); DMin = glm::min(DMin, D); DMax = glm::max(DMax, D); if(!glm::all(glm::lessThanEqual(D, glm::u64vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(D, glm::u64vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(DMin, glm::u64vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(DMax, glm::u64vec2(Max))) ? 0 : 1; assert(!Error); } } { glm::i8vec2 AMin(std::numeric_limits<glm::i8>::max()); glm::i8vec2 AMax(std::numeric_limits<glm::i8>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::i8vec2 A = glm::linearRand(glm::i8vec2(Min), glm::i8vec2(Max)); AMin = glm::min(AMin, A); AMax = glm::max(AMax, A); if(!glm::all(glm::lessThanEqual(A, glm::i8vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(A, glm::i8vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(AMin, glm::i8vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(AMax, glm::i8vec2(Max))) ? 0 : 1; assert(!Error); } glm::i16vec2 BMin(std::numeric_limits<glm::i16>::max()); glm::i16vec2 BMax(std::numeric_limits<glm::i16>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::i16vec2 B = glm::linearRand(glm::i16vec2(Min), glm::i16vec2(Max)); BMin = glm::min(BMin, B); BMax = glm::max(BMax, B); if(!glm::all(glm::lessThanEqual(B, glm::i16vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(B, glm::i16vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(BMin, glm::i16vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(BMax, glm::i16vec2(Max))) ? 0 : 1; assert(!Error); } glm::i32vec2 CMin(std::numeric_limits<glm::i32>::max()); glm::i32vec2 CMax(std::numeric_limits<glm::i32>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::i32vec2 C = glm::linearRand(glm::i32vec2(Min), glm::i32vec2(Max)); CMin = glm::min(CMin, C); CMax = glm::max(CMax, C); if(!glm::all(glm::lessThanEqual(C, glm::i32vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(C, glm::i32vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(CMin, glm::i32vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(CMax, glm::i32vec2(Max))) ? 0 : 1; assert(!Error); } glm::i64vec2 DMin(std::numeric_limits<glm::i64>::max()); glm::i64vec2 DMax(std::numeric_limits<glm::i64>::min()); { for(std::size_t i = 0; i < 100000; ++i) { glm::i64vec2 D = glm::linearRand(glm::i64vec2(Min), glm::i64vec2(Max)); DMin = glm::min(DMin, D); DMax = glm::max(DMax, D); if(!glm::all(glm::lessThanEqual(D, glm::i64vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(D, glm::i64vec2(Min)))) ++Error; assert(!Error); } Error += glm::all(glm::equal(DMin, glm::i64vec2(Min))) ? 0 : 1; Error += glm::all(glm::equal(DMax, glm::i64vec2(Max))) ? 0 : 1; assert(!Error); } } for(std::size_t i = 0; i < 100000; ++i) { glm::f32vec2 const A(glm::linearRand(glm::f32vec2(static_cast<float>(Min)), glm::f32vec2(static_cast<float>(Max)))); if(!glm::all(glm::lessThanEqual(A, glm::f32vec2(static_cast<float>(Max))))) ++Error; if(!glm::all(glm::greaterThanEqual(A, glm::f32vec2(static_cast<float>(Min))))) ++Error; glm::f64vec2 const B(glm::linearRand(glm::f64vec2(Min), glm::f64vec2(Max))); if(!glm::all(glm::lessThanEqual(B, glm::f64vec2(Max)))) ++Error; if(!glm::all(glm::greaterThanEqual(B, glm::f64vec2(Min)))) ++Error; assert(!Error); } { float ResultFloat = 0.0f; double ResultDouble = 0.0f; for(std::size_t i = 0; i < 100000; ++i) { ResultFloat += glm::linearRand(-1.0f, 1.0f); ResultDouble += glm::linearRand(-1.0, 1.0); } Error += glm::epsilonEqual(ResultFloat, 0.0f, 0.0001f); Error += glm::epsilonEqual(ResultDouble, 0.0, 0.0001); assert(!Error); } return Error; }
ABool ADisplayStackTraceback(AThread *t, ABool (*display)(const char *msg, void *data), void *data) { char msg[MAX_TRACEBACK_MESSAGE_LENGTH]; char buf[MAX_TRACEBACK_MESSAGE_LENGTH]; char buf2[MAX_TRACEBACK_MESSAGE_LENGTH]; AValue msgVal; int i; *t->tempStack = t->exception; if (!AAllocTempStack(t, 2)) return FALSE; TMP[0] = AZero; TMP[1] = *t->tempStack; t->exception = TMP[1]; TMP[0] = AFilterTracebackArray(t); if (AIsError(TMP[0])) goto Fail; if (!display("Traceback (most recent call last):", data)) goto Fail; for (i = AArrayLen(TMP[0]) - 1; i >= 0; i--) { AString *s; int len; /* Traceback array contents are known to narrow string objects. */ s = AValueToStr(AArrayItem(TMP[0], i)); len = AMin(AGetStrLen(s), MAX_TRACEBACK_MESSAGE_LENGTH - 1); ACopyMem(buf, s->elem, len); buf[len] = '\0'; AFormatMessage(msg, MAX_TRACEBACK_MESSAGE_LENGTH, " %s", buf); if (!display(msg, data)) goto Fail; } AFormatMessage(msg, MAX_TRACEBACK_MESSAGE_LENGTH, "%q", AGetInstanceType(AValueToInstance(TMP[1]))->sym); /* Add the exception message to the traceback if it is available. */ msgVal = AValueToInstance(TMP[1])->member[AError_MESSAGE]; if (!AIsNil(msgVal)) { msgVal = ANormalizeNarrowString(t, msgVal); /* If there was an exception, either the message type is invalid or we ran out of memory. In both cases, it is ok to simply skip displaying the message (although we could do better). */ if (!AIsError(msgVal)) { AString *str = AValueToStr(msgVal); int len = AMin(AGetStrLen(str), MAX_TRACEBACK_MESSAGE_LENGTH - 1); ACopyMem(buf2, str->elem, len); buf2[len] = '\0'; strcpy(buf, msg); AFormatMessage(msg, MAX_TRACEBACK_MESSAGE_LENGTH, "%s: %s", buf, buf2); } } if (!display(msg, data)) goto Fail; t->tempStackPtr -= 2; return TRUE; Fail: t->tempStackPtr -= 2; return FALSE; }