EXI: Store data for regenerating a GCI folder memory card header in EXI_Channel and pass it down to the memory card device.

This commit is contained in:
Admiral H. Curtiss 2020-06-16 02:10:14 +02:00
parent e810d492f2
commit 8b13e1882a
10 changed files with 78 additions and 42 deletions

View File

@ -9,17 +9,21 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/IniFile.h"
#include "Core/ConfigManager.h"
#include "Core/CoreTiming.h"
#include "Core/HW/EXI/EXI_Channel.h"
#include "Core/HW/EXI/EXI_DeviceMemoryCard.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "DiscIO/Enums.h"
Sram g_SRAM;
bool g_SRAM_netplay_initialized = false;
@ -69,8 +73,29 @@ void Init()
}
CEXIMemoryCard::Init();
for (u32 i = 0; i < MAX_EXI_CHANNELS; i++)
g_Channels[i] = std::make_unique<CEXIChannel>(i);
{
bool use_memcard_251;
IniFile gameIni = SConfig::GetInstance().LoadGameIni();
gameIni.GetOrCreateSection("Core")->Get("MemoryCard251", &use_memcard_251, false);
const u16 size_mbits =
use_memcard_251 ? Memcard::MBIT_SIZE_MEMORY_CARD_251 : Memcard::MBIT_SIZE_MEMORY_CARD_2043;
const bool shift_jis =
SConfig::ToGameCubeRegion(SConfig::GetInstance().m_region) == DiscIO::Region::NTSC_J;
const CardFlashId& flash_id = g_SRAM.settings_ex.flash_id[Memcard::SLOT_A];
const u32 rtc_bias = g_SRAM.settings.rtc_bias;
const u32 sram_language = static_cast<u32>(g_SRAM.settings.language);
const u64 format_time =
Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH;
for (u32 i = 0; i < MAX_EXI_CHANNELS; i++)
{
Memcard::HeaderData header_data;
Memcard::InitializeHeaderData(&header_data, flash_id, size_mbits, shift_jis, rtc_bias,
sram_language, format_time + i);
g_Channels[i] = std::make_unique<CEXIChannel>(i, header_data);
}
}
for (int i = 0; i < MAX_MEMORYCARD_SLOTS; i++)
AddMemoryCards(i);

View File

