Merge pull request #8891 from JosJuice/file-details
Show file format details in game properties
This commit is contained in:
commit
26ed3b318c
|
@ -449,6 +449,8 @@ public final class NativeLibrary
|
||||||
|
|
||||||
public static native boolean InstallWAD(String file);
|
public static native boolean InstallWAD(String file);
|
||||||
|
|
||||||
|
public static native String FormatSize(long bytes, int decimals);
|
||||||
|
|
||||||
private static boolean alertResult = false;
|
private static boolean alertResult = false;
|
||||||
|
|
||||||
public static boolean displayAlertMsg(final String caption, final String text,
|
public static boolean displayAlertMsg(final String caption, final String text,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.widget.TextView;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||||
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
||||||
|
@ -50,8 +51,17 @@ public final class GameDetailsDialog extends DialogFragment
|
||||||
TextView textGameId = contents.findViewById(R.id.text_game_id);
|
TextView textGameId = contents.findViewById(R.id.text_game_id);
|
||||||
TextView textRevision = contents.findViewById(R.id.text_revision);
|
TextView textRevision = contents.findViewById(R.id.text_revision);
|
||||||
|
|
||||||
|
TextView textFileFormat = contents.findViewById(R.id.text_file_format);
|
||||||
|
TextView textCompression = contents.findViewById(R.id.text_compression);
|
||||||
|
TextView textBlockSize = contents.findViewById(R.id.text_block_size);
|
||||||
|
|
||||||
|
TextView labelFileFormat = contents.findViewById(R.id.label_file_format);
|
||||||
|
TextView labelCompression = contents.findViewById(R.id.label_compression);
|
||||||
|
TextView labelBlockSize = contents.findViewById(R.id.label_block_size);
|
||||||
|
|
||||||
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
|
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
|
||||||
String description = gameFile.getDescription();
|
String description = gameFile.getDescription();
|
||||||
|
String fileSize = NativeLibrary.FormatSize(gameFile.getFileSize(), 2);
|
||||||
|
|
||||||
textTitle.setText(gameFile.getTitle());
|
textTitle.setText(gameFile.getTitle());
|
||||||
textDescription.setText(gameFile.getDescription());
|
textDescription.setText(gameFile.getDescription());
|
||||||
|
@ -59,11 +69,49 @@ public final class GameDetailsDialog extends DialogFragment
|
||||||
{
|
{
|
||||||
textDescription.setVisibility(View.GONE);
|
textDescription.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
textCountry.setText(country);
|
textCountry.setText(country);
|
||||||
textCompany.setText(gameFile.getCompany());
|
textCompany.setText(gameFile.getCompany());
|
||||||
textGameId.setText(gameFile.getGameId());
|
textGameId.setText(gameFile.getGameId());
|
||||||
textRevision.setText(Integer.toString(gameFile.getRevision()));
|
textRevision.setText(Integer.toString(gameFile.getRevision()));
|
||||||
|
|
||||||
|
if (!gameFile.shouldShowFileFormatDetails())
|
||||||
|
{
|
||||||
|
labelFileFormat.setText(R.string.game_details_file_size);
|
||||||
|
textFileFormat.setText(fileSize);
|
||||||
|
|
||||||
|
labelCompression.setVisibility(View.GONE);
|
||||||
|
textCompression.setVisibility(View.GONE);
|
||||||
|
labelBlockSize.setVisibility(View.GONE);
|
||||||
|
textBlockSize.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long blockSize = gameFile.getBlockSize();
|
||||||
|
String compression = gameFile.getCompressionMethod();
|
||||||
|
|
||||||
|
textFileFormat.setText(String.format("%1$s (%2$s)", gameFile.getBlobTypeString(), fileSize));
|
||||||
|
|
||||||
|
if (compression.isEmpty())
|
||||||
|
{
|
||||||
|
textCompression.setText(R.string.game_details_no_compression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textCompression.setText(gameFile.getCompressionMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockSize > 0)
|
||||||
|
{
|
||||||
|
textBlockSize.setText(NativeLibrary.FormatSize(blockSize, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
labelBlockSize.setVisibility(View.GONE);
|
||||||
|
textBlockSize.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PicassoUtils.loadGameBanner(banner, gameFile);
|
PicassoUtils.loadGameBanner(banner, gameFile);
|
||||||
|
|
||||||
builder.setView(contents);
|
builder.setView(contents);
|
||||||
|
|
|
@ -38,6 +38,16 @@ public class GameFile
|
||||||
|
|
||||||
public native int getRevision();
|
public native int getRevision();
|
||||||
|
|
||||||
|
public native String getBlobTypeString();
|
||||||
|
|
||||||
|
public native long getBlockSize();
|
||||||
|
|
||||||
|
public native String getCompressionMethod();
|
||||||
|
|
||||||
|
public native boolean shouldShowFileFormatDetails();
|
||||||
|
|
||||||
|
public native long getFileSize();
|
||||||
|
|
||||||
public native int[] getBanner();
|
public native int[] getBanner();
|
||||||
|
|
||||||
public native int getBannerWidth();
|
public native int getBannerWidth();
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@id/text_description" />
|
app:layout_constraintTop_toBottomOf="@id/text_description" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider_1"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="#1F000000"
|
android:background="#1F000000"
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:text="@string/game_details_country"
|
android:text="@string/game_details_country"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/divider" />
|
app:layout_constraintTop_toBottomOf="@id/divider_1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/label_company"
|
android:id="@+id/label_company"
|
||||||
|
@ -89,15 +89,14 @@
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:text="@string/game_details_revision"
|
android:text="@string/game_details_revision"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/label_game_id"
|
app:layout_constraintTop_toBottomOf="@id/label_game_id" />
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/label_barrier"
|
android:id="@+id/label_barrier"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:barrierDirection="end"
|
app:barrierDirection="end"
|
||||||
app:constraint_referenced_ids="label_country,label_company,label_game_id,label_revision" />
|
app:constraint_referenced_ids="label_country,label_company,label_game_id,label_revision,label_file_format,label_compression,label_block_size" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_country"
|
android:id="@+id/text_country"
|
||||||
|
@ -143,4 +142,77 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBaseline_toBaselineOf="@id/label_revision" />
|
app:layout_constraintBaseline_toBaselineOf="@id/label_revision" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider_2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#1F000000"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/label_revision" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_file_format"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/game_details_file_format"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/divider_2" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_compression"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/game_details_compression"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/label_file_format" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_block_size"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/game_details_block_size"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/label_compression" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_file_format"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:gravity="end"
|
||||||
|
tools:text="ISO (4.38 GiB)"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/label_barrier"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@id/label_file_format" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_compression"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:gravity="end"
|
||||||
|
tools:text="No Compression"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/label_barrier"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@id/label_compression" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_block_size"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:gravity="end"
|
||||||
|
tools:text="0 B"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/label_barrier"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBaseline_toBaselineOf="@id/label_block_size" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -317,6 +317,11 @@
|
||||||
<string name="game_details_company">Company</string>
|
<string name="game_details_company">Company</string>
|
||||||
<string name="game_details_game_id">Game ID</string>
|
<string name="game_details_game_id">Game ID</string>
|
||||||
<string name="game_details_revision">Revision</string>
|
<string name="game_details_revision">Revision</string>
|
||||||
|
<string name="game_details_file_size">File Size</string>
|
||||||
|
<string name="game_details_file_format">File Format</string>
|
||||||
|
<string name="game_details_compression">Compression</string>
|
||||||
|
<string name="game_details_block_size">Block Size</string>
|
||||||
|
<string name="game_details_no_compression">No Compression</string>
|
||||||
|
|
||||||
<!-- Emulation Menu -->
|
<!-- Emulation Menu -->
|
||||||
<string name="emulation_screenshot">Take Screenshot</string>
|
<string name="emulation_screenshot">Take Screenshot</string>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
#include "UICommon/GameFile.h"
|
#include "UICommon/GameFile.h"
|
||||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||||
|
@ -62,6 +63,16 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getDiscNumb
|
||||||
jobject obj);
|
jobject obj);
|
||||||
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getRevision(JNIEnv* env,
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getRevision(JNIEnv* env,
|
||||||
jobject obj);
|
jobject obj);
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobTypeString(JNIEnv* env, jobject obj);
|
||||||
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBlockSize(JNIEnv* env,
|
||||||
|
jobject obj);
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_getCompressionMethod(JNIEnv* env, jobject obj);
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldShowFileFormatDetails(JNIEnv* env, jobject obj);
|
||||||
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getFileSize(JNIEnv* env,
|
||||||
|
jobject obj);
|
||||||
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
|
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
|
||||||
jobject obj);
|
jobject obj);
|
||||||
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBannerWidth(JNIEnv* env,
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBannerWidth(JNIEnv* env,
|
||||||
|
@ -143,6 +154,36 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getRevision
|
||||||
return GetRef(env, obj)->GetRevision();
|
return GetRef(env, obj)->GetRevision();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobTypeString(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return ToJString(env, DiscIO::GetName(GetRef(env, obj)->GetBlobType(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBlockSize(JNIEnv* env,
|
||||||
|
jobject obj)
|
||||||
|
{
|
||||||
|
return GetRef(env, obj)->GetBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_getCompressionMethod(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return ToJString(env, GetRef(env, obj)->GetCompressionMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldShowFileFormatDetails(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return GetRef(env, obj)->ShouldShowFileFormatDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getFileSize(JNIEnv* env,
|
||||||
|
jobject obj)
|
||||||
|
{
|
||||||
|
return GetRef(env, obj)->GetFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
|
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
|
||||||
jobject obj)
|
jobject obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -742,6 +742,14 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_InstallW
|
||||||
return static_cast<jboolean>(WiiUtils::InstallWAD(path));
|
return static_cast<jboolean>(WiiUtils::InstallWAD(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_FormatSize(JNIEnv* env,
|
||||||
|
jobject obj,
|
||||||
|
jlong bytes,
|
||||||
|
jint decimals)
|
||||||
|
{
|
||||||
|
return ToJString(env, UICommon::FormatSize(bytes, decimals));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Common/CDUtils.h"
|
#include "Common/CDUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/File.h"
|
#include "Common/File.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/CISOBlob.h"
|
#include "DiscIO/CISOBlob.h"
|
||||||
|
@ -25,6 +26,35 @@
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
|
std::string GetName(BlobType blob_type, bool translate)
|
||||||
|
{
|
||||||
|
const auto translate_str = [translate](const std::string& str) {
|
||||||
|
return translate ? Common::GetStringT(str.c_str()) : str;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (blob_type)
|
||||||
|
{
|
||||||
|
case BlobType::PLAIN:
|
||||||
|
return "ISO";
|
||||||
|
case BlobType::DIRECTORY:
|
||||||
|
return translate_str("Directory");
|
||||||
|
case BlobType::GCZ:
|
||||||
|
return "GCZ";
|
||||||
|
case BlobType::CISO:
|
||||||
|
return "CISO";
|
||||||
|
case BlobType::WBFS:
|
||||||
|
return "WBFS";
|
||||||
|
case BlobType::TGC:
|
||||||
|
return "TGC";
|
||||||
|
case BlobType::WIA:
|
||||||
|
return "WIA";
|
||||||
|
case BlobType::RVZ:
|
||||||
|
return "RVZ";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SectorReader::SetSectorSize(int blocksize)
|
void SectorReader::SetSectorSize(int blocksize)
|
||||||
{
|
{
|
||||||
m_block_size = std::max(blocksize, 0);
|
m_block_size = std::max(blocksize, 0);
|
||||||
|
|
|
@ -41,6 +41,8 @@ enum class BlobType
|
||||||
RVZ,
|
RVZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string GetName(BlobType blob_type, bool translate);
|
||||||
|
|
||||||
class BlobReader
|
class BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -55,6 +57,7 @@ public:
|
||||||
// Returns 0 if the format does not use blocks
|
// Returns 0 if the format does not use blocks
|
||||||
virtual u64 GetBlockSize() const = 0;
|
virtual u64 GetBlockSize() const = 0;
|
||||||
virtual bool HasFastRandomAccessInBlock() const = 0;
|
virtual bool HasFastRandomAccessInBlock() const = 0;
|
||||||
|
virtual std::string GetCompressionMethod() const = 0;
|
||||||
|
|
||||||
// NOT thread-safe - can't call this from multiple threads.
|
// NOT thread-safe - can't call this from multiple threads.
|
||||||
virtual bool Read(u64 offset, u64 size, u8* out_ptr) = 0;
|
virtual bool Read(u64 offset, u64 size, u8* out_ptr) = 0;
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return m_block_size; }
|
u64 GetBlockSize() const override { return m_block_size; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return true; }
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return m_header.block_size; }
|
u64 GetBlockSize() const override { return m_header.block_size; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return false; }
|
bool HasFastRandomAccessInBlock() const override { return false; }
|
||||||
|
std::string GetCompressionMethod() const override { return "Deflate"; }
|
||||||
|
|
||||||
u64 GetBlockCompressedSize(u64 block_num) const;
|
u64 GetBlockCompressedSize(u64 block_num) const;
|
||||||
bool GetBlock(u64 block_num, u8* out_ptr) override;
|
bool GetBlock(u64 block_num, u8* out_ptr) override;
|
||||||
|
|
|
@ -168,6 +168,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return 0; }
|
u64 GetBlockSize() const override { return 0; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return true; }
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PartitionWithType
|
struct PartitionWithType
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return ECC_BLOCK_SIZE; }
|
u64 GetBlockSize() const override { return ECC_BLOCK_SIZE; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return false; }
|
bool HasFastRandomAccessInBlock() const override { return false; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DriveReader(const std::string& drive);
|
DriveReader(const std::string& drive);
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return 0; }
|
u64 GetBlockSize() const override { return 0; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return true; }
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ public:
|
||||||
{
|
{
|
||||||
return m_blob_reader->HasFastRandomAccessInBlock();
|
return m_blob_reader->HasFastRandomAccessInBlock();
|
||||||
}
|
}
|
||||||
|
std::string GetCompressionMethod() const override
|
||||||
|
{
|
||||||
|
return m_blob_reader->GetCompressionMethod();
|
||||||
|
}
|
||||||
|
|
||||||
bool Read(u64 offset, u64 size, u8* out_ptr) override;
|
bool Read(u64 offset, u64 size, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return 0; }
|
u64 GetBlockSize() const override { return 0; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return true; }
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,11 @@ bool VolumeFileBlobReader::HasFastRandomAccessInBlock() const
|
||||||
return m_volume.GetBlobReader().HasFastRandomAccessInBlock();
|
return m_volume.GetBlobReader().HasFastRandomAccessInBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string VolumeFileBlobReader::GetCompressionMethod() const
|
||||||
|
{
|
||||||
|
return m_volume.GetBlobReader().GetCompressionMethod();
|
||||||
|
}
|
||||||
|
|
||||||
bool VolumeFileBlobReader::Read(u64 offset, u64 length, u8* out_ptr)
|
bool VolumeFileBlobReader::Read(u64 offset, u64 length, u8* out_ptr)
|
||||||
{
|
{
|
||||||
if (offset + length > m_file_info->GetSize())
|
if (offset + length > m_file_info->GetSize())
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override;
|
u64 GetBlockSize() const override;
|
||||||
bool HasFastRandomAccessInBlock() const override;
|
bool HasFastRandomAccessInBlock() const override;
|
||||||
|
std::string GetCompressionMethod() const override;
|
||||||
|
|
||||||
bool Read(u64 offset, u64 length, u8* out_ptr) override;
|
bool Read(u64 offset, u64 length, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,26 @@ BlobType WIARVZFileReader<RVZ>::GetBlobType() const
|
||||||
return RVZ ? BlobType::RVZ : BlobType::WIA;
|
return RVZ ? BlobType::RVZ : BlobType::WIA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool RVZ>
|
||||||
|
std::string WIARVZFileReader<RVZ>::GetCompressionMethod() const
|
||||||
|
{
|
||||||
|
switch (m_compression_type)
|
||||||
|
{
|
||||||
|
case WIARVZCompressionType::Purge:
|
||||||
|
return "Purge";
|
||||||
|
case WIARVZCompressionType::Bzip2:
|
||||||
|
return "bzip2";
|
||||||
|
case WIARVZCompressionType::LZMA:
|
||||||
|
return "LZMA";
|
||||||
|
case WIARVZCompressionType::LZMA2:
|
||||||
|
return "LZMA2";
|
||||||
|
case WIARVZCompressionType::Zstd:
|
||||||
|
return "Zstandard";
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
bool WIARVZFileReader<RVZ>::Read(u64 offset, u64 size, u8* out_ptr)
|
bool WIARVZFileReader<RVZ>::Read(u64 offset, u64 size, u8* out_ptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return Common::swap32(m_header_2.chunk_size); }
|
u64 GetBlockSize() const override { return Common::swap32(m_header_2.chunk_size); }
|
||||||
bool HasFastRandomAccessInBlock() const override { return false; }
|
bool HasFastRandomAccessInBlock() const override { return false; }
|
||||||
|
std::string GetCompressionMethod() const override;
|
||||||
|
|
||||||
bool Read(u64 offset, u64 size, u8* out_ptr) override;
|
bool Read(u64 offset, u64 size, u8* out_ptr) override;
|
||||||
bool SupportsReadWiiDecrypted() const override;
|
bool SupportsReadWiiDecrypted() const override;
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
|
|
||||||
u64 GetBlockSize() const override { return m_wbfs_sector_size; }
|
u64 GetBlockSize() const override { return m_wbfs_sector_size; }
|
||||||
bool HasFastRandomAccessInBlock() const override { return true; }
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
|
||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ InfoWidget::InfoWidget(const UICommon::GameFile& game) : m_game(game)
|
||||||
{
|
{
|
||||||
QVBoxLayout* layout = new QVBoxLayout();
|
QVBoxLayout* layout = new QVBoxLayout();
|
||||||
|
|
||||||
layout->addWidget(CreateISODetails());
|
layout->addWidget(CreateFileDetails());
|
||||||
|
layout->addWidget(CreateGameDetails());
|
||||||
|
|
||||||
if (!game.GetLanguages().empty())
|
if (!game.GetLanguages().empty())
|
||||||
layout->addWidget(CreateBannerDetails());
|
layout->addWidget(CreateBannerDetails());
|
||||||
|
@ -35,19 +36,54 @@ InfoWidget::InfoWidget(const UICommon::GameFile& game) : m_game(game)
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
QGroupBox* InfoWidget::CreateISODetails()
|
QGroupBox* InfoWidget::CreateFileDetails()
|
||||||
{
|
{
|
||||||
const QString UNKNOWN_NAME = tr("Unknown");
|
QGroupBox* group = new QGroupBox(tr("File Details"));
|
||||||
|
|
||||||
QGroupBox* group = new QGroupBox(tr("ISO Details"));
|
|
||||||
QFormLayout* layout = new QFormLayout;
|
QFormLayout* layout = new QFormLayout;
|
||||||
|
|
||||||
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||||
|
|
||||||
QLineEdit* file_path = CreateValueDisplay(
|
QString path = QDir::toNativeSeparators(QString::fromStdString(m_game.GetFilePath()));
|
||||||
|
layout->addRow(tr("Path:"), CreateValueDisplay(path));
|
||||||
|
|
||||||
|
const std::string file_size = UICommon::FormatSize(m_game.GetFileSize());
|
||||||
|
|
||||||
|
if (!m_game.ShouldShowFileFormatDetails())
|
||||||
|
{
|
||||||
|
layout->addRow(tr("File Size:"), CreateValueDisplay(file_size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const QString file_format =
|
||||||
QStringLiteral("%1 (%2)")
|
QStringLiteral("%1 (%2)")
|
||||||
.arg(QDir::toNativeSeparators(QString::fromStdString(m_game.GetFilePath())))
|
.arg(QString::fromStdString(DiscIO::GetName(m_game.GetBlobType(), true)))
|
||||||
.arg(QString::fromStdString(UICommon::FormatSize(m_game.GetFileSize()))));
|
.arg(QString::fromStdString(file_size));
|
||||||
|
layout->addRow(tr("File Format:"), CreateValueDisplay(file_format));
|
||||||
|
|
||||||
|
QString compression = QString::fromStdString(m_game.GetCompressionMethod());
|
||||||
|
if (compression.isEmpty())
|
||||||
|
compression = tr("No Compression");
|
||||||
|
layout->addRow(tr("Compression:"), CreateValueDisplay(compression));
|
||||||
|
|
||||||
|
if (m_game.GetBlockSize() > 0)
|
||||||
|
{
|
||||||
|
const std::string block_size = UICommon::FormatSize(m_game.GetBlockSize(), 0);
|
||||||
|
layout->addRow(tr("Block Size:"), CreateValueDisplay(block_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group->setLayout(layout);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox* InfoWidget::CreateGameDetails()
|
||||||
|
{
|
||||||
|
const QString UNKNOWN_NAME = tr("Unknown");
|
||||||
|
|
||||||
|
QGroupBox* group = new QGroupBox(tr("Game Details"));
|
||||||
|
QFormLayout* layout = new QFormLayout;
|
||||||
|
|
||||||
|
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||||
|
|
||||||
const QString game_name = QString::fromStdString(m_game.GetInternalName());
|
const QString game_name = QString::fromStdString(m_game.GetInternalName());
|
||||||
|
|
||||||
|
@ -79,7 +115,6 @@ QGroupBox* InfoWidget::CreateISODetails()
|
||||||
m_game.GetMakerID() + ")");
|
m_game.GetMakerID() + ")");
|
||||||
|
|
||||||
layout->addRow(tr("Name:"), internal_name);
|
layout->addRow(tr("Name:"), internal_name);
|
||||||
layout->addRow(tr("File:"), file_path);
|
|
||||||
layout->addRow(tr("Game ID:"), game_id);
|
layout->addRow(tr("Game ID:"), game_id);
|
||||||
layout->addRow(tr("Country:"), country);
|
layout->addRow(tr("Country:"), country);
|
||||||
layout->addRow(tr("Maker:"), maker);
|
layout->addRow(tr("Maker:"), maker);
|
||||||
|
|
|
@ -26,8 +26,9 @@ private:
|
||||||
void ChangeLanguage();
|
void ChangeLanguage();
|
||||||
void SaveBanner();
|
void SaveBanner();
|
||||||
|
|
||||||
|
QGroupBox* CreateFileDetails();
|
||||||
|
QGroupBox* CreateGameDetails();
|
||||||
QGroupBox* CreateBannerDetails();
|
QGroupBox* CreateBannerDetails();
|
||||||
QGroupBox* CreateISODetails();
|
|
||||||
QLineEdit* CreateValueDisplay(const QString& value);
|
QLineEdit* CreateValueDisplay(const QString& value);
|
||||||
QLineEdit* CreateValueDisplay(const std::string& value = "");
|
QLineEdit* CreateValueDisplay(const std::string& value = "");
|
||||||
void CreateLanguageSelector();
|
void CreateLanguageSelector();
|
||||||
|
|
|
@ -115,6 +115,8 @@ GameFile::GameFile(std::string path) : m_file_path(std::move(path))
|
||||||
m_region = volume->GetRegion();
|
m_region = volume->GetRegion();
|
||||||
m_country = volume->GetCountry();
|
m_country = volume->GetCountry();
|
||||||
m_blob_type = volume->GetBlobType();
|
m_blob_type = volume->GetBlobType();
|
||||||
|
m_block_size = volume->GetBlobReader().GetBlockSize();
|
||||||
|
m_compression_method = volume->GetBlobReader().GetCompressionMethod();
|
||||||
m_file_size = volume->GetRawSize();
|
m_file_size = volume->GetRawSize();
|
||||||
m_volume_size = volume->GetSize();
|
m_volume_size = volume->GetSize();
|
||||||
m_volume_size_is_accurate = volume->IsSizeAccurate();
|
m_volume_size_is_accurate = volume->IsSizeAccurate();
|
||||||
|
@ -320,6 +322,8 @@ void GameFile::DoState(PointerWrap& p)
|
||||||
p.Do(m_country);
|
p.Do(m_country);
|
||||||
p.Do(m_platform);
|
p.Do(m_platform);
|
||||||
p.Do(m_blob_type);
|
p.Do(m_blob_type);
|
||||||
|
p.Do(m_block_size);
|
||||||
|
p.Do(m_compression_method);
|
||||||
p.Do(m_revision);
|
p.Do(m_revision);
|
||||||
p.Do(m_disc_number);
|
p.Do(m_disc_number);
|
||||||
p.Do(m_apploader_date);
|
p.Do(m_apploader_date);
|
||||||
|
@ -566,6 +570,29 @@ std::string GameFile::GetWiiFSPath() const
|
||||||
return Common::GetTitleDataPath(m_title_id, Common::FROM_CONFIGURED_ROOT);
|
return Common::GetTitleDataPath(m_title_id, Common::FROM_CONFIGURED_ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameFile::ShouldShowFileFormatDetails() const
|
||||||
|
{
|
||||||
|
switch (m_blob_type)
|
||||||
|
{
|
||||||
|
case DiscIO::BlobType::PLAIN:
|
||||||
|
break;
|
||||||
|
case DiscIO::BlobType::DRIVE:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_platform)
|
||||||
|
{
|
||||||
|
case DiscIO::Platform::WiiWAD:
|
||||||
|
return false;
|
||||||
|
case DiscIO::Platform::ELFOrDOL:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const GameBanner& GameFile::GetBannerImage() const
|
const GameBanner& GameFile::GetBannerImage() const
|
||||||
{
|
{
|
||||||
return m_custom_banner.empty() ? m_volume_banner : m_custom_banner;
|
return m_custom_banner.empty() ? m_volume_banner : m_custom_banner;
|
||||||
|
|
|
@ -86,6 +86,9 @@ public:
|
||||||
DiscIO::Country GetCountry() const { return m_country; }
|
DiscIO::Country GetCountry() const { return m_country; }
|
||||||
DiscIO::Platform GetPlatform() const { return m_platform; }
|
DiscIO::Platform GetPlatform() const { return m_platform; }
|
||||||
DiscIO::BlobType GetBlobType() const { return m_blob_type; }
|
DiscIO::BlobType GetBlobType() const { return m_blob_type; }
|
||||||
|
u64 GetBlockSize() const { return m_block_size; }
|
||||||
|
const std::string& GetCompressionMethod() const { return m_compression_method; }
|
||||||
|
bool ShouldShowFileFormatDetails() const;
|
||||||
const std::string& GetApploaderDate() const { return m_apploader_date; }
|
const std::string& GetApploaderDate() const { return m_apploader_date; }
|
||||||
u64 GetFileSize() const { return m_file_size; }
|
u64 GetFileSize() const { return m_file_size; }
|
||||||
u64 GetVolumeSize() const { return m_volume_size; }
|
u64 GetVolumeSize() const { return m_volume_size; }
|
||||||
|
@ -144,6 +147,8 @@ private:
|
||||||
DiscIO::Country m_country{DiscIO::Country::Unknown};
|
DiscIO::Country m_country{DiscIO::Country::Unknown};
|
||||||
DiscIO::Platform m_platform{};
|
DiscIO::Platform m_platform{};
|
||||||
DiscIO::BlobType m_blob_type{};
|
DiscIO::BlobType m_blob_type{};
|
||||||
|
u64 m_block_size{};
|
||||||
|
std::string m_compression_method{};
|
||||||
u16 m_revision{};
|
u16 m_revision{};
|
||||||
u8 m_disc_number{};
|
u8 m_disc_number{};
|
||||||
std::string m_apploader_date;
|
std::string m_apploader_date;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
namespace UICommon
|
namespace UICommon
|
||||||
{
|
{
|
||||||
static constexpr u32 CACHE_REVISION = 17; // Last changed in PR 8738
|
static constexpr u32 CACHE_REVISION = 18; // Last changed in PR 8891
|
||||||
|
|
||||||
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
|
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
|
||||||
bool recursive_scan)
|
bool recursive_scan)
|
||||||
|
|
Loading…
Reference in New Issue