Skip to content

Commit

Permalink
Merge pull request #10496 from unknownbrackets/cpu-bgstart
Browse files Browse the repository at this point in the history
Core: Asynchronously load the main ELF
  • Loading branch information
hrydgard committed Jan 2, 2018
2 parents 3b9d001 + 9952d4b commit 690a409
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 20 deletions.
41 changes: 38 additions & 3 deletions Core/PSPLoaders.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// Official git repository and contact information can be found at // Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.


#include <thread>
#include "file/file_util.h" #include "file/file_util.h"
#include "util/text/utf8.h" #include "util/text/utf8.h"


Expand Down Expand Up @@ -250,7 +251,20 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
g_Config.loadGameConfig(id); g_Config.loadGameConfig(id);
host->SendUIMessage("config_loaded", ""); host->SendUIMessage("config_loaded", "");
INFO_LOG(LOADER,"Loading %s...", bootpath.c_str()); INFO_LOG(LOADER,"Loading %s...", bootpath.c_str());
return __KernelLoadExec(bootpath.c_str(), 0, error_string);
std::thread th([bootpath] {
// TODO: We can't use the initial error_string pointer.
bool success = __KernelLoadExec(bootpath.c_str(), 0, &PSP_CoreParameter().errorString);
if (success && coreState == CORE_POWERUP) {
coreState = PSP_CoreParameter().startPaused ? CORE_STEPPING : CORE_RUNNING;
} else {
coreState = CORE_ERROR;
// TODO: This is a crummy way to communicate the error...
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true;
} }


static std::string NormalizePath(const std::string &path) { static std::string NormalizePath(const std::string &path) {
Expand Down Expand Up @@ -354,13 +368,34 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
} }
// End of temporary code // End of temporary code


return __KernelLoadExec(finalName.c_str(), 0, error_string); std::thread th([finalName] {
bool success = __KernelLoadExec(finalName.c_str(), 0, &PSP_CoreParameter().errorString);
if (success && coreState == CORE_POWERUP) {
coreState = PSP_CoreParameter().startPaused ? CORE_STEPPING : CORE_RUNNING;
} else {
coreState = CORE_ERROR;
// TODO: This is a crummy way to communicate the error...
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true;
} }


bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) { bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
BlobFileSystem *umd = new BlobFileSystem(&pspFileSystem, fileLoader, "data.ppdmp"); BlobFileSystem *umd = new BlobFileSystem(&pspFileSystem, fileLoader, "data.ppdmp");
pspFileSystem.Mount("disc0:", umd); pspFileSystem.Mount("disc0:", umd);


__KernelLoadGEDump("disc0:/data.ppdmp", error_string); std::thread th([] {
bool success = __KernelLoadGEDump("disc0:/data.ppdmp", &PSP_CoreParameter().errorString);
if (success && coreState == CORE_POWERUP) {
coreState = PSP_CoreParameter().startPaused ? CORE_STEPPING : CORE_RUNNING;
} else {
coreState = CORE_ERROR;
// TODO: This is a crummy way to communicate the error...
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true; return true;
} }
7 changes: 4 additions & 3 deletions Core/System.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ bool CPU_NextStateNot(CPUThreadState from, CPUThreadState to) {
} }


bool CPU_IsReady() { bool CPU_IsReady() {
if (coreState == CORE_POWERUP)
return false;
return cpuThreadState == CPU_THREAD_RUNNING || cpuThreadState == CPU_THREAD_NOT_RUNNING; return cpuThreadState == CPU_THREAD_RUNNING || cpuThreadState == CPU_THREAD_NOT_RUNNING;
} }


Expand Down Expand Up @@ -270,7 +272,8 @@ void CPU_Init() {


// TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly // TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly


// Why did we check for CORE_POWERDOWN here? // If they shut down early, we'll catch it when load completes.
// Note: this may return before init is complete, which is checked if CPU_IsReady().
if (!LoadFile(&loadedFile, &coreParameter.errorString)) { if (!LoadFile(&loadedFile, &coreParameter.errorString)) {
CPU_Shutdown(); CPU_Shutdown();
coreParameter.fileToStart = ""; coreParameter.fileToStart = "";
Expand All @@ -282,8 +285,6 @@ void CPU_Init() {
if (coreParameter.updateRecent) { if (coreParameter.updateRecent) {
g_Config.AddRecent(filename); g_Config.AddRecent(filename);
} }

coreState = coreParameter.startPaused ? CORE_STEPPING : CORE_RUNNING;
} }


void CPU_Shutdown() { void CPU_Shutdown() {
Expand Down
64 changes: 55 additions & 9 deletions UI/EmuScreen.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -231,17 +231,15 @@ void EmuScreen::bootGame(const std::string &filename) {
host->NotifyUserMessage(gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 15.0f); host->NotifyUserMessage(gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 15.0f);
} }


loadingViewColor_->Divert(0xFFFFFFFF, 0.15f); loadingViewColor_->Divert(0xFFFFFFFF, 0.75f);
loadingViewVisible_->Divert(UI::V_VISIBLE, 0.15f); loadingViewVisible_->Divert(UI::V_VISIBLE, 0.75f);
} }


void EmuScreen::bootComplete() { void EmuScreen::bootComplete() {
UpdateUIState(UISTATE_INGAME); UpdateUIState(UISTATE_INGAME);
host->BootDone(); host->BootDone();
host->UpdateDisassembly(); host->UpdateDisassembly();


g_gameInfoCache->FlushBGs();

NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str()); NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str());
autoLoad(); autoLoad();


Expand Down Expand Up @@ -811,6 +809,37 @@ void EmuScreen::processAxis(const AxisInput &axis, int direction) {
} }
} }


