std::string CVolumeGC::GetUniqueID() const { static const std::string NO_UID("NO_UID"); if (m_pReader == nullptr) return NO_UID; char ID[6]; if (!Read(0, sizeof(ID), reinterpret_cast<u8*>(ID))) { PanicAlertT("Failed to read unique ID from disc image"); return NO_UID; } return DecodeString(ID); }
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset) { if (_Size > 0) { u8* pTmpBuffer = new u8[_Size]; _dbg_assert_msg_(BOOT, pTmpBuffer!=nullptr, "WiiWAD: Can't allocate memory for WAD entry"); if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) { ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); PanicAlertT("WiiWAD: Could not read from file"); } return pTmpBuffer; } return nullptr; }
s32 MemoryCard::Write(u32 destaddress, s32 length, u8 *srcaddress) { if (!IsAddressInBounds(destaddress)) { PanicAlertT("MemoryCard: Write called with invalid destination address, %x", destaddress); return -1; } { std::unique_lock<std::mutex> l(m_flush_mutex); memcpy(&m_memcard_data[destaddress], srcaddress, length); } MakeDirty(); return length; }
bool operator()(const BootParameters::Executable& executable) const { NOTICE_LOG(BOOT, "Booting from executable: %s", executable.path.c_str()); if (!executable.reader->IsValid()) return false; if (!executable.reader->LoadIntoMemory()) { PanicAlertT("Failed to load the executable to memory."); return false; } SetDefaultDisc(); SetupMSR(); SetupBAT(config.bWii); CopyDefaultExceptionHandlers(); if (config.bWii) { PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464; PowerPC::ppcState.spr[SPR_HID4] = 0x82000000; // Set a value for the SP. It doesn't matter where this points to, // as long as it is a valid location. This value is taken from a homebrew binary. PowerPC::ppcState.gpr[1] = 0x8004d4bc; // Because there is no TMD to get the requested system (IOS) version from, // we default to IOS58, which is the version used by the Homebrew Channel. SetupWiiMemory(); IOS::HLE::GetIOS()->BootIOS(Titles::IOS(58)); } else { SetupGCMemory(); } PC = executable.reader->GetEntryPoint(); if (executable.reader->LoadSymbols() || LoadMapFromFilename()) { UpdateDebugger_MapLoaded(); HLE::PatchFunctions(); } return true; }
void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA) { std::string ext("." + gameRegion + ".raw"); if (memcardPath.empty()) { // Use default memcard path if there is no user defined name std::string defaultFilename = isSlotA ? GC_MEMCARDA : GC_MEMCARDB; memcardPath = File::GetUserPath(D_GCUSER_IDX) + defaultFilename + ext; } else { std::string filename = memcardPath; std::string region = filename.substr(filename.size() - 7, 3); bool hasregion = false; hasregion |= region.compare(USA_DIR) == 0; hasregion |= region.compare(JAP_DIR) == 0; hasregion |= region.compare(EUR_DIR) == 0; if (!hasregion) { // filename doesn't have region in the extension if (File::Exists(filename)) { // If the old file exists we are polite and ask if we should copy it std::string oldFilename = filename; filename.replace(filename.size() - 4, 4, ext); if (PanicYesNoT("Memory Card filename in Slot %c is incorrect\n" "Region not specified\n\n" "Slot %c path was changed to\n" "%s\n" "Would you like to copy the old file to this new location?\n", isSlotA ? 'A' : 'B', isSlotA ? 'A' : 'B', filename.c_str())) { if (!File::Copy(oldFilename, filename)) PanicAlertT("Copy failed"); } } memcardPath = filename; // Always correct the path! } else if (region.compare(gameRegion) != 0) { // filename has region, but it's not == gameRegion // Just set the correct filename, the EXI Device will create it if it doesn't exist memcardPath = filename.replace(filename.size() - ext.size(), ext.size(), ext); } } }
void GamepadPage::SaveProfile(wxCommandEvent&) { std::string fname; GamepadPage::GetProfilePath(fname); File::CreateFullPath(fname); if (false == fname.empty()) { IniFile inifile; controller->SaveConfig(inifile.GetOrCreateSection("Profile")); inifile.Save(fname); m_config_dialog->UpdateProfileComboBox(); } else PanicAlertT("You must enter a valid profile name."); }
void SetState(EState _State) { switch (_State) { case CORE_PAUSE: CCPU::EnableStepping(true); // Break Wiimote::Pause(); break; case CORE_RUN: CCPU::EnableStepping(false); Wiimote::Resume(); break; default: PanicAlertT("Invalid state"); break; } }
GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u16 sizeMb, bool ascii, DiscIO::Country card_region, int gameId) : MemoryCardBase(slot, sizeMb), m_GameId(gameId), m_LastBlock(-1), m_hdr(slot, sizeMb, ascii), m_bat1(sizeMb), m_saves(0), m_SaveDirectory(directory), m_exiting(false) { // Use existing header data if available if (File::Exists(m_SaveDirectory + MC_HDR)) { File::IOFile hdrfile((m_SaveDirectory + MC_HDR), "rb"); hdrfile.ReadBytes(&m_hdr, BLOCK_SIZE); } std::vector<std::string> rFilenames = DoFileSearch({".gci"}, {m_SaveDirectory}); if (rFilenames.size() > 112) { Core::DisplayMessage("Warning: There are more than 112 save files on this memory card.\n" " Only loading the first 112 in the folder, unless the game ID is the " "same as the current game's ID", 4000); } for (const std::string& gciFile : rFilenames) { if (m_saves.size() == DIRLEN) { PanicAlertT( "There are too many GCI files in the folder\n%s.\nOnly the first 127 will be available", m_SaveDirectory.c_str()); break; } int index = LoadGCI(gciFile, card_region, m_saves.size() > 112); if (index != NO_INDEX) { m_loaded_saves.push_back(m_saves.at(index).m_gci_header.GCI_FileName()); } } m_loaded_saves.clear(); m_dir1.fixChecksums(); m_dir2 = m_dir1; m_bat2 = m_bat1; m_flush_thread = std::thread(&GCMemcardDirectory::FlushThread, this); }
// called from ---GUI--- thread and ---NETPLAY--- thread (client side) bool NetPlayClient::StopGame() { if (!m_is_running.load()) { PanicAlertT("Game isn't running!"); return false; } m_dialog->AppendChat(" -- STOPPING GAME -- "); m_is_running.store(false); NetPlay_Disable(); // stop game m_dialog->StopGame(); return true; }
void SetState(EState _State) { switch (_State) { case CORE_UNINITIALIZED: Stop(); break; case CORE_PAUSE: CCPU::EnableStepping(true); // Break break; case CORE_RUN: CCPU::EnableStepping(false); break; default: PanicAlertT("Invalid state"); break; } }
std::string GetScheduledEventsSummary() { Event *ptr = first; std::string text = "Scheduled events\n"; text.reserve(1000); while (ptr) { unsigned int t = ptr->type; if (t >= event_types.size()) PanicAlertT("Invalid event type %i", t); const char *name = event_types[ptr->type].name; if (!name) name = "[unknown]"; text += StringFromFormat("%s : %i %08x%08x\n", event_types[ptr->type].name, ptr->time, ptr->userdata >> 32, ptr->userdata); ptr = ptr->next; } return text; }
void DriveReader::GetBlock(u64 block_num, u8* out_ptr) { u8* const lpSector = new u8[m_blocksize]; #ifdef _WIN32 u32 NotUsed; u64 offset = m_blocksize * block_num; LONG off_low = (LONG)offset & 0xFFFFFFFF; LONG off_high = (LONG)(offset >> 32); SetFilePointer(hDisc, off_low, &off_high, FILE_BEGIN); if (!ReadFile(hDisc, lpSector, m_blocksize, (LPDWORD)&NotUsed, nullptr)) PanicAlertT("Disc Read Error"); #else file_.Seek(m_blocksize * block_num, SEEK_SET); file_.ReadBytes(lpSector, m_blocksize); #endif memcpy(out_ptr, lpSector, m_blocksize); delete[] lpSector; }
std::string GetScheduledEventsSummary() { Event *ptr = first; std::string text = "Scheduled events\n"; text.reserve(1000); while (ptr) { unsigned int t = ptr->type; if (t >= event_types.size()) PanicAlertT("Invalid event type %i", t); const std::string& name = event_types[ptr->type].name; text += StringFromFormat("%s : %" PRIi64 " %016" PRIx64 "\n", name.c_str(), ptr->time, ptr->userdata); ptr = ptr->next; } return text; }
void DoState(PointerWrap& p) { // By waiting for the DVD thread to be done working, we ensure // that s_request_queue will be empty and that the DVD thread // won't be touching anything while this function runs. WaitUntilIdle(); // Move all results from s_result_queue to s_result_map because // PointerWrap::Do supports std::map but not Common::SPSCQueue. // This won't affect the behavior of FinishRead. ReadResult result; while (s_result_queue.Pop(result)) s_result_map.emplace(result.first.id, std::move(result)); // Both queues are now empty, so we don't need to savestate them. p.Do(s_result_map); p.Do(s_next_id); // s_disc isn't savestated (because it points to files on the // local system). Instead, we check that the status of the disc // is the same as when the savestate was made. This won't catch // cases of having the wrong disc inserted, though. // TODO: Check the game ID, disc number, revision? bool had_disc = HasDisc(); p.Do(had_disc); if (had_disc != HasDisc()) { if (had_disc) PanicAlertT("An inserted disc was expected but not found."); else s_disc.reset(); } // TODO: Savestates can be smaller if the buffers of results aren't saved, // but instead get re-read from the disc when loading the savestate. // TODO: It would be possible to create a savestate faster by stopping // the DVD thread regardless of whether there are pending requests. // After loading a savestate, the debug log in FinishRead will report // screwed up times for requests that were submitted before the savestate // was made. Handling that properly may be more effort than it's worth. }
// called from ---GUI--- thread bool NetPlayServer::RequestStartGame() { if (m_settings.m_SyncSaveData && m_players.size() > 1) { if (!SyncSaveData()) { PanicAlertT("Error synchronizing save data!"); return false; } m_start_pending = true; } else { return StartGame(); } return true; }
// called from ---NETPLAY--- thread void NetPlayClient::ThreadFunc() { while (m_do_loop.load()) { ENetEvent netEvent; int net; if (m_traversal_client) m_traversal_client->HandleResends(); net = enet_host_service(m_client, &netEvent, 250); while (!m_async_queue.Empty()) { Send(*(m_async_queue.Front().get())); m_async_queue.Pop(); } if (net > 0) { sf::Packet rpac; switch (netEvent.type) { case ENET_EVENT_TYPE_RECEIVE: rpac.append(netEvent.packet->data, netEvent.packet->dataLength); OnData(rpac); enet_packet_destroy(netEvent.packet); break; case ENET_EVENT_TYPE_DISCONNECT: m_is_running.store(false); NetPlay_Disable(); m_dialog->AppendChat("< LOST CONNECTION TO SERVER >"); PanicAlertT("Lost connection to server!"); m_do_loop.store(false); netEvent.peer->data = nullptr; break; default: break; } } } Disconnect(); return; }
void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count, int sample_rate) { if (!file) PanicAlertT("WaveFileWriter - file not open."); if (count > BUFFER_SIZE * 2) PanicAlert("WaveFileWriter - buffer too small (count = %u).", count); if (skip_silence) { bool all_zero = true; for (u32 i = 0; i < count * 2; i++) { if (sample_data[i]) all_zero = false; } if (all_zero) return; } for (u32 i = 0; i < count; i++) { // Flip the audio channels from RL to LR conv_buffer[2 * i] = Common::swap16((u16)sample_data[2 * i + 1]); conv_buffer[2 * i + 1] = Common::swap16((u16)sample_data[2 * i]); } if (sample_rate != current_sample_rate) { Stop(); file_index++; std::stringstream filename; filename << File::GetUserPath(D_DUMPAUDIO_IDX) << basename << file_index << ".wav"; Start(filename.str(), sample_rate); current_sample_rate = sample_rate; } file.WriteBytes(conv_buffer.data(), count * 4); audio_size += count * 4; }
void InstallExceptionHandler() { #ifdef _M_IX86 PanicAlertT("InstallExceptionHandler called, but this platform does not yet support it."); #else mach_port_t port; CheckKR("mach_port_allocate", mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port)); std::thread exc_thread(ExceptionThread, port); exc_thread.detach(); // Obtain a send right for thread_set_exception_ports to copy... CheckKR("mach_port_insert_right", mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)); // Mach tries the following exception ports in order: thread, task, host. // Debuggers set the task port, so we grab the thread port. CheckKR("thread_set_exception_ports", thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, x86_THREAD_STATE64)); // ...and get rid of our copy so that MACH_NOTIFY_NO_SENDERS works. CheckKR("mach_port_mod_refs", mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, -1)); mach_port_t previous; CheckKR("mach_port_request_notification", mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_NO_SENDERS, 0, port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous)); #endif }
void NetPlayDiag::OnConfigPads(wxCommandEvent&) { int mapping[4]; // get selected player id int pid = m_player_lbox->GetSelection(); if (pid < 0) return; pid = m_playerids.at(pid); if (false == ((NetPlayServer*)netplay_ptr)->GetPadMapping(pid, mapping)) return; PadMapDiag pmd(this, mapping); pmd.ShowModal(); if (false == ((NetPlayServer*)netplay_ptr)->SetPadMapping(pid, mapping)) PanicAlertT("Could not set pads. The player left or the game is currently running!\n" "(setting pads while the game is running is not yet supported)"); }
// called from ---GUI--- thread and ---NETPLAY--- thread (client side) bool NetPlay::StopGame() { std::lock_guard<std::recursive_mutex> lkg(m_crit.game); if (false == m_is_running) { PanicAlertT("Game isn't running!"); return false; } m_dialog->AppendChat(" -- STOPPING GAME -- "); m_is_running = false; NetPlay_Disable(); // stop game m_dialog->StopGame(); return true; }
bool DriveReader::ReadMultipleAlignedBlocks(u64 block_num, u64 num_blocks, u8* out_ptr) { #ifdef _WIN32 u32 NotUsed; u64 offset = m_blocksize * block_num; LONG off_low = (LONG)offset & 0xFFFFFFFF; LONG off_high = (LONG)(offset >> 32); SetFilePointer(hDisc, off_low, &off_high, FILE_BEGIN); if (!ReadFile(hDisc, out_ptr, (DWORD)(m_blocksize * num_blocks), (LPDWORD)&NotUsed, nullptr)) { PanicAlertT("Disc Read Error"); return false; } #else fseeko(file_.GetHandle(), m_blocksize*block_num, SEEK_SET); if (fread(out_ptr, 1, m_blocksize * num_blocks, file_.GetHandle()) != m_blocksize * num_blocks) return false; #endif return true; }
bool DecompressBlobToFile(const char* infile, const char* outfile, CompressCB callback, void* arg) { if (!IsCompressedBlob(infile)) { PanicAlertT("File not compressed"); return false; } CompressedBlobReader* reader = CompressedBlobReader::Create(infile); if (!reader) return false; File::IOFile f(outfile, "wb"); if (!f) { delete reader; return false; } const CompressedBlobHeader &header = reader->GetHeader(); u8* buffer = new u8[header.block_size]; int progress_monitor = max<int>(1, header.num_blocks / 100); for (u64 i = 0; i < header.num_blocks; i++) { if (i % progress_monitor == 0) { callback("Unpacking", (float)i / (float)header.num_blocks, arg); } reader->Read(i * header.block_size, header.block_size, buffer); f.WriteBytes(buffer, header.block_size); } delete[] buffer; f.Resize(header.data_size); delete reader; return true; }
// This is called from the GUI thread. See the booting call schedule in // BootManager.cpp bool Init() { const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; if (s_emu_thread.joinable()) { if (IsRunning()) { PanicAlertT("Emu Thread already running"); return false; } // The Emu Thread was stopped, synchronize with it. s_emu_thread.join(); } Core::UpdateWantDeterminism(/*initial*/ true); INFO_LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "GameCube"); INFO_LOG(OSREPORT, "CPU Thread separate = %s", _CoreParameter.bCPUThread ? "Yes" : "No"); Host_UpdateMainFrame(); // Disable any menus or buttons at boot g_aspect_wide = _CoreParameter.bWii; if (g_aspect_wide) { IniFile gameIni = _CoreParameter.LoadGameIni(); gameIni.GetOrCreateSection("Wii")->Get("Widescreen", &g_aspect_wide, !!SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.AR")); } s_window_handle = Host_GetRenderHandle(); // Start the emu thread s_emu_thread = std::thread(EmuThread); return true; }
CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume) : m_country(volume->GetCountry()) { // load the opening.bnr size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE) { m_pBannerFile = new u8[FileSize]; if (m_pBannerFile) { _rFileSystem.ReadFile("opening.bnr", m_pBannerFile, FileSize); m_BNRType = getBannerType(); if (m_BNRType == BANNER_UNKNOWN) PanicAlertT("Invalid opening.bnr found in gcm:\n%s\n You may need to redump this game.", _rFileSystem.GetVolume()->GetName().c_str()); else m_IsValid = true; } } else WARN_LOG(DISCIO, "Invalid opening.bnr size: %0lx", (unsigned long)FileSize); }
void NetPlayDiag::OnStart(wxCommandEvent&) { // find path for selected game std::string ntmp, ptmp, path; std::istringstream nss(m_game_list->GetGameNames()), pss(m_game_list->GetGamePaths()); while(std::getline(nss,ntmp)) { std::getline(pss,ptmp); if (m_selected_game == ntmp) { path = ptmp; break; } } if (path.length()) netplay_ptr->StartGame(path); else PanicAlertT("Game not found!!"); }
// This is called from the GUI thread. See the booting call schedule in // BootManager.cpp bool Init() { const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; if (g_EmuThread.joinable()) { PanicAlertT("Emu Thread already running"); return false; } g_CoreStartupParameter = _CoreParameter; INFO_LOG(OSREPORT, "Starting core = %s mode", g_CoreStartupParameter.bWii ? "Wii" : "Gamecube"); INFO_LOG(OSREPORT, "CPU Thread separate = %s", g_CoreStartupParameter.bCPUThread ? "Yes" : "No"); Host_UpdateMainFrame(); // Disable any menus or buttons at boot g_aspect_wide = _CoreParameter.bWii; if (g_aspect_wide) { IniFile gameIni; gameIni.Load(_CoreParameter.m_strGameIni.c_str()); gameIni.Get("Wii", "Widescreen", &g_aspect_wide, !!SConfig::GetInstance().m_SYSCONF-> GetData<u8>("IPL.AR")); } // g_pWindowHandle is first the m_Panel handle, // then it is updated to the render window handle, // within g_video_backend->Initialize() g_pWindowHandle = Host_GetRenderHandle(); // Start the emu thread g_EmuThread = std::thread(EmuThread); return true; }
static void UnknownOpcode(u8 cmd_byte, void* buffer, bool preprocess) { // TODO(Omega): Maybe dump FIFO to file on this error PanicAlertT("GFX FIFO: Unknown Opcode (0x%02x @ %p, %s).\n" "This means one of the following:\n" "* The emulated GPU got desynced, disabling dual core can help\n" "* Command stream corrupted by some spurious memory bug\n" "* This really is an unknown opcode (unlikely)\n" "* Some other sort of bug\n\n" "Further errors will be sent to the Video Backend log and\n" "Dolphin will now likely crash or hang. Enjoy.", cmd_byte, buffer, preprocess ? "preprocess=true" : "preprocess=false"); { SCPFifoStruct& fifo = CommandProcessor::fifo; PanicAlert("Illegal command %02x\n" "CPBase: 0x%08x\n" "CPEnd: 0x%08x\n" "CPHiWatermark: 0x%08x\n" "CPLoWatermark: 0x%08x\n" "CPReadWriteDistance: 0x%08x\n" "CPWritePointer: 0x%08x\n" "CPReadPointer: 0x%08x\n" "CPBreakpoint: 0x%08x\n" "bFF_GPReadEnable: %s\n" "bFF_BPEnable: %s\n" "bFF_BPInt: %s\n" "bFF_Breakpoint: %s\n" "bFF_GPLinkEnable: %s\n" "bFF_HiWatermarkInt: %s\n" "bFF_LoWatermarkInt: %s\n", cmd_byte, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance, fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false", fifo.bFF_BPEnable ? "true" : "false", fifo.bFF_BPInt ? "true" : "false", fifo.bFF_Breakpoint ? "true" : "false", fifo.bFF_GPLinkEnable ? "true" : "false", fifo.bFF_HiWatermarkInt ? "true" : "false", fifo.bFF_LoWatermarkInt ? "true" : "false"); } }
void GCMemcardDirectory::ClearBlock(u32 address) { if (address % BLOCK_SIZE) { PanicAlertT("GCMemcardDirectory: ClearBlock called with invalid block address"); return; } u32 block = address / BLOCK_SIZE; INFO_LOG(EXPANSIONINTERFACE, "clearing block %d", block); switch (block) { case 0: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_hdr; break; case 1: m_LastBlock = -1; m_LastBlockAddress = (u8 *)&m_dir1; break; case 2: m_LastBlock = -1; m_LastBlockAddress = (u8 *)&m_dir2; break; case 3: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_bat1; break; case 4: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_bat2; break; default: m_LastBlock = SaveAreaRW(block, true); if (m_LastBlock == -1) return; } ((GCMBlock *)m_LastBlockAddress)->Erase(); }
void WaveFileWriter::AddStereoSamples(const short *sample_data, u32 count) { if (!file) PanicAlertT("WaveFileWriter - file not open."); if (skip_silence) { bool all_zero = true; for (u32 i = 0; i < count * 2; i++) { if (sample_data[i]) all_zero = false; } if (all_zero) return; } file.WriteBytes(sample_data, count * 4); audio_size += count * 4; }
File::IOFile CWII_IPC_HLE_Device_FileIO::OpenFile() { const char* open_mode = ""; switch (m_Mode) { case ISFS_OPEN_READ: open_mode = "rb"; break; case ISFS_OPEN_WRITE: case ISFS_OPEN_RW: open_mode = "r+b"; break; default: PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode); break; } return File::IOFile(m_filepath, open_mode); }