mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #19347 from hrydgard/scefont-fixes
sceFont and savestate fixes
This commit is contained in:
@@ -32,7 +32,7 @@ public:
|
||||
size_t fileSize;
|
||||
uint8_t *buffer = g_VFS.ReadFile(filename_.c_str(), &fileSize);
|
||||
if (!buffer) {
|
||||
ERROR_LOG(Log::IO, "Failed to read file '%s'", filename_.c_str());
|
||||
WARN_LOG(Log::IO, "Failed to read file '%s'", filename_.c_str());
|
||||
filename_.clear();
|
||||
*state_ = ManagedTexture::LoadState::FAILED;
|
||||
waitable_->Notify();
|
||||
|
||||
@@ -60,6 +60,8 @@ PointerWrapSection PointerWrap::Section(const char *title, int minVer, int ver)
|
||||
char marker[16] = {0};
|
||||
int foundVersion = ver;
|
||||
|
||||
curTitle_ = title;
|
||||
|
||||
// This is strncpy because we rely on its weird non-null-terminating zero-filling truncation behaviour.
|
||||
// Can't replace it with the more sensible truncate_cpy because that would break savestates.
|
||||
strncpy(marker, title, sizeof(marker));
|
||||
@@ -122,6 +124,8 @@ void PointerWrap::SetError(Error error_) {
|
||||
// For the rest of this run, do nothing, to avoid running off the end of memory or something,
|
||||
// and also not logspam like MEASURE will do in an error case.
|
||||
mode = PointerWrap::MODE_NOOP;
|
||||
// Also, remember the bad section.
|
||||
firstBadSectionTitle_ = curTitle_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool Failed() const {
|
||||
return error == ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void RewindForWrite(u8 *writePtr);
|
||||
bool CheckAfterWrite();
|
||||
|
||||
@@ -156,6 +160,7 @@ public:
|
||||
|
||||
private:
|
||||
const char *firstBadSectionTitle_ = nullptr;
|
||||
const char *curTitle_;
|
||||
u8 *ptrStart_;
|
||||
std::vector<SerializeCheckpoint> checkpoints_;
|
||||
size_t curCheckpoint_ = 0;
|
||||
|
||||
+68
-39
@@ -127,7 +127,7 @@ static std::vector<Font *> internalFonts;
|
||||
// However, these we must save - but we could take a shortcut
|
||||
// for LoadedFonts that point to internal fonts.
|
||||
static std::map<u32, LoadedFont *> fontMap;
|
||||
static std::map<u32, u32> fontLibMap;
|
||||
static std::map<u32, int> fontLibMap;
|
||||
// We keep this list to avoid ptr references, even before alloc is called.
|
||||
static std::vector<FontLib *> fontLibList;
|
||||
|
||||
@@ -152,7 +152,7 @@ enum FontOpenMode {
|
||||
class Font {
|
||||
public:
|
||||
// For savestates only.
|
||||
Font() {
|
||||
Font() : valid_(false) {
|
||||
}
|
||||
|
||||
Font(const u8 *data, size_t dataSize) {
|
||||
@@ -273,8 +273,7 @@ private:
|
||||
class LoadedFont {
|
||||
public:
|
||||
// For savestates only.
|
||||
LoadedFont() : font_(NULL) {
|
||||
}
|
||||
LoadedFont() {}
|
||||
|
||||
LoadedFont(Font *font, FontOpenMode mode, u32 fontLibID, u32 handle)
|
||||
: fontLibID_(fontLibID), font_(font), handle_(handle), mode_(mode), open_(true) {}
|
||||
@@ -296,9 +295,18 @@ public:
|
||||
|
||||
const Font *GetFont() const { return font_; }
|
||||
const PGF *GetPGF() const { return font_->GetPGF(); }
|
||||
const FontLib *GetFontLib() const { return fontLibList[fontLibID_]; }
|
||||
FontLib *GetFontLib() { return fontLibList[fontLibID_]; }
|
||||
const FontLib *GetFontLib() const {
|
||||
_dbg_assert_(IsValid());
|
||||
return fontLibList[fontLibID_];
|
||||
}
|
||||
FontLib *GetFontLib() {
|
||||
_dbg_assert_(IsValid());
|
||||
return fontLibList[fontLibID_];
|
||||
}
|
||||
u32 Handle() const { return handle_; }
|
||||
bool IsValid() const {
|
||||
return fontLibID_ >= 0 && fontLibID_ < (int)fontLibList.size();
|
||||
}
|
||||
|
||||
bool GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType = FONT_PGF_CHARGLYPH) const;
|
||||
void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const;
|
||||
@@ -319,7 +327,7 @@ public:
|
||||
Do(p, numInternalFonts);
|
||||
// It's okay if numInternalFonts was zero and we've now loaded them.
|
||||
if (numInternalFonts != (int)internalFonts.size() && numInternalFonts != 0) {
|
||||
ERROR_LOG(Log::sceFont, "Unable to load state: different internal font count.");
|
||||
ERROR_LOG(Log::sceFont, "Unable to load state: different internal font count (%d in save, %d in memory)", numInternalFonts, (int)internalFonts.size());
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
@@ -351,11 +359,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
Font *font_;
|
||||
u32 handle_;
|
||||
FontOpenMode mode_;
|
||||
bool open_;
|
||||
int fontLibID_ = -1;
|
||||
Font *font_ = nullptr;
|
||||
u32 handle_ = 0;
|
||||
FontOpenMode mode_ = FONT_OPEN_INTERNAL_STINGY;
|
||||
bool open_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LoadedFont);
|
||||
};
|
||||
|
||||
@@ -379,8 +388,10 @@ public:
|
||||
void SetFontLib(u32 fontLibID, u32 errorCodePtr) { fontLibID_ = fontLibID; errorCodePtr_ = errorCodePtr; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
u32 errorCodePtr_;
|
||||
int fontLibID_ = -1;
|
||||
u32 errorCodePtr_ = 0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PostAllocCallback);
|
||||
};
|
||||
|
||||
class PostOpenCallback : public PSPAction {
|
||||
@@ -395,10 +406,12 @@ public:
|
||||
Do(p, fontLibID_);
|
||||
}
|
||||
void run(MipsCall &call) override;
|
||||
void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
int fontLibID_ = -1;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PostOpenCallback);
|
||||
};
|
||||
|
||||
class PostOpenAllocCallback : public PSPAction {
|
||||
@@ -415,13 +428,15 @@ public:
|
||||
Do(p, fontIndex_);
|
||||
}
|
||||
void run(MipsCall &call) override;
|
||||
void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetFont(u32 handle, int index) { fontHandle_ = handle; fontIndex_ = index; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
u32 fontHandle_;
|
||||
int fontIndex_;
|
||||
int fontLibID_ = -1;
|
||||
u32 fontHandle_ = 0;
|
||||
int fontIndex_ = -1;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PostOpenAllocCallback);
|
||||
};
|
||||
|
||||
class PostCharInfoAllocCallback : public PSPAction {
|
||||
@@ -436,10 +451,12 @@ public:
|
||||
Do(p, fontLibID_);
|
||||
}
|
||||
void run(MipsCall &call) override;
|
||||
void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
int fontLibID_ = -1;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PostCharInfoAllocCallback);
|
||||
};
|
||||
|
||||
class PostCharInfoFreeCallback : public PSPAction {
|
||||
@@ -455,18 +472,19 @@ public:
|
||||
Do(p, charInfo_);
|
||||
}
|
||||
void run(MipsCall &call) override;
|
||||
void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }
|
||||
void SetCharInfo(PSPPointer<PGFCharInfo> charInfo) { charInfo_ = charInfo; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
int fontLibID_ = -1;
|
||||
PSPPointer<PGFCharInfo> charInfo_;
|
||||
};
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PostCharInfoFreeCallback);
|
||||
};
|
||||
|
||||
struct NativeFontLib {
|
||||
FontNewLibParams params;
|
||||
// TODO
|
||||
// TODO (what?)
|
||||
u32_le fontInfo1;
|
||||
u32_le fontInfo2;
|
||||
u16_le unk1;
|
||||
@@ -485,7 +503,7 @@ struct FontImageRect {
|
||||
};
|
||||
|
||||
// A "fontLib" is a container of loaded fonts.
|
||||
// One can open either "internal" fonts or custom fonts into a fontlib.
|
||||
// One can open either "internal" fonts or load custom fonts into a fontlib.
|
||||
class FontLib {
|
||||
public:
|
||||
FontLib() {
|
||||
@@ -507,8 +525,8 @@ public:
|
||||
hleEnqueueCall(allocFuncAddr(), 2, args, action);
|
||||
}
|
||||
|
||||
u32 GetListID() {
|
||||
return (u32)(std::find(fontLibList.begin(), fontLibList.end(), this) - fontLibList.begin());
|
||||
int GetListID() {
|
||||
return (int)(std::find(fontLibList.begin(), fontLibList.end(), this) - fontLibList.begin());
|
||||
}
|
||||
|
||||
void Done() {
|
||||
@@ -623,7 +641,7 @@ public:
|
||||
// Before replacing it and forgetting about it, let's free it.
|
||||
delete prevFont->second;
|
||||
}
|
||||
fontMap[loadedFont->Handle()] = loadedFont;
|
||||
fontMap.insert_or_assign(loadedFont->Handle(), loadedFont);
|
||||
} else {
|
||||
loadedFont = fontMap[fonts_[foundFontIndex]];
|
||||
}
|
||||
@@ -770,7 +788,6 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FontLib);
|
||||
};
|
||||
|
||||
|
||||
void PostAllocCallback::run(MipsCall &call) {
|
||||
INFO_LOG(Log::sceFont, "Entering PostAllocCallback::run");
|
||||
u32 v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
@@ -780,6 +797,7 @@ void PostAllocCallback::run(MipsCall &call) {
|
||||
Memory::Write_U32(ERROR_FONT_OUT_OF_MEMORY, errorCodePtr_);
|
||||
call.setReturnValue(0);
|
||||
} else {
|
||||
_dbg_assert_(fontLibID_ >= 0);
|
||||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
fontLib->AllocDone(v0);
|
||||
fontLibMap[fontLib->handle()] = fontLibID_;
|
||||
@@ -790,18 +808,21 @@ void PostAllocCallback::run(MipsCall &call) {
|
||||
}
|
||||
|
||||
void PostOpenCallback::run(MipsCall &call) {
|
||||
_dbg_assert_(fontLibID_ >= 0);
|
||||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
u32 v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
fontLib->SetFileFontHandle(v0);
|
||||
}
|
||||
|
||||
void PostOpenAllocCallback::run(MipsCall &call) {
|
||||
_dbg_assert_(fontLibID_ >= 0);
|
||||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
u32 v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
fontLib->SetOpenAllocatedAddress(fontIndex_, v0);
|
||||
}
|
||||
|
||||
void PostCharInfoAllocCallback::run(MipsCall &call) {
|
||||
_dbg_assert_(fontLibID_ >= 0);
|
||||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
u32 v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
if (v0 == 0) {
|
||||
@@ -824,20 +845,23 @@ void PostCharInfoFreeCallback::run(MipsCall &call) {
|
||||
}
|
||||
|
||||
inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {
|
||||
_dbg_assert_(IsValid());
|
||||
auto fontLib = GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
return GetPGF()->GetCharInfo(charCode, charInfo, altCharCode, glyphType);
|
||||
}
|
||||
|
||||
inline void LoadedFont::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const {
|
||||
_dbg_assert_(IsValid());
|
||||
auto fontLib = GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
GetPGF()->DrawCharacter(image, clipX, clipY, clipWidth, clipHeight, charCode, altCharCode, glyphType);
|
||||
}
|
||||
|
||||
static FontLib *GetFontLib(u32 handle) {
|
||||
if (fontLibMap.find(handle) != fontLibMap.end()) {
|
||||
return fontLibList[fontLibMap[handle]];
|
||||
auto iter = fontLibMap.find(handle);
|
||||
if (iter != fontLibMap.end()) {
|
||||
return fontLibList[iter->second];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -935,9 +959,14 @@ void __FontInit() {
|
||||
|
||||
void __FontShutdown() {
|
||||
for (auto iter = fontMap.begin(); iter != fontMap.end(); iter++) {
|
||||
FontLib *fontLib = iter->second->GetFontLib();
|
||||
if (fontLib)
|
||||
fontLib->CloseFont(iter->second, true);
|
||||
if (iter->second->IsValid()) {
|
||||
FontLib *fontLib = iter->second->GetFontLib();
|
||||
if (fontLib) {
|
||||
fontLib->CloseFont(iter->second, true);
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(Log::HLE, "__FontShutdown: Bad entry in fontMap");
|
||||
}
|
||||
delete iter->second;
|
||||
}
|
||||
fontMap.clear();
|
||||
@@ -963,7 +992,7 @@ void __FontDoState(PointerWrap &p) {
|
||||
needInternalFonts = !internalFonts.empty();
|
||||
Do(p, needInternalFonts);
|
||||
}
|
||||
if (needInternalFonts)
|
||||
if (needInternalFonts && p.mode == PointerWrap::MODE_READ)
|
||||
__LoadInternalFonts();
|
||||
|
||||
Do(p, fontLibList);
|
||||
@@ -1477,9 +1506,9 @@ static int sceFontFlush(u32 fontHandle) {
|
||||
return ERROR_FONT_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (font->GetFontLib())
|
||||
if (font->GetFontLib()) {
|
||||
font->GetFontLib()->flushFont();
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -599,7 +599,7 @@ void AuCtx::DoState(PointerWrap &p) {
|
||||
Do(p, Channels);
|
||||
Do(p, MaxOutputSample);
|
||||
Do(p, readPos);
|
||||
int audioType = (int)decoder->GetAudioType();
|
||||
int audioType = decoder ? (int)decoder->GetAudioType() : 0;
|
||||
Do(p, audioType);
|
||||
Do(p, BitRate);
|
||||
Do(p, SamplingRate);
|
||||
|
||||
+15
-14
@@ -835,20 +835,21 @@ namespace SaveState
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool HandleLoadFailure()
|
||||
bool HandleLoadFailure(bool wasRewinding)
|
||||
{
|
||||
WARN_LOG(Log::SaveState, "HandleLoadFailure - trying a rewind state.");
|
||||
if (wasRewinding) {
|
||||
WARN_LOG(Log::SaveState, "HandleLoadFailure - trying a rewind state.");
|
||||
// Okay, first, let's give the next rewind state a shot - maybe we can at least not reset entirely.
|
||||
// Actually, this seems like a bad thing - some systems can end up in bad states, like sceFont :(
|
||||
CChunkFileReader::Error result;
|
||||
do {
|
||||
std::string errorString;
|
||||
result = rewindStates.Restore(&errorString);
|
||||
} while (result == CChunkFileReader::ERROR_BROKEN_STATE);
|
||||
|
||||
// Okay, first, let's give the rewind state a shot - maybe we can at least not reset entirely.
|
||||
// Even if this was a rewind, maybe we can still load a previous one.
|
||||
CChunkFileReader::Error result;
|
||||
do {
|
||||
std::string errorString;
|
||||
result = rewindStates.Restore(&errorString);
|
||||
} while (result == CChunkFileReader::ERROR_BROKEN_STATE);
|
||||
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
return true;
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We tried, our only remaining option is to reset the game.
|
||||
@@ -972,7 +973,7 @@ namespace SaveState
|
||||
}
|
||||
#endif
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
HandleLoadFailure();
|
||||
HandleLoadFailure(false);
|
||||
callbackMessage = std::string(i18nLoadFailure) + ": " + errorString;
|
||||
ERROR_LOG(Log::SaveState, "Load state failure: %s", errorString.c_str());
|
||||
callbackResult = Status::FAILURE;
|
||||
@@ -1037,7 +1038,7 @@ namespace SaveState
|
||||
Core_ResetException();
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
// Cripes. Good news is, we might have more. Let's try those too, better than a reset.
|
||||
if (HandleLoadFailure()) {
|
||||
if (HandleLoadFailure(true)) {
|
||||
// Well, we did rewind, even if too much...
|
||||
callbackMessage = sc->T("Loaded State");
|
||||
callbackResult = Status::SUCCESS;
|
||||
|
||||
+3
-1
@@ -632,7 +632,9 @@ void PSP_RunLoopUntil(u64 globalticks) {
|
||||
return;
|
||||
}
|
||||
|
||||
mipsr4k.RunLoopUntil(globalticks);
|
||||
if (coreState != CORE_NEXTFRAME) { // Can be set by SaveState as well as by sceDisplay
|
||||
mipsr4k.RunLoopUntil(globalticks);
|
||||
}
|
||||
}
|
||||
|
||||
void PSP_RunLoopFor(int cycles) {
|
||||
|
||||
@@ -540,7 +540,7 @@ bool GameManager::ExtractFile(struct zip *z, int file_index, const Path &outFile
|
||||
return true;
|
||||
} else {
|
||||
auto iz = GetI18NCategory(I18NCat::INSTALLZIP);
|
||||
g_OSD.Show(OSDType::MESSAGE_ERROR, iz->T("Installation failed"));
|
||||
g_OSD.Show(OSDType::MESSAGE_ERROR, iz->T("Installation failed"), outFilename.ToVisualString());
|
||||
ERROR_LOG(Log::HLE, "Failed to open file for writing: %s", outFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -601,6 +601,8 @@ bool GameManager::InstallMemstickGame(struct zip *z, const Path &zipfile, const
|
||||
g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, info.numFiles, (i + 1) * 0.1f, 0.1f);
|
||||
}
|
||||
|
||||
INFO_LOG(Log::HLE, "Created %d directories", (int)createdDirs.size());
|
||||
|
||||
// Now, loop through again in a second pass, writing files.
|
||||
std::vector<Path> createdFiles;
|
||||
for (int i = 0; i < info.numFiles; i++) {
|
||||
|
||||
Reference in New Issue
Block a user