CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/HLE/sceFont.cpp
Views: 1401
#include "sceFont.h"12#include "Common/TimeUtil.h"34#include <cmath>5#include <vector>6#include <map>7#include <algorithm>89#include "Common/Serialize/Serializer.h"10#include "Common/Serialize/SerializeFuncs.h"11#include "Common/Serialize/SerializeMap.h"12#include "Core/HLE/HLE.h"13#include "Core/HLE/FunctionWrappers.h"14#include "Core/HLE/sceFont.h"15#include "Core/HLE/sceKernel.h"16#include "Core/HLE/sceKernelThread.h"17#include "Core/MIPS/MIPS.h"18#include "Core/FileSystems/FileSystem.h"19#include "Core/FileSystems/MetaFileSystem.h"20#include "Core/MemMapHelpers.h"21#include "Core/Reporting.h"22#include "Core/System.h"23#include "Core/Font/PGF.h"2425enum {26ERROR_FONT_OUT_OF_MEMORY = 0x80460001,27ERROR_FONT_INVALID_LIBID = 0x80460002,28ERROR_FONT_INVALID_PARAMETER = 0x80460003,29ERROR_FONT_HANDLER_OPEN_FAILED = 0x80460005,30ERROR_FONT_TOO_MANY_OPEN_FONTS = 0x80460009,31ERROR_FONT_INVALID_FONT_DATA = 0x8046000a,32};3334constexpr int MAX_FONT_REFS = 4;3536// For the save states.37static bool useAllocCallbacks = true;3839// Actions40static int actionPostAllocCallback;41static int actionPostOpenCallback;42static int actionPostOpenAllocCallback;43static int actionPostCharInfoAllocCallback;44static int actionPostCharInfoFreeCallback;4546// Monster Hunter sequence:47// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:469 E[HLE]: sceFontNewLib 89ad4a0, 9fff5cc48// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:699 E[HLE]: UNIMPL sceFontGetNumFontList 1, 9fff5cc49// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:526 E[HLE]: sceFontFindOptimumFont 1, 9fff524, 9fff5cc50// 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:490 E[HLE]: sceFontOpenFont 1, 1, 0, 9fff5cc51// 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:542 E[HLE]: sceFontGetFontInfo 1, 997140c5253typedef u32 FontLibraryHandle;54typedef u32 FontHandle;5556struct FontNewLibParams {57u32_le userDataAddr;58u32_le numFonts;59u32_le cacheDataAddr;6061// Driver callbacks.62u32_le allocFuncAddr;63u32_le freeFuncAddr;64u32_le openFuncAddr;65u32_le closeFuncAddr;66u32_le readFuncAddr;67u32_le seekFuncAddr;68u32_le errorFuncAddr;69u32_le ioFinishFuncAddr;70};7172struct FontRegistryEntry {73int hSize;74int vSize;75int hResolution;76int vResolution;77int extraAttributes;78int weight;79int familyCode;80int style;81int styleSub;82int languageCode;83int regionCode;84int countryCode;85const char *fileName;86const char *fontName;87int expireDate;88int shadow_option;89u32 fontFileSize;90u32 stingySize; // for the FONT_OPEN_INTERNAL_STINGY mode, from pspautotests.91bool ignoreIfMissing;92};9394static const FontRegistryEntry fontRegistry[] = {95// This was added for Chinese translations and is not normally loaded on a PSP.96{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_CHINESE, 0, 1, "zh_gb.pgf", "FTT-NewRodin Pro DB", 0, 0, 1581700, 145844, true },97{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_JAPANESE, 0, 1, "jpn0.pgf", "FTT-NewRodin Pro DB", 0, 0, 1581700, 145844 },98{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn0.pgf", "FTT-NewRodin Pro Latin", 0, 0, 69108, 16680 },99{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn1.pgf", "FTT-Matisse Pro Latin", 0, 0, 65124, 16920 },100{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn2.pgf", "FTT-NewRodin Pro Latin", 0, 0, 72948, 16872 },101{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn3.pgf", "FTT-Matisse Pro Latin", 0, 0, 67700, 17112 },102{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn4.pgf", "FTT-NewRodin Pro Latin", 0, 0, 72828, 16648 },103{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn5.pgf", "FTT-Matisse Pro Latin", 0, 0, 68220, 16928 },104{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn6.pgf", "FTT-NewRodin Pro Latin", 0, 0, 77032, 16792 },105{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn7.pgf", "FTT-Matisse Pro Latin", 0, 0, 71144, 17160 },106{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn8.pgf", "FTT-NewRodin Pro Latin", 0, 0, 41000, 16192 },107{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn9.pgf", "FTT-Matisse Pro Latin", 0, 0, 40164, 16476 },108{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn10.pgf", "FTT-NewRodin Pro Latin", 0, 0, 42692, 16300 },109{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn11.pgf", "FTT-Matisse Pro Latin", 0, 0, 41488, 16656 },110{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn12.pgf", "FTT-NewRodin Pro Latin", 0, 0, 43136, 16176 },111{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn13.pgf", "FTT-Matisse Pro Latin", 0, 0, 41772, 16436 },112{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn14.pgf", "FTT-NewRodin Pro Latin", 0, 0, 45184, 16272 },113{ 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn15.pgf", "FTT-Matisse Pro Latin", 0, 0, 43044, 16704 },114{ 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_KOREAN, 0, 3, "kr0.pgf", "AsiaNHH(512Johab)", 0, 0, 394192, 51856 },115};116117static const float pointDPI = 72.f;118119class LoadedFont;120class FontLib;121class Font;122int GetInternalFontIndex(Font *font);123124// These should not need to be state saved.125static std::vector<Font *> internalFonts;126// However, these we must save - but we could take a shortcut127// for LoadedFonts that point to internal fonts.128static std::map<u32, LoadedFont *> fontMap;129static std::map<u32, int> fontLibMap;130// We keep this list to avoid ptr references, even before alloc is called.131static std::vector<FontLib *> fontLibList;132133enum MatchQuality {134MATCH_UNKNOWN,135MATCH_NONE,136MATCH_GOOD,137};138139enum FontOpenMode {140FONT_OPEN_INTERNAL_STINGY = 0,141FONT_OPEN_INTERNAL_FULL = 1,142// Calls open/seek/read/close handlers to read the file partially.143FONT_OPEN_USERFILE_HANDLERS = 2,144// Reads directly from filesystem.145FONT_OPEN_USERFILE_FULL = 3,146FONT_OPEN_USERBUFFER = 4,147};148149// TODO: Merge this class with PGF? That'd make it harder to support .bwfon150// fonts though, unless that's added directly to PGF.151class Font {152public:153// For savestates only.154Font() : valid_(false) {155}156157Font(const u8 *data, size_t dataSize) {158Init(data, dataSize);159}160161Font(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {162Init(data, dataSize, entry);163}164165Font(const std::vector<u8> &data) {166Init(&data[0], data.size());167}168169Font(const std::vector<u8> &data, const FontRegistryEntry &entry) {170Init(&data[0], data.size(), entry);171}172173const PGFFontStyle &GetFontStyle() const { return style_; }174175MatchQuality MatchesStyle(const PGFFontStyle &style) const {176// If no field matches, it doesn't match.177MatchQuality match = MATCH_UNKNOWN;178179#define CHECK_FIELD(f, m) \180if (style.f != 0) { \181if (style.f != style_.f) { \182return MATCH_NONE; \183} \184if (match < m) { \185match = m; \186} \187}188#define CHECK_FIELD_STR(f, m) \189if (style.f[0] != '\0') { \190if (strcmp(style.f, style_.f) != 0) { \191return MATCH_NONE; \192} \193if (match < m) { \194match = m; \195} \196}197198CHECK_FIELD(fontFamily, MATCH_GOOD);199CHECK_FIELD(fontStyle, MATCH_GOOD);200CHECK_FIELD(fontLanguage, MATCH_GOOD);201CHECK_FIELD(fontCountry, MATCH_GOOD);202203CHECK_FIELD_STR(fontName, MATCH_GOOD);204CHECK_FIELD_STR(fontFileName, MATCH_GOOD);205206#undef CHECK_FIELD_STR207#undef CHECK_FIELD208return match;209}210211PGF *GetPGF() { return &pgf_; }212const PGF *GetPGF() const { return &pgf_; }213u32 getSize() const { return dataSize_; }214u32 getStingySize() const { return stingySize_; }215bool IsValid() const { return valid_; }216217void DoState(PointerWrap &p) {218auto s = p.Section("Font", 1, 2);219if (!s)220return;221222Do(p, pgf_);223Do(p, style_);224if (s < 2) {225valid_ = true;226} else {227Do(p, valid_);228}229}230231private:232void Init(const u8 *data, size_t dataSize) {233valid_ = pgf_.ReadPtr(data, dataSize);234memset(&style_, 0, sizeof(style_));235style_.fontH = (float)pgf_.header.hSize / 64.0f;236style_.fontV = (float)pgf_.header.vSize / 64.0f;237style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;238style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;239this->dataSize_ = (u32)dataSize;240this->stingySize_ = 0; // Unused241}242243void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {244valid_ = pgf_.ReadPtr(data, dataSize);245style_.fontH = entry.hSize / 64.f;246style_.fontV = entry.vSize / 64.f;247style_.fontHRes = entry.hResolution / 64.f;248style_.fontVRes = entry.vResolution / 64.f;249style_.fontWeight = (float)entry.weight;250style_.fontFamily = (u16)entry.familyCode;251style_.fontStyle = (u16)entry.style;252style_.fontStyleSub = (u16)entry.styleSub;253style_.fontLanguage = (u16)entry.languageCode;254style_.fontRegion = (u16)entry.regionCode;255style_.fontCountry = (u16)entry.countryCode;256strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName));257strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));258style_.fontAttributes = entry.extraAttributes;259style_.fontExpire = entry.expireDate;260this->dataSize_ = entry.fontFileSize;261this->stingySize_ = entry.stingySize;262}263264PGF pgf_;265PGFFontStyle style_;266bool valid_;267u32 dataSize_;268u32 stingySize_;269DISALLOW_COPY_AND_ASSIGN(Font);270};271272class LoadedFont {273public:274// For savestates only.275LoadedFont() {}276277LoadedFont(Font *font, FontOpenMode mode, u32 fontLibID, u32 handle)278: fontLibID_(fontLibID), font_(font), handle_(handle), mode_(mode), open_(true) {}279280~LoadedFont() {281switch (mode_) {282case FONT_OPEN_USERBUFFER:283case FONT_OPEN_USERFILE_FULL:284case FONT_OPEN_USERFILE_HANDLERS:285// For these types, it's our responsibility to delete.286delete font_;287font_ = NULL;288break;289default:290// Otherwise, it's an internal font, we keep those.291break;292}293}294295const Font *GetFont() const { return font_; }296const PGF *GetPGF() const { return font_->GetPGF(); }297const FontLib *GetFontLib() const {298_dbg_assert_(IsValid());299return fontLibList[fontLibID_];300}301FontLib *GetFontLib() {302_dbg_assert_(IsValid());303return fontLibList[fontLibID_];304}305u32 Handle() const { return handle_; }306bool IsValid() const {307return fontLibID_ >= 0 && fontLibID_ < (int)fontLibList.size();308}309310bool GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType = FONT_PGF_CHARGLYPH) const;311void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const;312313bool IsOpen() const { return open_; }314void Close() {315open_ = false;316// We keep the rest around until deleted, as some queries are allowed317// on closed fonts (which is rather strange).318}319320void DoState(PointerWrap &p) {321auto s = p.Section("LoadedFont", 1, 3);322if (!s)323return;324325int numInternalFonts = (int)internalFonts.size();326Do(p, numInternalFonts);327// It's okay if numInternalFonts was zero and we've now loaded them.328if (numInternalFonts != (int)internalFonts.size() && numInternalFonts != 0) {329ERROR_LOG(Log::sceFont, "Unable to load state: different internal font count (%d in save, %d in memory)", numInternalFonts, (int)internalFonts.size());330p.SetError(p.ERROR_FAILURE);331return;332}333334Do(p, fontLibID_);335int internalFont = GetInternalFontIndex(font_);336Do(p, internalFont);337if (internalFont == -1) {338Do(p, font_);339} else if (p.mode == p.MODE_READ) {340if (internalFont < 0 || internalFont >= (int)internalFonts.size()) {341ERROR_LOG(Log::sceFont, "Unable to load state: unexpected internal font index.");342p.SetError(p.ERROR_FAILURE);343return;344}345font_ = internalFonts[internalFont];346}347Do(p, handle_);348if (s >= 2) {349Do(p, open_);350} else {351open_ = fontLibID_ != (u32)-1;352}353if (s >= 3) {354Do(p, mode_);355} else {356mode_ = FONT_OPEN_INTERNAL_FULL;357}358}359360private:361int fontLibID_ = -1;362Font *font_ = nullptr;363u32 handle_ = 0;364FontOpenMode mode_ = FONT_OPEN_INTERNAL_STINGY;365bool open_ = false;366367DISALLOW_COPY_AND_ASSIGN(LoadedFont);368};369370class PostAllocCallback : public PSPAction {371public:372PostAllocCallback() {}373static PSPAction *Create() { return new PostAllocCallback(); }374void DoState(PointerWrap &p) override {375auto s = p.Section("PostAllocCallback", 1, 2);376if (!s)377return;378379Do(p, fontLibID_);380if (s >= 2) {381Do(p, errorCodePtr_);382} else {383errorCodePtr_ = 0;384}385}386void run(MipsCall &call) override;387void SetFontLib(u32 fontLibID, u32 errorCodePtr) { fontLibID_ = fontLibID; errorCodePtr_ = errorCodePtr; }388389private:390int fontLibID_ = -1;391u32 errorCodePtr_ = 0;392393DISALLOW_COPY_AND_ASSIGN(PostAllocCallback);394};395396class PostOpenCallback : public PSPAction {397public:398PostOpenCallback() {}399static PSPAction *Create() { return new PostOpenCallback(); }400void DoState(PointerWrap &p) override {401auto s = p.Section("PostOpenCallback", 1);402if (!s)403return;404405Do(p, fontLibID_);406}407void run(MipsCall &call) override;408void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }409410private:411int fontLibID_ = -1;412413DISALLOW_COPY_AND_ASSIGN(PostOpenCallback);414};415416class PostOpenAllocCallback : public PSPAction {417public:418PostOpenAllocCallback() {}419static PSPAction *Create() { return new PostOpenAllocCallback(); }420void DoState(PointerWrap &p) override {421auto s = p.Section("PostOpenAllocCallback", 1);422if (!s)423return;424425Do(p, fontLibID_);426Do(p, fontHandle_);427Do(p, fontIndex_);428}429void run(MipsCall &call) override;430void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }431void SetFont(u32 handle, int index) { fontHandle_ = handle; fontIndex_ = index; }432433private:434int fontLibID_ = -1;435u32 fontHandle_ = 0;436int fontIndex_ = -1;437438DISALLOW_COPY_AND_ASSIGN(PostOpenAllocCallback);439};440441class PostCharInfoAllocCallback : public PSPAction {442public:443PostCharInfoAllocCallback() {}444static PSPAction *Create() { return new PostCharInfoAllocCallback(); }445void DoState(PointerWrap &p) override {446auto s = p.Section("PostCharInfoAllocCallback", 1);447if (!s)448return;449450Do(p, fontLibID_);451}452void run(MipsCall &call) override;453void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }454455private:456int fontLibID_ = -1;457458DISALLOW_COPY_AND_ASSIGN(PostCharInfoAllocCallback);459};460461class PostCharInfoFreeCallback : public PSPAction {462public:463PostCharInfoFreeCallback() {}464static PSPAction *Create() { return new PostCharInfoFreeCallback(); }465void DoState(PointerWrap &p) override {466auto s = p.Section("PostCharInfoFreeCallback", 1);467if (!s)468return;469470Do(p, fontLibID_);471Do(p, charInfo_);472}473void run(MipsCall &call) override;474void SetFontLib(int fontLibID) { fontLibID_ = fontLibID; }475void SetCharInfo(PSPPointer<PGFCharInfo> charInfo) { charInfo_ = charInfo; }476477private:478int fontLibID_ = -1;479PSPPointer<PGFCharInfo> charInfo_;480481DISALLOW_COPY_AND_ASSIGN(PostCharInfoFreeCallback);482};483484struct NativeFontLib {485FontNewLibParams params;486// TODO (what?)487u32_le fontInfo1;488u32_le fontInfo2;489u16_le unk1;490u16_le unk2;491float_le hRes;492float_le vRes;493u32_le internalFontCount;494u32_le internalFontInfo;495u16_le altCharCode;496u16_le unk5;497};498499struct FontImageRect {500s16_le width;501s16_le height;502};503504// A "fontLib" is a container of loaded fonts.505// One can open either "internal" fonts or load custom fonts into a fontlib.506class FontLib {507public:508FontLib() {509// For save states only.510}511512FontLib(FontNewLibParams *params, u32 errorCodePtr) {513params_ = *params;514if (params_.numFonts > 9) {515params_.numFonts = 9;516}517518// Technically, this should be four separate allocations.519u32 allocSize = 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230 + (u32)internalFonts.size() * 0xA8;520PostAllocCallback *action = (PostAllocCallback *) __KernelCreateAction(actionPostAllocCallback);521action->SetFontLib(GetListID(), errorCodePtr);522523u32 args[2] = { userDataAddr(), allocSize };524hleEnqueueCall(allocFuncAddr(), 2, args, action);525}526527int GetListID() {528return (int)(std::find(fontLibList.begin(), fontLibList.end(), this) - fontLibList.begin());529}530531void Done() {532for (size_t i = 0; i < fonts_.size(); i++) {533if (fontRefCount_[i] > 0) {534CloseFont(fontMap[fonts_[i]], true);535delete fontMap[fonts_[i]];536fontMap.erase(fonts_[i]);537}538}539// TODO: The return value of this is leaking.540if (handle_) { // Avoid calling free-callback on double-free541if (coreState != CORE_POWERDOWN) {542u32 args[2] = { userDataAddr(), (u32)handle_ };543hleEnqueueCall(freeFuncAddr(), 2, args);544}545}546handle_ = 0;547fonts_.clear();548fontRefCount_.clear();549openAllocatedAddresses_.clear();550}551552void AllocDone(u32 allocatedAddr) {553handle_ = allocatedAddr;554fonts_.resize(params_.numFonts);555fontRefCount_.resize(params_.numFonts);556openAllocatedAddresses_.resize(params_.numFonts);557for (size_t i = 0; i < fonts_.size(); i++) {558u32 addr = allocatedAddr + 0x4C + (u32)i * 0x4C;559fontRefCount_[i] = 0;560fonts_[i] = addr;561}562563// Let's write out the native struct to make tests easier.564// It's possible games may depend on this staying in ram, e.g. copying it, we may move to that.565nfl_ = allocatedAddr;566nfl_->params = params_;567nfl_->fontInfo1 = allocatedAddr + 0x4C;568nfl_->fontInfo2 = allocatedAddr + 0x4C + params_.numFonts * 0x4C;569nfl_->unk1 = 0;570nfl_->unk2 = 0;571nfl_->hRes = fontHRes_;572nfl_->vRes = fontVRes_;573nfl_->internalFontCount = (u32)internalFonts.size();574nfl_->internalFontInfo = allocatedAddr + 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230;575nfl_->altCharCode = altCharCode_;576}577578u32 handle() const { return handle_; }579int numFonts() const { return params_.numFonts; }580u32_le userDataAddr() const{ return params_.userDataAddr; }581u32_le allocFuncAddr() const { return params_.allocFuncAddr; }582u32_le freeFuncAddr() const { return params_.freeFuncAddr; }583584void SetResolution(float hres, float vres) {585fontHRes_ = hres;586fontVRes_ = vres;587if (nfl_.IsValid()) {588nfl_->hRes = hres;589nfl_->vRes = vres;590}591}592593float FontHRes() const { return fontHRes_; }594float FontVRes() const { return fontVRes_; }595596void SetAltCharCode(int charCode) {597altCharCode_ = charCode;598if (nfl_.IsValid())599nfl_->altCharCode = charCode;600}601602int GetFontHandle(int index) const {603return fonts_[index];604}605606int GetFontRefCount(Font *font) const {607int foundFontIndex = FindExistingIndex(font);608if (foundFontIndex >= 0)609return fontRefCount_.at(foundFontIndex);610return 0;611}612613// For FONT_OPEN_USER* modes, the font will automatically be freed.614LoadedFont *OpenFont(Font *font, FontOpenMode mode, int &error) {615// TODO: Do something with mode, possibly save it where the PSP does in the struct.616// Maybe needed in Font, though? Handlers seem... difficult to emulate.617618// First, check if the font is already open. We need to refcount, see font/open test.619int foundFontIndex = FindExistingIndex(font);620if (foundFontIndex < 0)621foundFontIndex = FindFreeIndex();622623if (foundFontIndex < 0 || fontRefCount_[foundFontIndex] >= MAX_FONT_REFS) {624error = ERROR_FONT_TOO_MANY_OPEN_FONTS;625hleLogError(Log::sceFont, 0, "Too many fonts opened in FontLib");626return nullptr;627}628if (!font->IsValid()) {629error = ERROR_FONT_INVALID_FONT_DATA;630hleLogError(Log::sceFont, 0, "Invalid font data");631return nullptr;632}633634LoadedFont *loadedFont = nullptr;635if (fontRefCount_[foundFontIndex] == 0) {636loadedFont = new LoadedFont(font, mode, GetListID(), fonts_[foundFontIndex]);637638auto prevFont = fontMap.find(loadedFont->Handle());639if (prevFont != fontMap.end()) {640// Before replacing it and forgetting about it, let's free it.641delete prevFont->second;642}643fontMap.insert_or_assign(loadedFont->Handle(), loadedFont);644} else {645loadedFont = fontMap[fonts_[foundFontIndex]];646}647fontRefCount_[foundFontIndex]++;648649// Only need to allocate the first time.650if (!useAllocCallbacks || fontRefCount_[foundFontIndex] > 1)651return loadedFont;652653u32 allocSize = 12;654if (mode == FONT_OPEN_INTERNAL_STINGY) {655allocSize = loadedFont->GetFont()->getStingySize();656} else if (mode == FONT_OPEN_INTERNAL_FULL) {657allocSize += loadedFont->GetFont()->getSize();658}659660PostOpenAllocCallback *action = (PostOpenAllocCallback *)__KernelCreateAction(actionPostOpenAllocCallback);661action->SetFontLib(GetListID());662action->SetFont(loadedFont->Handle(), foundFontIndex);663664u32 args[2] = { userDataAddr(), allocSize };665hleEnqueueCall(allocFuncAddr(), 2, args, action);666667return loadedFont;668}669670void CloseFont(LoadedFont *font, bool releaseAll) {671bool allowClose = true;672for (size_t i = 0; i < fonts_.size(); i++) {673if (fonts_[i] == font->Handle() && fontRefCount_[i] > 0) {674if (releaseAll)675fontRefCount_[i] = 0;676else677fontRefCount_[i]--;678679allowClose = fontRefCount_[i] == 0;680bool deallocate = allowClose && openAllocatedAddresses_[i] != 0;681if (deallocate && coreState != CORE_POWERDOWN) {682u32 args[2] = { userDataAddr(), openAllocatedAddresses_[i] };683hleEnqueueCall(freeFuncAddr(), 2, args);684openAllocatedAddresses_[i] = 0;685}686break;687}688}689flushFont();690if (allowClose)691font->Close();692}693694void flushFont() {695if (charInfoBitmapAddress_ != 0 && coreState != CORE_POWERDOWN) {696u32 args[2] = { userDataAddr(), charInfoBitmapAddress_ };697hleEnqueueCall(freeFuncAddr(), 2, args);698charInfoBitmapAddress_ = 0;699}700}701702void DoState(PointerWrap &p) {703auto s = p.Section("FontLib", 1, 3);704if (!s)705return;706707Do(p, fonts_);708Do(p, fontRefCount_);709Do(p, params_);710Do(p, fontHRes_);711Do(p, fontVRes_);712Do(p, fileFontHandle_);713Do(p, handle_);714Do(p, altCharCode_);715if (s >= 2) {716Do(p, nfl_);717} else {718nfl_ = 0;719}720721if (s >= 3) {722Do(p, openAllocatedAddresses_);723Do(p, charInfoBitmapAddress_);724} else {725openAllocatedAddresses_.resize(params_.numFonts);726charInfoBitmapAddress_ = 0;727}728}729730void SetFileFontHandle(u32 handle) {731fileFontHandle_ = handle;732}733734u32 GetAltCharCode() const { return altCharCode_; }735736u32 GetOpenAllocatedAddress(int index) const {737if(index < numFonts())738return openAllocatedAddresses_[index];739return 0;740}741742void SetOpenAllocatedAddress(int index, u32 addr) {743if (index < numFonts())744openAllocatedAddresses_[index] = addr;745}746747u32 GetCharInfoBitmapAddress() const { return charInfoBitmapAddress_; }748void SetCharInfoBitmapAddress(u32 addr) { charInfoBitmapAddress_ = addr; }749750private:751int FindExistingIndex(Font *font) const {752// TODO: Should this also match for memory fonts, or only internal fonts?753for (auto it : fontMap) {754if (it.second->GetFont() != font || it.second->GetFontLib() != this)755continue;756for (size_t i = 0; i < fonts_.size(); i++) {757if (fonts_[i] == it.first) {758return (int)i;759}760}761}762return -1;763}764765int FindFreeIndex() const {766for (size_t i = 0; i < fonts_.size(); i++) {767if (fontRefCount_[i] == 0) {768return (int)i;769}770}771return -1;772}773774std::vector<u32> fonts_;775std::vector<u32> fontRefCount_;776777FontNewLibParams params_;778float fontHRes_ = 128.0f;779float fontVRes_ = 128.0f;780int fileFontHandle_ = -1;781int handle_ = -1;782int altCharCode_ = 0x5F;783std::vector<u32> openAllocatedAddresses_;784u32 charInfoBitmapAddress_ = 0;785PSPPointer<NativeFontLib> nfl_{};786787DISALLOW_COPY_AND_ASSIGN(FontLib);788};789790void PostAllocCallback::run(MipsCall &call) {791INFO_LOG(Log::sceFont, "Entering PostAllocCallback::run");792u32 v0 = currentMIPS->r[MIPS_REG_V0];793if (v0 == 0) {794// TODO: Who deletes fontLib?795if (errorCodePtr_)796Memory::Write_U32(ERROR_FONT_OUT_OF_MEMORY, errorCodePtr_);797call.setReturnValue(0);798} else {799_dbg_assert_(fontLibID_ >= 0);800FontLib *fontLib = fontLibList[fontLibID_];801fontLib->AllocDone(v0);802fontLibMap[fontLib->handle()] = fontLibID_;803// This is the same as v0 above.804call.setReturnValue(fontLib->handle());805}806INFO_LOG(Log::sceFont, "Leaving PostAllocCallback::run");807}808809void PostOpenCallback::run(MipsCall &call) {810_dbg_assert_(fontLibID_ >= 0);811FontLib *fontLib = fontLibList[fontLibID_];812u32 v0 = currentMIPS->r[MIPS_REG_V0];813fontLib->SetFileFontHandle(v0);814}815816void PostOpenAllocCallback::run(MipsCall &call) {817_dbg_assert_(fontLibID_ >= 0);818FontLib *fontLib = fontLibList[fontLibID_];819u32 v0 = currentMIPS->r[MIPS_REG_V0];820fontLib->SetOpenAllocatedAddress(fontIndex_, v0);821}822823void PostCharInfoAllocCallback::run(MipsCall &call) {824_dbg_assert_(fontLibID_ >= 0);825FontLib *fontLib = fontLibList[fontLibID_];826u32 v0 = currentMIPS->r[MIPS_REG_V0];827if (v0 == 0) {828call.setReturnValue(ERROR_FONT_OUT_OF_MEMORY); // From JPCSP, if alloc size is 0, still this error value?829} else {830fontLib->SetCharInfoBitmapAddress(v0);831}832}833834void PostCharInfoFreeCallback::run(MipsCall &call) {835FontLib *fontLib = fontLibList[fontLibID_];836fontLib->SetCharInfoBitmapAddress(0);837838u32 allocSize = charInfo_->bitmapWidth * charInfo_->bitmapHeight;839PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);840action->SetFontLib(fontLibID_);841842u32 args[2] = { fontLib->userDataAddr(), allocSize };843hleEnqueueCall(fontLib->allocFuncAddr(), 2, args, action);844}845846inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {847_dbg_assert_(IsValid());848auto fontLib = GetFontLib();849int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();850return GetPGF()->GetCharInfo(charCode, charInfo, altCharCode, glyphType);851}852853inline void LoadedFont::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const {854_dbg_assert_(IsValid());855auto fontLib = GetFontLib();856int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();857GetPGF()->DrawCharacter(image, clipX, clipY, clipWidth, clipHeight, charCode, altCharCode, glyphType);858}859860static FontLib *GetFontLib(u32 handle) {861auto iter = fontLibMap.find(handle);862if (iter != fontLibMap.end()) {863return fontLibList[iter->second];864}865return nullptr;866}867868static LoadedFont *GetLoadedFont(u32 handle, bool allowClosed) {869auto iter = fontMap.find(handle);870if (iter != fontMap.end()) {871if (iter->second->IsOpen() || allowClosed) {872return fontMap[handle];873} else {874ERROR_LOG(Log::sceFont, "Font exists but is closed, which was not allowed in this call.");875return 0;876}877} else {878ERROR_LOG(Log::sceFont, "No font with handle %08x", handle);879return 0;880}881}882883static void __LoadInternalFonts() {884if (internalFonts.size()) {885// Fonts already loaded.886return;887}888const std::string fontPath = "flash0:/font/";889const std::string fontOverridePath = "ms0:/PSP/flash0/font/";890const std::string gameFontPath = "disc0:/PSP_GAME/USRDIR/";891892if (!pspFileSystem.GetFileInfo(fontPath).exists) {893pspFileSystem.MkDir(fontPath);894}895if ((pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/zh_gb.pgf").exists) && (pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/oldfont.prx").exists)) {896for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {897const FontRegistryEntry &entry = fontRegistry[i];898std::string fontFilename = gameFontPath + entry.fileName;899std::vector<u8> buffer;900if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {901ERROR_LOG(Log::sceFont, "Failed opening font %s", fontFilename.c_str());902continue;903}904DEBUG_LOG(Log::sceFont, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)buffer.size());905internalFonts.push_back(new Font(buffer, entry));906DEBUG_LOG(Log::sceFont, "Loaded font %s", fontFilename.c_str());907return;908}909}910911for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {912const FontRegistryEntry &entry = fontRegistry[i];913std::vector<u8> buffer;914bool bufferRead = false;915916std::string fontFilename = gameFontPath + entry.fileName;917bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer, true) >= 0;918919if (!bufferRead) {920// No game font, let's try override path.921fontFilename = fontOverridePath + entry.fileName;922bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer, true) >= 0;923}924925if (!bufferRead) {926// No override, let's use the default path.927fontFilename = fontPath + entry.fileName;928bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer) >= 0;929}930931if (bufferRead) {932DEBUG_LOG(Log::sceFont, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)buffer.size());933internalFonts.push_back(new Font(buffer, entry));934935DEBUG_LOG(Log::sceFont, "Loaded font %s", fontFilename.c_str());936} else if (!entry.ignoreIfMissing) {937WARN_LOG(Log::sceFont, "Font file not found: %s", fontFilename.c_str());938}939}940}941942int GetInternalFontIndex(Font *font) {943for (size_t i = 0; i < internalFonts.size(); i++) {944if (internalFonts[i] == font)945return (int)i;946}947return -1;948}949950void __FontInit() {951useAllocCallbacks = true;952actionPostAllocCallback = __KernelRegisterActionType(PostAllocCallback::Create);953actionPostOpenCallback = __KernelRegisterActionType(PostOpenCallback::Create);954actionPostOpenAllocCallback = __KernelRegisterActionType(PostOpenAllocCallback::Create);955actionPostCharInfoAllocCallback = __KernelRegisterActionType(PostCharInfoAllocCallback::Create);956actionPostCharInfoFreeCallback = __KernelRegisterActionType(PostCharInfoFreeCallback::Create);957}958959void __FontShutdown() {960for (const auto &[_, font] : fontMap) {961if (font->IsValid()) {962FontLib *fontLib = font->GetFontLib();963if (fontLib) {964fontLib->CloseFont(font, true);965}966} else {967ERROR_LOG(Log::HLE, "__FontShutdown: Bad entry in fontMap");968}969delete font;970}971fontMap.clear();972for (auto *fontlib : fontLibList) {973delete fontlib;974}975fontLibList.clear();976fontLibMap.clear();977for (auto *font : internalFonts) {978delete font;979}980internalFonts.clear();981}982983void __FontDoState(PointerWrap &p) {984auto s = p.Section("sceFont", 1, 3);985if (!s)986return;987988bool needInternalFonts = true;989if (s >= 3) {990// If we loaded internal fonts, we need to load them when loading the state.991needInternalFonts = !internalFonts.empty();992Do(p, needInternalFonts);993}994if (needInternalFonts && p.mode == PointerWrap::MODE_READ)995__LoadInternalFonts();996997Do(p, fontLibList);998Do(p, fontLibMap);999Do(p, fontMap);10001001Do(p, actionPostAllocCallback);1002__KernelRestoreActionType(actionPostAllocCallback, PostAllocCallback::Create);1003Do(p, actionPostOpenCallback);1004__KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);1005if (s >= 2) {1006Do(p, actionPostOpenAllocCallback);1007__KernelRestoreActionType(actionPostOpenAllocCallback, PostOpenAllocCallback::Create);1008Do(p, actionPostCharInfoAllocCallback);1009__KernelRestoreActionType(actionPostCharInfoAllocCallback, PostCharInfoAllocCallback::Create);1010Do(p, actionPostCharInfoFreeCallback);1011__KernelRestoreActionType(actionPostCharInfoFreeCallback, PostCharInfoFreeCallback::Create);1012} else {1013useAllocCallbacks = false;1014}1015}10161017static u32 sceFontNewLib(u32 paramPtr, u32 errorCodePtr) {1018// Lazy load internal fonts, only when font library first inited.1019__LoadInternalFonts();10201021auto params = PSPPointer<FontNewLibParams>::Create(paramPtr);1022auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);10231024if (!params.IsValid() || !errorCode.IsValid()) {1025ERROR_LOG_REPORT(Log::sceFont, "sceFontNewLib(%08x, %08x): invalid addresses", paramPtr, errorCodePtr);1026// The PSP would crash in this situation, not a real error code.1027return SCE_KERNEL_ERROR_ILLEGAL_ADDR;1028}1029if (!Memory::IsValidAddress(params->allocFuncAddr) || !Memory::IsValidAddress(params->freeFuncAddr)) {1030ERROR_LOG_REPORT(Log::sceFont, "sceFontNewLib(%08x, %08x): missing alloc func", paramPtr, errorCodePtr);1031*errorCode = ERROR_FONT_INVALID_PARAMETER;1032return 0;1033}10341035INFO_LOG(Log::sceFont, "sceFontNewLib(%08x, %08x)", paramPtr, errorCodePtr);1036*errorCode = 0;10371038FontLib *newLib = new FontLib(params, errorCodePtr);1039fontLibList.push_back(newLib);1040// The game should never see this value, the return value is replaced1041// by the action. Except if we disable the alloc, in this case we return1042// the handle correctly here.1043return hleDelayResult(newLib->handle(), "new fontlib", 30000);1044}10451046static int sceFontDoneLib(u32 fontLibHandle) {1047FontLib *fl = GetFontLib(fontLibHandle);1048if (fl) {1049fl->Done();1050return hleLogSuccessInfoI(Log::sceFont, 0);1051}10521053return hleLogWarning(Log::sceFont, 0, "invalid font lib");1054}10551056// Open internal font into a FontLib1057static u32 sceFontOpen(u32 libHandle, u32 index, u32 mode, u32 errorCodePtr) {1058auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1059if (!errorCode.IsValid()) {1060// Would crash on the PSP.1061return hleLogError(Log::sceFont, -1, "invalid error address");1062}10631064FontLib *fontLib = GetFontLib(libHandle);1065if (!fontLib) {1066*errorCode = ERROR_FONT_INVALID_LIBID;1067return hleLogDebug(Log::sceFont, 0, "invalid font lib");1068}1069if (index >= internalFonts.size()) {1070*errorCode = ERROR_FONT_INVALID_PARAMETER;1071return hleLogDebug(Log::sceFont, 0, "invalid font index");1072}10731074FontOpenMode openMode = mode != 1 ? FONT_OPEN_INTERNAL_STINGY : FONT_OPEN_INTERNAL_FULL;1075LoadedFont *font = fontLib->OpenFont(internalFonts[index], openMode, *errorCode);1076if (font) {1077*errorCode = 0;1078// Delay only on the first open.1079if (fontLib->GetFontRefCount(internalFonts[index]) == 1)1080return hleDelayResult(hleLogSuccessX(Log::sceFont, font->Handle()), "font open", 10000);1081return hleLogSuccessX(Log::sceFont, font->Handle());1082}1083return 0;1084}10851086// Open a user font in RAM into a FontLib1087static u32 sceFontOpenUserMemory(u32 libHandle, u32 memoryFontPtr, u32 memoryFontLength, u32 errorCodePtr) {1088auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1089if (!errorCode.IsValid()) {1090return hleReportError(Log::sceFont, -1, "invalid error address");1091}1092if (!Memory::IsValidAddress(memoryFontPtr)) {1093*errorCode = ERROR_FONT_INVALID_PARAMETER;1094return hleReportError(Log::sceFont, 0, "invalid address");1095}10961097FontLib *fontLib = GetFontLib(libHandle);1098if (!fontLib) {1099*errorCode = ERROR_FONT_INVALID_LIBID;1100return hleReportError(Log::sceFont, 0, "invalid font lib");1101}1102if (memoryFontLength == 0) {1103*errorCode = ERROR_FONT_INVALID_PARAMETER;1104return hleReportError(Log::sceFont, 0, "invalid size");1105}11061107const u8 *fontData = Memory::GetPointer(memoryFontPtr);1108// Games are able to overstate the size of a font. Let's avoid crashing when we memcpy() it.1109// Unsigned 0xFFFFFFFF is treated as max, but that's impossible, so let's clamp to 64MB.1110if (memoryFontLength > 0x03FFFFFF)1111memoryFontLength = 0x03FFFFFF;1112while (!Memory::IsValidAddress(memoryFontPtr + memoryFontLength - 1)) {1113--memoryFontLength;1114}1115Font *f = new Font(fontData, memoryFontLength);1116LoadedFont *font = fontLib->OpenFont(f, FONT_OPEN_USERBUFFER, *errorCode);1117if (font) {1118*errorCode = 0;1119return hleLogSuccessX(Log::sceFont, font->Handle());1120}1121delete f;1122return 0;1123}11241125// Open a user font in a file into a FontLib1126static u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u32 errorCodePtr) {1127auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1128if (!errorCode.IsValid()) {1129return hleReportError(Log::sceFont, ERROR_FONT_INVALID_PARAMETER, "invalid error address");1130}11311132if (!fileName) {1133*errorCode = ERROR_FONT_INVALID_PARAMETER;1134return hleReportError(Log::sceFont, 0, "invalid filename");1135}11361137FontLib *fontLib = GetFontLib(libHandle);1138if (!fontLib) {1139*errorCode = ERROR_FONT_INVALID_LIBID;1140return hleReportError(Log::sceFont, 0, "invalid font lib");1141}11421143// TODO: Technically, we only do this if mode = 1. Mode 0 uses the handlers.1144if (mode != 1) {1145WARN_LOG_REPORT(Log::sceFont, "Loading file directly instead of using handlers: %s", fileName);1146}11471148std::vector<u8> buffer;1149if (pspFileSystem.ReadEntireFile(fileName, buffer) != 0) {1150*errorCode = ERROR_FONT_HANDLER_OPEN_FAILED;1151return hleLogError(Log::sceFont, 0, "file does not exist");1152}11531154Font *f = new Font(buffer);1155FontOpenMode openMode = mode == 0 ? FONT_OPEN_USERFILE_HANDLERS : FONT_OPEN_USERFILE_FULL;1156LoadedFont *font = fontLib->OpenFont(f, openMode, *errorCode);1157if (font) {1158*errorCode = 0;1159return hleLogSuccessInfoX(Log::sceFont, font->Handle());1160}11611162delete f;1163// Message was already logged.1164return 0;1165}11661167static int sceFontClose(u32 fontHandle) {1168LoadedFont *font = GetLoadedFont(fontHandle, false);1169if (font) {1170DEBUG_LOG(Log::sceFont, "sceFontClose(%x)", fontHandle);1171FontLib *fontLib = font->GetFontLib();1172if (fontLib) {1173fontLib->CloseFont(font, false);1174}1175} else1176ERROR_LOG(Log::sceFont, "sceFontClose(%x) - font not open?", fontHandle);1177return 0;1178}11791180static int sceFontFindOptimumFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {1181auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1182if (!errorCode.IsValid()) {1183return hleReportError(Log::sceFont, SCE_KERNEL_ERROR_INVALID_ARGUMENT, "invalid error address");1184}11851186FontLib *fontLib = GetFontLib(libHandle);1187if (!fontLib) {1188*errorCode = ERROR_FONT_INVALID_LIBID;1189return hleReportError(Log::sceFont, 0, "invalid font lib");1190}11911192if (!Memory::IsValidAddress(fontStylePtr)) {1193// Yes, actually. Must've been a typo in the library.1194*errorCode = ERROR_FONT_INVALID_LIBID;1195return hleReportError(Log::sceFont, 0, "invalid style address");1196}11971198auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);1199DEBUG_LOG(Log::sceFont, "requestedStyle fontAttributes %i,fontCountry %i,fontExpire %i,fontFamily %i,fontFileName %s,fontH %f,fontHRes %f,fontLanguage %i,fontName %s,fontRegion %i,fontStyle %i,fontStyleSub %i,fontV %f,fontVRes %f,fontWeight %f", requestedStyle->fontAttributes, requestedStyle->fontCountry, requestedStyle->fontExpire, requestedStyle->fontFamily, requestedStyle->fontFileName, requestedStyle->fontH, requestedStyle->fontHRes, requestedStyle->fontLanguage, requestedStyle->fontName, requestedStyle->fontRegion, requestedStyle->fontStyle, requestedStyle->fontStyleSub, requestedStyle->fontV, requestedStyle->fontVRes, requestedStyle->fontWeight);12001201// Find the first nearest match for H/V, OR the last exact match for others.1202float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();1203float vRes = requestedStyle->fontVRes > 0.0f ? (float)requestedStyle->fontVRes : fontLib->FontVRes();1204Font *optimumFont = 0;1205Font *nearestFont = 0;1206float nearestDist = std::numeric_limits<float>::infinity();12071208if (PSP_CoreParameter().compat.flags().Fontltn12Hack && requestedStyle->fontLanguage == 2) {1209for (size_t j = 0; j < internalFonts.size(); j++) {1210const auto tempmatchStyle = internalFonts[j]->GetFontStyle();1211const std::string str(tempmatchStyle.fontFileName);1212if (str == "ltn12.pgf") {1213optimumFont = internalFonts[j];1214*errorCode = 0;1215return GetInternalFontIndex(optimumFont);1216}1217}1218}12191220for (size_t i = 0; i < internalFonts.size(); i++) {1221MatchQuality q = internalFonts[i]->MatchesStyle(*requestedStyle);1222if (q != MATCH_NONE) {1223const auto &matchStyle = internalFonts[i]->GetFontStyle();1224if (requestedStyle->fontH > 0.0f) {1225float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);1226if (hDist < nearestDist) {1227nearestDist = hDist;1228nearestFont = internalFonts[i];1229}1230}1231if (requestedStyle->fontV > 0.0f) {1232// Appears to be a bug? It seems to match H instead of V.1233float vDist = fabs(matchStyle.fontVRes * matchStyle.fontV - vRes * requestedStyle->fontH);1234if (vDist < nearestDist) {1235nearestDist = vDist;1236nearestFont = internalFonts[i];1237}1238}1239}1240if (q == MATCH_GOOD) {1241optimumFont = internalFonts[i];1242}1243}1244if (nearestFont) {1245optimumFont = nearestFont;1246}1247if (optimumFont) {1248*errorCode = 0;1249return hleLogSuccessInfoX(Log::sceFont, GetInternalFontIndex(optimumFont) ,"");1250} else {1251*errorCode = 0;1252return hleLogSuccessInfoX(Log::sceFont, 0, "");1253}1254}12551256// Returns the font index, not handle1257static int sceFontFindFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {1258auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1259if (!errorCode.IsValid()) {1260ERROR_LOG_REPORT(Log::sceFont, "sceFontFindFont(%x, %x, %x): invalid error address", libHandle, fontStylePtr, errorCodePtr);1261return SCE_KERNEL_ERROR_INVALID_ARGUMENT;1262}12631264FontLib *fontLib = GetFontLib(libHandle);1265if (!fontLib) {1266ERROR_LOG_REPORT(Log::sceFont, "sceFontFindFont(%08x, %08x, %08x): invalid font lib", libHandle, fontStylePtr, errorCodePtr);1267*errorCode = ERROR_FONT_INVALID_LIBID;1268return 0;1269}12701271if (!Memory::IsValidAddress(fontStylePtr)) {1272ERROR_LOG_REPORT(Log::sceFont, "sceFontFindFont(%08x, %08x, %08x): invalid style address", libHandle, fontStylePtr, errorCodePtr);1273*errorCode = ERROR_FONT_INVALID_PARAMETER;1274return 0;1275}12761277DEBUG_LOG(Log::sceFont, "sceFontFindFont(%x, %x, %x)", libHandle, fontStylePtr, errorCodePtr);12781279auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);1280DEBUG_LOG(Log::sceFont, "requestedStyle fontAttributes %i,fontCountry %i,fontExpire %i,fontFamily %i,fontFileName %s,fontH %f,fontHRes %f,fontLanguage %i,fontName %s,fontRegion %i,fontStyle %i,fontStyleSub %i,fontV %f,fontVRes %f,fontWeight %f", requestedStyle->fontAttributes, requestedStyle->fontCountry, requestedStyle->fontExpire, requestedStyle->fontFamily, requestedStyle->fontFileName, requestedStyle->fontH, requestedStyle->fontHRes, requestedStyle->fontLanguage, requestedStyle->fontName, requestedStyle->fontRegion, requestedStyle->fontStyle, requestedStyle->fontStyleSub, requestedStyle->fontV, requestedStyle->fontVRes, requestedStyle->fontWeight);12811282// Find the closest exact match for the fields specified.1283float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();1284for (size_t i = 0; i < internalFonts.size(); i++) {1285if (internalFonts[i]->MatchesStyle(*requestedStyle) != MATCH_NONE) {1286const auto &matchStyle = internalFonts[i]->GetFontStyle();1287if (requestedStyle->fontH > 0.0f) {1288float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);1289if (hDist > 0.001f) {1290continue;1291}1292} else if (requestedStyle->fontV > 0.0f) {1293// V seems to be ignored, unless H isn't specified.1294// If V is specified alone, the match always fails.1295continue;1296}1297*errorCode = 0;1298return (int)i;1299}1300}1301*errorCode = 0;1302return -1;1303}13041305static int sceFontGetFontInfo(u32 fontHandle, u32 fontInfoPtr) {1306if (!Memory::IsValidAddress(fontInfoPtr)) {1307ERROR_LOG(Log::sceFont, "sceFontGetFontInfo(%x, %x): bad fontInfo pointer", fontHandle, fontInfoPtr);1308return ERROR_FONT_INVALID_PARAMETER;1309}1310LoadedFont *font = GetLoadedFont(fontHandle, true);1311if (!font) {1312ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontInfo(%x, %x): bad font", fontHandle, fontInfoPtr);1313return ERROR_FONT_INVALID_PARAMETER;1314}13151316DEBUG_LOG(Log::sceFont, "sceFontGetFontInfo(%x, %x)", fontHandle, fontInfoPtr);1317auto fi = PSPPointer<PGFFontInfo>::Create(fontInfoPtr);1318font->GetPGF()->GetFontInfo(fi);1319fi->fontStyle = font->GetFont()->GetFontStyle();13201321return 0;1322}13231324// It says FontInfo but it means Style - this is like sceFontGetFontList().1325static int sceFontGetFontInfoByIndexNumber(u32 libHandle, u32 fontInfoPtr, u32 index) {1326auto fontStyle = PSPPointer<PGFFontStyle>::Create(fontInfoPtr);1327FontLib *fl = GetFontLib(libHandle);1328if (!fl || fl->handle() == 0) {1329ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font lib", libHandle, fontInfoPtr, index);1330return !fl ? ERROR_FONT_INVALID_LIBID : ERROR_FONT_INVALID_PARAMETER;1331}1332if (index >= internalFonts.size()) {1333ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font index", libHandle, fontInfoPtr, index);1334return ERROR_FONT_INVALID_PARAMETER;1335}1336if (!fontStyle.IsValid()) {1337ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid info pointer", libHandle, fontInfoPtr, index);1338return ERROR_FONT_INVALID_PARAMETER;1339}13401341DEBUG_LOG(Log::sceFont, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i)", libHandle, fontInfoPtr, index);1342auto font = internalFonts[index];1343*fontStyle = font->GetFontStyle();13441345return 0;1346}13471348static int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {1349charCode &= 0xffff;1350if (!Memory::IsValidAddress(charInfoPtr)) {1351ERROR_LOG(Log::sceFont, "sceFontGetCharInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);1352return ERROR_FONT_INVALID_PARAMETER;1353}1354LoadedFont *font = GetLoadedFont(fontHandle, true);1355if (!font) {1356// The PSP crashes, but we assume it'd work like sceFontGetFontInfo(), and not touch charInfo.1357ERROR_LOG_REPORT(Log::sceFont, "sceFontGetCharInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);1358return ERROR_FONT_INVALID_PARAMETER;1359}13601361DEBUG_LOG(Log::sceFont, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);1362auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);1363font->GetCharInfo(charCode, charInfo);13641365if (!useAllocCallbacks)1366return 0;13671368u32 allocSize = charInfo->bitmapWidth * charInfo->bitmapHeight;1369if (font->GetFontLib() && (charInfo->sfp26AdvanceH != 0 || charInfo->sfp26AdvanceV != 0)) {1370if (font->GetFontLib()->GetCharInfoBitmapAddress() != 0) {1371PostCharInfoFreeCallback *action = (PostCharInfoFreeCallback *)__KernelCreateAction(actionPostCharInfoFreeCallback);1372action->SetFontLib(font->GetFontLib()->GetListID());1373action->SetCharInfo(charInfo);13741375u32 args[2] = { font->GetFontLib()->userDataAddr(), font->GetFontLib()->GetCharInfoBitmapAddress() };1376hleEnqueueCall(font->GetFontLib()->freeFuncAddr(), 2, args, action);1377} else {1378PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);1379action->SetFontLib(font->GetFontLib()->GetListID());13801381u32 args[2] = { font->GetFontLib()->userDataAddr(), allocSize };1382hleEnqueueCall(font->GetFontLib()->allocFuncAddr(), 2, args, action);1383}1384}13851386return 0;1387}13881389static int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {1390charCode &= 0xffff;1391if (!Memory::IsValidAddress(charInfoPtr)) {1392ERROR_LOG(Log::sceFont, "sceFontGetShadowInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);1393return ERROR_FONT_INVALID_PARAMETER;1394}1395LoadedFont *font = GetLoadedFont(fontHandle, true);1396if (!font) {1397ERROR_LOG_REPORT(Log::sceFont, "sceFontGetShadowInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);1398return ERROR_FONT_INVALID_PARAMETER;1399}14001401DEBUG_LOG(Log::sceFont, "sceFontGetShadowInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);1402auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);1403font->GetCharInfo(charCode, charInfo, FONT_PGF_SHADOWGLYPH);14041405return 0;1406}14071408static int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {1409charCode &= 0xffff;1410auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);1411LoadedFont *font = GetLoadedFont(fontHandle, true);1412if (!font) {1413ERROR_LOG_REPORT(Log::sceFont, "sceFontGetCharImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);1414return ERROR_FONT_INVALID_PARAMETER;1415}1416if (!charRect.IsValid()) {1417ERROR_LOG_REPORT(Log::sceFont, "sceFontGetCharImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);1418return ERROR_FONT_INVALID_PARAMETER;1419}14201421DEBUG_LOG(Log::sceFont, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);1422PGFCharInfo charInfo;1423font->GetCharInfo(charCode, &charInfo);1424charRect->width = charInfo.bitmapWidth;1425charRect->height = charInfo.bitmapHeight;1426return 0;1427}14281429static int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {1430charCode &= 0xffff;1431auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);1432LoadedFont *font = GetLoadedFont(fontHandle, true);1433if (!font) {1434ERROR_LOG_REPORT(Log::sceFont, "sceFontGetShadowImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);1435return ERROR_FONT_INVALID_PARAMETER;1436}1437if (!charRect.IsValid()) {1438ERROR_LOG_REPORT(Log::sceFont, "sceFontGetShadowImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);1439return ERROR_FONT_INVALID_PARAMETER;1440}14411442DEBUG_LOG(Log::sceFont, "sceFontGetShadowImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);1443PGFCharInfo charInfo;1444font->GetCharInfo(charCode, &charInfo, FONT_PGF_SHADOWGLYPH);1445charRect->width = charInfo.bitmapWidth;1446charRect->height = charInfo.bitmapHeight;1447return 0;1448}14491450static int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {1451charCode &= 0xffff;1452if (!Memory::IsValidAddress(glyphImagePtr)) {1453ERROR_LOG(Log::sceFont, "sceFontGetCharGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);1454return ERROR_FONT_INVALID_PARAMETER;1455}1456LoadedFont *font = GetLoadedFont(fontHandle, true);1457if (!font) {1458ERROR_LOG_REPORT(Log::sceFont, "sceFontGetCharGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);1459return ERROR_FONT_INVALID_PARAMETER;1460}14611462DEBUG_LOG(Log::sceFont, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);1463auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);1464font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_CHARGLYPH);1465return 0;1466}14671468static int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {1469charCode &= 0xffff;1470if (!Memory::IsValidAddress(glyphImagePtr)) {1471ERROR_LOG(Log::sceFont, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1472return ERROR_FONT_INVALID_PARAMETER;1473}1474LoadedFont *font = GetLoadedFont(fontHandle, true);1475if (!font) {1476ERROR_LOG_REPORT(Log::sceFont, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1477return ERROR_FONT_INVALID_PARAMETER;1478}14791480DEBUG_LOG(Log::sceFont, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1481auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);1482font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_CHARGLYPH);1483return 0;1484}14851486static int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode) {1487charCode &= 0xffff;1488FontLib *fl = GetFontLib(fontLibHandle);1489if (!fl) {1490ERROR_LOG_REPORT(Log::sceFont, "sceFontSetAltCharacterCode(%08x, %08x): invalid font lib", fontLibHandle, charCode);1491return ERROR_FONT_INVALID_LIBID;1492}14931494INFO_LOG(Log::sceFont, "sceFontSetAltCharacterCode(%08x, %08x)", fontLibHandle, charCode);1495fl->SetAltCharCode(charCode & 0xFFFF);1496return 0;1497}14981499static int sceFontFlush(u32 fontHandle) {1500INFO_LOG(Log::sceFont, "sceFontFlush(%i)", fontHandle);15011502LoadedFont *font = GetLoadedFont(fontHandle, true);1503if (!font) {1504ERROR_LOG_REPORT(Log::sceFont, "sceFontFlush(%08x): bad font", fontHandle);1505return ERROR_FONT_INVALID_PARAMETER;1506}15071508if (font->GetFontLib()) {1509font->GetFontLib()->flushFont();1510}1511return 0;1512}15131514// One would think that this should loop through the fonts loaded in the fontLibHandle,1515// but it seems not.1516static int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, int numFonts) {1517auto fontStyles = PSPPointer<PGFFontStyle>::Create(fontStylePtr);1518FontLib *fl = GetFontLib(fontLibHandle);1519if (!fl) {1520ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontList(%08x, %08x, %i): invalid font lib", fontLibHandle, fontStylePtr, numFonts);1521return ERROR_FONT_INVALID_LIBID;1522}1523if (!fontStyles.IsValid()) {1524ERROR_LOG_REPORT(Log::sceFont, "sceFontGetFontList(%08x, %08x, %i): invalid style pointer", fontLibHandle, fontStylePtr, numFonts);1525return ERROR_FONT_INVALID_PARAMETER;1526}15271528DEBUG_LOG(Log::sceFont, "sceFontGetFontList(%08x, %08x, %i)", fontLibHandle, fontStylePtr, numFonts);1529if (fl->handle() != 0) {1530numFonts = std::min(numFonts, (int)internalFonts.size());1531for (int i = 0; i < numFonts; i++)1532fontStyles[i] = internalFonts[i]->GetFontStyle();1533}15341535return hleDelayResult(0, "font list read", 100);1536}15371538static int sceFontGetNumFontList(u32 fontLibHandle, u32 errorCodePtr) {1539auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1540if (!errorCode.IsValid()) {1541ERROR_LOG_REPORT(Log::sceFont, "sceFontGetNumFontList(%08x, %08x): invalid error address", fontLibHandle, errorCodePtr);1542return ERROR_FONT_INVALID_PARAMETER;1543}1544FontLib *fl = GetFontLib(fontLibHandle);1545if (!fl) {1546ERROR_LOG_REPORT(Log::sceFont, "sceFontGetNumFontList(%08x, %08x): invalid font lib", fontLibHandle, errorCodePtr);1547*errorCode = ERROR_FONT_INVALID_LIBID;1548return 0;1549}1550DEBUG_LOG(Log::sceFont, "sceFontGetNumFontList(%08x, %08x)", fontLibHandle, errorCodePtr);1551*errorCode = 0;1552return fl->handle() == 0 ? 0 : (int)internalFonts.size();1553}15541555static int sceFontSetResolution(u32 fontLibHandle, float hRes, float vRes) {1556FontLib *fl = GetFontLib(fontLibHandle);1557if (!fl) {1558ERROR_LOG_REPORT(Log::sceFont, "sceFontSetResolution(%08x, %f, %f): invalid font lib", fontLibHandle, hRes, vRes);1559return ERROR_FONT_INVALID_LIBID;1560}1561if (hRes <= 0.0f || vRes <= 0.0f) {1562ERROR_LOG_REPORT(Log::sceFont, "sceFontSetResolution(%08x, %f, %f): negative value", fontLibHandle, hRes, vRes);1563return ERROR_FONT_INVALID_PARAMETER;1564}1565INFO_LOG(Log::sceFont, "sceFontSetResolution(%08x, %f, %f)", fontLibHandle, hRes, vRes);1566fl->SetResolution(hRes, vRes);1567return 0;1568}15691570static float sceFontPixelToPointH(int fontLibHandle, float fontPixelsH, u32 errorCodePtr) {1571auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1572if (!errorCode.IsValid()) {1573ERROR_LOG_REPORT(Log::sceFont, "sceFontPixelToPointH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsH, errorCodePtr);1574return 0.0f;1575}1576FontLib *fl = GetFontLib(fontLibHandle);1577if (!fl) {1578ERROR_LOG_REPORT(Log::sceFont, "sceFontPixelToPointH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsH, errorCodePtr);1579*errorCode = ERROR_FONT_INVALID_LIBID;1580return 0.0f;1581}1582DEBUG_LOG(Log::sceFont, "sceFontPixelToPointH(%08x, %f, %08x)", fontLibHandle, fontPixelsH, errorCodePtr);1583*errorCode = 0;1584return fontPixelsH * pointDPI / fl->FontHRes();1585}15861587static float sceFontPixelToPointV(int fontLibHandle, float fontPixelsV, u32 errorCodePtr) {1588auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1589if (!errorCode.IsValid()) {1590ERROR_LOG_REPORT(Log::sceFont, "sceFontPixelToPointV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsV, errorCodePtr);1591return 0.0f;1592}1593FontLib *fl = GetFontLib(fontLibHandle);1594if (!fl) {1595ERROR_LOG_REPORT(Log::sceFont, "sceFontPixelToPointV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsV, errorCodePtr);1596*errorCode = ERROR_FONT_INVALID_LIBID;1597return 0.0f;1598}1599DEBUG_LOG(Log::sceFont, "sceFontPixelToPointV(%08x, %f, %08x)", fontLibHandle, fontPixelsV, errorCodePtr);1600*errorCode = 0;1601return fontPixelsV * pointDPI / fl->FontVRes();1602}16031604static float sceFontPointToPixelH(int fontLibHandle, float fontPointsH, u32 errorCodePtr) {1605auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1606if (!errorCode.IsValid()) {1607ERROR_LOG_REPORT(Log::sceFont, "sceFontPointToPixelH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsH, errorCodePtr);1608return 0.0f;1609}1610FontLib *fl = GetFontLib(fontLibHandle);1611if (!fl) {1612ERROR_LOG_REPORT(Log::sceFont, "sceFontPointToPixelH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsH, errorCodePtr);1613*errorCode = ERROR_FONT_INVALID_LIBID;1614return 0.0f;1615}1616DEBUG_LOG(Log::sceFont, "sceFontPointToPixelH(%08x, %f, %08x)", fontLibHandle, fontPointsH, errorCodePtr);1617*errorCode = 0;1618return fontPointsH * fl->FontHRes() / pointDPI;1619}16201621static float sceFontPointToPixelV(int fontLibHandle, float fontPointsV, u32 errorCodePtr) {1622auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);1623if (!errorCode.IsValid()) {1624ERROR_LOG_REPORT(Log::sceFont, "sceFontPointToPixelV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsV, errorCodePtr);1625return 0.0f;1626}1627FontLib *fl = GetFontLib(fontLibHandle);1628if (!fl) {1629ERROR_LOG_REPORT(Log::sceFont, "sceFontPointToPixelV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsV, errorCodePtr);1630*errorCode = ERROR_FONT_INVALID_LIBID;1631return 0.0f;1632}1633DEBUG_LOG(Log::sceFont, "sceFontPointToPixelV(%08x, %f, %08x)", fontLibHandle, fontPointsV, errorCodePtr);1634*errorCode = 0;1635return fontPointsV * fl->FontVRes() / pointDPI;1636}16371638static int sceFontCalcMemorySize() {1639ERROR_LOG_REPORT(Log::sceFont, "UNIMPL sceFontCalcMemorySize()");1640return 0;1641}16421643static int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {1644charCode &= 0xffff;1645if (!Memory::IsValidAddress(glyphImagePtr)) {1646ERROR_LOG(Log::sceFont, "sceFontGetShadowGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);1647return ERROR_FONT_INVALID_PARAMETER;1648}1649LoadedFont *font = GetLoadedFont(fontHandle, true);1650if (!font) {1651ERROR_LOG_REPORT(Log::sceFont, "sceFontGetShadowGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);1652return ERROR_FONT_INVALID_PARAMETER;1653}16541655DEBUG_LOG(Log::sceFont, "sceFontGetShadowGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);1656auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);1657font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_SHADOWGLYPH);1658return 0;1659}16601661static int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {1662charCode &= 0xffff;1663if (!Memory::IsValidAddress(glyphImagePtr)) {1664ERROR_LOG(Log::sceFont, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1665return ERROR_FONT_INVALID_PARAMETER;1666}1667LoadedFont *font = GetLoadedFont(fontHandle, true);1668if (!font) {1669ERROR_LOG_REPORT(Log::sceFont, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1670return ERROR_FONT_INVALID_PARAMETER;1671}16721673DEBUG_LOG(Log::sceFont, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);1674auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);1675font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_SHADOWGLYPH);1676return 0;1677}16781679// sceLibFont is a user level library so it can touch the stack. Some games appear to rely a bit of stack1680// being wiped - although in reality, it won't be wiped with just zeroes..1681const HLEFunction sceLibFont[] = {1682{0X67F17ED7, &WrapU_UU<sceFontNewLib>, "sceFontNewLib", 'x', "xx", HLE_CLEAR_STACK_BYTES, 0x5A0 },1683{0X574B6FBC, &WrapI_U<sceFontDoneLib>, "sceFontDoneLib", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x2C },1684{0X48293280, &WrapI_UFF<sceFontSetResolution>, "sceFontSetResolution", 'i', "xff" },1685{0X27F6E642, &WrapI_UU<sceFontGetNumFontList>, "sceFontGetNumFontList", 'i', "xx" },1686{0XBC75D85B, &WrapI_UUI<sceFontGetFontList>, "sceFontGetFontList", 'i', "xxi", HLE_CLEAR_STACK_BYTES, 0x31C },1687{0X099EF33C, &WrapI_UUU<sceFontFindOptimumFont>, "sceFontFindOptimumFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0xF0 },1688{0X681E61A7, &WrapI_UUU<sceFontFindFont>, "sceFontFindFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x40 },1689{0X2F67356A, &WrapI_V<sceFontCalcMemorySize>, "sceFontCalcMemorySize", 'i', "" },1690{0X5333322D, &WrapI_UUU<sceFontGetFontInfoByIndexNumber>, "sceFontGetFontInfoByIndexNumber", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x20 },1691{0XA834319D, &WrapU_UUUU<sceFontOpen>, "sceFontOpen", 'x', "xxxp", HLE_CLEAR_STACK_BYTES, 0x460 },1692{0X57FCB733, &WrapU_UCUU<sceFontOpenUserFile>, "sceFontOpenUserFile", 'x', "xsxp" },1693{0XBB8E7FE6, &WrapU_UUUU<sceFontOpenUserMemory>, "sceFontOpenUserMemory", 'x', "xxxp", HLE_CLEAR_STACK_BYTES, 0x440 /*from JPCSP*/ },1694{0X3AEA8CB6, &WrapI_U<sceFontClose>, "sceFontClose", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x54 },1695{0X0DA7535E, &WrapI_UU<sceFontGetFontInfo>, "sceFontGetFontInfo", 'i', "xx" },1696{0XDCC80C2F, &WrapI_UUU<sceFontGetCharInfo>, "sceFontGetCharInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x110 },1697{0XAA3DE7B5, &WrapI_UUU<sceFontGetShadowInfo>, "sceFontGetShadowInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },1698{0X5C3E4A9E, &WrapI_UUU<sceFontGetCharImageRect>, "sceFontGetCharImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },1699{0X48B06520, &WrapI_UUU<sceFontGetShadowImageRect>, "sceFontGetShadowImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },1700{0X980F4895, &WrapI_UUU<sceFontGetCharGlyphImage>, "sceFontGetCharGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },1701{0XCA1E6945, &WrapI_UUUIIII<sceFontGetCharGlyphImage_Clip>, "sceFontGetCharGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x130 },1702{0X74B21701, &WrapF_IFU<sceFontPixelToPointH>, "sceFontPixelToPointH", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },1703{0XF8F0752E, &WrapF_IFU<sceFontPixelToPointV>, "sceFontPixelToPointV", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },1704{0X472694CD, &WrapF_IFU<sceFontPointToPixelH>, "sceFontPointToPixelH", 'f', "ifx" },1705{0X3C4B7E82, &WrapF_IFU<sceFontPointToPixelV>, "sceFontPointToPixelV", 'f', "ifx" },1706{0XEE232411, &WrapI_UU<sceFontSetAltCharacterCode>, "sceFontSetAltCharacterCode", 'i', "xx" },1707{0X568BE516, &WrapI_UUU<sceFontGetShadowGlyphImage>, "sceFontGetShadowGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x160 },1708{0X5DCF6858, &WrapI_UUUIIII<sceFontGetShadowGlyphImage_Clip>, "sceFontGetShadowGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x170 },1709{0X02D7F94B, &WrapI_U<sceFontFlush>, "sceFontFlush", 'i', "x" },1710};17111712void Register_sceFont() {1713RegisterModule("sceLibFont", ARRAY_SIZE(sceLibFont), sceLibFont);1714}17151716void Register_sceLibFttt() {1717RegisterModule("sceLibFttt", ARRAY_SIZE(sceLibFont), sceLibFont);1718}171917201721