class GameInfoBGView : public UI::InertView {
public:
GameInfoBGView(const std::string &gamePath, UI::LayoutParams *layoutParams) : InertView(layoutParams), gamePath_(gamePath) {
}

void Draw(UIContext &dc) {
// Should only be called when visible.
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GAMEINFO_WANTBG);
dc.Flush();

// PIC1 is the loading image, so let's only draw if it's available.
if (ginfo && ginfo->pic1.texture) {
dc.GetDrawContext()->BindTexture(0, ginfo->pic1.texture->GetTexture());

double loadTime = ginfo->pic1.timeLoaded;
uint32_t color = alphaMul(color_, ease((time_now_d() - loadTime) * 3));
dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color);
dc.Flush();
dc.RebindTexture();
}
}

void SetColor(uint32_t c) {
color_ = c;
}

protected:
std::string gamePath_;
uint32_t color_ = 0xFFC0C0C0;
};

void EmuScreen::CreateViews() { void EmuScreen::CreateViews() {
using namespace UI; using namespace UI;


Expand All @@ -831,14 +860,31 @@ void EmuScreen::CreateViews() {
root_->Add(saveStatePreview_); root_->Add(saveStatePreview_);
root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h))); root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h)));


loadingView_ = new TextView(sc->T("Loading game..."), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true)); GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT)));
root_->Add(loadingView_); TextView *loadingTextView = root_->Add(new TextView(sc->T("Loading game..."), new AnchorLayoutParams(bounds.centerX(), bounds.centerY(), NONE, NONE, true)));
loadingTextView->SetShadow(true);
loadingView_ = loadingTextView;


// We start invisible here, in case of recreated views. loadingViewColor_ = loadingTextView->AddTween(new CallbackColorTween(0x00FFFFFF, 0x00FFFFFF, 0.2f, &bezierEaseInOut));
loadingViewColor_ = loadingView_->AddTween(new TextColorTween(0x00FFFFFF, 0x00FFFFFF, 0.2f, &bezierEaseInOut)); loadingViewColor_->SetCallback([loadingBG, loadingTextView](View *v, uint32_t c) {
loadingBG->SetColor(c & 0xFFC0C0C0);
loadingTextView->SetTextColor(c);
});
loadingViewColor_->Persist(); loadingViewColor_->Persist();
loadingViewVisible_ = loadingView_->AddTween(new VisibilityTween(UI::V_INVISIBLE, UI::V_INVISIBLE, 0.2f, &bezierEaseInOut));
// We start invisible here, in case of recreated views.
loadingViewVisible_ = loadingTextView->AddTween(new VisibilityTween(UI::V_INVISIBLE, UI::V_INVISIBLE, 0.2f, &bezierEaseInOut));
loadingViewVisible_->Persist(); loadingViewVisible_->Persist();
loadingViewVisible_->Finish.Add([loadingBG](EventParams &p) {
loadingBG->SetVisibility(p.v->GetVisibility());

// If we just became invisible, flush BGs since we don't need them anymore.
// Saves some VRAM for the game, but don't do it before we fade out...
if (p.v->GetVisibility() == V_INVISIBLE) {
g_gameInfoCache->FlushBGs();
}
return EVENT_DONE;
});
} }


