Esempio n. 1
0
GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u16 sizeMb, bool ascii, DiscIO::IVolume::ECountry 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);
	}

	File::FSTEntry FST_Temp;
	File::ScanDirectoryTree(m_SaveDirectory, FST_Temp);

	CFileSearch::XStringVector Directory;
	Directory.push_back(m_SaveDirectory);
	CFileSearch::XStringVector Extensions;
	Extensions.push_back("*.gci");

	CFileSearch FileSearch(Extensions, Directory);
	const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();

	if (rFilenames.size() > 112)
	{
		Core::DisplayMessage(
		StringFromFormat("WARNING: There are more than 112 save files on this memorycards"\
		"\n Only loading the first 112 in the folder, unless the gameid is the current games id"),
		4000);
	}

	for (auto 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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
void GCMemcardDirectory::FlushToFile()
{
	std::unique_lock<std::mutex> l(m_write_mutex);
	int errors = 0;
	DEntry invalid;
	for (u16 i = 0; i < m_saves.size(); ++i)
	{
		if (m_saves[i].m_dirty)
		{
			if (BE32(m_saves[i].m_gci_header.Gamecode) != 0xFFFFFFFF)
			{
				m_saves[i].m_dirty = false;
				if (m_saves[i].m_filename.empty())
				{
					std::string defaultSaveName = m_SaveDirectory + m_saves[i].m_gci_header.GCI_FileName();

					// Check to see if another file is using the same name
					// This seems unlikely except in the case of file corruption
					// otherwise what user would name another file this way?
					for (int j = 0; File::Exists(defaultSaveName) && j < 10; ++j)
					{
						defaultSaveName.insert(defaultSaveName.end() - 4, '0');
					}
					if (File::Exists(defaultSaveName))
						PanicAlertT("Failed to find new filename\n %s\n will be overwritten", defaultSaveName.c_str());
					m_saves[i].m_filename = defaultSaveName;
				}
				File::IOFile GCI(m_saves[i].m_filename, "wb");
				if (GCI)
				{
					GCI.WriteBytes(&m_saves[i].m_gci_header, DENTRY_SIZE);
					GCI.WriteBytes(m_saves[i].m_save_data.data(), BLOCK_SIZE * m_saves[i].m_save_data.size());

					if (GCI.IsGood())
					{
						Core::DisplayMessage(
							StringFromFormat("Wrote save contents to %s", m_saves[i].m_filename.c_str()), 4000);
					}
					else
					{
						++errors;
						Core::DisplayMessage(
							StringFromFormat("Failed to write save contents to %s", m_saves[i].m_filename.c_str()),
							4000);
						ERROR_LOG(EXPANSIONINTERFACE, "Failed to save data to %s", m_saves[i].m_filename.c_str());
					}
				}
			}
			else if (m_saves[i].m_filename.length() != 0)
			{
				m_saves[i].m_dirty = false;
				std::string &oldname = m_saves[i].m_filename;
				std::string deletedname = oldname + ".deleted";
				if (File::Exists(deletedname))
					File::Delete(deletedname);
				File::Rename(oldname, deletedname);
				m_saves[i].m_filename.clear();
				m_saves[i].m_save_data.clear();
				m_saves[i].m_used_blocks.clear();
			}
		}

		// Unload the save data for any game that is not running
		// we could use !m_dirty, but some games have multiple gci files and may not write to them simultaneously
		// this ensures that the save data for all of the current games gci files are stored in the savestate
		u32 gamecode = BE32(m_saves[i].m_gci_header.Gamecode);
		if (gamecode != m_GameId && gamecode != 0xFFFFFFFF && m_saves[i].m_save_data.size())
		{
			INFO_LOG(EXPANSIONINTERFACE, "Flushing savedata to disk for %s", m_saves[i].m_filename.c_str());
			m_saves[i].m_save_data.clear();
		}
	}
#if _WRITE_MC_HEADER
	u8 mc[BLOCK_SIZE * MC_FST_BLOCKS];
	Read(0, BLOCK_SIZE * MC_FST_BLOCKS, mc);
	File::IOFile hdrfile(m_SaveDirectory + MC_HDR, "wb");
	hdrfile.WriteBytes(mc, BLOCK_SIZE * MC_FST_BLOCKS);
#endif
}