Skip to content
Permalink
Browse files

Merge pull request #8104 from AdmiralCurtiss/memcard-folder-small

GCMemcardDirectory: Improve logic for initial load of GCI files.
  • Loading branch information...
leoetlino committed May 26, 2019
2 parents 9136abf + 15abb1c commit 526698d2fc293aa915ed318b5cfa9bb55753b8bf
@@ -107,6 +107,7 @@ add_library(core
HW/EXI/EXI_DeviceMic.cpp
HW/GCKeyboard.cpp
HW/GCKeyboardEmu.cpp
HW/GCMemcard/GCIFile.cpp
HW/GCMemcard/GCMemcard.cpp
HW/GCMemcard/GCMemcardDirectory.cpp
HW/GCMemcard/GCMemcardRaw.cpp
@@ -146,6 +146,7 @@
<ClCompile Include="HW\EXI\EXI_DeviceMic.cpp" />
<ClCompile Include="HW\GCKeyboard.cpp" />
<ClCompile Include="HW\GCKeyboardEmu.cpp" />
<ClCompile Include="HW\GCMemcard\GCIFile.cpp" />
<ClCompile Include="HW\GCMemcard\GCMemcard.cpp" />
<ClCompile Include="HW\GCMemcard\GCMemcardDirectory.cpp" />
<ClCompile Include="HW\GCMemcard\GCMemcardRaw.cpp" />
@@ -414,6 +415,7 @@
<ClInclude Include="HW\EXI\EXI_DeviceMic.h" />
<ClInclude Include="HW\GCKeyboard.h" />
<ClInclude Include="HW\GCKeyboardEmu.h" />
<ClInclude Include="HW\GCMemcard\GCIFile.h" />
<ClInclude Include="HW\GCMemcard\GCMemcard.h" />
<ClInclude Include="HW\GCMemcard\GCMemcardDirectory.h" />
<ClInclude Include="HW\GCMemcard\GCMemcardRaw.h" />
@@ -462,6 +462,9 @@
<ClCompile Include="HW\Sram.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile>
<ClCompile Include="HW\GCMemcard\GCIFile.cpp">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClCompile>
<ClCompile Include="HW\GCMemcard\GCMemcard.cpp">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClCompile>
@@ -1173,6 +1176,9 @@
<ClInclude Include="HW\Sram.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude>
<ClInclude Include="HW\GCMemcard\GCIFile.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>
<ClInclude Include="HW\GCMemcard\GCMemcard.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>
@@ -0,0 +1,102 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "Core/HW/GCMemcard/GCIFile.h"

#include <cinttypes>

#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/File.h"
#include "Common/Logging/Log.h"

bool GCIFile::LoadHeader()
{
if (m_filename.empty())
return false;

File::IOFile save_file(m_filename, "rb");
if (!save_file)
return false;

INFO_LOG(EXPANSIONINTERFACE, "Reading header from disk for %s", m_filename.c_str());
if (!save_file.ReadBytes(&m_gci_header, sizeof(m_gci_header)))
{
ERROR_LOG(EXPANSIONINTERFACE, "Failed to read header for %s", m_filename.c_str());
return false;
}

return true;
}

bool GCIFile::LoadSaveBlocks()
{
if (m_save_data.empty())
{
if (m_filename.empty())
return false;

File::IOFile save_file(m_filename, "rb");
if (!save_file)
return false;

INFO_LOG(EXPANSIONINTERFACE, "Reading savedata from disk for %s", m_filename.c_str());
u16 num_blocks = m_gci_header.m_block_count;

const u32 size = num_blocks * BLOCK_SIZE;
u64 file_size = save_file.GetSize();
if (file_size != size + DENTRY_SIZE)
{
ERROR_LOG(EXPANSIONINTERFACE,
"%s\nwas not loaded because it is an invalid GCI.\n File size (0x%" PRIx64
") does not match the size recorded in the header (0x%x)",
m_filename.c_str(), file_size, size + DENTRY_SIZE);
return false;
}

m_save_data.resize(num_blocks);
save_file.Seek(DENTRY_SIZE, SEEK_SET);
if (!save_file.ReadBytes(m_save_data.data(), size))
{
ERROR_LOG(EXPANSIONINTERFACE, "Failed to read data from GCI file %s", m_filename.c_str());
m_save_data.clear();
return false;
}
}
return true;
}

bool GCIFile::HasCopyProtection() const
{
if ((strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "PSO_SYSTEM") == 0) ||
(strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "PSO3_SYSTEM") == 0) ||
(strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "f_zero.dat") == 0))
return true;
return false;
}

int GCIFile::UsesBlock(u16 block_num)
{
for (u16 i = 0; i < m_used_blocks.size(); ++i)
{
if (m_used_blocks[i] == block_num)
return i;
}
return -1;
}

void GCIFile::DoState(PointerWrap& p)
{
p.DoPOD<DEntry>(m_gci_header);
p.Do(m_dirty);
p.Do(m_filename);
int num_blocks = (int)m_save_data.size();
p.Do(num_blocks);
m_save_data.resize(num_blocks);
for (auto itr = m_save_data.begin(); itr != m_save_data.end(); ++itr)
{
p.DoPOD<GCMBlock>(*itr);
}
p.Do(m_used_blocks);
}
@@ -0,0 +1,29 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <string>
#include <vector>

#include "Common/CommonTypes.h"
#include "Core/HW/GCMemcard/GCMemcard.h"

class PointerWrap;

class GCIFile
{
public:
bool LoadHeader();
bool LoadSaveBlocks();
bool HasCopyProtection() const;
void DoState(PointerWrap& p);
int UsesBlock(u16 blocknum);

DEntry m_gci_header;
std::vector<GCMBlock> m_save_data;
std::vector<u16> m_used_blocks;
bool m_dirty;
std::string m_filename;
};
@@ -337,30 +337,6 @@ struct BlockAlloc
static_assert(sizeof(BlockAlloc) == BLOCK_SIZE);
#pragma pack(pop)

class GCIFile
{
public:
bool LoadSaveBlocks();
bool HasCopyProtection() const
{
if ((strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "PSO_SYSTEM") ==
0) ||
(strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "PSO3_SYSTEM") ==
0) ||
(strcmp(reinterpret_cast<const char*>(m_gci_header.m_filename.data()), "f_zero.dat") == 0))
return true;
return false;
}

void DoState(PointerWrap& p);
DEntry m_gci_header;
std::vector<GCMBlock> m_save_data;
std::vector<u16> m_used_blocks;
int UsesBlock(u16 blocknum);
bool m_dirty;
std::string m_filename;
};

class GCMemcard
{
private:

0 comments on commit 526698d

Please sign in to comment.
You can’t perform that action at this time.