UI::EventReturn EmuScreen::OnDevTools(UI::EventParams &params) { UI::EventReturn EmuScreen::OnDevTools(UI::EventParams &params) {
Expand Down
2 changes: 1 addition & 1 deletion UI/EmuScreen.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@ class EmuScreen : public UIScreen {
int saveStateSlot_; int saveStateSlot_;


UI::View *loadingView_ = nullptr; UI::View *loadingView_ = nullptr;
UI::TextColorTween *loadingViewColor_ = nullptr; UI::CallbackColorTween *loadingViewColor_ = nullptr;
UI::VisibilityTween *loadingViewVisible_ = nullptr; UI::VisibilityTween *loadingViewVisible_ = nullptr;
}; };
7 changes: 4 additions & 3 deletions UI/ReportScreen.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ class RatingChoice : public LinearLayout {


RatingChoice::RatingChoice(const char *captionKey, int *value, LayoutParams *layoutParams) RatingChoice::RatingChoice(const char *captionKey, int *value, LayoutParams *layoutParams)
: LinearLayout(ORIENT_VERTICAL, layoutParams), value_(value) { : LinearLayout(ORIENT_VERTICAL, layoutParams), value_(value) {
SetSpacing(-8.0f); SetSpacing(0.0f);


I18NCategory *rp = GetI18NCategory("Reporting"); I18NCategory *rp = GetI18NCategory("Reporting");
group_ = new LinearLayout(ORIENT_HORIZONTAL); group_ = new LinearLayout(ORIENT_HORIZONTAL);
Add(new InfoItem(rp->T(captionKey), "")); Add(new TextView(rp->T(captionKey)))->SetShadow(true);
Add(group_); Add(group_);


group_->SetSpacing(0.0f); group_->SetSpacing(0.0f);
Expand Down Expand Up @@ -223,7 +223,7 @@ void ReportScreen::CreateViews() {
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL); LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL);


leftColumnItems->Add(new TextView(rp->T("FeedbackDesc", "How's the emulation? Let us and the community know!"), new LinearLayoutParams(Margins(12, 5, 0, 5)))); leftColumnItems->Add(new TextView(rp->T("FeedbackDesc", "How's the emulation? Let us and the community know!"), new LinearLayoutParams(Margins(12, 5, 0, 5))))->SetShadow(true);
if (!Reporting::IsEnabled()) { if (!Reporting::IsEnabled()) {
reportingNotice_ = leftColumnItems->Add(new TextView(rp->T("FeedbackDisabled", "Compatibility server reports must be enabled."), new LinearLayoutParams(Margins(12, 5, 0, 5)))); reportingNotice_ = leftColumnItems->Add(new TextView(rp->T("FeedbackDisabled", "Compatibility server reports must be enabled."), new LinearLayoutParams(Margins(12, 5, 0, 5))));
reportingNotice_->SetShadow(true); reportingNotice_->SetShadow(true);
Expand Down Expand Up @@ -258,6 +258,7 @@ void ReportScreen::CreateViews() {


leftColumnItems->Add(new CompatRatingChoice("Overall", (int *)&overall_))->SetEnabledPtr(&enableReporting_)->OnChoice.Handle(this, &ReportScreen::HandleChoice); leftColumnItems->Add(new CompatRatingChoice("Overall", (int *)&overall_))->SetEnabledPtr(&enableReporting_)->OnChoice.Handle(this, &ReportScreen::HandleChoice);
overallDescription_ = leftColumnItems->Add(new TextView("", new LinearLayoutParams(Margins(10, 0)))); overallDescription_ = leftColumnItems->Add(new TextView("", new LinearLayoutParams(Margins(10, 0))));
overallDescription_->SetShadow(true);
leftColumnItems->Add(new RatingChoice("Graphics", &graphics_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice); leftColumnItems->Add(new RatingChoice("Graphics", &graphics_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice);
leftColumnItems->Add(new RatingChoice("Speed", &speed_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice); leftColumnItems->Add(new RatingChoice("Speed", &speed_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice);
leftColumnItems->Add(new RatingChoice("Gameplay", &gameplay_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice); leftColumnItems->Add(new RatingChoice("Gameplay", &gameplay_))->SetEnabledPtr(&ratingEnabled_)->OnChoice.Handle(this, &ReportScreen::HandleChoice);
Expand Down
2 changes: 1 addition & 1 deletion ext/native/ui/view.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ void TextView::Draw(UIContext &dc) {
dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont);
if (shadow_) { if (shadow_) {
uint32_t shadowColor = 0x80000000; uint32_t shadowColor = 0x80000000;
dc.DrawTextRect(text_.c_str(), bounds_, shadowColor, textAlign_); dc.DrawTextRect(text_.c_str(), bounds_.Offset(1.0f, 1.0f), shadowColor, textAlign_);
} }
uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor; uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor;
dc.DrawTextRect(text_.c_str(), bounds_, textColor, textAlign_); dc.DrawTextRect(text_.c_str(), bounds_, textColor, textAlign_);
Expand Down

0 comments on commit 690a409

Please sign in to comment.