00001
00002 #include "revolt.h"
00003 #include "main.h"
00004 #include "dx.h"
00005 #include "geom.h"
00006 #include "model.h"
00007 #include "texture.h"
00008 #include "particle.h"
00009 #include "aerial.h"
00010 #include "play.h"
00011 #include "NewColl.h"
00012 #include "Body.h"
00013 #include "car.h"
00014 #include "input.h"
00015 #include "sfx.h"
00016 #include "text.h"
00017 #include "shadow.h"
00018 #include "camera.h"
00019 #include "light.h"
00020 #include "world.h"
00021 #include "draw.h"
00022 #include "DrawObj.h"
00023 #include "visibox.h"
00024 #include "editobj.h"
00025 #include "level.h"
00026 #include "ReadInit.h"
00027 #include "gameloop.h"
00028 #include "gaussian.h"
00029 #include "timing.h"
00030 #include "registry.h"
00031 #include "ctrlread.h"
00032 #include "object.h"
00033 #include "control.h"
00034 #include "player.h"
00035 #include "Ghost.h"
00036
00037 #include "TitleScreen.h"
00038
00039
00040
00041 #if SHOW_PHYSICS_INFO
00042 long DEBUG_CollGrid = 0;
00043 int DEBUG_NCols = 0;
00044 int DEBUG_LastNCols = 0;
00045 int DEBUG_N2Cols = 0;
00046 VEC DEBUG_dR = {0, 0, 0};
00047 VEC DEBUG_Impulse = {0, 0, 0};
00048 VEC DEBUG_AngImpulse = {0, 0, 0};
00049 VEC DEBUG_SNorm[256];
00050 FACING_POLY DEBUG_Faces[256];
00051 #endif
00052
00053
00054
00055 char Everything = TRUE;
00056 char NoGamma = FALSE;
00057 char AppRestore = FALSE;
00058 char QuitGame = FALSE;
00059 char FullScreen = TRUE;
00060 unsigned long FrameCount, FrameCountLast, FrameTime, FrameTimeLast, FrameRate;
00061 long EditMode = 0;
00062 char DetailMenuTogg = 0;
00063 REAL TimeFactor;
00064 REAL TimeStep;
00065 REAL EditScale = 1.0f;
00066 HWND hwnd;
00067 HBITMAP TitleHbm;
00068 GAME_SETTINGS GameSettings;
00069 RENDER_SETTINGS RenderSettings;
00070 char *CarInfoFile = "CarInfo.txt";
00071
00072 static WNDCLASS wcl;
00073 static char WinName[] = "Revolt";
00074 static char AppActive = TRUE;
00075 static char CheatStringBuffer[MAX_CHEAT_STRING_BUFFER + 1];
00076 static long ActivePriority = HIGH_PRIORITY_CLASS;
00077
00078
00079
00080 char *CheatStrings[] = {
00081 "yak",
00082
00083 NULL
00084 };
00085
00086
00087
00088 void (*Event)(void);
00089
00091
00093
00094 int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
00095 {
00096 char i;
00097 MSG msg;
00098 HRESULT r;
00099 LARGE_INTEGER time;
00100
00101
00102
00103 for (i = 1 ; i < __argc ; i++)
00104 {
00105
00106
00107
00108 if (!strcmp(__argv[i], "-nosound"))
00109 {
00110 SoundOff = TRUE;
00111 continue;
00112 }
00113
00114
00115
00116 if (!strcmp(__argv[i], "-nocolorkey"))
00117 {
00118 NoColorKey = TRUE;
00119 continue;
00120 }
00121
00122
00123
00124 if (!strcmp(__argv[i], "-carinfo"))
00125 {
00126 CarInfoFile = __argv[++i];
00127 continue;
00128 }
00129
00130
00131
00132 if (!strcmp(__argv[i], "-rightaboutnow"))
00133 {
00134 Everything = TRUE;
00135 continue;
00136 }
00137
00138
00139
00140 if (!strcmp(__argv[i], "-window"))
00141 {
00142 FullScreen = FALSE;
00143 continue;
00144 }
00145
00146
00147
00148 if (!strcmp(__argv[i], "-normalpriority"))
00149 {
00150 ActivePriority = NORMAL_PRIORITY_CLASS;
00151 continue;
00152 }
00153
00154
00155
00156 if (!strcmp(__argv[i], "-paulsgotnewbansheedrivers"))
00157 {
00158 NoGamma = TRUE;
00159 continue;
00160 }
00161
00162
00163
00164 if (!strcmp(__argv[i], "-matttneedsvisicockingperpolyturnedoff"))
00165 {
00166 VisiPerPoly = FALSE;
00167 continue;
00168 }
00169
00170
00171
00172 if (!strcmp(__argv[i], "-editscale"))
00173 {
00174 EditScale = (float)atof(__argv[++i]);
00175 continue;
00176 }
00177 }
00178
00179
00180
00181 if (FindWindow(WinName, WinName) && FullScreen)
00182 {
00183 Box(NULL, "Revolt is already running!", MB_OK);
00184 return FALSE;
00185 }
00186
00187
00188
00189 #if USE_DEBUG_ROUTINES
00190 DBG_LogFile = "C:\\Windows\\Temp\\ReVolt.log";
00191 InitLogFile();
00192 #endif
00193
00194
00195
00196 r = CoInitialize(NULL);
00197 if (r != S_OK)
00198 {
00199 Box(NULL, "Can't initialize COM library!", MB_OK);
00200 return FALSE;
00201 }
00202
00203
00204
00205 LobbyRegister();
00206
00207
00208
00209 GetRegistrySettings();
00210
00211
00212
00213 if (!InitWin(hThisInst, nWinMode))
00214 return FALSE;
00215
00216
00217
00218 FindLevels();
00219 GameSettings.Level = GetLevelNum(RegistrySettings.LevelDir);
00220 if (GameSettings.Level == -1)
00221 GameSettings.Level = 0;
00222
00223
00224
00225 if (!ReadAllCarInfo(CarInfoFile))
00226 return FALSE;
00227
00228 SetAllCarCoMs();
00229
00230
00231
00232 if (!CreateTPages(TPAGE_NUM))
00233 return FALSE;
00234
00235
00236
00237 QueryPerformanceFrequency(&time);
00238 TimerFreq = time.LowPart;
00239
00240
00241
00242 srand(CurrentTimer());
00243
00244
00245
00246 GetDrawDevices();
00247
00248
00249
00250 InitInput(hThisInst);
00251
00252 if (!InitDD())
00253 {
00254 QuitGame = TRUE;
00255 }
00256
00257
00258
00259 InitSound();
00260
00261
00262
00263 #if CHECK_IP
00264 if (!CheckLegalIP())
00265 {
00266 Box(NULL, "Illegal copy of Revolt!", MB_OK);
00267 QuitGame = TRUE;
00268 }
00269 #endif
00270
00271
00272
00273 Event = Go;
00274
00275
00276
00277 while (!QuitGame)
00278 {
00279
00280
00281
00282 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
00283 {
00284 if (msg.message == WM_QUIT)
00285 {
00286 QuitGame = TRUE;
00287 }
00288 else
00289 {
00290 TranslateMessage(&msg);
00291 DispatchMessage(&msg);
00292 }
00293 }
00294
00295
00296
00297 if (AppActive)
00298 Event();
00299 }
00300
00301
00302
00303 DD->RestoreDisplayMode();
00304 FreeTextures();
00305 KillInput();
00306 KillPlay();
00307 ReleaseD3D();
00308 ReleaseDX();
00309
00310
00311
00312 ReleaseSound();
00313
00314
00315
00316 DestroyTPages();
00317
00318
00319
00320 DestroyCarInfo();
00321
00322
00323
00324 FreeLevels();
00325
00326
00327
00328 SetRegistrySettings();
00329
00330
00331
00332 CoUninitialize();
00333
00334
00335
00336 #if USE_DEBUG_ROUTINES
00337 CheckMemoryAllocation();
00338 #endif
00339
00340
00341
00342 return msg.wParam;
00343 }
00344
00346
00347
00349
00350 bool InitWin(HINSTANCE hThisInst, int nWinMode)
00351 {
00352 long bx, by, cy;
00353
00354
00355
00356 wcl.style = CS_HREDRAW | CS_VREDRAW;
00357 wcl.lpfnWndProc = WindowFunc;
00358 wcl.hInstance = hThisInst;
00359 wcl.lpszClassName = WinName;
00360
00361 wcl.hIcon = NULL;
00362 wcl.hCursor = LoadCursor(NULL, IDC_CROSS);
00363 wcl.lpszMenuName = NULL;
00364
00365 wcl.cbClsExtra = 0;
00366 wcl.cbWndExtra = 0;
00367 wcl.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
00368
00369 if (!RegisterClass(&wcl)) return FALSE;
00370
00371
00372
00373 if (FullScreen)
00374 {
00375 hwnd = CreateWindow(WinName, WinName, WS_POPUP,
00376 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
00377 NULL, NULL, hThisInst, NULL);
00378 }
00379 else
00380 {
00381 bx = GetSystemMetrics(SM_CXSIZEFRAME);
00382 by = GetSystemMetrics(SM_CYSIZEFRAME);
00383 cy = GetSystemMetrics(SM_CYCAPTION);
00384
00385 hwnd = CreateWindow(WinName, WinName, WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
00386 (GetSystemMetrics(SM_CXSCREEN) - RegistrySettings.ScreenWidth) / 2 - bx, (GetSystemMetrics(SM_CYSCREEN) - RegistrySettings.ScreenHeight) / 2 - by - cy / 2,
00387 RegistrySettings.ScreenWidth + bx + bx, RegistrySettings.ScreenHeight + by + by + cy,
00388 NULL, NULL, hThisInst, NULL);
00389 }
00390
00391 if (!hwnd) return FALSE;
00392
00393 ShowWindow(hwnd, nWinMode);
00394 UpdateWindow(hwnd);
00395 SetCursor(NULL);
00396
00397
00398
00399 return TRUE;
00400 }
00401
00403
00405
00406 long Box(char *title, char *mess, long flag)
00407 {
00408 if (DD)
00409 DD->FlipToGDISurface();
00410 return MessageBox(hwnd, mess, title, flag);
00411 }
00412
00414
00416
00417 void Vblank(char count)
00418 {
00419 for ( ; count ; count--)
00420 {
00421 while (DD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL) != DD_OK);
00422 }
00423 }
00424
00426
00428
00429 LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00430 {
00431 HANDLE handle;
00432
00433
00434
00435 switch (message)
00436 {
00437
00438
00439
00440 case WM_ACTIVATEAPP:
00441 AppActive = wParam;
00442 AppRestore = wParam;
00443
00444 handle = GetCurrentProcess();
00445
00446 if (AppActive)
00447 {
00448 SetPriorityClass(handle, ActivePriority);
00449 ResumeAllSfx();
00450 }
00451 else
00452 {
00453 SetPriorityClass(handle, IDLE_PRIORITY_CLASS);
00454 PauseAllSfx();
00455 }
00456
00457 return TRUE;
00458
00459
00460
00461 case WM_SETCURSOR:
00462 if (FullScreen)
00463 {
00464 SetCursor(NULL);
00465 return TRUE;
00466 }
00467 else
00468 {
00469 SetCursor(wcl.hCursor);
00470 break;
00471 }
00472
00473
00474
00475 case WM_DESTROY:
00476 PostQuitMessage(0);
00477
00478 return TRUE;
00479 }
00480
00481
00482
00483 return DefWindowProc(hwnd, message, wParam, lParam);
00484 }
00485
00487
00489
00490 void Go(void)
00491 {
00492
00493
00494
00495 Event = GoFront;
00496 }
00497
00499
00501
00502 void GoFront(void)
00503 {
00504
00505
00506
00507 #if DEBUG_SOLVER
00508 TestConjGrad();
00509 #endif
00510
00511
00512
00513 if (!InitD3D(DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Width, DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Height, DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Bpp, 0))
00514 {
00515 QuitGame = TRUE;
00516 return;
00517 }
00518
00519 GetTextureFormat(RegistrySettings.TextureBpp);
00520 InitTextures();
00521
00522
00523
00524 SetupDxState();
00525
00526
00527
00528 RenderSettings.GeomPers = BaseGeomPers;
00529 SetNearFar(48.0f, 4096.0f);
00530 SetViewport(0, 0, (float)ScreenXsize, (float)ScreenYsize, RenderSettings.GeomPers);
00531
00532
00533
00534 LoadMipTexture("gfx\\font1.bmp", TPAGE_FONT, 256, 256, 0, 1);
00535
00536 LoadBitmap("gfx\\title.bmp", &TitleHbm);
00537
00538 MenuCount = 0;
00539 Event = MainMenu;
00540 }
00541
00543
00545
00546 void SetupGame(void)
00547 {
00548
00549
00550
00551 FreeBitmap(TitleHbm);
00552 FreeTextures();
00553
00554
00555
00556 if (RegistrySettings.DrawDevice != (DWORD)CurrentDrawDevice)
00557 {
00558 DD->FlipToGDISurface();
00559 FreeTextures();
00560 ReleaseD3D();
00561 InitDD();
00562 }
00563
00564
00565
00566 if (!InitD3D(DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Width, DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Height, DrawDevices[RegistrySettings.DrawDevice].DisplayMode[DisplayModeCount].Bpp, 0))
00567 {
00568 QuitGame = TRUE;
00569 return;
00570 }
00571
00572 GetTextureFormat(RegistrySettings.TextureBpp);
00573 InitTextures();
00574
00575
00576
00577 SetupDxState();
00578
00579
00580
00581 if (GameSettings.GameType == GAMETYPE_TRIAL)
00582 PickTextureSets(2);
00583 else
00584 PickTextureSets(MAX_NUM_PLAYERS);
00585
00586
00587
00588 if (!GRD_AllocGrids())
00589 {
00590 QuitGame = TRUE;
00591 }
00592
00593
00594
00595 LEV_InitLevel();
00596
00597
00598
00599 if (GameSettings.GameType == GAMETYPE_TRIAL) {
00600 InitPlayersTrial();
00601
00602 } else if (GameSettings.GameType == GAMETYPE_SINGLE) {
00603 InitPlayersSingle();
00604 } else {
00605 InitPlayersNetwork();
00606 }
00607
00608
00609
00610 SetCameraFollow(CAM_MainCamera, PLR_LocalPlayer->ownobj, CAM_FOLLOW_BEHIND);
00611
00612
00613
00614 TotalRaceTime = 0;
00615 TimeQueue = 0;
00616 UpdateTimeFactor();
00617 Event = GLP_GameLoop;
00618 }
00619
00620
00622
00623
00624
00625
00627
00628 void InitPlayeresFullArray(void)
00629 {
00630 int playerCarID;
00631 REAL sep;
00632 MAT mat;
00633 VEC pos, sepVec;
00634 PLAYER *anotherPlayer;
00635
00636 SetVec(&sepVec, ONE, ZERO, ZERO);
00637 sep = Real(100);
00638
00639 for (playerCarID = 0; playerCarID < 6; playerCarID++) {
00640
00641 GetCarGrid(playerCarID, &pos, &mat);
00642
00643 anotherPlayer = PLR_CreatePlayer(PLAYER_LOCAL, CTRL_TYPE_KBD, 1, &pos, &mat);
00644 if (anotherPlayer == NULL) {
00645 return;
00646 }
00647 if (playerCarID == 0) {
00648 PLR_LocalPlayer = anotherPlayer;
00649 }
00650 }
00651
00652
00653 GHO_GhostExists = LoadGhostData(&LevelInf[GameSettings.Level]);
00654
00655 if (GHO_GhostExists)
00656 playerCarID = GHO_BestGhostInfo->CarID;
00657 else
00658 playerCarID = 0;
00659
00660 GetCarGrid(0, &pos, &mat);
00661 GHO_GhostPlayer = PLR_CreatePlayer(PLAYER_GHOST, CTRL_TYPE_NONE, playerCarID, &pos, &mat);
00662 if (GHO_GhostPlayer == NULL)
00663 {
00664 Box(NULL, "Can't create ghost player!", MB_OK | MB_ICONERROR);
00665 QuitGame = TRUE;
00666 return;
00667 }
00668
00669 if (!GHO_GhostExists)
00670 ClearBestGhostData();
00671
00672 InitGhostData(PLR_LocalPlayer);
00673 InitBestGhostData();
00674 InitGhostLight();
00675
00676
00677 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START);
00678 CountdownTime = TRUE;
00679 }
00680
00682
00684
00685 void InitPlayersTrial(void)
00686 {
00687 int playerCarID;
00688 MAT mat;
00689 VEC pos;
00690
00691
00692
00693 if (GameSettings.CarID < (DWORD)NCarTypes)
00694 playerCarID = GameSettings.CarID;
00695 else
00696 playerCarID = 0;
00697
00698 if (CurrentJoystick != -1) PLR_LocalCtrlType = CTRL_TYPE_JOY;
00699 else PLR_LocalCtrlType = CTRL_TYPE_KBD;
00700
00701 GetCarGrid(0, &pos, &mat);
00702
00703 PLR_LocalPlayer = PLR_CreatePlayer(PLAYER_LOCAL, PLR_LocalCtrlType, playerCarID, &pos, &mat);
00704 if (PLR_LocalPlayer == NULL)
00705 {
00706 Box(NULL, "Can't create local player!", MB_OK | MB_ICONERROR);
00707 QuitGame = TRUE;
00708 return;
00709 }
00710
00711
00712
00713 GHO_GhostExists = LoadGhostData(&LevelInf[GameSettings.Level]);
00714
00715 if (GHO_GhostExists)
00716 playerCarID = GHO_BestGhostInfo->CarID;
00717 else
00718 playerCarID = 0;
00719
00720 GetCarGrid(0, &pos, &mat);
00721 GHO_GhostPlayer = PLR_CreatePlayer(PLAYER_GHOST, CTRL_TYPE_NONE, playerCarID, &pos, &mat);
00722 if (GHO_GhostPlayer == NULL)
00723 {
00724 Box(NULL, "Can't create ghost player!", MB_OK | MB_ICONERROR);
00725 QuitGame = TRUE;
00726 return;
00727 }
00728
00729 if (!GHO_GhostExists)
00730 ClearBestGhostData();
00731
00732 InitGhostData(PLR_LocalPlayer);
00733 InitBestGhostData();
00734 InitGhostLight();
00735
00736
00737
00738 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START);
00739 CountdownTime = TRUE;
00740 }
00741
00743
00745
00746 void InitPlayersSingle(void)
00747 {
00748 int playerCarID;
00749 MAT mat;
00750 VEC pos;
00751
00752
00753
00754 if (GameSettings.CarID < (DWORD)NCarTypes)
00755 playerCarID = GameSettings.CarID;
00756 else
00757 playerCarID = 0;
00758
00759 if (CurrentJoystick != -1) PLR_LocalCtrlType = CTRL_TYPE_JOY;
00760 else PLR_LocalCtrlType = CTRL_TYPE_KBD;
00761
00762 GetCarGrid(0, &pos, &mat);
00763 PLR_LocalPlayer = PLR_CreatePlayer(PLAYER_LOCAL, CTRL_TYPE_KBD, playerCarID, &pos, &mat);
00764 if (PLR_LocalPlayer == NULL)
00765 {
00766 Box(NULL, "Can't create local player!", MB_OK | MB_ICONERROR);
00767 QuitGame = TRUE;
00768 return;
00769 }
00770
00771 GetCarGrid(1, &pos, &mat);
00772 if(!PLR_CreatePlayer(PLAYER_CPU, CTRL_TYPE_CPU, 0, &pos, &mat))
00773 {
00774 Box(NULL, "Can't create computer player!", MB_OK | MB_ICONERROR);
00775 QuitGame = TRUE;
00776 return;
00777 }
00778
00779
00780
00781
00782 GHO_GhostExists = FALSE;
00783 GHO_GhostPlayer = NULL;
00784
00785
00786
00787 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START);
00788 CountdownTime = TRUE;
00789 }
00790
00792
00794
00795 void InitPlayersNetwork(void)
00796 {
00797 int i;
00798 PLAYER *player;
00799 MAT mat;
00800 VEC pos;
00801 char buf[256];
00802
00803
00804
00805 if (CurrentJoystick != -1) PLR_LocalCtrlType = CTRL_TYPE_JOY;
00806 else PLR_LocalCtrlType = CTRL_TYPE_KBD;
00807
00808
00809
00810 for (i = 0 ; i < StartData.PlayerNum ; i++)
00811 {
00812 GetCarGrid(StartData.PlayerData[i].GridNum, &pos, &mat);
00813
00814 if (StartData.PlayerData[i].PlayerID == LocalPlayerID)
00815 PLR_LocalPlayer = player = PLR_CreatePlayer(PLAYER_LOCAL, PLR_LocalCtrlType, StartData.PlayerData[i].CarID, &pos, &mat);
00816 else
00817 player = PLR_CreatePlayer(PLAYER_REMOTE, CTRL_TYPE_NONE, StartData.PlayerData[i].CarID, &pos, &mat);
00818
00819 if (!player)
00820 {
00821 wsprintf(buf, "Can't create player %s", StartData.PlayerData[i].Name);
00822 Box(NULL, buf, MB_OK);
00823 QuitGame = TRUE;
00824 return;
00825 }
00826
00827 player->PlayerID = StartData.PlayerData[i].PlayerID;
00828 strncpy(player->PlayerName, StartData.PlayerData[i].Name, MAX_PLAYER_NAME);
00829 }
00830
00831
00832
00833 GHO_GhostExists = FALSE;
00834 GHO_GhostPlayer = NULL;
00835
00836
00837
00838
00839 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START);
00840 CountdownTime = TRUE;
00841 }
00842
00844
00846
00847 void CheckCheatStrings(void)
00848 {
00849 long flag;
00850 unsigned char ch;
00851
00852
00853
00854 ch = GetKeyPress();
00855 if (!ch) return;
00856
00857 memcpy(CheatStringBuffer, CheatStringBuffer + 1, MAX_CHEAT_STRING_BUFFER - 1);
00858 CheatStringBuffer[MAX_CHEAT_STRING_BUFFER - 1] = ch;
00859 CheatStringBuffer[MAX_CHEAT_STRING_BUFFER] = 0;
00860
00861
00862
00863 flag = 0;
00864
00865 while (1)
00866 {
00867 if (!CheatStrings[flag])
00868 return;
00869
00870 if (!strcmp(&CheatStringBuffer[16 - strlen(CheatStrings[flag])], CheatStrings[flag]))
00871 break;
00872
00873 flag++;
00874 }
00875
00876
00877
00878 ZeroMemory(CheatStringBuffer, MAX_CHEAT_STRING_BUFFER);
00879 PlaySfx(SFX_HONK, SFX_MAX_VOL, SFX_CENTRE_PAN, 22050);
00880
00881 switch (flag)
00882 {
00883 case 0:
00884 Everything = !Everything;
00885 break;
00886 }
00887 }