summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2020-09-23 12:27:43 -0400
committerGitHub <noreply@github.com>2020-09-23 12:27:43 -0400
commit54e570a95f2cb54fdc7be29d04870746c69a8b9e (patch)
tree1db68bbdaa591d6cd8025493478fa5d0dadf7980 /Source/Core
parentf33767f19cca6ee95af9727f0050f27e2571f770 (diff)
parent5ba083215852a7f1afa2ac73316c2c0c500a6e7d (diff)
Merge pull request #8902 from JosJuice/android-convert
Android: Add disc image conversion
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/CMakeLists.txt5
-rw-r--r--Source/Core/Common/File.cpp23
-rw-r--r--Source/Core/Common/FileUtil.cpp18
-rw-r--r--Source/Core/DiscIO/Blob.h12
-rw-r--r--Source/Core/DiscIO/CompressedBlob.cpp12
-rw-r--r--Source/Core/DiscIO/FileBlob.cpp4
-rw-r--r--Source/Core/DiscIO/WIABlob.cpp19
-rw-r--r--Source/Core/DiscIO/WIABlob.h6
-rw-r--r--Source/Core/DolphinQt/ConvertDialog.cpp36
-rw-r--r--Source/Core/DolphinQt/GameList/GameList.cpp7
-rw-r--r--Source/Core/UICommon/GameFile.cpp5
-rw-r--r--Source/Core/UICommon/GameFile.h1
12 files changed, 91 insertions, 57 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index a805635af6..9592043954 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -164,6 +164,11 @@ elseif(WIN32)
if (_M_X86_64)
target_link_libraries(common PRIVATE opengl32.lib)
endif()
+elseif (ANDROID)
+ target_link_libraries(common
+ PRIVATE
+ androidcommon
+ )
endif()
if(ANDROID)
diff --git a/Source/Core/Common/File.cpp b/Source/Core/Common/File.cpp
index 9dfcdbd7d8..a724cbb723 100644
--- a/Source/Core/Common/File.cpp
+++ b/Source/Core/Common/File.cpp
@@ -15,6 +15,13 @@
#include <unistd.h>
#endif
+#ifdef ANDROID
+#include <algorithm>
+
+#include "Common/StringUtil.h"
+#include "jni/AndroidCommon/AndroidCommon.h"
+#endif
+
#include "Common/CommonTypes.h"
#include "Common/File.h"
#include "Common/FileUtil.h"
@@ -62,7 +69,21 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
#ifdef _WIN32
m_good = _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()) == 0;
#else
- m_file = std::fopen(filename.c_str(), openmode);
+#ifdef ANDROID
+ if (StringBeginsWith(filename, "content://"))
+ {
+ // The Java method which OpenAndroidContent passes the mode to does not support the b specifier.
+ // Since we're on POSIX, it's fine to just remove the b.
+ std::string mode_without_b(openmode);
+ mode_without_b.erase(std::remove(mode_without_b.begin(), mode_without_b.end(), 'b'),
+ mode_without_b.end());
+ m_file = fdopen(OpenAndroidContent(filename, mode_without_b), mode_without_b.c_str());
+ }
+ else
+#endif
+ {
+ m_file = std::fopen(filename.c_str(), openmode);
+ }
m_good = m_file != nullptr;
#endif
diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp
index b3efa6b868..3c524ed9d8 100644
--- a/Source/Core/Common/FileUtil.cpp
+++ b/Source/Core/Common/FileUtil.cpp
@@ -46,6 +46,11 @@
#include <sys/param.h>
#endif
+#ifdef ANDROID
+#include "Common/StringUtil.h"
+#include "jni/AndroidCommon/AndroidCommon.h"
+#endif
+
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
@@ -132,10 +137,19 @@ bool Delete(const std::string& filename)
{
INFO_LOG(COMMON, "Delete: file %s", filename.c_str());
+#ifdef ANDROID
+ if (StringBeginsWith(filename, "content://"))
+ {
+ const bool success = DeleteAndroidContent(filename);
+ if (!success)
+ WARN_LOG(COMMON, "Delete failed on %s", filename.c_str());
+ return success;
+ }
+#endif
+
const FileInfo file_info(filename);
- // Return true because we care about the file no
- // being there, not the actual delete.
+ // Return true because we care about the file not being there, not the actual delete.
if (!file_info.Exists())
{
WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());
diff --git a/Source/Core/DiscIO/Blob.h b/Source/Core/DiscIO/Blob.h
index 473aa9bfce..2166d8c677 100644
--- a/Source/Core/DiscIO/Blob.h
+++ b/Source/Core/DiscIO/Blob.h
@@ -15,6 +15,7 @@
// automatically do the right thing.
#include <array>
+#include <functional>
#include <memory>
#include <optional>
#include <string>
@@ -175,17 +176,16 @@ private:
// Factory function - examines the path to choose the right type of BlobReader, and returns one.
std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename);
-typedef bool (*CompressCB)(const std::string& text, float percent, void* arg);
+using CompressCB = std::function<bool(const std::string& text, float percent)>;
bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
- const std::string& outfile_path, u32 sub_type, int sector_size = 16384,
- CompressCB callback = nullptr, void* arg = nullptr);
+ const std::string& outfile_path, u32 sub_type, int sector_size,
+ CompressCB callback);
bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
- const std::string& outfile_path, CompressCB callback = nullptr,
- void* arg = nullptr);
+ const std::string& outfile_path, CompressCB callback);
bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path,
const std::string& outfile_path, bool rvz,
WIARVZCompressionType compression_type, int compression_level,
- int chunk_size, CompressCB callback = nullptr, void* arg = nullptr);
+ int chunk_size, CompressCB callback);
} // namespace DiscIO
diff --git a/Source/Core/DiscIO/CompressedBlob.cpp b/Source/Core/DiscIO/CompressedBlob.cpp
index fdfd65baf8..4486b54827 100644
--- a/Source/Core/DiscIO/CompressedBlob.cpp
+++ b/Source/Core/DiscIO/CompressedBlob.cpp
@@ -238,7 +238,7 @@ static ConversionResult<OutputParameters> Compress(CompressThreadState* state,
static ConversionResultCode Output(OutputParameters parameters, File::IOFile* outfile,
u64* position, std::vector<u64>* offsets, int progress_monitor,
- u32 num_blocks, CompressCB callback, void* arg)
+ u32 num_blocks, CompressCB callback)
{
u64 offset = *position;
if (!parameters.compressed)
@@ -261,7 +261,7 @@ static ConversionResultCode Output(OutputParameters parameters, File::IOFile* ou
const float completion = static_cast<float>(parameters.block_number) / num_blocks;
- if (!callback(text, completion, arg))
+ if (!callback(text, completion))
return ConversionResultCode::Canceled;
}
@@ -270,7 +270,7 @@ static ConversionResultCode Output(OutputParameters parameters, File::IOFile* ou
bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
const std::string& outfile_path, u32 sub_type, int block_size,
- CompressCB callback, void* arg)
+ CompressCB callback)
{
ASSERT(infile->IsDataSizeAccurate());
@@ -284,7 +284,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
return false;
}
- callback(Common::GetStringT("Files opened, ready to compress."), 0, arg);
+ callback(Common::GetStringT("Files opened, ready to compress."), 0);
CompressedBlobHeader header;
header.magic_cookie = GCZ_MAGIC;
@@ -317,7 +317,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
const auto output = [&](OutputParameters parameters) {
return Output(std::move(parameters), &outfile, &position, &offsets, progress_monitor,
- header.num_blocks, callback, arg);
+ header.num_blocks, callback);
};
MultithreadedCompressor<CompressThreadState, CompressParameters, OutputParameters> compressor(
@@ -364,7 +364,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
outfile.WriteArray(offsets.data(), header.num_blocks);
outfile.WriteArray(hashes.data(), header.num_blocks);
- callback(Common::GetStringT("Done compressing disc image."), 1.0f, arg);
+ callback(Common::GetStringT("Done compressing disc image."), 1.0f);
}
if (result == ConversionResultCode::ReadFailed)
diff --git a/Source/Core/DiscIO/FileBlob.cpp b/Source/Core/DiscIO/FileBlob.cpp
index ca0aa2cfd0..980b158dc9 100644
--- a/Source/Core/DiscIO/FileBlob.cpp
+++ b/Source/Core/DiscIO/FileBlob.cpp
@@ -42,7 +42,7 @@ bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
}
bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
- const std::string& outfile_path, CompressCB callback, void* arg)
+ const std::string& outfile_path, CompressCB callback)
{
ASSERT(infile->IsDataSizeAccurate());
@@ -78,7 +78,7 @@ bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
if (i % progress_monitor == 0)
{
const bool was_cancelled =
- !callback(Common::GetStringT("Unpacking"), (float)i / (float)num_buffers, arg);
+ !callback(Common::GetStringT("Unpacking"), (float)i / (float)num_buffers);
if (was_cancelled)
{
success = false;
diff --git a/Source/Core/DiscIO/WIABlob.cpp b/Source/Core/DiscIO/WIABlob.cpp
index 51a9c65694..4d4b104242 100644
--- a/Source/Core/DiscIO/WIABlob.cpp
+++ b/Source/Core/DiscIO/WIABlob.cpp
@@ -1686,9 +1686,9 @@ ConversionResultCode WIARVZFileReader<RVZ>::Output(std::vector<OutputParametersE
}
template <bool RVZ>
-ConversionResultCode
-WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read, u64 bytes_written,
- u32 total_groups, u64 iso_size, CompressCB callback, void* arg)
+ConversionResultCode WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read,
+ u64 bytes_written, u32 total_groups,
+ u64 iso_size, CompressCB callback)
{
int ratio = 0;
if (bytes_read != 0)
@@ -1700,8 +1700,8 @@ WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read, u64 by
const float completion = static_cast<float>(bytes_read) / iso_size;
- return callback(text, completion, arg) ? ConversionResultCode::Success :
- ConversionResultCode::Canceled;
+ return callback(text, completion) ? ConversionResultCode::Success :
+ ConversionResultCode::Canceled;
}
template <bool RVZ>
@@ -1729,8 +1729,7 @@ template <bool RVZ>
ConversionResultCode
WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volume,
File::IOFile* outfile, WIARVZCompressionType compression_type,
- int compression_level, int chunk_size, CompressCB callback,
- void* arg)
+ int compression_level, int chunk_size, CompressCB callback)
{
ASSERT(infile->IsDataSizeAccurate());
ASSERT(chunk_size > 0);
@@ -1832,7 +1831,7 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu
return result;
return RunCallback(parameters.group_index + parameters.entries.size(), parameters.bytes_read,
- bytes_written, total_groups, iso_size, callback, arg);
+ bytes_written, total_groups, iso_size, callback);
};
MultithreadedCompressor<CompressThreadState, CompressParameters, OutputParameters> mt_compressor(
@@ -2030,7 +2029,7 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu
bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path,
const std::string& outfile_path, bool rvz,
WIARVZCompressionType compression_type, int compression_level,
- int chunk_size, CompressCB callback, void* arg)
+ int chunk_size, CompressCB callback)
{
File::IOFile outfile(outfile_path, "wb");
if (!outfile)
@@ -2047,7 +2046,7 @@ bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path,
const auto convert = rvz ? RVZFileReader::Convert : WIAFileReader::Convert;
const ConversionResultCode result =
convert(infile, infile_volume.get(), &outfile, compression_type, compression_level,
- chunk_size, callback, arg);
+ chunk_size, callback);
if (result == ConversionResultCode::ReadFailed)
PanicAlertT("Failed to read from the input file \"%s\".", infile_path.c_str());
diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h
index c76af169f2..5b08dd227c 100644
--- a/Source/Core/DiscIO/WIABlob.h
+++ b/Source/Core/DiscIO/WIABlob.h
@@ -64,8 +64,7 @@ public:
static ConversionResultCode Convert(BlobReader* infile, const VolumeDisc* infile_volume,
File::IOFile* outfile, WIARVZCompressionType compression_type,
- int compression_level, int chunk_size, CompressCB callback,
- void* arg);
+ int compression_level, int chunk_size, CompressCB callback);
private:
using SHA1 = std::array<u8, 20>;
@@ -351,8 +350,7 @@ private:
std::mutex* reusable_groups_mutex, GroupEntry* group_entry,
u64* bytes_written);
static ConversionResultCode RunCallback(size_t groups_written, u64 bytes_read, u64 bytes_written,
- u32 total_groups, u64 iso_size, CompressCB callback,
- void* arg);
+ u32 total_groups, u64 iso_size, CompressCB callback);
bool m_valid;
WIARVZCompressionType m_compression_type;
diff --git a/Source/Core/DolphinQt/ConvertDialog.cpp b/Source/Core/DolphinQt/ConvertDialog.cpp
index 5a41ccea36..a14e728c40 100644
--- a/Source/Core/DolphinQt/ConvertDialog.cpp
+++ b/Source/Core/DolphinQt/ConvertDialog.cpp
@@ -32,17 +32,6 @@
#include "UICommon/GameFile.h"
#include "UICommon/UICommon.h"
-static bool CompressCB(const std::string& text, float percent, void* ptr)
-{
- if (ptr == nullptr)
- return false;
-
- auto* progress_dialog = static_cast<ParallelProgressDialog*>(ptr);
-
- progress_dialog->SetValue(percent * 100);
- return !progress_dialog->WasCanceled();
-}
-
ConvertDialog::ConvertDialog(QList<std::shared_ptr<const UICommon::GameFile>> files,
QWidget* parent)
: QDialog(parent), m_files(std::move(files))
@@ -463,15 +452,19 @@ void ConvertDialog::Convert()
}
else
{
+ const auto callback = [&progress_dialog](const std::string& text, float percent) {
+ progress_dialog.SetValue(percent * 100);
+ return !progress_dialog.WasCanceled();
+ };
+
std::future<bool> success;
switch (format)
{
case DiscIO::BlobType::PLAIN:
success = std::async(std::launch::async, [&] {
- const bool good =
- DiscIO::ConvertToPlain(blob_reader.get(), original_path, dst_path.toStdString(),
- &CompressCB, &progress_dialog);
+ const bool good = DiscIO::ConvertToPlain(blob_reader.get(), original_path,
+ dst_path.toStdString(), callback);
progress_dialog.Reset();
return good;
});
@@ -479,10 +472,9 @@ void ConvertDialog::Convert()
case DiscIO::BlobType::GCZ:
success = std::async(std::launch::async, [&] {
- const bool good =
- DiscIO::ConvertToGCZ(blob_reader.get(), original_path, dst_path.toStdString(),
- file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0,
- block_size, &CompressCB, &progress_dialog);
+ const bool good = DiscIO::ConvertToGCZ(
+ blob_reader.get(), original_path, dst_path.toStdString(),
+ file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0, block_size, callback);
progress_dialog.Reset();
return good;
});
@@ -491,10 +483,10 @@ void ConvertDialog::Convert()
case DiscIO::BlobType::WIA:
case DiscIO::BlobType::RVZ:
success = std::async(std::launch::async, [&] {
- const bool good = DiscIO::ConvertToWIAOrRVZ(
- blob_reader.get(), original_path, dst_path.toStdString(),
- format == DiscIO::BlobType::RVZ, compression, compression_level, block_size,
- &CompressCB, &progress_dialog);
+ const bool good =
+ DiscIO::ConvertToWIAOrRVZ(blob_reader.get(), original_path, dst_path.toStdString(),
+ format == DiscIO::BlobType::RVZ, compression,
+ compression_level, block_size, callback);
progress_dialog.Reset();
return good;
});
diff --git a/Source/Core/DolphinQt/GameList/GameList.cpp b/Source/Core/DolphinQt/GameList/GameList.cpp
index 956bc704dc..11cbadb2d3 100644
--- a/Source/Core/DolphinQt/GameList/GameList.cpp
+++ b/Source/Core/DolphinQt/GameList/GameList.cpp
@@ -267,9 +267,8 @@ void GameList::ShowContextMenu(const QPoint&)
{
const auto selected_games = GetSelectedGames();
- if (std::all_of(selected_games.begin(), selected_games.end(), [](const auto& game) {
- return DiscIO::IsDisc(game->GetPlatform()) && game->IsVolumeSizeAccurate();
- }))
+ if (std::all_of(selected_games.begin(), selected_games.end(),
+ [](const auto& game) { return game->ShouldAllowConversion(); }))
{
menu->addAction(tr("Convert Selected Files..."), this, &GameList::ConvertFile);
menu->addSeparator();
@@ -301,7 +300,7 @@ void GameList::ShowContextMenu(const QPoint&)
{
menu->addAction(tr("Set as &Default ISO"), this, &GameList::SetDefaultISO);
- if (game->IsVolumeSizeAccurate())
+ if (game->ShouldAllowConversion())
menu->addAction(tr("Convert File..."), this, &GameList::ConvertFile);
QAction* change_disc = menu->addAction(tr("Change &Disc"), this, &GameList::ChangeDisc);
diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp
index 30641d58e5..ff0fa84798 100644
--- a/Source/Core/UICommon/GameFile.cpp
+++ b/Source/Core/UICommon/GameFile.cpp
@@ -672,6 +672,11 @@ std::string GameFile::GetFileFormatName() const
}
}
+bool GameFile::ShouldAllowConversion() const
+{
+ return DiscIO::IsDisc(m_platform) && m_volume_size_is_accurate;
+}
+
const GameBanner& GameFile::GetBannerImage() const
{
return m_custom_banner.empty() ? m_volume_banner : m_custom_banner;
diff --git a/Source/Core/UICommon/GameFile.h b/Source/Core/UICommon/GameFile.h
index 9366b33f2e..3aa693507f 100644
--- a/Source/Core/UICommon/GameFile.h
+++ b/Source/Core/UICommon/GameFile.h
@@ -101,6 +101,7 @@ public:
const std::string& GetCompressionMethod() const { return m_compression_method; }
bool ShouldShowFileFormatDetails() const;
std::string GetFileFormatName() const;
+ bool ShouldAllowConversion() const;
const std::string& GetApploaderDate() const { return m_apploader_date; }
u64 GetFileSize() const { return m_file_size; }
u64 GetVolumeSize() const { return m_volume_size; }