summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp6
-rw-r--r--Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp8
-rw-r--r--Source/Core/Core/IOS/FS/FileSystemCommon.cpp101
3 files changed, 94 insertions, 21 deletions
diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
index 923680e88e..5638a7aab4 100644
--- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
+++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp
@@ -628,7 +628,11 @@ void ZeldaUCode::RenderAudio()
if (m_rendering_curr_voice == 0)
m_renderer.PrepareFrame();
- while (m_rendering_curr_voice < m_rendering_voices_per_frame)
+ // TODO: Find out the actual hardware behavior for the case where
+ // (m_rendering_voices_per_frame >> 4) >= m_sync_voice_skip_flags.size()
+ const u16 number_of_voices = std::min(m_rendering_voices_per_frame,
+ static_cast<u16>(m_sync_voice_skip_flags.size() << 4));
+ while (m_rendering_curr_voice < number_of_voices)
{
// If we are not meant to render this voice yet, go back to message
// processing.
diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp
index 791b471be4..36e5b36c35 100644
--- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp
+++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp
@@ -536,7 +536,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing)
}
const int idx = m_saves[i].UsesBlock(block);
- if (idx != -1)
+ if (idx >= 0)
{
if (!m_saves[i].LoadSaveBlocks())
{
@@ -553,6 +553,12 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing)
m_saves[i].m_dirty = true;
}
+ if (static_cast<size_t>(idx) >= m_saves[i].m_save_data.size())
+ {
+ PanicAlertFmt("Block index ({0}) is larger than the number of available blocks ({1})",
+ idx, m_saves[i].m_save_data.size());
+ return -1;
+ }
m_last_block = block;
m_last_block_address = m_saves[i].m_save_data[idx].m_block.data();
return m_last_block;
diff --git a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp
index 0e13192c5b..225084c177 100644
--- a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp
+++ b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp
@@ -139,12 +139,45 @@ ResultCode FileSystem::CreateFullPath(Uid uid, Gid gid, const std::string& path,
void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path)
{
- const ResultCode delete_result = Delete(0, 0, directory_path);
- if (delete_result != ResultCode::Success && delete_result != ResultCode::NotFound)
+ const auto delete_ = [this](const std::string& directory_path_) {
+ const ResultCode delete_result = Delete(0, 0, directory_path_);
+ if (delete_result != ResultCode::Success && delete_result != ResultCode::NotFound)
+ {
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Delete for {}: {}", directory_path_,
+ delete_result);
+ return false;
+ }
+ return true;
+ };
+
+ if (directory_path != "/")
{
- ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Delete: {}", delete_result);
- p.SetVerifyMode();
- return;
+ if (!delete_(directory_path))
+ {
+ p.SetVerifyMode();
+ return;
+ }
+ }
+ else
+ {
+ // Calling Delete for the root would return Invalid. Let's delete all children instead.
+ auto children = ReadDirectory(0, 0, directory_path);
+ if (!children)
+ {
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call ReadDirectory for {}: {}", directory_path,
+ children.error());
+ p.SetVerifyMode();
+ return;
+ }
+
+ for (const std::string& child_name : children.value())
+ {
+ if (!delete_(directory_path + child_name))
+ {
+ p.SetVerifyMode();
+ return;
+ }
+ }
}
Metadata metadata{};
@@ -156,12 +189,29 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path)
p.Do(metadata.size);
p.Do(metadata.fst_index);
- const ResultCode create_directory_result = CreateDirectory(
- metadata.uid, metadata.gid, directory_path, metadata.attribute, metadata.modes);
- if (create_directory_result != ResultCode::Success)
+ // Again here, calling CreateDirectory for the root would return Invalid.
+ // The root always exists, so we can skip creating it.
+ if (directory_path != "/")
{
- ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateDirectory: {}",
- create_directory_result);
+ // UID 0 is used to avoid AccessDenied.
+ const ResultCode create_directory_result =
+ CreateDirectory(0, 0, directory_path, metadata.attribute, metadata.modes);
+ if (create_directory_result != ResultCode::Success)
+ {
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateDirectory for {}: {}", directory_path,
+ create_directory_result);
+ p.SetVerifyMode();
+ return;
+ }
+ }
+
+ // Change the UID and GID from 0 to the intended values.
+ const ResultCode set_metadata_result = SetMetadata(0, directory_path, metadata.uid, metadata.gid,
+ metadata.attribute, metadata.modes);
+ if (set_metadata_result != ResultCode::Success)
+ {
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call SetMetadata for {}: {}", directory_path,
+ set_metadata_result);
p.SetVerifyMode();
return;
}
@@ -182,22 +232,34 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path)
if (child_metadata.is_file)
{
+ // UID 0 is used to avoid AccessDenied.
const ResultCode create_file_result =
- CreateFile(child_metadata.uid, child_metadata.gid, child_path, child_metadata.attribute,
- child_metadata.modes);
+ CreateFile(0, 0, child_path, child_metadata.attribute, child_metadata.modes);
if (create_file_result != ResultCode::Success)
{
- ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateFile for {}: {}", child_name,
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateFile for {}: {}", child_path,
create_file_result);
p_.SetVerifyMode();
return;
}
+ // Change the UID and GID from 0 to the intended values.
+ const ResultCode set_metadata_result =
+ SetMetadata(0, child_path, child_metadata.uid, child_metadata.gid,
+ child_metadata.attribute, child_metadata.modes);
+ if (set_metadata_result != ResultCode::Success)
+ {
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call SetMetadata for {}: {}", child_path,
+ set_metadata_result);
+ p_.SetVerifyMode();
+ return;
+ }
+
std::array<u8, BUFFER_CHUNK_SIZE> buffer;
Result<FileHandle> handle = OpenFile(0, 0, child_path, Mode::Write);
if (!handle)
{
- ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call OpenFile for {}: {}", child_name,
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call OpenFile for {}: {}", child_path,
handle.error());
p_.SetVerifyMode();
return;
@@ -213,7 +275,7 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path)
Result<size_t> write_result = handle->Write(buffer.data(), bytes_to_write);
if (!write_result)
{
- ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Write for {}: {}", child_name,
+ ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Write for {}: {}", child_path,
write_result.error());
p_.SetVerifyMode();
return;
@@ -221,7 +283,7 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path)
if (*write_result != bytes_to_write)
{
ERROR_LOG_FMT(IOS_FS, "DoStateRead tried to write {} bytes to {} but wrote {} bytes",
- child_name, bytes_to_write, *write_result);
+ child_path, bytes_to_write, *write_result);
p_.SetVerifyMode();
return;
}
@@ -241,7 +303,8 @@ void FileSystem::DoStateWriteOrMeasure(PointerWrap& p, const std::string& direct
const Result<Metadata> metadata = GetMetadata(0, 0, directory_path);
if (!metadata)
{
- ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call GetMetadata: {}", metadata.error());
+ ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call GetMetadata for {}: {}",
+ directory_path, metadata.error());
p.SetVerifyMode();
return;
}
@@ -256,8 +319,8 @@ void FileSystem::DoStateWriteOrMeasure(PointerWrap& p, const std::string& direct
auto children = ReadDirectory(0, 0, directory_path);
if (!children)
{
- ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call ReadDirectory: {}",
- children.error());
+ ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call ReadDirectory for {}: {}",
+ directory_path, children.error());
p.SetVerifyMode();
return;
}