@ -22,7 +22,8 @@ enum
EXI_READWRITE
};
CEXIChannel::CEXIChannel(u32 channel_id) : m_channel_id(channel_id)
CEXIChannel::CEXIChannel(u32 channel_id, const Memcard::HeaderData& memcard_header_data)
: m_channel_id(channel_id), m_memcard_header_data(memcard_header_data)
{
if (m_channel_id == 0 || m_channel_id == 1)
m_status.EXTINT = 1;
@ -30,7 +31,7 @@ CEXIChannel::CEXIChannel(u32 channel_id) : m_channel_id(channel_id)
m_status.CHIP_SELECT = 1;
for (auto& device : m_devices)
device = EXIDevice_Create(EXIDEVICE_NONE, m_channel_id);
device = EXIDevice_Create(EXIDEVICE_NONE, m_channel_id, m_memcard_header_data);
}
CEXIChannel::~CEXIChannel()
@ -166,7 +167,7 @@ void CEXIChannel::RemoveDevices()
void CEXIChannel::AddDevice(const TEXIDevices device_type, const int device_num)
{
AddDevice(EXIDevice_Create(device_type, m_channel_id), device_num);
AddDevice(EXIDevice_Create(device_type, m_channel_id, m_memcard_header_data), device_num);
}
void CEXIChannel::AddDevice(std::unique_ptr<IEXIDevice> device, const int device_num,
@ -229,6 +230,7 @@ void CEXIChannel::DoState(PointerWrap& p)
p.Do(m_dma_length);
p.Do(m_control);
p.Do(m_imm_data);
p.DoPOD(m_memcard_header_data);
for (int device_index = 0; device_index < NUM_DEVICES; ++device_index)
{
@ -242,7 +244,8 @@ void CEXIChannel::DoState(PointerWrap& p)
}
else
{
std::unique_ptr<IEXIDevice> save_device = EXIDevice_Create(type, m_channel_id);
std::unique_ptr<IEXIDevice> save_device =
EXIDevice_Create(type, m_channel_id, m_memcard_header_data);
save_device->DoState(p);
AddDevice(std::move(save_device), device_index, false);
}

View File

@ -6,8 +6,11 @@
#include <array>
#include <memory>
#include "Common/CommonTypes.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
class PointerWrap;
namespace MMIO
@ -23,7 +26,7 @@ enum TEXIDevices : int;
class CEXIChannel
{
public:
explicit CEXIChannel(u32 channel_id);
explicit CEXIChannel(u32 channel_id, const Memcard::HeaderData& memcard_header_data);
~CEXIChannel();
// get device
@ -106,6 +109,12 @@ private:
UEXI_CONTROL m_control;
u32 m_imm_data = 0;
// This data is needed in order to reinitialize a GCI folder memory card when switching between
// GCI folder and other devices in the memory card slot or after loading a savestate. Even though
// this data is only vaguely related to the EXI_Channel, this seems to be the best place to store
// it, as this class creates the CEXIMemoryCard instances.
Memcard::HeaderData m_memcard_header_data;
// Devices
enum
{

View File

@ -102,7 +102,8 @@ void IEXIDevice::TransferByte(u8& byte)
}
// F A C T O R Y
std::unique_ptr<IEXIDevice> EXIDevice_Create(const TEXIDevices device_type, const int channel_num)
std::unique_ptr<IEXIDevice> EXIDevice_Create(const TEXIDevices device_type, const int channel_num,
const Memcard::HeaderData& memcard_header_data)
{
std::unique_ptr<IEXIDevice> result;
@ -116,7 +117,7 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(const TEXIDevices device_type, cons
case EXIDEVICE_MEMORYCARDFOLDER:
{
bool gci_folder = (device_type == EXIDEVICE_MEMORYCARDFOLDER);
result = std::make_unique<CEXIMemoryCard>(channel_num, gci_folder);
result = std::make_unique<CEXIMemoryCard>(channel_num, gci_folder, memcard_header_data);
break;
}
case EXIDEVICE_MASKROM:

View File

@ -9,6 +9,11 @@
class PointerWrap;
namespace Memcard
{
struct HeaderData;
}
namespace ExpansionInterface
{
enum TEXIDevices : int
@ -65,5 +70,6 @@ private:
virtual void TransferByte(u8& byte);
};
std::unique_ptr<IEXIDevice> EXIDevice_Create(TEXIDevices device_type, int channel_num);
std::unique_ptr<IEXIDevice> EXIDevice_Create(TEXIDevices device_type, int channel_num,
const Memcard::HeaderData& memcard_header_data);
} // namespace ExpansionInterface

View File

@ -106,7 +106,9 @@ void CEXIMemoryCard::Shutdown()
s_et_transfer_complete.fill(nullptr);
}
CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(index)
CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder,
const Memcard::HeaderData& header_data)
: card_index(index)
{
ASSERT_MSG(EXPANSIONINTERFACE, static_cast<std::size_t>(index) < s_et_cmd_done.size(),
"Trying to create invalid memory card index %d.", index);
@ -132,25 +134,13 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(ind
// card_id = 0xc243;
card_id = 0xc221; // It's a Nintendo brand memcard
// The following games have issues with memory cards bigger than 16Mb
// Darkened Skye GDQE6S GDQP6S
// WTA Tour Tennis GWTEA4 GWTJA4 GWTPA4
// Disney Sports : Skate Boarding GDXEA4 GDXPA4 GDXJA4
// Disney Sports : Soccer GDKEA4
// Wallace and Gromit in Pet Zoo GWLE6L GWLX6L
// Use a 16Mb (251 block) memory card for these games
bool useMC251;
IniFile gameIni = SConfig::GetInstance().LoadGameIni();
gameIni.GetOrCreateSection("Core")->Get("MemoryCard251", &useMC251, false);
u16 sizeMb = useMC251 ? Memcard::MBIT_SIZE_MEMORY_CARD_251 : Memcard::MBIT_SIZE_MEMORY_CARD_2043;
if (gciFolder)
{
SetupGciFolder(sizeMb);
SetupGciFolder(header_data);
}
else
{
SetupRawMemcard(sizeMb);
SetupRawMemcard(header_data.m_size_mb);
}
memory_card_size = memorycard->GetCardId() * SIZE_TO_Mb;
@ -185,7 +175,7 @@ CEXIMemoryCard::GetGCIFolderPath(int card_index, AllowMovieFolder allow_movie_fo
return {std::move(path), !use_movie_folder};
}
void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
{
const std::string& game_id = SConfig::GetInstance().GetGameID();
u32 CurrentGameId = 0;
@ -195,8 +185,7 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
CurrentGameId = Common::swap32(reinterpret_cast<const u8*>(game_id.c_str()));
}
const bool shift_jis =
SConfig::ToGameCubeRegion(SConfig::GetInstance().m_region) == DiscIO::Region::NTSC_J;
const bool shift_jis = header_data.m_encoding != 0;
const auto [strDirectoryName, migrate] = GetGCIFolderPath(card_index, AllowMovieFolder::Yes);
@ -228,8 +217,8 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
}
}
memorycard = std::make_unique<GCMemcardDirectory>(strDirectoryName + DIR_SEP, card_index, sizeMb,
shift_jis, CurrentGameId);
memorycard = std::make_unique<GCMemcardDirectory>(strDirectoryName + DIR_SEP, card_index,
header_data, CurrentGameId);
}
void CEXIMemoryCard::SetupRawMemcard(u16 sizeMb)

