////===========================================================================// //// File: rp4lbe4.cc // //// Project: MUNGA Brick: Red Planet LBE Application // //// Contents: // ////---------------------------------------------------------------------------// //// Date Who Modification // //// -------- --- ---------------------------------------------------------- // //// // ////---------------------------------------------------------------------------// //// Copyright (C) 1994, Virtual World Entertainment, Inc. // //// All Rights reserved worldwide // //// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // ////===========================================================================// // #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0500 #define WINVER 0x0500 #include #include "rpl4.h" #pragma hdrstop #include "rpl4pb.h" #include "rpl4fe.h" #include "rpl4console.h" #include "..\munga_l4\l4steamtransport.h" #include "..\munga_l4\l4splr.h" #include "rpl4ver.h" #include "..\munga\resver.h" #include "..\munga\resource.h" // added for game status drawing support #include "..\munga\player.h" #include "..\munga\mission.h" #include "..\munga_l4\l4ctrl.h" // end add #include #include #include #include #define SPOOL_SIZE 0x600000 //#define SCREEN_WIDTH 1024 //#define SCREEN_HEIGHT 768 Byte version[3] = {MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}; char* names[] = {"InitializingState", "WaitingForEgg", "LoadingMission", "WaitingForLaunch", "LaunchingMission", "RunningMission", "EndingMission", "StoppingMission", "SuspendingMission", "ResumingMission", "AbortingMission", "CreatingMission", "ApplicationStateCount"}; //########################################################################## //################## RP4L4Application Globals ######################## //########################################################################## extern const char* const ProgName; const char* const ProgName = "rpl4"; Application *rpl4App; HWND hWnd; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: DestroyWindow(hWnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { char filename[50]; strcpy_s(filename, 50, "rpl4.log"); std::ofstream logfile; logfile.open(filename); std::cout.rdbuf(logfile.rdbuf()); // load up our environment variables //controls if(getenv("L4CONTROLS") == NULL) putenv("L4CONTROLS=KEYBOARD"); if(getenv("DPLARG") == NULL) putenv("DPLARG=1"); if(getenv("L4DPLCFG") == NULL) putenv("L4DPLCFG=RPDPL.INI"); if(getenv("MULTISAMPLE") == NULL) putenv("MULTISAMPLE=0"); if(getenv("TARGETFPS") == NULL) putenv("TARGETFPS=60"); if(getenv("MAXPARTICLES") == NULL) putenv("MAXPARTICLES=8192"); FILE *file; char line[1024]; if (fopen_s(&file, "environ.ini", "r") == 0) { while (!feof(file)) { if (fgets(line, sizeof(line), file)) { for (int i = strlen(line); i >= 0; i--) if (line[i] == '\n' || line[i] == '\r') line[i] = 0; putenv(line); } } fclose(file); } DEBUG_STREAM << "Red Planet v4.10" << std::endl << std::flush; DEBUG_STREAM << "L4CONTROLS=" << getenv("L4CONTROLS") << std::endl << std::flush; #ifdef RP412_STEAM // // RP412STEAM=1 (environ.ini or a Steam launch) swaps the wire to // ISteamNetworkingSockets. Failure logs the reason and the game // carries on over TCP - dev boxes without Steam are unaffected. // { const char *steam_switch = getenv("RP412STEAM"); if (steam_switch != NULL && atoi(steam_switch) != 0) { SteamNetTransport_Install(); } } #endif // GetProcessAffinityMask(GetCurrentProcess(), DWORD_PTR res = SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1); if (res == 0) { DWORD err = GetLastError(); DEBUG_STREAM << "Could not set thread affinity. Err Code = " << err << std::endl << std::flush; } // //---------------------------------------------------------------------- // Parse command line for an egg notation file name //---------------------------------------------------------------------- // int argc; LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); Logical run_application = RPL4Application::ParseCommandLine(argc, argv); if (!run_application) { return 1; } else { Start_Registering(); } // //------------------------------------------------------------------------- // Create our window. This is only temporary because this will move after // the graphics are moved over. //------------------------------------------------------------------------- // WNDCLASS wc; if (!hPrevInstance) { wc.style = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = L"MainWndClass"; if (!RegisterClass(&wc)) return FALSE; } DWORD wsStyle = WS_OVERLAPPED | WS_SYSMENU; if (L4Application::GetFullscreen()) wsStyle = WS_POPUP; hWnd = CreateWindowEx(0, L"MainWndClass", L"RPL4", WS_OVERLAPPEDWINDOW, 0, 0, L4Application::GetScreenWidth(), L4Application::GetScreenHeight(), (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nShowCmd); #if !_DEBUG // Arcade pods have no mouse - but desktop/windowed play needs the // cursor for the on-screen cockpit buttons, so hide it only when // running fullscreen. if (L4Application::GetFullscreen()) { ShowCursor(FALSE); } #endif // //------------------------------------------------------------------------- // Front-end mode: started without an egg, a network, or mission review. // The race loop below keeps everything in ONE process - setup screen, // mission, teardown, and back to the setup screen - with the local // console marshaling each race. (-egg / -net / -mr run a single pass, // exactly as before.) //------------------------------------------------------------------------- // Logical front_end_mode = L4Application::GetMissionReviewMode() == 0 && L4Application::GetNetworkCommonFlatAddress() == 0 && !L4Application::GetEggNotationFileName(); // no egg on the command line for (;;) { if (front_end_mode) { if (!IsWindow(hWnd)) { break; // the cockpit window is gone (closed mid-race) } // drain any WM_QUIT left over from the previous mission's // teardown so it cannot instantly close the setup screen MSG leftover; while (PeekMessage(&leftover, NULL, WM_QUIT, WM_QUIT, PM_REMOVE)) { } // last race's final scores first (no-op on first boot) if (!RPL4FrontEnd_ShowResults(hInstance, hWnd)) { break; } static char frontend_egg[MAX_PATH]; if (!RPL4FrontEnd_Run(hInstance, hWnd, frontend_egg, sizeof(frontend_egg))) { break; // player closed the menu without launching } L4Application::SetEggNotationFileName(frontend_egg); Exit_Code = 0; // Front-end games are marshaled by the in-process console: it // ends the race when the selected time expires. (Hand-fed -egg // runs stay unmarshaled - the developer shortcut.) // // RP412HOSTPODS turns the launch into a hosted network race: // this pod switches to network mode (it meshes like any pod) // and the console also marshals the listed member pods over // the wire. (The Steam lobby will feed this same path.) const char *host_pods = getenv("RP412HOSTPODS"); if (host_pods != NULL && host_pods[0] != '\0') { int host_port = 1501; const char *port_override = getenv("RP412HOSTPORT"); if (port_override != NULL && atoi(port_override) > 0) { host_port = atoi(port_override); } L4Application::SetNetworkCommonFlatAddress(host_port); if (!RPL4LocalConsole_InstallNetworkRace( RPL4FrontEnd_LastMissionSeconds(), frontend_egg, host_pods, RPL4FrontEnd_LastPilotNames())) { DEBUG_STREAM << "Network race setup failed - back to the menu\n" << std::flush; L4Application::SetNetworkCommonFlatAddress(0); continue; } } else { L4Application::SetNetworkCommonFlatAddress(0); RPL4LocalConsole_Install(RPL4FrontEnd_LastMissionSeconds()); } } // //------------------------------------------------------------------------- // Open the resource file. The brace will help correct the scoping problem // of destruction the resource file //------------------------------------------------------------------------- // { StreamableResourceFile resources("rpl4.res", version); Check(&resources); // //---------------------------------------------- // Create and initialize the application manager //---------------------------------------------- // ApplicationManager* app_manager; Application *new_app; int review_mode = RPL4Application::GetMissionReviewMode(); if (review_mode > 0) { MissionReviewApplicationManager *spool_mgr = new MissionReviewApplicationManager(hInstance, hWnd, atoi(getenv("TARGETFPS")), (review_mode == 2) ? 1 : 2, SPOOL_SIZE); app_manager = spool_mgr; Register_Object(app_manager); // //------------------------------------------------------------------- // Create and initialize the playback application if there is a spool // file //------------------------------------------------------------------- // #if 1 CString spoolFileName = L4Application::GetSpoolFileName(); if (!spoolFileName) spoolFileName = "last.spl"; SpoolFile *spool = spool_mgr->GetStoredSpoolFile(spoolFileName); if (spool) { new_app = new RPL4PlaybackApplication(hInstance, hWnd, &resources, spool); } else { new_app = new RPL4IdleApplication(hInstance, hWnd, &resources); } Register_Object(new_app); app_manager->StartApplication(new_app); #else new_app = new RPL4PlaybackApplication(hInstance, hWnd, &resources, NULL); Register_Object(new_app); app_manager->StartApplication(new_app); #endif // //------------------------------------ // Initialize the spooling application //------------------------------------ // if (review_mode == 1) { new_app = new L4SpoolingApplication(hInstance, hWnd, &resources, RPL4); Register_Object(new_app); app_manager->StartApplication(new_app); } } else { app_manager = new ApplicationManager(hInstance, hWnd, atoi(getenv("TARGETFPS"))); Register_Object(app_manager); // //-------------------------------------- // Create and initialize the application //-------------------------------------- // Application *new_app = new RPL4Application(hInstance, hWnd, &resources); rpl4App = new_app; Register_Object(new_app); SetCursorPos(1680 / 2, 1050 / 2); app_manager->StartApplication(new_app); } // //-------------------------- // Run missions till we done //-------------------------- // app_manager->RunMissions(); rpl4App = NULL; Unregister_Object(app_manager); delete app_manager; } // //------------------------------------------------------------------------- // Single-binary race loop: if the local console ended this mission, // go back to the setup screen for the next one; anything else (user // quit, -egg / -net / -mr single pass) falls out. //------------------------------------------------------------------------- // if (!front_end_mode || !RPL4LocalConsole_MissionCompleted()) { break; } } #if !_DEBUG // symmetric with the fullscreen-only hide at startup if (L4Application::GetFullscreen()) { ShowCursor(TRUE); } #endif Stop_Registering(); return Exit_Code; }