Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Add button to show CRC on feedback screen #14041

Merged
merged 5 commits into from
Feb 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Core/FileSystems/BlockDevices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/BlockDevices.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class BlockDevice {
virtual u32 GetNumBlocks() = 0;
virtual bool IsDisc() = 0;

u32 CalculateCRC();
u32 CalculateCRC(volatile bool *cancel = nullptr);
void NotifyReadError();

protected:
Expand Down
34 changes: 29 additions & 5 deletions Core/Reporting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -113,14 +115,15 @@ namespace Reporting

u32 crc = 0;
if (blockDevice) {
crc = blockDevice->CalculateCRC();
crc = blockDevice->CalculateCRC(&crcCancel);
}

delete blockDevice;
delete fileLoader;

std::lock_guard<std::mutex> guard(crcLock);
crcResults[crcFilename] = crc;
crcPending = false;
crcCond.notify_one();

return 0;
Expand All @@ -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();
}
Expand All @@ -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()
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 4 additions & 1 deletion Core/Reporting.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 10 additions & 1 deletion GPU/Common/FramebufferManagerCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions GPU/Directx9/FramebufferManagerDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions UI/GameScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions UI/GameScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class GameScreen : public UIDialogScreenWithGameBackground {
UI::TextView *tvSaveDataSize_;
UI::TextView *tvInstallDataSize_;
UI::TextView *tvRegion_;
UI::TextView *tvCRC_;

UI::Choice *btnGameSettings_;
UI::Choice *btnCreateGameConfig_;
Expand Down
36 changes: 35 additions & 1 deletion UI/ReportScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ void ReportScreen::update() {
}
}
UIDialogScreenWithGameBackground::update();
UpdateCRCInfo();
}

void ReportScreen::resized() {
Expand Down Expand Up @@ -269,14 +270,19 @@ 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_);
leftColumnItems->Add(crcWarning);
}
#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))));
Expand All @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
}
Expand Down
5 changes: 5 additions & 0 deletions UI/ReportScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,21 @@ class ReportScreen : public UIDialogScreenWithGameBackground {
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;
Expand All @@ -63,6 +67,7 @@ class ReportScreen : public UIDialogScreenWithGameBackground {
bool ratingEnabled_;
bool tookScreenshot_ = false;
bool includeScreenshot_ = true;
bool showCRC_ = false;
};

class ReportFinishScreen : public UIDialogScreenWithGameBackground {
Expand Down