View File

@ -14,6 +14,11 @@
class MemoryCardBase;
class PointerWrap;
namespace Memcard
{
struct HeaderData;
}
namespace ExpansionInterface
{
enum class AllowMovieFolder
@ -25,7 +30,7 @@ enum class AllowMovieFolder
class CEXIMemoryCard : public IEXIDevice
{
public:
CEXIMemoryCard(const int index, bool gciFolder);
CEXIMemoryCard(const int index, bool gciFolder, const Memcard::HeaderData& header_data);
virtual ~CEXIMemoryCard();
void SetCS(int cs) override;
bool IsInterruptSet() override;
@ -46,7 +51,7 @@ public:
GetGCIFolderPath(int card_index, AllowMovieFolder allow_movie_folder);
private:
void SetupGciFolder(u16 sizeMb);
void SetupGciFolder(const Memcard::HeaderData& header_data);
void SetupRawMemcard(u16 sizeMb);
static void EventCompleteFindInstance(u64 userdata,
std::function<void(CEXIMemoryCard*)> callback);

View File

@ -149,13 +149,11 @@ std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::st
return filenames;
}
GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u16 size_mbits,
bool shift_jis, int game_id)
: MemoryCardBase(slot, size_mbits), m_game_id(game_id), m_last_block(-1),
m_hdr(g_SRAM.settings_ex.flash_id[slot], size_mbits, shift_jis, g_SRAM.settings.rtc_bias,
static_cast<u32>(g_SRAM.settings.language),
Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH),
m_bat1(size_mbits), m_saves(0), m_save_directory(directory), m_exiting(false)
GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot,
const Memcard::HeaderData& header_data, u32 game_id)
: MemoryCardBase(slot, header_data.m_size_mb), m_game_id(game_id), m_last_block(-1),
m_hdr(header_data), m_bat1(header_data.m_size_mb), m_saves(0), m_save_directory(directory),
m_exiting(false)
{
// Use existing header data if available
{

View File

@ -21,8 +21,8 @@ void MigrateFromMemcardFile(const std::string& directory_name, int card_index);
class GCMemcardDirectory : public MemoryCardBase
{
public:
GCMemcardDirectory(const std::string& directory, int slot, u16 size_mbits, bool shift_jis,
int game_id);
GCMemcardDirectory(const std::string& directory, int slot, const Memcard::HeaderData& header_data,
u32 game_id);
~GCMemcardDirectory();
GCMemcardDirectory(const GCMemcardDirectory&) = delete;

View File

@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
constexpr u32 STATE_VERSION = 115; // Last changed in PR 8722
constexpr u32 STATE_VERSION = 116; // Last changed in PR 8879
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,