#include "mungal4.h" #pragma hdrstop #include "..\munga\camship.h" #include "..\munga\appmsg.h" #include "l4app.h" #include "l4ctrl.h" #include "l4icom.h" #include "l4video.h" #include "l4audrnd.h" #include "l4grend.h" #include "l4net.h" #include "l4mppr.h" #include "..\munga\player.h" #include "..\munga\mission.h" // // Minimal stand-in for ATL's USES_CONVERSION / W2A macros. // VC++ Express and the Windows SDK do not ship ATL, and the only ATL feature // this file used was wide-to-ANSI conversion of command-line tokens below. // L4WideToAnsi mirrors ATL's W2A semantics: each use produces an independent // buffer that stays valid until the end of the enclosing full-expression. // namespace { class L4WideToAnsi { public: explicit L4WideToAnsi(const wchar_t* wide) : mBuffer(0) { int needed = (wide != 0) ? ::WideCharToMultiByte(CP_ACP, 0, wide, -1, 0, 0, 0, 0) : 0; if (needed <= 0) { needed = 1; } mBuffer = new char[needed]; if (wide == 0 || ::WideCharToMultiByte(CP_ACP, 0, wide, -1, mBuffer, needed, 0, 0) <= 0) { mBuffer[0] = '\0'; } } ~L4WideToAnsi() { delete [] mBuffer; } operator char*() { return mBuffer; } private: char* mBuffer; L4WideToAnsi(const L4WideToAnsi&); // non-copyable L4WideToAnsi& operator=(const L4WideToAnsi&); }; } #define USES_CONVERSION ((void)0) #define W2A(w) (static_cast(L4WideToAnsi(w))) L4Application*& l4_application = (L4Application*&)application; const Receiver::HandlerEntry L4Application::MessageHandlerEntries[]= { MESSAGE_ENTRY(L4Application, RunMission), MESSAGE_ENTRY(L4Application, StopMission), MESSAGE_ENTRY(L4Application, LightsOut), MESSAGE_ENTRY(L4Application, KeyCommand) }; Receiver::MessageHandlerSet& L4Application::GetMessageHandlers() { static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4Application::MessageHandlerEntries), L4Application::MessageHandlerEntries, Application::GetMessageHandlers()); return messageHandlers; } //############################################################################# // Virtual Data support // Derivation* L4Application::GetClassDerivations() { static Derivation classDerivations(Application::GetClassDerivations(), "L4Application"); return &classDerivations; } L4Application::SharedData L4Application::DefaultData( L4Application::GetClassDerivations(), L4Application::GetMessageHandlers() ); //########################################################################## //################## L4Application Static Data ####################### //########################################################################## HINSTANCE L4Application::mhInstance = NULL; unsigned int L4Application::mScreenWidth = 800; unsigned int L4Application::mScreenHeight = 600; bool L4Application::mFullscreen = true; Logical L4Application::seeSolids = False; CString L4Application::eggNotationFileName; CString L4Application::spoolFileName; unsigned long L4Application::networkCommonFlatAddress; Logical L4Application::missionReviewMode = False; CString L4Application::rioPlaybackFileName; CString L4Application::rioRecordingFileName; // //############################################################################# // ParseCommandLine //############################################################################# // Logical L4Application::ParseToken( int *arguement, int argc, LPWSTR argv[] ) { USES_CONVERSION; Check_Pointer(argv); if (!stricmp(W2A(argv[*arguement]), "-egg")) { if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') { eggNotationFileName = W2A(argv[++(*arguement)]); } else { DEBUG_STREAM << "\nEgg file not specified after -egg\n" << std::flush << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-spool")) { if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') { spoolFileName = W2A(argv[++(*arguement)]); } else { DEBUG_STREAM << "\nSpool file not specified after -spool\n" << std::flush << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-net")) { if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') { networkCommonFlatAddress = atol(W2A(argv[++(*arguement)])); } else { DEBUG_STREAM << "\nAddress not specified after -net\n" << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-r")) { if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') { rioRecordingFileName = W2A(argv[++(*arguement)]); CString playback = GetRIOPlaybackFileName(); if (playback && strlen(playback)) { DEBUG_STREAM << "\nPlayback already specified!\n" << std::flush; return False; } } else { DEBUG_STREAM << "\nRecording file not specified after -r\n" << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-p")) { if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') { rioPlaybackFileName = W2A(argv[++(*arguement)]); CString recording = GetRIORecordingFileName(); if (recording && strlen(recording)) { DEBUG_STREAM << "\nRecording already specified!\n" << std::flush; return False; } } else { DEBUG_STREAM << "\nPlayback file not specified after -egg\n" << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-solids")) { seeSolids = True; } else if (!stricmp(W2A(argv[*arguement]), "-res")) { if ((*arguement+2) < argc && W2A(argv[*arguement+1])[0] != '-' && W2A(argv[*arguement+2])[0] != '-') { mScreenWidth = atoi(W2A(argv[++(*arguement)])); mScreenHeight = atoi(W2A(argv[++(*arguement)])); } else { DEBUG_STREAM << "\nScreen width and height not specified after -res\n" << std::flush; return False; } } else if (!stricmp(W2A(argv[*arguement]), "-windowed")) { mFullscreen = false; } else if ( !stricmp(W2A(argv[*arguement]), "-h") || !stricmp(W2A(argv[*arguement]), "-help") ) { DEBUG_STREAM << "\n" << argv[0] << " -egg -net -solids -h -help\n"; return False; } return True; } // //############################################################################# // ParseCommandLine //############################################################################# // Logical L4Application::ParseCommandLine( int argc, LPWSTR argv[], TokenParser parser ) { USES_CONVERSION; Check_Pointer(argv); // // Process options // seeSolids = False; eggNotationFileName = ""; networkCommonFlatAddress = NULL; missionReviewMode = 0; suppressGauges = FALSE; if (argc > 1) { for (int i = 1; i < argc; ++i) { if (!stricmp(W2A(argv[i]), "-lc")) { suppressGauges = TRUE; } else if (!stricmp(W2A(argv[i]), "-mr")) { suppressGauges = TRUE; missionReviewMode = 1; } else if (!(*parser)(&i, argc, argv)) { return False; } } } return True; } // //############################################################################# // TestInstance //############################################################################# // Logical L4Application::TestInstance() const { if (!IsDerivedFrom(*GetClassDerivations())) { return False; } return True; } // //############################################################################# // L4Application //############################################################################# // L4Application::L4Application( HINSTANCE hInstance, HWND hWnd, ResourceFile *resource_file, ApplicationID application_ID, ClassID class_ID, SharedData &shared_data ): Application(resource_file, application_ID, class_ID, shared_data), mIsDead(false) { mhInstance = hInstance; // this is a static member, the app instance should never change during execution //ghWnd = hWnd; divisionParameters = getenv("DPLARG"); } // //############################################################################# // Initialize //############################################################################# // void L4Application::Initialize() { Check(this); InitializeTillConsole(); // // Create the console host and socket // L4NetworkManager *net_mgr = GetNetworkManager(); net_mgr->CreateConsoleHost(); } // //############################################################################# // Initialize //############################################################################# // void L4Application::InitializeTillConsole() { Check(this); Application::Initialize(); } // //############################################################################# // MakeModeManager //############################################################################# // ModeManager* L4Application::MakeModeManager() { return new ModeManager((ModeMask)ModeManager::ModeAlwaysActive); // Normally called at top level!! } // //############################################################################# // MakeNetworkManager //############################################################################# // NetworkManager* L4Application::MakeNetworkManager() { return new L4NetworkManager; } // //############################################################################# // MakeControlsManager //############################################################################# // ControlsManager* L4Application::MakeControlsManager() { LBE4ControlsManager *manager = new LBE4ControlsManager(); Check(manager); manager->keyboardGroup[LBE4ControlsManager::KeyboardPC].Add(ModeManager::ModeAlwaysActive, this, KeyCommandMessageID, this); return manager; } // //############################################################################# // MakeIntercomManager //############################################################################# // IcomManager* L4Application::MakeIntercomManager() { L4IcomManager *manager = new L4IcomManager(); Check(manager); return manager; } // //############################################################################# // MakeVideoRenderer //############################################################################# // VideoRenderer* L4Application::MakeVideoRenderer() { if (divisionParameters) { return new DPLRenderer( ghWnd, mScreenWidth, mScreenHeight, mFullscreen, VisualInterestType, DefaultInterestDepth ); } return NULL; } // //############################################################################# // MakeAudioRenderer //############################################################################# // AudioRenderer* L4Application::MakeAudioRenderer() { /* char *blaster1, *blaster2; blaster1 = getenv(FRONT_CARD_ENV_VAR); blaster2 = getenv(REAR_CARD_ENV_VAR); if (blaster1 != NULL && blaster2 != NULL) { return new L4AudioRenderer(DefaultRendererRate, False); } return NULL;*/ return new L4AudioRenderer(DefaultRendererRate, False); } // //############################################################################# // MakeGaugeRenderer //############################################################################# // GaugeRenderer* L4Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index) { char *mode_string = getenv("L4GAUGE"); if (mode_string != NULL) { return new L4GaugeRenderer(!mFullscreen, secondaryIndex, aux1Index, aux2Index); } return NULL; } // //############################################################################# // Terminate //############################################################################# // void L4Application::Terminate() { Check(this); // //-------------------------------------------------------------------------- // Turn off illumination //-------------------------------------------------------------------------- // PilotIllumination(False); // // Call inherited method // Application::Terminate(); } // //############################################################################# // ~L4Application //############################################################################# // L4Application::~L4Application() { } // //############################################################################# // MakeAndLinkViewpointEntity //############################################################################# // Entity* L4Application::MakeAndLinkViewpointEntity(Entity::MakeMessage* message) { Check(this); Check(message); Application::MakeAndLinkViewpointEntity(message); // //-------------------------------------------------------------------------- // Turn on lights for pilot // (turned off by RunMissionMessageHandler) //-------------------------------------------------------------------------- // PilotIllumination(True); // //-------------------------------------------------------------------------- // Return viewpoint entity //-------------------------------------------------------------------------- // return GetViewpointEntity(); } // //############################################################################# // MakeViewpointEntity //############################################################################# // Entity* L4Application::MakeViewpointEntity(Entity::MakeMessage *message) { Entity *viewing_entity; viewing_entity = NULL; switch(message->classToCreate) { case CameraShipClassID: viewing_entity = CameraShip::Make((CameraShip::MakeMessage*)message); Check(viewing_entity); CameraShip *viewing_camera = Cast_Object(CameraShip*, viewing_entity); Check(viewing_camera); // // Create controls mapping object // CameraControlsMapper *camera_mapper; Verify(GetControlsManager() != NULL); CameraControlsMapper::SubsystemResource control_subsystem_resource; Str_Copy( control_subsystem_resource.subsystemName, "ControlsMapper", sizeof(control_subsystem_resource.subsystemName) ); control_subsystem_resource.classID = TrivialSubsystemClassID; control_subsystem_resource.subsystemModelSize = sizeof(control_subsystem_resource); LBE4ControlsManager* controls = GetControlsManager(); Check(controls); switch (controls->primaryControlType) { case LBE4ControlsManager::PrimaryThrustMaster: Tell("L4Application::MakeViewpointEntity, using ThrustMaster\n"); camera_mapper = new CameraThrustmasterMapper( viewing_camera, CameraShip::ControlsMapperSubsystem, &control_subsystem_resource ); Register_Object(camera_mapper); viewing_camera->SetMappingSubsystem(camera_mapper); break; case LBE4ControlsManager::PrimaryRIO: Tell("L4Application::MakeViewpointEntity, using RIO\n"); camera_mapper = new CameraRIOMapper( viewing_camera, CameraShip::ControlsMapperSubsystem, &control_subsystem_resource ); Register_Object(camera_mapper); viewing_camera->SetMappingSubsystem(camera_mapper); break; default: Fail("L4Application::MakeViewpointEntity, *** NO MAPPER! ***\n"); break; } // //------------------------------------------- // Create gauges for this entity //------------------------------------------- // if (GetGaugeRenderer() != NULL) { L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); Check(gauge_renderer); gauge_renderer->ConfigureForModel( "Init", viewing_entity ); } break; } return viewing_entity; } // //############################################################################# // RunMissionMessageHandler //############################################################################# // void L4Application::RunMissionMessageHandler(RunMissionMessage *message) { Check(this); Verify(message->messageID == RunMissionMessageID); // //-------------------------------------------------------------------------- // If the application is already running then ignore this message //-------------------------------------------------------------------------- // switch (GetApplicationState()) { case RunningMission: break; // //------------------------------------- // Start the playback if it is required //------------------------------------- // case LaunchingMission: { LBE4ControlsManager *controls = GetControlsManager(); Check(controls); if (controls->IsRecording()) { controls->StartRecording(); } else if (controls->IsPlayingBack()) { controls->StartPlayback(); } } break; case WaitingForLaunch: PilotIllumination(False); break; default: Fail("Application::RunMissionMessageHandler - Not ready to run!\n"); break; } // //-------------------------------------------------------------------------- // Call previous handler //-------------------------------------------------------------------------- // Application::RunMissionMessageHandler(message); } // //############################################################################# // StopMissionMessageHandler //############################################################################# // void L4Application::StopMissionMessageHandler(StopMissionMessage *message) { Check(this); Verify(message->messageID == StopMissionMessageID); // //-------------------------------------------------------------------------- // Call inherited handler //-------------------------------------------------------------------------- // Application::StopMissionMessageHandler(message); // //-------------------------------------------------------------------------- // Turn on illumination //-------------------------------------------------------------------------- // PilotIllumination(True); // //-------------------------------------------------------------------------- // Post a delayed message to ourselves to turn off the illumination //-------------------------------------------------------------------------- // Receiver::Message lights_out_message(LightsOutMessageID, sizeof(Receiver::Message)); Time event_time; event_time = Now(); event_time += 30.0f; Post( LowEventPriority, // priority this, // target &lights_out_message, // message event_time // when ); } // //############################################################################# // KeyCommandMessageHandler //############################################################################# // void L4Application::KeyCommandMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); switch (message->dataContents) { //-------------------------------------------- // FrameDump from Division card to Targa file //-------------------------------------------- case PCK_ALT_F: { DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); if (dpl_renderer) { Check(dpl_renderer); dpl_renderer->DPLFrameDump(True); // True indicates antialiased } break; } //------------------------------------ // Report current free memory in card //------------------------------------ case PCK_ALT_K: { //STUBBED: HEAP RB 1/20/07 /*DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); if (dpl_renderer) { Check(dpl_renderer); dpl_renderer->DPLReportFreeMemory(DEBUG_STREAM) << std::flush; } DEBUG_STREAM << UserHeap::MainStorage.GetTotalHeapLeft() << '(' << UserHeap::MainStorage.GetBiggestHeapLeft() << " contiguous) bytes of MUNGA core left\n" << UserHeap::MainStorage.GetHeapUsed() << " bytes of heap used\n"; #if defined(USE_MEMORY_ANALYSIS) DEBUG_STREAM << UserHeap::MainStorage.GetLowestTotalHeapLeft() << " bytes minimum available so far\n" << UserHeap::MainStorage.GetMostHeapUsed() << " bytes maximum used so far\n"; #endif MemoryBlockBase::UsageReport();*/ break; } //------------------------------------ // Report current event queue //------------------------------------ case 'E': { Check(application); application->DumpEventQueue(); break; } //--------------------------------------- // Report performance statistics (Alt-?) //--------------------------------------- case PCK_ALT_SLASH: { DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); if (dpl_renderer) { Check(dpl_renderer); dpl_renderer->DPLReportPerfStats(DEBUG_STREAM); } break; } //-------------------------- // Toggle Wireframe display //-------------------------- case PCK_ALT_W: { DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); if (dpl_renderer) { Check(dpl_renderer); dpl_renderer->DPLToggleWireframe(); } break; } //-------------------------- // Toggle "Predator-vision" //-------------------------- case PCK_ALT_V: { DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); if (dpl_renderer) { Check(dpl_renderer); dpl_renderer->DPLTogglePVision(); } break; } //-------------------------------------------------------------- // Toggle transparency dither pattern between random and static //-------------------------------------------------------------- case PCK_ALT_R: //----------------------------- // Report position of eyepoint //----------------------------- case PCK_ALT_P: DEBUG_STREAM << "Function net yet enabled.\n" << std::flush; break; //------------------------------ // Pass event on to Application //------------------------------ default: Application::KeyCommandMessageHandler(message); break; } } // //############################################################################# // LightsOutMessageHandler //############################################################################# // #if DEBUG_LEVEL == 0 void L4Application::LightsOutMessageHandler(Receiver::Message */*message*/) { #else void L4Application::LightsOutMessageHandler(Receiver::Message *message) { Check(this); Verify(message->messageID == LightsOutMessageID); #endif // //-------------------------------------------------------------------------- // Turn off illumination //-------------------------------------------------------------------------- // PilotIllumination(False); } // //############################################################################# // TeslaCoil //############################################################################# // void L4Application::TeslaCoil(Logical light_on) { Check(controlsManager); if (light_on) { ((LBE4ControlsManager *) controlsManager)->SetLamp( LBE4ControlsManager::LampTesla1, RIO::solid + RIO::state1Bright + RIO::state2Bright ); ((LBE4ControlsManager *) controlsManager)->SetLamp( LBE4ControlsManager::LampTesla2, RIO::solid + RIO::state1Bright + RIO::state2Bright ); ((LBE4ControlsManager *) controlsManager)->SetLamp( LBE4ControlsManager::LampTesla3, RIO::solid + RIO::state1Bright + RIO::state2Bright ); } else { ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla1, RIO::solid + RIO::state1Off + RIO::state2Off); ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla2, RIO::solid + RIO::state1Off + RIO::state2Off); ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla3, RIO::solid + RIO::state1Off + RIO::state2Off); } } // //############################################################################# // PilotIllumination //############################################################################# // void L4Application::PilotIllumination(Logical light_on) { Check(controlsManager); TeslaCoil(light_on); if (light_on) { //-------------------------------------------- // Turn on floor light //-------------------------------------------- ((LBE4ControlsManager *) controlsManager)->SetLamp( LBE4ControlsManager::LampFloor, RIO::solid + RIO::state1Bright + RIO::state2Bright ); //-------------------------------------------- // Ramp all aux screens to white //-------------------------------------------- L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); if (gauge_renderer != NULL) { Check(gauge_renderer); gauge_renderer->FadeToWhite(1.5); } } else { //-------------------------------------------- // Turn off floor light //-------------------------------------------- ((LBE4ControlsManager *) controlsManager)->SetLamp( LBE4ControlsManager::LampFloor, RIO::solid + RIO::state1Off + RIO::state2Off ); //-------------------------------------------- // Ramp all aux screens to normal //-------------------------------------------- L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); if (gauge_renderer != NULL) { Check(gauge_renderer); gauge_renderer->FadeToNormal(1.5); } } } #ifdef TEST_CLASS # include "l4app.tcp" #endif