mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-11 16:49:27 +01:00
Merge pull request #14041 from unknownbrackets/ui-crc
UI: Add button to show CRC on feedback screen
This commit is contained in:
10 files changed
+103
-10
No files matched your search
@@ -50,11 +50,13 @@ BlockDevice *constructBlockDevice(FileLoader *fileLoader) {
|
||||
return new FileBlockDevice(fileLoader);
|
||||
}
|
||||
|
||||
u32 BlockDevice::CalculateCRC() {
|
||||
u32 BlockDevice::CalculateCRC(volatile bool *cancel) {
|
||||
u32 crc = crc32(0, Z_NULL, 0);
|
||||
|
||||
u8 block[2048];
|
||||
for (u32 i = 0; i < GetNumBlocks(); ++i) {
|
||||
if (cancel && *cancel)
|
||||
return 0;
|
||||
if (!ReadBlock(i, block, true)) {
|
||||
ERROR_LOG(FILESYS, "Failed to read block for CRC");
|
||||
return 0;
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
virtual u32 GetNumBlocks() = 0;
|
||||
virtual bool IsDisc() = 0;
|
||||
|
||||
u32 CalculateCRC();
|
||||
u32 CalculateCRC(volatile bool *cancel = nullptr);
|
||||
void NotifyReadError();
|
||||
|
||||
protected:
|
||||
|
||||
+29
-5
@@ -102,6 +102,8 @@ namespace Reporting
|
||||
static std::condition_variable crcCond;
|
||||
static std::string crcFilename;
|
||||
static std::map<std::string, u32> crcResults;
|
||||
static volatile bool crcPending = false;
|
||||
static volatile bool crcCancel = false;
|
||||
static std::thread crcThread;
|
||||
|
||||
static int CalculateCRCThread() {
|
||||
@@ -113,7 +115,7 @@ namespace Reporting
|
||||
|
||||
u32 crc = 0;
|
||||
if (blockDevice) {
|
||||
crc = blockDevice->CalculateCRC();
|
||||
crc = blockDevice->CalculateCRC(&crcCancel);
|
||||
}
|
||||
|
||||
delete blockDevice;
|
||||
@@ -121,6 +123,7 @@ namespace Reporting
|
||||
|
||||
std::lock_guard<std::mutex> guard(crcLock);
|
||||
crcResults[crcFilename] = crc;
|
||||
crcPending = false;
|
||||
crcCond.notify_one();
|
||||
|
||||
return 0;
|
||||
@@ -136,18 +139,18 @@ namespace Reporting
|
||||
return;
|
||||
}
|
||||
|
||||
if (crcFilename == gamePath) {
|
||||
if (crcPending) {
|
||||
// Already in process.
|
||||
return;
|
||||
}
|
||||
|
||||
crcFilename = gamePath;
|
||||
crcPending = true;
|
||||
crcCancel = false;
|
||||
crcThread = std::thread(CalculateCRCThread);
|
||||
}
|
||||
|
||||
bool HasCRC(const std::string &gamePath) {
|
||||
QueueCRC(gamePath);
|
||||
|
||||
std::lock_guard<std::mutex> guard(crcLock);
|
||||
return crcResults.find(gamePath) != crcResults.end();
|
||||
}
|
||||
@@ -167,6 +170,26 @@ namespace Reporting
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static uint32_t RetrieveCRCUnlessPowerSaving(const std::string &gamePath) {
|
||||
// It's okay to use it if we have it already.
|
||||
if (Core_GetPowerSaving() && !HasCRC(gamePath)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return RetrieveCRC(gamePath);
|
||||
}
|
||||
|
||||
static void PurgeCRC() {
|
||||
std::unique_lock<std::mutex> guard(crcLock);
|
||||
crcCancel = true;
|
||||
while (crcPending) {
|
||||
crcCond.wait(guard);
|
||||
}
|
||||
|
||||
if (crcThread.joinable())
|
||||
crcThread.join();
|
||||
}
|
||||
|
||||
// Returns the full host (e.g. report.ppsspp.org:80.)
|
||||
std::string ServerHost()
|
||||
{
|
||||
@@ -325,6 +348,7 @@ namespace Reporting
|
||||
compatThread.join();
|
||||
if (messageThread.joinable())
|
||||
messageThread.join();
|
||||
PurgeCRC();
|
||||
|
||||
// Just so it can be enabled in the menu again.
|
||||
Init();
|
||||
@@ -472,7 +496,7 @@ namespace Reporting
|
||||
postdata.Add("graphics", StringFromFormat("%d", payload.int1));
|
||||
postdata.Add("speed", StringFromFormat("%d", payload.int2));
|
||||
postdata.Add("gameplay", StringFromFormat("%d", payload.int3));
|
||||
postdata.Add("crc", StringFromFormat("%08x", Core_GetPowerSaving() ? 0 : RetrieveCRC(PSP_CoreParameter().fileToStart)));
|
||||
postdata.Add("crc", StringFromFormat("%08x", RetrieveCRCUnlessPowerSaving(PSP_CoreParameter().fileToStart)));
|
||||
postdata.Add("suggestions", payload.string1 != "perfect" && payload.string1 != "playable" ? "1" : "0");
|
||||
AddScreenshotData(postdata, payload.string2);
|
||||
payload.string1.clear();
|
||||
|
||||
+4
-1
@@ -87,7 +87,10 @@ namespace Reporting
|
||||
// Get the latest compatibility result. Only valid when GetStatus() is not BUSY.
|
||||
std::vector<std::string> CompatibilitySuggestions();
|
||||
|
||||
// Queues game for CRC hash if needed, and returns true if the hash is available.
|
||||
// Queues game for CRC hash if needed.
|
||||
void QueueCRC(const std::string &gamePath);
|
||||
|
||||
// Returns true if the hash is available, does not queue if not.
|
||||
bool HasCRC(const std::string &gamePath);
|
||||
|
||||
// Blocks until the CRC hash is available for game, and returns it.
|
||||
|
||||
@@ -1657,8 +1657,11 @@ void FramebufferManagerCommon::ApplyClearToMemory(int x1, int y1, int x2, int y2
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Memory::IsValidAddress(gstate.getFrameBufAddress())) {
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *addr = Memory::GetPointer(gstate.getFrameBufAddress());
|
||||
u8 *addr = Memory::GetPointerUnchecked(gstate.getFrameBufAddress());
|
||||
const int bpp = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
|
||||
|
||||
u32 clearBits = clearColor;
|
||||
@@ -1988,6 +1991,8 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
if (!Memory::IsValidAddress(fb_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, format);
|
||||
return true;
|
||||
@@ -2043,6 +2048,8 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
if (!Memory::IsValidAddress(z_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
return true;
|
||||
@@ -2078,6 +2085,8 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
if (!Memory::IsValidAddress(fb_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
// TODO: Actually get the stencil.
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888);
|
||||
|
||||
@@ -464,6 +464,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
if (!Memory::IsValidAddress(fb_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, fb_format);
|
||||
return true;
|
||||
|
||||
@@ -27,10 +27,12 @@
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
#include "UI/CwCheatScreen.h"
|
||||
#include "UI/EmuScreen.h"
|
||||
@@ -92,12 +94,16 @@ void GameScreen::CreateViews() {
|
||||
tvInstallDataSize_->SetVisibility(V_GONE);
|
||||
tvRegion_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvRegion_->SetShadow(true);
|
||||
tvCRC_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvCRC_->SetShadow(true);
|
||||
tvCRC_->SetVisibility(Reporting::HasCRC(gamePath_) ? V_VISIBLE : V_GONE);
|
||||
} else {
|
||||
tvTitle_ = nullptr;
|
||||
tvGameSize_ = nullptr;
|
||||
tvSaveDataSize_ = nullptr;
|
||||
tvInstallDataSize_ = nullptr;
|
||||
tvRegion_ = nullptr;
|
||||
tvCRC_ = nullptr;
|
||||
}
|
||||
|
||||
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
|
||||
@@ -234,6 +240,13 @@ void GameScreen::render() {
|
||||
}
|
||||
}
|
||||
|
||||
if (tvCRC_ && Reporting::HasCRC(gamePath_)) {
|
||||
auto rp = GetI18NCategory("Reporting");
|
||||
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_));
|
||||
tvCRC_->SetText(ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: [VALUE]"), "[VALUE]", crc));
|
||||
tvCRC_->SetVisibility(UI::V_VISIBLE);
|
||||
}
|
||||
|
||||
if (!info->id.empty()) {
|
||||
btnGameSettings_->SetVisibility(info->hasConfig ? UI::V_VISIBLE : UI::V_GONE);
|
||||
btnDeleteGameConfig_->SetVisibility(info->hasConfig ? UI::V_VISIBLE : UI::V_GONE);
|
||||
|
||||
@@ -67,6 +67,7 @@ private:
|
||||
UI::TextView *tvSaveDataSize_;
|
||||
UI::TextView *tvInstallDataSize_;
|
||||
UI::TextView *tvRegion_;
|
||||
UI::TextView *tvCRC_;
|
||||
|
||||
UI::Choice *btnGameSettings_;
|
||||
UI::Choice *btnCreateGameConfig_;
|
||||
|
||||
+35
-1
@@ -195,6 +195,7 @@ void ReportScreen::update() {
|
||||
}
|
||||
}
|
||||
UIDialogScreenWithGameBackground::update();
|
||||
UpdateCRCInfo();
|
||||
}
|
||||
|
||||
void ReportScreen::resized() {
|
||||
@@ -269,7 +270,7 @@ void ReportScreen::CreateViews() {
|
||||
}
|
||||
|
||||
#ifdef MOBILE_DEVICE
|
||||
if (!Core_GetPowerSaving()) {
|
||||
if (!Core_GetPowerSaving() && !Reporting::HasCRC(gamePath_)) {
|
||||
auto crcWarning = new TextView(rp->T("FeedbackIncludeCRC", "Note: Battery will be used to send a disc CRC"), FLAG_WRAP_TEXT, false, new LinearLayoutParams(Margins(12, 5, 0, 5)));
|
||||
crcWarning->SetShadow(true);
|
||||
crcWarning->SetEnabledPtr(&enableReporting_);
|
||||
@@ -277,6 +278,11 @@ void ReportScreen::CreateViews() {
|
||||
}
|
||||
#endif
|
||||
|
||||
crcInfo_ = new TextView("", FLAG_WRAP_TEXT, false, new LinearLayoutParams(Margins(12, 5, 0, 5)));
|
||||
crcInfo_->SetShadow(true);
|
||||
crcInfo_->SetVisibility(V_GONE);
|
||||
leftColumnItems->Add(crcInfo_);
|
||||
|
||||
if (tookScreenshot_ && !screenshotFilename_.empty()) {
|
||||
leftColumnItems->Add(new CheckBox(&includeScreenshot_, rp->T("FeedbackIncludeScreen", "Include a screenshot")))->SetEnabledPtr(&enableReporting_);
|
||||
screenshot_ = leftColumnItems->Add(new AsyncImageFileView(screenshotFilename_, IS_KEEP_ASPECT, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(12, 0))));
|
||||
@@ -300,6 +306,8 @@ void ReportScreen::CreateViews() {
|
||||
|
||||
rightColumnItems->SetSpacing(0.0f);
|
||||
rightColumnItems->Add(new Choice(rp->T("Open Browser")))->OnClick.Handle(this, &ReportScreen::HandleBrowser);
|
||||
showCrcButton_ = new Choice(rp->T("Show disc CRC"));
|
||||
rightColumnItems->Add(showCrcButton_)->OnClick.Handle(this, &ReportScreen::HandleShowCRC);
|
||||
submit_ = new Choice(rp->T("Submit Feedback"));
|
||||
rightColumnItems->Add(submit_)->OnClick.Handle(this, &ReportScreen::HandleSubmit);
|
||||
UpdateSubmit();
|
||||
@@ -314,12 +322,32 @@ void ReportScreen::CreateViews() {
|
||||
|
||||
leftColumn->Add(leftColumnItems);
|
||||
rightColumn->Add(rightColumnItems);
|
||||
|
||||
UpdateCRCInfo();
|
||||
}
|
||||
|
||||
void ReportScreen::UpdateSubmit() {
|
||||
submit_->SetEnabled(enableReporting_ && overall_ != ReportingOverallScore::INVALID && graphics_ >= 0 && speed_ >= 0 && gameplay_ >= 0);
|
||||
}
|
||||
|
||||
void ReportScreen::UpdateCRCInfo() {
|
||||
auto rp = GetI18NCategory("Reporting");
|
||||
std::string updated;
|
||||
|
||||
if (Reporting::HasCRC(gamePath_)) {
|
||||
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_));
|
||||
updated = ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: [VALUE]"), "[VALUE]", crc);
|
||||
} else if (showCRC_) {
|
||||
updated = rp->T("FeedbackCRCCalculating", "Disc CRC: Calculating...");
|
||||
}
|
||||
|
||||
if (!updated.empty()) {
|
||||
crcInfo_->SetText(updated);
|
||||
crcInfo_->SetVisibility(V_VISIBLE);
|
||||
showCrcButton_->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ReportScreen::UpdateOverallDescription() {
|
||||
auto rp = GetI18NCategory("Reporting");
|
||||
const char *desc;
|
||||
@@ -366,6 +394,12 @@ EventReturn ReportScreen::HandleBrowser(EventParams &e) {
|
||||
return EVENT_DONE;
|
||||
}
|
||||
|
||||
EventReturn ReportScreen::HandleShowCRC(EventParams &e) {
|
||||
Reporting::QueueCRC(gamePath_);
|
||||
showCRC_ = true;
|
||||
return EVENT_DONE;
|
||||
}
|
||||
|
||||
ReportFinishScreen::ReportFinishScreen(const std::string &gamePath, ReportingOverallScore score)
|
||||
: UIDialogScreenWithGameBackground(gamePath), score_(score) {
|
||||
}
|
||||
|
||||
@@ -42,17 +42,21 @@ protected:
|
||||
void resized() override;
|
||||
void CreateViews() override;
|
||||
void UpdateSubmit();
|
||||
void UpdateCRCInfo();
|
||||
void UpdateOverallDescription();
|
||||
|
||||
UI::EventReturn HandleChoice(UI::EventParams &e);
|
||||
UI::EventReturn HandleSubmit(UI::EventParams &e);
|
||||
UI::EventReturn HandleBrowser(UI::EventParams &e);
|
||||
UI::EventReturn HandleShowCRC(UI::EventParams &e);
|
||||
UI::EventReturn HandleReportingChange(UI::EventParams &e);
|
||||
|
||||
UI::Choice *submit_ = nullptr;
|
||||
UI::View *screenshot_ = nullptr;
|
||||
UI::TextView *reportingNotice_ = nullptr;
|
||||
UI::TextView *overallDescription_ = nullptr;
|
||||
UI::TextView *crcInfo_ = nullptr;
|
||||
UI::Choice *showCrcButton_ = nullptr;
|
||||
std::string screenshotFilename_;
|
||||
|
||||
ReportingOverallScore overall_ = ReportingOverallScore::INVALID;
|
||||
@@ -63,6 +67,7 @@ protected:
|
||||
bool ratingEnabled_;
|
||||
bool tookScreenshot_ = false;
|
||||
bool includeScreenshot_ = true;
|
||||
bool showCRC_ = false;
|
||||
};
|
||||
|
||||
class ReportFinishScreen : public UIDialogScreenWithGameBackground {
|
||||
|
||||
Reference in new issue
Block a user