/** ** Wait for interactive input event for one frame. ** ** Handles system events, joystick, keyboard, mouse. ** Handles the network messages. ** Handles the sound queue. ** ** All events available are fetched. Sound and network only if available. ** Returns if the time for one frame is over. */ void WaitEventsOneFrame() { ++FrameCounter; Uint32 ticks = SDL_GetTicks(); if (ticks > NextFrameTicks) { // We are too slow :( ++SlowFrameCounter; } InputMouseTimeout(*GetCallbacks(), ticks); InputKeyTimeout(*GetCallbacks(), ticks); CursorAnimate(ticks); int interrupts = 0; for (;;) { // Time of frame over? This makes the CPU happy. :( ticks = SDL_GetTicks(); if (!interrupts && ticks < NextFrameTicks) { SDL_Delay(NextFrameTicks - ticks); ticks = SDL_GetTicks(); } while (ticks >= NextFrameTicks) { ++interrupts; FrameFraction += FrameRemainder; if (FrameFraction > 10) { FrameFraction -= 10; ++NextFrameTicks; } NextFrameTicks += FrameTicks; } SDL_Event event[1]; const int i = SDL_PollEvent(event); if (i) { // Handle SDL event SdlDoEvent(*GetCallbacks(), *event); } // Network int s = 0; if (IsNetworkGame()) { s = NetworkFildes.HasDataToRead(0); if (s > 0) { GetCallbacks()->NetworkEvent(); } } // No more input and time for frame over: return if (!i && s <= 0 && interrupts) { break; } } handleInput(NULL); if (!SkipGameCycle--) { SkipGameCycle = SkipFrames; } }
void Emulator::Run() { if (!IsReady()) { Load(); if(!IsReady()) return; } if (IsRunning()) Stop(); if (IsPaused()) { Resume(); return; } GetCallbacks().on_run(); m_pause_start_time = 0; m_pause_amend_time = 0; m_state = system_state::running; auto on_select = [](u32, cpu_thread& cpu) { cpu.run(); }; idm::select<ppu_thread>(on_select); idm::select<ARMv7Thread>(on_select); idm::select<RawSPUThread>(on_select); idm::select<SPUThread>(on_select); }
bool Emulator::Pause() { const u64 start = get_system_time(); // Try to pause if (!m_state.compare_and_swap_test(system_state::running, system_state::paused)) { return m_state.compare_and_swap_test(system_state::ready, system_state::paused); } GetCallbacks().on_pause(); // Update pause start time if (m_pause_start_time.exchange(start)) { LOG_ERROR(GENERAL, "Emulator::Pause() error: concurrent access"); } auto on_select = [](u32, cpu_thread& cpu) { cpu.state += cpu_flag::dbg_global_pause; }; idm::select<ppu_thread>(on_select); idm::select<ARMv7Thread>(on_select); idm::select<RawSPUThread>(on_select); idm::select<SPUThread>(on_select); if (auto mfc = fxm::check<mfc_thread>()) { on_select(0, *mfc); } return true; }
SndSysOggSoundStream::SndSysOggSoundStream (csRef<SndSysOggSoundData> pData, OggDataStore *pDataStore, csSndSysSoundFormat *pRenderFormat, int Mode3D) : SndSysBasicStream(pRenderFormat, Mode3D) { // Initialize the stream data m_StreamData.datastore=pDataStore; m_StreamData.position=0; m_pSoundData=pData; // Allocate an advance buffer m_pCyclicBuffer = new SoundCyclicBuffer ( (m_RenderFormat.Bits/8 * m_RenderFormat.Channels) * (m_RenderFormat.Freq * OGG_BUFFER_LENGTH_MULTIPLIER / OGG_BUFFER_LENGTH_DIVISOR)); CS_ASSERT(m_pCyclicBuffer!=0); // Initialize ogg file memset(&m_VorbisFile,0,sizeof(OggVorbis_File)); ov_open_callbacks (&m_StreamData,&m_VorbisFile,0,0, *(ov_callbacks*)GetCallbacks()); // Set to not a valid stream m_CurrentOggStream=-1; }
int TrackCount(const char* strFile) { VorbisContext* ctx = new VorbisContext; ctx->file = XBMC->OpenFile(strFile, 4); if (!ctx->file) { delete ctx; return 1; } ctx->callbacks = GetCallbacks(strFile); if (ov_open_callbacks(ctx->file, &ctx->vorbisfile, NULL, 0, ctx->callbacks) != 0) { delete ctx; return 1; } long iStreams=ov_streams(&ctx->vorbisfile); ov_clear(&ctx->vorbisfile); delete ctx; return iStreams; }
bool PlayListContainer::Load(sp_playlistcontainer *container) { container_ = container; sp_playlistcontainer_callbacks callbacks; GetCallbacks(&callbacks); sp_playlistcontainer_add_callbacks(container_, &callbacks, this); loading_ = true; return true; }
void Emulator::Stop() { if (m_status.exchange(Stopped) == Stopped) { return; } LOG_NOTICE(GENERAL, "Stopping emulator..."); rpcs3::on_stop()(); SendDbgCommand(DID_STOP_EMU); { LV2_LOCK; idm::select<PPUThread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu) { cpu.state += cpu_state::dbg_global_stop; cpu->lock(); cpu->set_exception(std::make_exception_ptr(EmulationStopped())); cpu->unlock(); cpu->notify(); }); } LOG_NOTICE(GENERAL, "All threads signaled..."); while (g_thread_count) { m_cb.process_events(); std::this_thread::sleep_for(10ms); } LOG_NOTICE(GENERAL, "All threads stopped..."); idm::clear(); fxm::clear(); LOG_NOTICE(GENERAL, "Objects cleared..."); GetCallbackManager().Clear(); RSXIOMem.Clear(); vm::close(); SendDbgCommand(DID_STOPPED_EMU); if (g_cfg_autoexit) { GetCallbacks().exit(); } else { Init(); } }
void PlayListContainer::Unload() { if (container_) { sp_playlistcontainer_callbacks callbacks; GetCallbacks(&callbacks); sp_playlistcontainer_remove_callbacks(container_, &callbacks, this); container_ = NULL; playlists_.clear(); loading_ = false; } }
void Emulator::Stop() { if (m_status.exchange(Stopped) == Stopped) { return; } LOG_NOTICE(GENERAL, "Stopping emulator..."); rpcs3::on_stop()(); SendDbgCommand(DID_STOP_EMU); { LV2_LOCK; for (auto& thread : get_all_cpu_threads()) { thread->state += cpu_state::dbg_global_stop; thread->safe_notify(); } } LOG_NOTICE(GENERAL, "All threads signaled..."); while (g_thread_count) { m_cb.process_events(); std::this_thread::sleep_for(10ms); } LOG_NOTICE(GENERAL, "All threads stopped..."); idm::clear(); fxm::clear(); LOG_NOTICE(GENERAL, "Objects cleared..."); GetCallbackManager().Clear(); RSXIOMem.Clear(); vm::close(); SendDbgCommand(DID_STOPPED_EMU); if (g_cfg_autoexit) { GetCallbacks().exit(); } else { Init(); } }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop() { const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; GameRunning = true; CParticleManager::init(); #ifdef REALVIDEO RealVideoSyncSpeed = VideoSyncSpeed; #endif CclCommand("if (GameStarting ~= nil) then GameStarting() end"); MultiPlayerReplayEachCycle(); SingleGameLoop(); // // Game over // if (GameResult == GameExit) { Exit(0); return; } #ifdef REALVIDEO if (FastForwardCycle > GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } #endif NetworkQuitGame(); EndReplayLog(); GameCycle = 0;//???? CParticleManager::exit(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
JSBool Library::Open(JSContext* cx, uintN argc, jsval *vp) { JSObject* ctypesObj = JS_THIS_OBJECT(cx, vp); if (!ctypesObj || !IsCTypesGlobal(cx, ctypesObj)) { JS_ReportError(cx, "not a ctypes object"); return JS_FALSE; } if (argc != 1 || JSVAL_IS_VOID(JS_ARGV(cx, vp)[0])) { JS_ReportError(cx, "open requires a single argument"); return JS_FALSE; } JSObject* library = Create(cx, JS_ARGV(cx, vp)[0], GetCallbacks(cx, ctypesObj)); if (!library) return JS_FALSE; JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(library)); return JS_TRUE; }
void Emulator::Resume() { // Get pause start time const u64 time = m_pause_start_time.exchange(0); // Try to increment summary pause time if (time) { m_pause_amend_time += get_system_time() - time; } // Try to resume if (!m_state.compare_and_swap_test(system_state::paused, system_state::running)) { return; } if (!time) { LOG_ERROR(GENERAL, "Emulator::Resume() error: concurrent access"); } auto on_select = [](u32, cpu_thread& cpu) { cpu.state -= cpu_flag::dbg_global_pause; cpu.notify(); }; idm::select<ppu_thread>(on_select); idm::select<ARMv7Thread>(on_select); idm::select<RawSPUThread>(on_select); idm::select<SPUThread>(on_select); if (auto mfc = fxm::check<mfc_thread>()) { on_select(0, *mfc); } GetCallbacks().on_resume(); }
/** ** Show a title image */ void TitleScreen::ShowTitleImage() { const EventCallback *old_callbacks = GetCallbacks(); EventCallback callbacks; WaitNoEvent = true; callbacks.ButtonPressed = WaitCallbackButtonPressed; callbacks.ButtonReleased = WaitCallbackButtonReleased; callbacks.MouseMoved = WaitCallbackMouse; callbacks.MouseExit = WaitCallbackExit; callbacks.KeyPressed = WaitCallbackKeyPressed; callbacks.KeyReleased = WaitCallbackKeyReleased; callbacks.KeyRepeated = WaitCallbackKeyRepeated; //callbacks.NetworkEvent = NetworkEvent; callbacks.NetworkEvent = nullptr; SetCallbacks(&callbacks); CGraphic *g = CGraphic::New(this->File); g->Load(); if (this->StretchImage) { g->Resize(Video.Width, Video.Height); } int timeout = this->Timeout ? this->Timeout * CYCLES_PER_SECOND : -1; while (timeout-- && WaitNoEvent) { g->DrawClip((Video.Width - g->Width) / 2, (Video.Height - g->Height) / 2); this->ShowLabels(); Invalidate(); RealizeVideoMemory(); WaitEventsOneFrame(); } SetCallbacks(old_callbacks); CGraphic::Free(g); }
bool Library::Open(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* ctypesObj = JS_THIS_OBJECT(cx, vp); if (!ctypesObj) return false; if (!IsCTypesGlobal(ctypesObj)) { JS_ReportErrorASCII(cx, "not a ctypes object"); return false; } if (args.length() != 1 || args[0].isUndefined()) { JS_ReportErrorASCII(cx, "open requires a single argument"); return false; } JSObject* library = Create(cx, args[0], GetCallbacks(ctypesObj)); if (!library) return false; args.rval().setObject(*library); return true; }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop() { const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; //Wyrmgus start GameEstablishing = false; //Wyrmgus end GameRunning = true; CParticleManager::init(); #ifdef REALVIDEO RealVideoSyncSpeed = VideoSyncSpeed; #endif CclCommand("if (GameStarting ~= nil) then GameStarting() end"); MultiPlayerReplayEachCycle(); //Wyrmgus start if (GameCycle == 0) { // so that these don't trigger when loading a saved game if (CurrentCampaign != NULL) { for (int i = 0; i < NumPlayers; ++i) { if (Players[i].Type != PlayerNobody && Players[i].Race != 0 && Players[i].Faction != -1) { if (CurrentCampaign->StartDate.year) { CCivilization *civilization = PlayerRaces.Civilizations[Players[i].Race]; CFaction *faction = PlayerRaces.Factions[Players[i].Race][Players[i].Faction]; for (std::map<std::string, std::map<CDate, bool>>::iterator iterator = civilization->HistoricalUpgrades.begin(); iterator != civilization->HistoricalUpgrades.end(); ++iterator) { int upgrade_id = UpgradeIdByIdent(iterator->first); if (upgrade_id == -1) { fprintf(stderr, "Upgrade \"%s\" doesn't exist.\n", iterator->first.c_str()); continue; } for (std::map<CDate, bool>::reverse_iterator second_iterator = iterator->second.rbegin(); second_iterator != iterator->second.rend(); ++second_iterator) { if (second_iterator->first.year == 0 || CurrentCampaign->StartDate >= second_iterator->first) { if (second_iterator->second && UpgradeIdentAllowed(Players[i], iterator->first.c_str()) != 'R') { UpgradeAcquire(Players[i], AllUpgrades[upgrade_id]); } else if (!second_iterator->second) { break; } } } } for (std::map<std::string, std::map<CDate, bool>>::iterator iterator = faction->HistoricalUpgrades.begin(); iterator != faction->HistoricalUpgrades.end(); ++iterator) { int upgrade_id = UpgradeIdByIdent(iterator->first); if (upgrade_id == -1) { fprintf(stderr, "Upgrade \"%s\" doesn't exist.\n", iterator->first.c_str()); continue; } for (std::map<CDate, bool>::reverse_iterator second_iterator = iterator->second.rbegin(); second_iterator != iterator->second.rend(); ++second_iterator) { if (second_iterator->first.year == 0 || CurrentCampaign->StartDate >= second_iterator->first) { if (second_iterator->second && UpgradeIdentAllowed(Players[i], iterator->first.c_str()) != 'R') { UpgradeAcquire(Players[i], AllUpgrades[upgrade_id]); } else if (!second_iterator->second) { break; } } } } for (std::map<std::pair<int, CFaction *>, int>::iterator iterator = faction->HistoricalDiplomacyStates.begin(); iterator != faction->HistoricalDiplomacyStates.end(); ++iterator) { //set the appropriate historical diplomacy states to other factions if (iterator->second == 0 || CurrentCampaign->StartDate.year >= iterator->first.first) { CPlayer *diplomacy_state_player = GetFactionPlayer(iterator->first.second); if (diplomacy_state_player) { CommandDiplomacy(i, iterator->second, diplomacy_state_player->Index); CommandDiplomacy(diplomacy_state_player->Index, iterator->second, i); if (iterator->second == DiplomacyAllied) { CommandSharedVision(i, true, diplomacy_state_player->Index); CommandSharedVision(diplomacy_state_player->Index, true, i); } } } } for (std::map<std::pair<CDate, int>, int>::iterator iterator = faction->HistoricalResources.begin(); iterator != faction->HistoricalResources.end(); ++iterator) { //set the appropriate historical resource quantities if (iterator->second == 0 || CurrentCampaign->StartDate >= iterator->first.first) { Players[i].SetResource(iterator->first.second, iterator->second); } } } } } if (CurrentCampaign->StartEffects) { CurrentCampaign->StartEffects->pushPreamble(); CurrentCampaign->StartEffects->run(); } } //if the person player has no faction, bring up the faction choice interface if (!GrandStrategy && ThisPlayer && ThisPlayer->Faction == -1) { char buf[256]; snprintf(buf, sizeof(buf), "if (ChooseFaction ~= nil) then ChooseFaction(\"%s\", \"%s\") end", ThisPlayer->Race != -1 ? PlayerRaces.Name[ThisPlayer->Race].c_str() : "", ""); CclCommand(buf); } if (!IsNetworkGame() && ThisPlayer && CurrentCustomHero != NULL) { Vec2i resPos; FindNearestDrop(*CurrentCustomHero->Type, ThisPlayer->StartPos, resPos, LookingW, ThisPlayer->StartMapLayer); CUnit *custom_hero = MakeUnitAndPlace(resPos, *CurrentCustomHero->Type, ThisPlayer, ThisPlayer->StartMapLayer); custom_hero->SetCharacter(CurrentCustomHero->Ident, true); } if (CurrentQuest != NULL && CurrentQuest->IntroductionDialogue != NULL) { CurrentQuest->IntroductionDialogue->Call(ThisPlayer->Index); } } //Wyrmgus end SingleGameLoop(); // // Game over // if (GameResult == GameExit) { Exit(0); return; } #ifdef REALVIDEO if (FastForwardCycle > GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } #endif NetworkQuitGame(); EndReplayLog(); GameCycle = 0;//???? CParticleManager::exit(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
void Emulator::Load(bool add_only) { Stop(); try { Init(); // Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations) YAML::Node games = YAML::Load(fs::file{fs::get_config_dir() + "/games.yml", fs::read + fs::create}.to_string()); if (!games.IsMap()) { games.reset(); } LOG_NOTICE(LOADER, "Path: %s", m_path); const std::string elf_dir = fs::get_parent_dir(m_path); // Load PARAM.SFO (TODO) const auto _psf = psf::load_object([&] { if (fs::file sfov{elf_dir + "/sce_sys/param.sfo"}) { return sfov; } else { return fs::file(elf_dir + "/../PARAM.SFO"); } }()); m_title = psf::get_string(_psf, "TITLE", m_path); m_title_id = psf::get_string(_psf, "TITLE_ID"); const auto _cat = psf::get_string(_psf, "CATEGORY"); LOG_NOTICE(LOADER, "Title: %s", GetTitle()); LOG_NOTICE(LOADER, "Serial: %s", GetTitleID()); // Initialize data/cache directory m_cache_path = fs::get_data_dir(m_title_id, m_path); LOG_NOTICE(LOADER, "Cache: %s", GetCachePath()); // Load custom config-0 if (fs::file cfg_file{m_cache_path + "/config.yml"}) { LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path); g_cfg.from_string(cfg_file.to_string()); } // Load custom config-1 if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"}) { LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id); g_cfg.from_string(cfg_file.to_string()); } // Load custom config-2 if (fs::file cfg_file{m_path + ".yml"}) { LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path); g_cfg.from_string(cfg_file.to_string()); } LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string()); // Load patches from different locations fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml"); fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml"); // Mount all devices const std::string emu_dir_ = g_cfg.vfs.emulator_dir; const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_; const std::string home_dir = g_cfg.vfs.app_home; std::string bdvd_dir = g_cfg.vfs.dev_bdvd; vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir)); // Detect boot location const std::string hdd0_game = vfs::get("/dev_hdd0/game/"); const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/"); if (_cat == "DG" && m_path.find(hdd0_game + m_title_id + '/') != -1) { // Booting disc game from wrong location LOG_ERROR(LOADER, "Disc game found at invalid location: /dev_hdd0/game/%s/", m_title_id); // Move and retry from correct location if (fs::rename(hdd0_game + m_title_id, hdd0_disc + m_title_id)) { LOG_SUCCESS(LOADER, "Disc game moved to special location: /dev_hdd0/disc/%s/", m_title_id); return SetPath(hdd0_disc + m_path.substr(hdd0_game.size())), Load(); } else { LOG_ERROR(LOADER, "Failed to move disc game to /dev_hdd0/disc/%s/ (%s)", m_title_id, fs::g_tls_error); return; } } // Booting disc game if (_cat == "DG" && bdvd_dir.empty()) { // Mount /dev_bdvd/ if necessary if (auto pos = elf_dir.rfind("/PS3_GAME") + 1) { bdvd_dir = elf_dir.substr(0, pos); } } // Booting patch data if (_cat == "GD" && bdvd_dir.empty()) { // Load /dev_bdvd/ from game list if available if (auto node = games[m_title_id]) { bdvd_dir = node.Scalar(); } else { LOG_FATAL(LOADER, "Disc directory not found. Try to run the game from the actual game disc directory."); } } // Check /dev_bdvd/ if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir)) { fs::file sfb_file; vfs::mount("dev_bdvd", bdvd_dir); LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd")); if (!sfb_file.open(vfs::get("/dev_bdvd/PS3_DISC.SFB")) || sfb_file.size() < 4 || sfb_file.read<u32>() != ".SFB"_u32) { LOG_ERROR(LOADER, "Invalid disc directory for the disc game %s", m_title_id); return; } const std::string bdvd_title_id = psf::get_string(psf::load_object(fs::file{vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")}), "TITLE_ID"); if (bdvd_title_id != m_title_id) { LOG_ERROR(LOADER, "Unexpected disc directory for the disc game %s (found %s)", m_title_id, bdvd_title_id); return; } // Store /dev_bdvd/ location games[m_title_id] = bdvd_dir; YAML::Emitter out; out << games; fs::file(fs::get_config_dir() + "/games.yml", fs::rewrite).write(out.c_str(), out.size()); } else if (_cat == "DG" || _cat == "GD") { LOG_ERROR(LOADER, "Failed to mount disc directory for the disc game %s", m_title_id); return; } if (add_only) { LOG_NOTICE(LOADER, "Finished to add data to games.yml by boot for: %s", m_path); return; } // Check game updates const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN"; if (_cat == "DG" && fs::is_file(hdd0_boot)) { // Booting game update LOG_SUCCESS(LOADER, "Updates found at /dev_hdd0/game/%s/!", m_title_id); return SetPath(hdd0_boot), Load(); } // Mount /host_root/ if necessary if (g_cfg.vfs.host_root) { vfs::mount("host_root", {}); } // Open SELF or ELF fs::file elf_file(m_path); if (!elf_file) { LOG_ERROR(LOADER, "Failed to open executable: %s", m_path); return; } // Check SELF header if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32) { const std::string decrypted_path = m_cache_path + "boot.elf"; fs::stat_t encrypted_stat = elf_file.stat(); fs::stat_t decrypted_stat; // Check modification time and try to load decrypted ELF if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime) { elf_file.open(decrypted_path); } else { // Decrypt SELF elf_file = decrypt_self(std::move(elf_file)); if (fs::file elf_out{decrypted_path, fs::rewrite}) { elf_out.write(elf_file.to_vector<u8>()); elf_out.close(); fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime); } else { LOG_ERROR(LOADER, "Failed to create boot.elf"); } } } ppu_exec_object ppu_exec; ppu_prx_object ppu_prx; spu_exec_object spu_exec; arm_exec_object arm_exec; if (!elf_file) { LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path); return; } else if (ppu_exec.open(elf_file) == elf_error::ok) { // PS3 executable g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); if (m_elf_path.empty()) { if (m_path.find(hdd0_game) != -1) { m_elf_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size()); } else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir)) { //Disc games are on /dev_bdvd/ size_t pos = m_path.rfind("PS3_GAME"); m_elf_path = "/dev_bdvd/" + m_path.substr(pos); } else { //For homebrew m_elf_path = "/host_root/" + m_path; } LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } ppu_load_exec(ppu_exec); fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall } else if (ppu_prx.open(elf_file) == elf_error::ok) { // PPU PRX (experimental) g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); ppu_load_prx(ppu_prx, m_path); } else if (spu_exec.open(elf_file) == elf_error::ok) { // SPU executable (experimental) g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); spu_load_exec(spu_exec); } else if (arm_exec.open(elf_file) == elf_error::ok) { // ARMv7 executable g_system = system_type::psv; m_state = system_state::ready; GetCallbacks().on_ready(); vm::psv::init(); if (m_elf_path.empty()) { m_elf_path = "host_root:" + m_path; LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } arm_load_exec(arm_exec); } else { LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path); LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error()); LOG_WARNING(LOADER, "** ppu_prx -> %s", ppu_prx.get_error()); LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error()); LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error()); return; } if (g_cfg.misc.autostart && IsReady()) { Run(); } else if (IsPaused()) { m_state = system_state::ready; GetCallbacks().on_ready(); } } catch (const std::exception& e) { LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what()); Stop(); } }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop() { const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; GameRunning = true; CParticleManager::init(); #ifdef REALVIDEO RealVideoSyncSpeed = VideoSyncSpeed; #endif CclCommand("if (GameStarting ~= nil) then GameStarting() end"); MultiPlayerReplayEachCycle(); //Wyrmgus start //if the person player has no faction, bring up the faction choice interface if (!GrandStrategy && ThisPlayer && ThisPlayer->Faction == -1) { char buf[256]; snprintf(buf, sizeof(buf), "if (ChooseFaction ~= nil) then ChooseFaction(\"%s\", \"%s\") end", ThisPlayer->Race != -1 ? PlayerRaces.Name[ThisPlayer->Race].c_str() : "", ""); CclCommand(buf); } if (!IsNetworkGame() && ThisPlayer && CurrentCustomHero != NULL) { Vec2i resPos; FindNearestDrop(*CurrentCustomHero->Type, ThisPlayer->StartPos, resPos, LookingW); CUnit *custom_hero = MakeUnitAndPlace(resPos, *CurrentCustomHero->Type, ThisPlayer); custom_hero->SetCharacter(CurrentCustomHero->GetFullName(), true); } //Wyrmgus end SingleGameLoop(); // // Game over // if (GameResult == GameExit) { Exit(0); return; } #ifdef REALVIDEO if (FastForwardCycle > GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } #endif NetworkQuitGame(); EndReplayLog(); GameCycle = 0;//???? //Wyrmgus start GameTimeOfDay = NoTimeOfDay; //Wyrmgus end CParticleManager::exit(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop(void) { #ifdef DEBUG // removes the setjmp warnings static bool showtip; #else bool showtip; #endif int player; int RealVideoSyncSpeed; const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; GameRunning = true; showtip = false; RealVideoSyncSpeed = VideoSyncSpeed; MultiPlayerReplayEachCycle(); // StratagusAI MOD GamePaused = true; // Minimap.Update(); while (GameRunning) { // StratagusAI MOD if ((GameCycle - socketInterface->lastPausedCycle) % socketInterface->cyclesPerTransition == 0) { socketInterface->handleInterface(); if (socketInterface->warpSpeed) FastForwardCycle = GameCycle + socketInterface->cyclesPerTransition + 1; } // Can't find a better place. SaveGameLoading = 0; // // Game logic part // if (!GamePaused && NetworkInSync && !SkipGameCycle) { SinglePlayerReplayEachCycle(); ++GameCycle; MultiPlayerReplayEachCycle(); NetworkCommands(); // Get network commands UnitActions(); // handle units MissileActions(); // handle missiles PlayersEachCycle(); // handle players UpdateTimer(); // update game timer // // Work todo each second. // Split into different frames, to reduce cpu time. // Increment mana of magic units. // Update mini-map. // Update map fog of war. // Call AI. // Check game goals. // Check rescue of units. // switch (GameCycle % CYCLES_PER_SECOND) { case 0: // At cycle 0, start all ai players... if (GameCycle == 0) { for (player = 0; player < NumPlayers; ++player) { PlayersEachSecond(player); } } break; case 1: break; case 2: break; case 3: // minimap update UI.Minimap.Update(); break; case 4: break; case 5: break; case 6: // overtaking units RescueUnits(); break; default: // FIXME: assume that NumPlayers < (CYCLES_PER_SECOND - 7) player = (GameCycle % CYCLES_PER_SECOND) - 7; Assert(player >= 0); if (player < NumPlayers) { PlayersEachSecond(player); } } } TriggersEachCycle(); // handle triggers UpdateMessages(); // update messages CheckMusicFinished(); // Check for next song // // Map scrolling // DoScrollArea(MouseScrollState | KeyScrollState, (KeyModifiers & ModifierControl) != 0); if (FastForwardCycle > GameCycle && RealVideoSyncSpeed != VideoSyncSpeed) { RealVideoSyncSpeed = VideoSyncSpeed; VideoSyncSpeed = 3000; } // MOD if (socketInterface->cyclesPerVideoUpdate != -1 && (GameCycle % socketInterface->cyclesPerVideoUpdate == 0 || GamePaused)) { if (FastForwardCycle <= GameCycle || GameCycle <= 10 || !(GameCycle & 0x3f)) { //FIXME: this might be better placed somewhere at front of the // program, as we now still have a game on the background and // need to go through the game-menu or supply a map file UpdateDisplay(); // // If double-buffered mode, we will display the contains of // VideoMemory. If direct mode this does nothing. In X11 it does // XFlush // RealizeVideoMemory(); } } if (FastForwardCycle == GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } if (FastForwardCycle <= GameCycle || !(GameCycle & 0x3f)) { WaitEventsOneFrame(); } if (!NetworkInSync) { NetworkRecover(); // recover network } } // // Game over // if (FastForwardCycle > GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } NetworkQuit(); EndReplayLog(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
/** ** Play a video file. ** ** @param name Filename of movie file. ** ** @return Non-zero if file isn't a supported movie. */ int PlayMovie(const std::string &name) { OggData data; CFile f; SDL_Rect rect; SDL_Overlay *yuv_overlay; CSample *sample; const EventCallback *old_callbacks; EventCallback callbacks; unsigned int start_ticks; int need_data; int diff; char buffer[PATH_MAX]; LibraryFileName(name.c_str(), buffer, sizeof(buffer)); if (f.open(buffer, CL_OPEN_READ) == -1) { fprintf(stderr, "Can't open file `%s'\n", name.c_str()); return -1; } memset(&data, 0, sizeof(data)); if (OggInit(&f, &data) || !data.video) { OggFree(&data); f.close(); return -1; } data.File = &f; if (data.tinfo.frame_width * 300 / 4 > data.tinfo.frame_height * 100) { rect.w = Video.Width; rect.h = Video.Width * data.tinfo.frame_height / data.tinfo.frame_width; rect.x = 0; rect.y = (Video.Height - rect.h) / 2; } else { rect.w = Video.Height * data.tinfo.frame_width / data.tinfo.frame_height; rect.h = Video.Height; rect.x = (Video.Width - rect.w) / 2; rect.y = 0; } yuv_overlay = SDL_CreateYUVOverlay(data.tinfo.frame_width, data.tinfo.frame_height, SDL_YV12_OVERLAY, TheScreen); if (yuv_overlay == NULL) { fprintf(stderr, "SDL_CreateYUVOverlay: %s\n", SDL_GetError()); OggFree(&data); f.close(); return 0; } StopMusic(); if ((sample = LoadVorbis(buffer, PlayAudioStream))) { if ((sample->Channels != 1 && sample->Channels != 2) || sample->SampleSize != 16) { fprintf(stderr, "Unsupported sound format in movie\n"); delete sample; SDL_FreeYUVOverlay(yuv_overlay); OggFree(&data); f.close(); return 0; } PlayMusic(sample); } callbacks.ButtonPressed = MovieCallbackButtonPressed; callbacks.ButtonReleased = MovieCallbackButtonReleased; callbacks.MouseMoved = MovieCallbackMouseMove; callbacks.MouseExit = MovieCallbackMouseExit; callbacks.KeyPressed = MovieCallbackKeyPressed; callbacks.KeyReleased = MovieCallbackKeyReleased; callbacks.KeyRepeated = MovieCallbackKeyRepeated; callbacks.NetworkEvent = NetworkEvent; old_callbacks = GetCallbacks(); SetCallbacks(&callbacks); Invalidate(); RealizeVideoMemory(); MovieStop = false; start_ticks = SDL_GetTicks(); need_data = 1; while (!MovieStop) { if (need_data) { if (TheoraProcessData(&data)) { break; } need_data = 0; } diff = SDL_GetTicks() - start_ticks - static_cast<int>( theora_granule_time(&data.tstate, data.tstate.granulepos) * 1000); if (diff > 100) { // too far behind, skip some frames need_data = 1; continue; } if (diff > 0) { OutputTheora(&data, yuv_overlay, &rect); need_data = 1; } WaitEventsOneFrame(); } StopMusic(); SDL_FreeYUVOverlay(yuv_overlay); OggFree(&data); f.close(); SetCallbacks(old_callbacks); return 0; }
void* Init(const char* strFile, unsigned int filecache, int* channels, int* samplerate, int* bitspersample, int64_t* totaltime, int* bitrate, AEDataFormat* format, const AEChannel** channelinfo) { VorbisContext* result = new VorbisContext; result->track=0; std::string toLoad(strFile); if (toLoad.find(".oggstream") != std::string::npos) { size_t iStart=toLoad.rfind('-') + 1; result->track = atoi(toLoad.substr(iStart, toLoad.size()-iStart-10).c_str()); // The directory we are in, is the file // that contains the bitstream to play, // so extract it size_t slash = toLoad.rfind('\\'); if (slash == std::string::npos) slash = toLoad.rfind('/'); toLoad = toLoad.substr(0, slash); } result->file = XBMC->OpenFile(toLoad.c_str(), 0); if (!result->file) { delete result; return NULL; } result->callbacks = GetCallbacks(strFile); if (ov_open_callbacks(result->file, &result->vorbisfile, NULL, 0, result->callbacks) != 0) { delete result; return NULL; } long iStreams=ov_streams(&result->vorbisfile); if (iStreams>1) { if (result->track > iStreams) { DeInit(result); return NULL; } } // Calculate the offset in secs where the bitstream starts result->timeoffset = 0; for (int i=0; i<result->track; ++i) result->timeoffset += ov_time_total(&result->vorbisfile, i); vorbis_info* pInfo=ov_info(&result->vorbisfile, result->track); if (!pInfo) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't get stream info from %s", toLoad.c_str()); DeInit(result); return NULL; } *channels = pInfo->channels; *samplerate = pInfo->rate; *bitspersample = 16; *totaltime = (int64_t)ov_time_total(&result->vorbisfile, result->track)*1000; *format = AE_FMT_S16NE; static enum AEChannel map[8][9] = { {AE_CH_FC, AE_CH_NULL}, {AE_CH_FL, AE_CH_FR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_LFE, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_SL, AE_CH_SR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_SL, AE_CH_SR, AE_CH_BL, AE_CH_BR, AE_CH_LFE, AE_CH_NULL} }; *channelinfo = NULL; if (*channels <= 8) *channelinfo = map[*channels - 1]; *bitrate = pInfo->bitrate_nominal; if (*samplerate == 0 || *channels == 0 || *bitspersample == 0 || *totaltime == 0) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't get stream info, SampleRate=%i, Channels=%i, BitsPerSample=%i, TotalTime=%" PRIu64, *samplerate, *channels, *bitspersample, *totaltime); delete result; return NULL; } if (result->timeoffset > 0.0) { if (ov_time_seek(&result->vorbisfile, result->timeoffset)!=0) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't seek to the bitstream start time (%s)", toLoad.c_str()); DeInit(result); return NULL; } } return result; }
/** ** Play a video file. ** ** @param name Filename of movie file. ** ** @return Non-zero if file isn't a supported movie. */ int PlayMovie(const std::string &name) { int videoWidth, videoHeight; #if defined(USE_OPENGL) || defined(USE_GLES) videoWidth = Video.ViewportWidth; videoHeight = Video.ViewportHeight; #else videoWidth = Video.Width; videoHeight = Video.Height; #endif const std::string filename = LibraryFileName(name.c_str()); CFile f; if (f.open(filename.c_str(), CL_OPEN_READ) == -1) { fprintf(stderr, "Can't open file '%s'\n", name.c_str()); return 0; } OggData data; memset(&data, 0, sizeof(data)); if (OggInit(&f, &data) || !data.video) { OggFree(&data); f.close(); return -1; } data.File = &f; SDL_Rect rect; if (data.tinfo.frame_width * 300 / 4 > data.tinfo.frame_height * 100) { rect.w = videoWidth; rect.h = videoWidth * data.tinfo.frame_height / data.tinfo.frame_width; rect.x = 0; rect.y = (videoHeight - rect.h) / 2; } else { rect.w = videoHeight * data.tinfo.frame_width / data.tinfo.frame_height; rect.h = videoHeight; rect.x = (videoWidth - rect.w) / 2; rect.y = 0; } #ifdef USE_OPENGL // When SDL_OPENGL is used, it is not possible to call SDL_CreateYUVOverlay, so turn temporary OpenGL off // With GLES is all ok if (UseOpenGL) { SDL_SetVideoMode(Video.ViewportWidth, Video.ViewportHeight, Video.Depth, SDL_GetVideoSurface()->flags & ~SDL_OPENGL); } #endif SDL_FillRect(SDL_GetVideoSurface(), NULL, 0); Video.ClearScreen(); SDL_Overlay *yuv_overlay = SDL_CreateYUVOverlay(data.tinfo.frame_width, data.tinfo.frame_height, SDL_YV12_OVERLAY, TheScreen); if (yuv_overlay == NULL) { fprintf(stderr, "SDL_CreateYUVOverlay: %s\n", SDL_GetError()); OggFree(&data); f.close(); return 0; } StopMusic(); CSample *sample = LoadVorbis(filename.c_str(), PlayAudioStream); if (sample) { if ((sample->Channels != 1 && sample->Channels != 2) || sample->SampleSize != 16) { fprintf(stderr, "Unsupported sound format in movie\n"); delete sample; SDL_FreeYUVOverlay(yuv_overlay); OggFree(&data); f.close(); return 0; } PlayMusic(sample); } EventCallback callbacks; callbacks.ButtonPressed = MovieCallbackButtonPressed; callbacks.ButtonReleased = MovieCallbackButtonReleased; callbacks.MouseMoved = MovieCallbackMouseMove; callbacks.MouseExit = MovieCallbackMouseExit; callbacks.KeyPressed = MovieCallbackKeyPressed; callbacks.KeyReleased = MovieCallbackKeyReleased; callbacks.KeyRepeated = MovieCallbackKeyRepeated; callbacks.NetworkEvent = NetworkEvent; const EventCallback *old_callbacks = GetCallbacks(); SetCallbacks(&callbacks); Invalidate(); RealizeVideoMemory(); MovieStop = false; const unsigned int start_ticks = SDL_GetTicks(); bool need_data = true; while (!MovieStop) { if (need_data) { if (TheoraProcessData(&data)) { break; } need_data = false; } const int diff = SDL_GetTicks() - start_ticks - static_cast<int>(theora_granule_time(&data.tstate, data.tstate.granulepos) * 1000); if (diff > 100) { // too far behind, skip some frames need_data = true; continue; } if (diff > 0) { OutputTheora(&data, yuv_overlay, &rect); need_data = true; } WaitEventsOneFrame(); } StopMusic(); SDL_FreeYUVOverlay(yuv_overlay); OggFree(&data); f.close(); #ifdef USE_OPENGL if (UseOpenGL) { SDL_SetVideoMode(Video.ViewportWidth, Video.ViewportHeight, Video.Depth, SDL_GetVideoSurface()->flags | SDL_OPENGL); ReloadOpenGL(); } #endif SetCallbacks(old_callbacks); return 0; }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop(void) { int player; const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; GameRunning = true; CParticleManager::init(); MultiPlayerReplayEachCycle(); CclCommand("GameStarting()"); std::ofstream output; std::wstring templ; firstClock = std::clock(); templateClock = 0; int messageNumber = 1; std::ofstream outputEventsPerSec; std::ofstream outputNT; outputEventsPerSec.open("/tmp/boswarseventspersec.csv",std::ios::out); outputNT.open("/tmp/boswarsclocksperevents.csv",std::ios::out); output.open("/tmp/beepbeep.fifo",std::ios::out); templ = templ = L"<message>\n" L" <units>\n" L"{% for unit in units.tabunits %}" L" <unit>\n" L" <id>{$unit.id}</id>\n" L" <type>{$unit.type}</type>\n" L" <isbuilding>{$unit.isbuilding}</isbuilding>\n" L" <player>{$unit.player}</player>\n" L" <order>\n" L" <action>{$unit.action}</action>\n" L" <goal>{$unit.goal}</goal>\n" L" </order>\n" L" <neworder>\n" L" <action>{$unit.neworder}</action>\n" L" <goal>{$unit.newgoal}</goal>\n" L" </neworder>\n" L" </unit>\n" L"{% endfor %}" L" </units>\n" L"<overhead>{$overhead}</overhead>\n" L"</message>\n"; while (GameRunning) { // Can't find a better place. SaveGameLoading = false; // // Game logic part // if (!GamePaused && NetworkInSync && !SkipGameCycle) { SinglePlayerReplayEachCycle(); ++GameCycle; MultiPlayerReplayEachCycle(); NetworkCommands(); // Get network commands UnitActions(); // handle units MissileActions(); // handle missiles PlayersEachCycle(); // handle players UpdateTimer(); // update game timer // // Work todo each second. // Split into different frames, to reduce cpu time. // Increment mana of magic units. // Update mini-map. // Update map fog of war. // Call AI. // Check game goals. // Check rescue of units. // switch (GameCycle % CYCLES_PER_SECOND) { case 0: // At cycle 0, start all ai players... if (GameCycle == 0) { for (player = 0; player < NumPlayers; ++player) { PlayersEachSecond(player); } } break; case 1: break; case 2: break; case 3: // minimap update UI.Minimap.Update(); break; case 4: break; case 5: break; case 6: // overtaking units RescueUnits(); break; default: // FIXME: assume that NumPlayers < (CYCLES_PER_SECOND - 7) player = (GameCycle % CYCLES_PER_SECOND) - 7; Assert(player >= 0); if (player < NumPlayers) { PlayersEachSecond(player); } } ////////////GET INFORMATION FOR MONITORING!!!//////////////////// if(NumUnits > 0) { std::clock_t littleClock = std::clock(); cpptempl::data_list theUnits; std::stringstream ss; for(int i = 0; i < NumUnits; i++) { cpptempl::data_map uni; /////////ID///////// ss.str(""); ss << Units[i]->Slot; std::string theID = ss.str(); std::wstring wTheID; wTheID.assign(theID.begin(),theID.end()); uni[L"id"] = cpptempl::make_data(wTheID); //////UNITTYPE////// ss.str(""); ss << Units[i]->Type->Name; std::string theType = ss.str(); std::wstring wTheType; wTheType.assign(theType.begin(),theType.end()); uni[L"type"] = cpptempl::make_data(wTheType); //////ISBUILDING////// ss.str(""); if (Units[i]->Type->Building == 1) ss << "true"; else ss << "false"; std::string theIsBuilding = ss.str(); std::wstring wTheIsBuilding; wTheIsBuilding.assign(theIsBuilding.begin(),theIsBuilding.end()); uni[L"isbuilding"] = cpptempl::make_data(wTheIsBuilding); //////PLAYER////// ss.str(""); ss << Units[i]->Player; std::string thePlayer = ss.str(); std::wstring wThePlayer; wThePlayer.assign(thePlayer.begin(),thePlayer.end()); uni[L"player"] = cpptempl::make_data(wThePlayer); //////UnitAction////// ss.str(""); switch(Units[i]->Orders[0]->Action) { case UnitActionNone: ss << "UnitActionNone"; break; case UnitActionStill: ss << "UnitActionStill"; break; case UnitActionStandGround: ss << "UnitActionStandGround"; break; case UnitActionFollow: ss << "UnitActionFollow"; break; case UnitActionMove: ss << "UnitActionMove"; break; case UnitActionAttack: ss << "UnitActionAttack"; break; case UnitActionAttackGround: ss << "UnitActionAttackGround"; break; case UnitActionDie: ss << "UnitActionDie"; break; case UnitActionSpellCast: ss << "UnitActionSpellCast"; break; case UnitActionTrain: ss << "UnitActionTrain"; break; case UnitActionBuilt: ss << "UnitActionBuilt"; break; case UnitActionBoard: ss << "UnitActionBoard"; break; case UnitActionUnload: ss << "UnitActionUnload"; break; case UnitActionPatrol: ss << "UnitActionPatrol"; break; case UnitActionBuild: ss << "UnitActionBuild"; break; case UnitActionRepair: ss << "UnitActionRepair"; break; case UnitActionResource: ss << "UnitActionResource"; break; default: ss << "None"; } std::string theAction = ss.str(); std::wstring wTheAction; wTheAction.assign(theAction.begin(),theAction.end()); uni[L"action"] = cpptempl::make_data(wTheAction); //////UnitGoal////// ss.str(""); if(Units[i]->Orders[0]->Goal != NULL) ss << Units[i]->Orders[0]->Goal->Slot; else ss << "None"; std::string theGoal = ss.str(); std::wstring wTheGoal; wTheGoal.assign(theGoal.begin(),theGoal.end()); uni[L"goal"] = cpptempl::make_data(wTheGoal); ///////NEW ORDER///////// ss.str(""); switch(Units[i]->NewOrder.Action) { case UnitActionNone: ss << "UnitActionNone"; break; case UnitActionStill: ss << "UnitActionStill"; break; case UnitActionStandGround: ss << "UnitActionStandGround"; break; case UnitActionFollow: ss << "UnitActionFollow"; break; case UnitActionMove: ss << "UnitActionMove"; break; case UnitActionAttack: ss << "UnitActionAttack"; break; case UnitActionAttackGround: ss << "UnitActionAttackGround"; break; case UnitActionDie: ss << "UnitActionDie"; break; case UnitActionSpellCast: ss << "UnitActionSpellCast"; break; case UnitActionTrain: ss << "UnitActionTrain"; break; case UnitActionBuilt: ss << "UnitActionBuilt"; break; case UnitActionBoard: ss << "UnitActionBoard"; break; case UnitActionUnload: ss << "UnitActionUnload"; break; case UnitActionPatrol: ss << "UnitActionPatrol"; break; case UnitActionBuild: ss << "UnitActionBuild"; break; case UnitActionRepair: ss << "UnitActionRepair"; break; case UnitActionResource: ss << "UnitActionResource"; break; default: ss << "None"; } std::string theNewOrder = ss.str(); std::wstring wTheNewOrder; wTheNewOrder.assign(theNewOrder.begin(),theNewOrder.end()); uni[L"neworder"] = cpptempl::make_data(wTheNewOrder); //////NEW GOAL////// ss.str(""); if(Units[i]->NewOrder.Goal != NULL) ss << Units[i]->NewOrder.Goal->Slot; else ss << "None"; std::string theNewGoal = ss.str(); std::wstring wTheNewGoal; wTheNewGoal.assign(theNewGoal.begin(),theNewGoal.end()); uni[L"newgoal"] = cpptempl::make_data(wTheNewGoal); theUnits.push_back((cpptempl::make_data(uni))); } cpptempl::data_map lesUnits; lesUnits[L"tabunits"] = cpptempl::make_data(theUnits); // Now set this in the data map cpptempl::data_map data; data[L"units"] = cpptempl::make_data(lesUnits); //////////////////TIMESTAMP///////////////////////// std::clock_t t = std::clock() - firstClock; double timeStamp = ((double)t/(double)CLOCKS_PER_SEC); ss.str(""); ss << std::setprecision(8) << timeStamp; std::string sTimeStamp = ss.str(); std::string gnuPlotStringT = ss.str(); std::wstring wTimeStamp; wTimeStamp.assign(sTimeStamp.begin(),sTimeStamp.end()); data[L"timestamp"] = cpptempl::make_data(wTimeStamp); ///OVERHEAD///// templateClock += std::clock()-littleClock; long double overhead = (long double)templateClock / ((long double)std::clock()-(long double)firstClock)*(long double)100.0; ss.str(""); ss << std::setprecision(10) << overhead; std::string sOverhead = ss.str(); std::wstring wOverhead; wOverhead.assign(sOverhead.begin(),sOverhead.end()); data[L"overhead"] = cpptempl::make_data(wOverhead); std::cout << overhead << "% overhead\n"; //std::cout << std::clock() << " clocl\n"; /////////////////MESSAGENUMBER/////////////////////////< ss.str(""); ss << messageNumber; std::string gnuPlotStringN = ss.str(); std::string sMessageNumber = ss.str(); std::wstring wMessageNumber; wMessageNumber.assign(sMessageNumber.begin(),sMessageNumber.end()); data[L"messagenumber"] = cpptempl::make_data(wMessageNumber); std::wstring result = cpptempl::parse(templ, data); ss.str(""); double templateTime = ((double)templateClock/(double)CLOCKS_PER_SEC)*(double)1000; ss << std::setprecision(8) << templateTime; std::string templTime = ss.str(); double totalT = ((std::clock()-firstClock)/(double)CLOCKS_PER_SEC); std::cout << totalT << "totaltime\n"; std::cout << CYCLES_PER_SECOND << "cycles\n"; std::string s; s.assign(result.begin(), result.end()); if (messageNumber == 1) { std::ofstream traceoutput; traceoutput.open("/tmp/traceout.xml",std::ios::out); traceoutput << s; traceoutput.close(); } messageNumber++; /////STATS///// output << s; std::string out = gnuPlotStringN + "," + gnuPlotStringT + "\n"; outputEventsPerSec << out; //OutputNT //std::string theT; out = ""; //ss.str(""); //ss << templTime; //theT = ss.str(); out = templTime + "," + gnuPlotStringN + "\n"; outputNT << out; } ///////////////////////////////////////////////////////////////// } TriggersEachCycle(); // handle triggers UpdateMessages(); // update messages ParticleManager.update(); // handle particles CheckMusicFinished(); // Check for next song // // Map scrolling // DoScrollArea(MouseScrollState | KeyScrollState, (KeyModifiers & ModifierControl) != 0); if (FastForwardCycle <= GameCycle || GameCycle <= 10 || !(GameCycle & 0x3f)) { //FIXME: this might be better placed somewhere at front of the // program, as we now still have a game on the background and // need to go through the game-menu or supply a map file UpdateDisplay(); // // If double-buffered mode, we will display the contains of // VideoMemory. If direct mode this does nothing. In X11 it does // XFlush // RealizeVideoMemory(); } if (FastForwardCycle <= GameCycle || !(GameCycle & 0x3f)) { WaitEventsOneFrame(); } if (!NetworkInSync) { NetworkRecover(); // recover network } } output.close(); outputNT.close(); outputEventsPerSec.close(); // // Game over // NetworkQuit(); EndReplayLog(); CParticleManager::exit(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
/** ** Handle interactive input event. ** ** @param callbacks Callback structure for events. ** @param event SDL event structure pointer. */ static void SdlDoEvent(const EventCallback &callbacks, SDL_Event &event) { #if (defined(USE_OPENGL) || defined(USE_GLES)) // Scale mouse-coordinates to viewport if (ZoomNoResize && (event.type & (SDL_MOUSEBUTTONUP | SDL_MOUSEBUTTONDOWN | SDL_MOUSEMOTION))) { event.button.x = (Uint16)floorf(event.button.x * float(Video.Width) / Video.ViewportWidth); event.button.y = (Uint16)floorf(event.button.y * float(Video.Height) / Video.ViewportHeight); } #endif switch (event.type) { case SDL_MOUSEBUTTONDOWN: InputMouseButtonPress(callbacks, SDL_GetTicks(), event.button.button); break; case SDL_MOUSEBUTTONUP: InputMouseButtonRelease(callbacks, SDL_GetTicks(), event.button.button); break; // FIXME: check if this is only useful for the cursor // FIXME: if this is the case we don't need this. case SDL_MOUSEMOTION: InputMouseMove(callbacks, SDL_GetTicks(), event.motion.x, event.motion.y); // FIXME: Same bug fix from X11 if ((UI.MouseWarpPos.x != -1 || UI.MouseWarpPos.y != -1) && (event.motion.x != UI.MouseWarpPos.x || event.motion.y != UI.MouseWarpPos.y)) { int xw = UI.MouseWarpPos.x; int yw = UI.MouseWarpPos.y; UI.MouseWarpPos.x = -1; UI.MouseWarpPos.y = -1; SDL_WarpMouse(xw, yw); } break; case SDL_ACTIVEEVENT: if (event.active.state & SDL_APPMOUSEFOCUS) { static bool InMainWindow = true; if (InMainWindow && !event.active.gain) { InputMouseExit(callbacks, SDL_GetTicks()); } InMainWindow = (event.active.gain != 0); } if (!IsNetworkGame() && Preference.PauseOnLeave && (event.active.state & SDL_APPACTIVE || SDL_GetAppState() & SDL_APPACTIVE)) { static bool DoTogglePause = false; if (IsSDLWindowVisible && !event.active.gain) { IsSDLWindowVisible = false; if (!GamePaused) { DoTogglePause = true; UiTogglePause(); } } else if (!IsSDLWindowVisible && event.active.gain) { IsSDLWindowVisible = true; if (GamePaused && DoTogglePause) { DoTogglePause = false; UiTogglePause(); } } } break; case SDL_KEYDOWN: if (GLShaderPipelineSupported && event.key.keysym.sym == SDLK_SLASH && event.key.keysym.mod & KMOD_ALT && event.key.keysym.mod & KMOD_CTRL) { LoadShaders(); break; } InputKeyButtonPress(callbacks, SDL_GetTicks(), event.key.keysym.sym, event.key.keysym.unicode); break; case SDL_KEYUP: InputKeyButtonRelease(callbacks, SDL_GetTicks(), event.key.keysym.sym, event.key.keysym.unicode); break; case SDL_QUIT: Exit(0); break; } if (&callbacks == GetCallbacks()) { handleInput(&event); } }
void Emulator::Stop() { if (m_state.exchange(system_state::stopped) == system_state::stopped) { return; } LOG_NOTICE(GENERAL, "Stopping emulator..."); GetCallbacks().on_stop(); #ifdef WITH_GDB_DEBUGGER //fxm for some reason doesn't call on_stop fxm::get<GDBDebugServer>()->on_stop(); fxm::remove<GDBDebugServer>(); #endif auto e_stop = std::make_exception_ptr(cpu_flag::dbg_global_stop); auto on_select = [&](u32, cpu_thread& cpu) { cpu.state += cpu_flag::dbg_global_stop; cpu.get()->set_exception(e_stop); }; idm::select<ppu_thread>(on_select); idm::select<ARMv7Thread>(on_select); idm::select<RawSPUThread>(on_select); idm::select<SPUThread>(on_select); if (auto mfc = fxm::check<mfc_thread>()) { on_select(0, *mfc); } LOG_NOTICE(GENERAL, "All threads signaled..."); while (g_thread_count) { m_cb.process_events(); std::this_thread::sleep_for(10ms); } LOG_NOTICE(GENERAL, "All threads stopped..."); lv2_obj::cleanup(); idm::clear(); fxm::clear(); LOG_NOTICE(GENERAL, "Objects cleared..."); RSXIOMem.Clear(); vm::close(); if (g_cfg.misc.autoexit) { GetCallbacks().exit(); } else { Init(); } #ifdef LLVM_AVAILABLE extern void jit_finalize(); jit_finalize(); #endif }
/** ** Handle interactive input event. ** ** @param callbacks Callback structure for events. ** @param event SDL event structure pointer. */ static void SdlDoEvent(const EventCallback *callbacks, const SDL_Event *event) { #ifdef DUMP_SDL_EVENTS DumpSdlEvent(event); #endif switch (event->type) { case SDL_MOUSEBUTTONDOWN: if (event->motion.which != 0) return; // temporary ignore multitouch InputMouseButtonPress(callbacks, SDL_GetTicks(), event->button.button); break; case SDL_MOUSEBUTTONUP: if (event->motion.which != 0) return; // temporary ignore multitouch InputMouseButtonRelease(callbacks, SDL_GetTicks(), event->button.button); break; // FIXME: check if this is only useful for the cursor // FIXME: if this is the case we don't need this. case SDL_MOUSEMOTION: if (event->motion.which != 0) return; // temporary ignore multitouch InputMouseMove(callbacks, SDL_GetTicks(), event->motion.x, event->motion.y); // FIXME: Same bug fix from X11 if ((UI.MouseWarpX != -1 || UI.MouseWarpY != -1) && (event->motion.x != UI.MouseWarpX || event->motion.y != UI.MouseWarpY)) { int xw = UI.MouseWarpX; int yw = UI.MouseWarpY; UI.MouseWarpX = -1; UI.MouseWarpY = -1; SDL_WarpMouse(xw, yw); } break; case SDL_ACTIVEEVENT: if (event->active.state & SDL_APPMOUSEFOCUS) { static bool InMainWindow = true; if (InMainWindow && !event->active.gain) { InputMouseExit(callbacks, SDL_GetTicks()); } InMainWindow = (event->active.gain != 0); } if (event->active.state & SDL_APPACTIVE) { static bool IsVisible = true; static bool DoTogglePause = false; if (IsVisible && !event->active.gain) { IsVisible = false; if (!GamePaused) { DoTogglePause = true; UiTogglePause(); } } else if (!IsVisible && event->active.gain) { IsVisible = true; if (GamePaused && DoTogglePause) { DoTogglePause = false; UiTogglePause(); } if (UseOpenGL) { Video.ResizeScreen(Video.Width, Video.Height); } } } break; case SDL_KEYDOWN: InputKeyButtonPress(callbacks, SDL_GetTicks(), event->key.keysym.sym, event->key.keysym.unicode); break; case SDL_KEYUP: InputKeyButtonRelease(callbacks, SDL_GetTicks(), event->key.keysym.sym, event->key.keysym.unicode); break; case SDL_QUIT: Exit(0); break; } if (callbacks == GetCallbacks()) { handleInput(event); } }
/** ** Wait for interactive input event for one frame. ** ** Handles system events, joystick, keyboard, mouse. ** Handles the network messages. ** Handles the sound queue. ** ** All events available are fetched. Sound and network only if available. ** Returns if the time for one frame is over. */ void WaitEventsOneFrame() { struct timeval tv; fd_set rfds; fd_set wfds; Socket maxfd; int i; int s = 0; SDL_Event event[1]; Uint32 ticks; int interrupts; ++FrameCounter; ticks = SDL_GetTicks(); if (ticks > NextFrameTicks) { // We are too slow :( ++SlowFrameCounter; } InputMouseTimeout(GetCallbacks(), ticks); InputKeyTimeout(GetCallbacks(), ticks); CursorAnimate(ticks); interrupts = 0; for (;;) { // // Time of frame over? This makes the CPU happy. :( // ticks = SDL_GetTicks(); if (!interrupts && ticks < NextFrameTicks) { SDL_Delay(NextFrameTicks - ticks); ticks = SDL_GetTicks(); } while (ticks >= NextFrameTicks) { ++interrupts; FrameFraction += FrameRemainder; if (FrameFraction > 10) { FrameFraction -= 10; ++NextFrameTicks; } NextFrameTicks += FrameTicks; } // // Prepare select // maxfd = 0; tv.tv_sec = tv.tv_usec = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); // // Network // if (IsNetworkGame()) { if (NetworkFildes > maxfd) { maxfd = NetworkFildes; } FD_SET(NetworkFildes, &rfds); } #if 0 s = select(maxfd + 1, &rfds, &wfds, NULL, (i = SDL_PollEvent(event)) ? &tv : NULL); #else // QUICK HACK to fix the event/timer problem // The timer code didn't interrupt the select call. // Perhaps I could send a signal to the process // Not very nice, but this is the problem if you use other libraries // The event handling of SDL is wrong designed = polling only. // There is hope on SDL 1.3 which will have this fixed. //s = select(maxfd + 1, &rfds, &wfds, NULL, &tv); //printf("PollEvent\n"); i = SDL_PollEvent(event); #endif if (i) { // Handle SDL event SdlDoEvent(GetCallbacks(), event); } if (s > 0) { // // Network // if (IsNetworkGame() && FD_ISSET(NetworkFildes, &rfds) ) { GetCallbacks()->NetworkEvent(); } } // // No more input and time for frame over: return // if (!i && s <= 0 && interrupts) { break; } } handleInput(NULL); if (!SkipGameCycle--) { SkipGameCycle = SkipFrames; } if (!UseOpenGL && (GameRunning || Editor.Running || PatchEditorRunning)) { Video.ClearScreen(); } }
void Emulator::Load() { Stop(); try { Init(); // Open SELF or ELF fs::file elf_file(m_path); if (!elf_file) { LOG_ERROR(LOADER, "Failed to open file: %s", m_path); return; } LOG_NOTICE(LOADER, "Path: %s", m_path); const std::string elf_dir = fs::get_parent_dir(m_path); const fs::file sfov(elf_dir + "/sce_sys/param.sfo"); const fs::file sfo1(elf_dir + "/../PARAM.SFO"); // Load PARAM.SFO (TODO) const auto _psf = psf::load_object(sfov ? sfov : sfo1); m_title = psf::get_string(_psf, "TITLE", m_path); m_title_id = psf::get_string(_psf, "TITLE_ID"); LOG_NOTICE(LOADER, "Title: %s", GetTitle()); LOG_NOTICE(LOADER, "Serial: %s", GetTitleID()); // Initialize data/cache directory m_cache_path = fs::get_data_dir(m_title_id, m_path); LOG_NOTICE(LOADER, "Cache: %s", GetCachePath()); // Load custom config-0 if (fs::file cfg_file{m_cache_path + "/config.yml"}) { LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path); g_cfg.from_string(cfg_file.to_string()); } // Load custom config-1 if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"}) { LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id); g_cfg.from_string(cfg_file.to_string()); } // Load custom config-2 if (fs::file cfg_file{m_path + ".yml"}) { LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path); g_cfg.from_string(cfg_file.to_string()); } LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string()); // Load patches from different locations fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml"); fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml"); // Mount all devices const std::string emu_dir_ = g_cfg.vfs.emulator_dir; const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_; const std::string home_dir = g_cfg.vfs.app_home; std::string bdvd_dir = g_cfg.vfs.dev_bdvd; vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir)); // Mount /dev_bdvd/ if necessary if (bdvd_dir.empty()) { size_t pos = elf_dir.rfind("PS3_GAME"); std::string temp = elf_dir.substr(0, pos); if ((pos != std::string::npos) && fs::is_file(temp + "/PS3_DISC.SFB")) { bdvd_dir = temp; } } if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir)) { vfs::mount("dev_bdvd", fmt::replace_all(bdvd_dir, "$(EmulatorDir)", emu_dir)); LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd")); } // Mount /host_root/ if necessary if (g_cfg.vfs.host_root) { vfs::mount("host_root", {}); } // Check SELF header if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32) { const std::string decrypted_path = m_cache_path + "boot.elf"; fs::stat_t encrypted_stat = elf_file.stat(); fs::stat_t decrypted_stat; // Check modification time and try to load decrypted ELF if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime) { elf_file.open(decrypted_path); } else { // Decrypt SELF elf_file = decrypt_self(std::move(elf_file)); if (fs::file elf_out{decrypted_path, fs::rewrite}) { elf_out.write(elf_file.to_vector<u8>()); elf_out.close(); fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime); } else { LOG_ERROR(LOADER, "Failed to create boot.elf"); } } } ppu_exec_object ppu_exec; ppu_prx_object ppu_prx; spu_exec_object spu_exec; arm_exec_object arm_exec; if (!elf_file) { LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path); return; } else if (ppu_exec.open(elf_file) == elf_error::ok) { // PS3 executable g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); if (m_elf_path.empty()) { if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir)) { //Disc games are on /dev_bdvd/ size_t pos = m_path.rfind("PS3_GAME"); m_elf_path = "/dev_bdvd/" + m_path.substr(pos); } else if (m_path.find(vfs::get("/dev_hdd0/game/")) != -1) { m_elf_path = "/dev_hdd0/game/" + m_path.substr(vfs::get("/dev_hdd0/game/").size()); } else { //For homebrew m_elf_path = "/host_root/" + m_path; } LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } ppu_load_exec(ppu_exec); fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall } else if (ppu_prx.open(elf_file) == elf_error::ok) { // PPU PRX (experimental) g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); ppu_load_prx(ppu_prx, ""); } else if (spu_exec.open(elf_file) == elf_error::ok) { // SPU executable (experimental) g_system = system_type::ps3; m_state = system_state::ready; GetCallbacks().on_ready(); vm::ps3::init(); spu_load_exec(spu_exec); } else if (arm_exec.open(elf_file) == elf_error::ok) { // ARMv7 executable g_system = system_type::psv; m_state = system_state::ready; GetCallbacks().on_ready(); vm::psv::init(); if (m_elf_path.empty()) { m_elf_path = "host_root:" + m_path; LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } arm_load_exec(arm_exec); } else { LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path); LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error()); LOG_WARNING(LOADER, "** ppu_prx -> %s", ppu_prx.get_error()); LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error()); LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error()); return; } if (g_cfg.misc.autostart && IsReady()) { Run(); } else if (IsPaused()) { m_state = system_state::ready; GetCallbacks().on_ready(); } } catch (const std::exception& e) { LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what()); Stop(); } }