mirror of https://github.com/AxioDL/metaforce.git
Kabufuda updates and dolphin memory card path resolution
This commit is contained in:
parent
563ff28848
commit
fe3d375120
|
@ -11,8 +11,9 @@ namespace urde
|
|||
|
||||
using ECardResult = kabufuda::ECardResult;
|
||||
|
||||
kabufuda::SystemString g_CardImagePaths[2] = {};
|
||||
kabufuda::Card g_CardStates[2] = {};
|
||||
static kabufuda::SystemString g_CardImagePaths[2] = {};
|
||||
static kabufuda::Card g_CardStates[2] = {};
|
||||
static kabufuda::ECardResult g_OpResults[2] = {};
|
||||
|
||||
CSaveWorldIntermediate::CSaveWorldIntermediate(ResId mlvl, ResId savw)
|
||||
: x0_mlvlId(mlvl), x8_savwId(savw)
|
||||
|
@ -62,6 +63,9 @@ bool CSaveWorldIntermediate::InitializePump()
|
|||
|
||||
CMemoryCardSys::CMemoryCardSys()
|
||||
{
|
||||
g_CardImagePaths[0] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotA);
|
||||
g_CardImagePaths[1] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotB);
|
||||
|
||||
x0_hints = g_SimplePool->GetObj("HINT_Hints");
|
||||
xc_memoryWorlds.reserve(16);
|
||||
x1c_worldInter.emplace();
|
||||
|
@ -261,7 +265,7 @@ ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer()
|
|||
result = GetStatus(stat);
|
||||
if (result != ECardResult::READY)
|
||||
return result;
|
||||
result = CMemoryCardSys::SetStatus(GetCardPort(), GetFileNo(), stat);
|
||||
result = CMemoryCardSys::SetStatus(m_handle, stat);
|
||||
if (result != ECardResult::READY)
|
||||
return result;
|
||||
return ECardResult::BUSY;
|
||||
|
@ -277,7 +281,7 @@ ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer()
|
|||
|
||||
ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) const
|
||||
{
|
||||
ECardResult result = CMemoryCardSys::GetStatus(GetCardPort(), GetFileNo(), stat);
|
||||
ECardResult result = CMemoryCardSys::GetStatus(m_handle, stat);
|
||||
if (result != ECardResult::READY)
|
||||
return result;
|
||||
|
||||
|
@ -333,7 +337,9 @@ ECardResult CMemoryCardSys::CCardFileInfo::CloseFile()
|
|||
|
||||
kabufuda::ProbeResults CMemoryCardSys::CardProbe(kabufuda::ECardSlot port)
|
||||
{
|
||||
return kabufuda::Card::probeCardFile(g_CardImagePaths[int(port)]);
|
||||
kabufuda::ProbeResults res = kabufuda::Card::probeCardFile(g_CardImagePaths[int(port)]);
|
||||
g_OpResults[int(port)] = res.x0_error;
|
||||
return res;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::MountCard(kabufuda::ECardSlot port)
|
||||
|
@ -341,6 +347,7 @@ ECardResult CMemoryCardSys::MountCard(kabufuda::ECardSlot port)
|
|||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
card = kabufuda::Card(g_CardImagePaths[int(port)], "GM8E", "01");
|
||||
ECardResult result = card.getError();
|
||||
g_OpResults[int(port)] = result;
|
||||
if (result == ECardResult::READY)
|
||||
return ECardResult::READY;
|
||||
card = kabufuda::Card();
|
||||
|
@ -350,40 +357,61 @@ ECardResult CMemoryCardSys::MountCard(kabufuda::ECardSlot port)
|
|||
ECardResult CMemoryCardSys::CheckCard(kabufuda::ECardSlot port)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
return card.getError();
|
||||
ECardResult result = card.getError();
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::CreateFile(kabufuda::ECardSlot port, const char* name, u32 size, CardFileHandle& info)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
info.slot = port;
|
||||
return card.createFile(name, size, info.handle);
|
||||
ECardResult result = card.createFile(name, size, info.handle);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::OpenFile(kabufuda::ECardSlot port, const char* name, CardFileHandle& info)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
info.slot = port;
|
||||
info.handle = card.openFile(name);
|
||||
return info.handle ? ECardResult::READY : ECardResult::NOFILE;
|
||||
ECardResult result = card.openFile(name, info.handle);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::FastOpenFile(kabufuda::ECardSlot port, int fileNo, CardFileHandle& info)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
info.slot = port;
|
||||
info.handle = card.openFile(fileNo);
|
||||
return info.handle ? ECardResult::READY : ECardResult::NOFILE;
|
||||
ECardResult result = card.openFile(fileNo, info.handle);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::CloseFile(CardFileHandle& info)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(info.slot)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(info.slot)] = err;
|
||||
return err;
|
||||
}
|
||||
info.handle.reset();
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
@ -392,9 +420,13 @@ ECardResult CMemoryCardSys::ReadFile(const CardFileHandle& info, void* buf, s32
|
|||
{
|
||||
kabufuda::Card& card = g_CardStates[int(info.slot)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(info.slot)] = err;
|
||||
return err;
|
||||
}
|
||||
card.seek(info, offset, kabufuda::SeekOrigin::Begin);
|
||||
card.read(info, buf, length);
|
||||
g_OpResults[int(info.slot)] = ECardResult::READY;
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
|
@ -402,9 +434,13 @@ ECardResult CMemoryCardSys::WriteFile(const CardFileHandle& info, const void* bu
|
|||
{
|
||||
kabufuda::Card& card = g_CardStates[int(info.slot)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(info.slot)] = err;
|
||||
return err;
|
||||
}
|
||||
card.seek(info, offset, kabufuda::SeekOrigin::Begin);
|
||||
card.write(info, buf, length);
|
||||
g_OpResults[int(info.slot)] = ECardResult::READY;
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
|
@ -412,8 +448,12 @@ ECardResult CMemoryCardSys::GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeB
|
|||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
card.getFreeBlocks(freeBytes, freeFiles);
|
||||
g_OpResults[int(port)] = ECardResult::READY;
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
|
@ -421,56 +461,95 @@ ECardResult CMemoryCardSys::GetSerialNo(kabufuda::ECardSlot port, u64& serialOut
|
|||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
card.getSerial(serialOut);
|
||||
g_OpResults[int(port)] = ECardResult::READY;
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::GetResultCode(kabufuda::ECardSlot port)
|
||||
{
|
||||
return ECardResult::READY;
|
||||
return g_OpResults[int(port)];
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut)
|
||||
ECardResult CMemoryCardSys::GetStatus(const CardFileHandle& info, CardStat& statOut)
|
||||
{
|
||||
return ECardResult::READY;
|
||||
kabufuda::Card& card = g_CardStates[int(info.slot)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(info.slot)] = err;
|
||||
return err;
|
||||
}
|
||||
ECardResult result = card.getStatus(info, statOut);
|
||||
g_OpResults[int(info.slot)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat)
|
||||
ECardResult CMemoryCardSys::SetStatus(const CardFileHandle& info, const CardStat& stat)
|
||||
{
|
||||
return ECardResult::READY;
|
||||
kabufuda::Card& card = g_CardStates[int(info.slot)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(info.slot)] = err;
|
||||
return err;
|
||||
}
|
||||
ECardResult result = card.setStatus(info, stat);
|
||||
g_OpResults[int(info.slot)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::DeleteFile(kabufuda::ECardSlot port, const char* name)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
return card.deleteFile(name);
|
||||
}
|
||||
ECardResult result = card.deleteFile(name);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::FastDeleteFile(kabufuda::ECardSlot port, int fileNo)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
return card.deleteFile(fileNo);
|
||||
}
|
||||
ECardResult result = card.deleteFile(fileNo);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
return card.renameFile(oldName, newName);
|
||||
}
|
||||
ECardResult result = card.renameFile(oldName, newName);
|
||||
g_OpResults[int(port)] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ECardResult CMemoryCardSys::FormatCard(kabufuda::ECardSlot port)
|
||||
{
|
||||
kabufuda::Card& card = g_CardStates[int(port)];
|
||||
if (CardResult err = card.getError())
|
||||
{
|
||||
g_OpResults[int(port)] = err;
|
||||
return err;
|
||||
}
|
||||
card.format(port);
|
||||
g_OpResults[int(port)] = ECardResult::READY;
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ class CMemoryCardSys
|
|||
std::experimental::optional<std::vector<CSaveWorldIntermediate>> x1c_worldInter; /* used to be auto_ptr of vector */
|
||||
std::vector<std::pair<ResId, CSaveWorld::EScanCategory>> x20_scanStates;
|
||||
public:
|
||||
static kabufuda::SystemString ResolveDolphinCardPath(kabufuda::ECardSlot slot);
|
||||
|
||||
using ECardResult = kabufuda::ECardResult;
|
||||
struct CardResult
|
||||
{
|
||||
|
@ -153,8 +155,8 @@ public:
|
|||
static ECardResult GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeBytes, s32& freeFiles);
|
||||
static ECardResult GetSerialNo(kabufuda::ECardSlot port, u64& serialOut);
|
||||
static ECardResult GetResultCode(kabufuda::ECardSlot port);
|
||||
static ECardResult GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut);
|
||||
static ECardResult SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat);
|
||||
static ECardResult GetStatus(const CardFileHandle& info, CardStat& statOut);
|
||||
static ECardResult SetStatus(const CardFileHandle& info, const CardStat& stat);
|
||||
static ECardResult DeleteFile(kabufuda::ECardSlot port, const char* name);
|
||||
static ECardResult FastDeleteFile(kabufuda::ECardSlot port, int fileNo);
|
||||
static ECardResult Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName);
|
||||
|
|
|
@ -3,4 +3,31 @@
|
|||
namespace urde
|
||||
{
|
||||
|
||||
kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot)
|
||||
{
|
||||
const char* home = getenv("HOME");
|
||||
if (!home || home[0] != '/')
|
||||
return {};
|
||||
const char* dataHome = getenv("XDG_DATA_HOME");
|
||||
|
||||
/* XDG-selected data path */
|
||||
kabufuda::SystemString path =
|
||||
(dataHome && dataHome[0] == '/') ? dataHome : (home + "/.local/share") + "/.dolphin-emu";
|
||||
path += hecl::Format("/GC/MemoryCard%c.USA.raw",
|
||||
slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B');
|
||||
|
||||
hecl::Sstat theStat;
|
||||
if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode))
|
||||
{
|
||||
/* legacy case for older dolphin versions */
|
||||
path = home;
|
||||
path += hecl::Format("/.dolphin-emu/GC/MemoryCard%c.USA.raw",
|
||||
slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B');
|
||||
if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode))
|
||||
return {};
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#include "CMemoryCardSys.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot)
|
||||
{
|
||||
const char* home = getenv("HOME");
|
||||
if (!home)
|
||||
return {};
|
||||
|
||||
kabufuda::SystemString path = home;
|
||||
path += hecl::Format("/Library/Application Support/Dolphin/GC/MemoryCard%c.USA.raw",
|
||||
slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B');
|
||||
|
||||
hecl::Sstat theStat;
|
||||
if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode))
|
||||
return {};
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#include "CMemoryCardSys.hpp"
|
||||
#include <shlobj.h>
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
/* Partial path-selection logic from
|
||||
* https://github.com/dolphin-emu/dolphin/blob/master/Source/Core/UICommon/UICommon.cpp
|
||||
* Modified to not use dolphin-binary-relative paths. */
|
||||
kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot)
|
||||
{
|
||||
kabufuda::SystemString userPath;
|
||||
|
||||
/* Detect where the User directory is. There are two different cases
|
||||
* 1. HKCU\Software\Dolphin Emulator\UserConfigPath exists
|
||||
* -> Use this as the user directory path
|
||||
* 2. My Documents exists
|
||||
* -> Use My Documents\Dolphin Emulator as the User directory path
|
||||
*/
|
||||
|
||||
/* Check our registry keys */
|
||||
HKEY hkey;
|
||||
kabufuda::SystemChar configPath[MAX_PATH] = {0};
|
||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _S("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE,
|
||||
&hkey) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD size = MAX_PATH;
|
||||
if (RegQueryValueEx(hkey, _S("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath,
|
||||
&size) != ERROR_SUCCESS)
|
||||
configPath[0] = 0;
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
/* Get My Documents path in case we need it. */
|
||||
kabufuda::SystemChar my_documents[MAX_PATH];
|
||||
bool my_documents_found = SUCCEEDED(
|
||||
SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents));
|
||||
|
||||
if (configPath[0]) /* Case 1 */
|
||||
userPath = configPath;
|
||||
else if (my_documents_found) /* Case 2 */
|
||||
userPath = my_documents + _S("/Dolphin Emulator");
|
||||
else /* Unable to find */
|
||||
return {};
|
||||
|
||||
kabufuda::SystemString path = userPath;
|
||||
path += hecl::SysFormat(_S("/GC/MemoryCard%c.USA.raw"),
|
||||
slot == kabufuda::ECardSlot::SlotA ? _S('A') : _S('B'));
|
||||
|
||||
hecl::Sstat theStat;
|
||||
if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode))
|
||||
return {};
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,7 @@ ECardResult CMemoryCardDriver::SFileInfo::Close()
|
|||
ECardResult CMemoryCardDriver::SFileInfo::StartRead()
|
||||
{
|
||||
CMemoryCardSys::CardStat stat = {};
|
||||
ECardResult result = CMemoryCardSys::GetStatus(GetFileCardPort(), GetFileNo(), stat);
|
||||
ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo, stat);
|
||||
if (result != ECardResult::READY)
|
||||
return result;
|
||||
|
||||
|
@ -78,7 +78,7 @@ ECardResult CMemoryCardDriver::SFileInfo::FileRead()
|
|||
ECardResult CMemoryCardDriver::SFileInfo::GetSaveDataOffset(u32& offOut)
|
||||
{
|
||||
CMemoryCardSys::CardStat stat = {};
|
||||
ECardResult result = CMemoryCardSys::GetStatus(GetFileCardPort(), GetFileNo(), stat);
|
||||
ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo, stat);
|
||||
if (result != ECardResult::READY)
|
||||
{
|
||||
offOut = -1;
|
||||
|
@ -183,7 +183,7 @@ void CMemoryCardDriver::ReadFinished()
|
|||
{
|
||||
CMemoryCardSys::CardStat stat = {};
|
||||
SFileInfo& fileInfo = x100_mcFileInfos[x194_fileIdx].second;
|
||||
if (CMemoryCardSys::GetStatus(x0_cardPort, fileInfo.GetFileNo(), stat) != ECardResult::READY)
|
||||
if (CMemoryCardSys::GetStatus(fileInfo.x0_fileInfo, stat) != ECardResult::READY)
|
||||
{
|
||||
NoCardFound();
|
||||
return;
|
||||
|
@ -239,7 +239,7 @@ void CMemoryCardDriver::IndexFiles()
|
|||
else if (result == ECardResult::READY)
|
||||
{
|
||||
CMemoryCardSys::CardStat stat = {};
|
||||
if (CMemoryCardSys::GetStatus(x0_cardPort, info.second.GetFileNo(), stat) ==
|
||||
if (CMemoryCardSys::GetStatus(info.second.x0_fileInfo, stat) ==
|
||||
ECardResult::READY)
|
||||
{
|
||||
u32 comment = stat.GetCommentAddr();
|
||||
|
@ -272,11 +272,11 @@ void CMemoryCardDriver::IndexFiles()
|
|||
if (x100_mcFileInfos[1].first == EFileState::File)
|
||||
{
|
||||
CMemoryCardSys::CardStat stat = {};
|
||||
if (CMemoryCardSys::GetStatus(x0_cardPort, x100_mcFileInfos[0].second.GetFileNo(), stat) ==
|
||||
if (CMemoryCardSys::GetStatus(x100_mcFileInfos[0].second.x0_fileInfo, stat) ==
|
||||
ECardResult::READY)
|
||||
{
|
||||
u32 timeA = stat.GetTime();
|
||||
if (CMemoryCardSys::GetStatus(x0_cardPort, x100_mcFileInfos[1].second.GetFileNo(), stat) ==
|
||||
if (CMemoryCardSys::GetStatus(x100_mcFileInfos[1].second.x0_fileInfo, stat) ==
|
||||
ECardResult::READY)
|
||||
{
|
||||
u32 timeB = stat.GetTime();
|
||||
|
|
2
kabufuda
2
kabufuda
|
@ -1 +1 @@
|
|||
Subproject commit 223ea9a56ebc8ad7e03a2b920dbdc9d621cda551
|
||||
Subproject commit 7315a1dedd0ff060b5266e0d7a9d783447ed5cf2
|
Loading…
Reference in New Issue