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:
parent
e810d492f2
commit
8b13e1882a
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue