3
#include "base/timeutil.h"
10
#include "Common/ChunkFile.h"
11
#include "Core/HLE/HLE.h"
12
#include "Core/HLE/FunctionWrappers.h"
13
#include "Core/HLE/sceFont.h"
14
#include "Core/HLE/sceKernel.h"
15
#include "Core/HLE/sceKernelThread.h"
16
#include "Core/MIPS/MIPS.h"
17
#include "Core/FileSystems/FileSystem.h"
18
#include "Core/FileSystems/MetaFileSystem.h"
19
#include "Core/MemMapHelpers.h"
20
#include "Core/Reporting.h"
21
#include "Core/System.h"
22
#include "Core/Font/PGF.h"
25
ERROR_FONT_OUT_OF_MEMORY = 0x80460001,
26
ERROR_FONT_INVALID_LIBID = 0x80460002,
27
ERROR_FONT_INVALID_PARAMETER = 0x80460003,
28
ERROR_FONT_HANDLER_OPEN_FAILED = 0x80460005,
29
ERROR_FONT_TOO_MANY_OPEN_FONTS = 0x80460009,
30
ERROR_FONT_INVALID_FONT_DATA = 0x8046000a,
39
static int actionPostAllocCallback;
40
static int actionPostOpenCallback;
42
// Monster Hunter sequence:
43
// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:469 E[HLE]: sceFontNewLib 89ad4a0, 9fff5cc
44
// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:699 E[HLE]: UNIMPL sceFontGetNumFontList 1, 9fff5cc
45
// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:526 E[HLE]: sceFontFindOptimumFont 1, 9fff524, 9fff5cc
46
// 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:490 E[HLE]: sceFontOpenFont 1, 1, 0, 9fff5cc
47
// 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:542 E[HLE]: sceFontGetFontInfo 1, 997140c
49
typedef u32 FontLibraryHandle;
50
typedef u32 FontHandle;
52
struct FontNewLibParams {
65
u32_le ioFinishFuncAddr;
68
struct FontRegistryEntry {
88
static const FontRegistryEntry fontRegistry[] = {
89
// This was added for Chinese translations and is not normally loaded on a PSP.
90
{ 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, true },
91
{ 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 },
92
{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},
93
{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},
94
{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},
95
{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},
96
{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},
97
{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},
98
{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},
99
{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},
100
{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},
101
{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},
102
{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},
103
{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},
104
{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},
105
{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},
106
{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},
107
{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},
108
{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},
111
static const float pointDPI = 72.f;
116
int GetInternalFontIndex(Font *font);
118
// These should not need to be state saved.
119
static std::vector<Font *> internalFonts;
120
// However, these we must save - but we could take a shortcut
121
// for LoadedFonts that point to internal fonts.
122
static std::map<u32, LoadedFont *> fontMap;
123
static std::map<u32, u32> fontLibMap;
124
// We keep this list to avoid ptr references, even before alloc is called.
125
static std::vector<FontLib *> fontLibList;
134
FONT_OPEN_INTERNAL_STINGY = 0,
135
FONT_OPEN_INTERNAL_FULL = 1,
136
// Calls open/seek/read/close handlers to read the file partially.
137
FONT_OPEN_USERFILE_HANDLERS = 2,
138
// Reads directly from filesystem.
139
FONT_OPEN_USERFILE_FULL = 3,
140
FONT_OPEN_USERBUFFER = 4,
143
// TODO: Merge this class with PGF? That'd make it harder to support .bwfon
144
// fonts though, unless that's added directly to PGF.
147
// For savestates only.
151
Font(const u8 *data, size_t dataSize) {
152
Init(data, dataSize);
155
Font(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
156
Init(data, dataSize, entry);
159
Font(const std::vector<u8> &data) {
160
Init(&data[0], data.size());
163
Font(const std::vector<u8> &data, const FontRegistryEntry &entry) {
164
Init(&data[0], data.size(), entry);
167
const PGFFontStyle &GetFontStyle() const { return style_; }
169
MatchQuality MatchesStyle(const PGFFontStyle &style) const {
170
// If no field matches, it doesn't match.
171
MatchQuality match = MATCH_UNKNOWN;
173
#define CHECK_FIELD(f, m) \
174
if (style.f != 0) { \
175
if (style.f != style_.f) { \
182
#define CHECK_FIELD_STR(f, m) \
183
if (style.f[0] != '\0') { \
184
if (strcmp(style.f, style_.f) != 0) { \
192
CHECK_FIELD(fontFamily, MATCH_GOOD);
193
CHECK_FIELD(fontStyle, MATCH_GOOD);
194
CHECK_FIELD(fontLanguage, MATCH_GOOD);
195
CHECK_FIELD(fontCountry, MATCH_GOOD);
197
CHECK_FIELD_STR(fontName, MATCH_GOOD);
198
CHECK_FIELD_STR(fontFileName, MATCH_GOOD);
200
#undef CHECK_FIELD_STR
205
PGF *GetPGF() { return &pgf_; }
206
const PGF *GetPGF() const { return &pgf_; }
207
bool IsValid() const { return valid_; }
209
void DoState(PointerWrap &p) {
210
auto s = p.Section("Font", 1, 2);
224
void Init(const u8 *data, size_t dataSize) {
225
valid_ = pgf_.ReadPtr(data, dataSize);
226
memset(&style_, 0, sizeof(style_));
227
style_.fontH = (float)pgf_.header.hSize / 64.0f;
228
style_.fontV = (float)pgf_.header.vSize / 64.0f;
229
style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;
230
style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;
233
void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
234
valid_ = pgf_.ReadPtr(data, dataSize);
235
style_.fontH = entry.hSize / 64.f;
236
style_.fontV = entry.vSize / 64.f;
237
style_.fontHRes = entry.hResolution / 64.f;
238
style_.fontVRes = entry.vResolution / 64.f;
239
style_.fontWeight = (float)entry.weight;
240
style_.fontFamily = (u16)entry.familyCode;
241
style_.fontStyle = (u16)entry.style;
242
style_.fontStyleSub = (u16)entry.styleSub;
243
style_.fontLanguage = (u16)entry.languageCode;
244
style_.fontRegion = (u16)entry.regionCode;
245
style_.fontCountry = (u16)entry.countryCode;
246
strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName));
247
strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));
248
style_.fontAttributes = entry.extraAttributes;
249
style_.fontExpire = entry.expireDate;
255
DISALLOW_COPY_AND_ASSIGN(Font);
260
// For savestates only.
261
LoadedFont() : font_(NULL) {
264
LoadedFont(Font *font, FontOpenMode mode, u32 fontLibID, u32 handle)
265
: fontLibID_(fontLibID), font_(font), handle_(handle), mode_(mode), open_(true) {}
269
case FONT_OPEN_USERBUFFER:
270
case FONT_OPEN_USERFILE_FULL:
271
case FONT_OPEN_USERFILE_HANDLERS:
272
// For these types, it's our responsibility to delete.
277
// Otherwise, it's an internal font, we keep those.
282
const Font *GetFont() const { return font_; }
283
const PGF *GetPGF() const { return font_->GetPGF(); }
284
const FontLib *GetFontLib() const { return fontLibList[fontLibID_]; }
285
FontLib *GetFontLib() { return fontLibList[fontLibID_]; }
286
u32 Handle() const { return handle_; }
288
bool GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType = FONT_PGF_CHARGLYPH) const;
289
void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const;
291
bool IsOpen() const { return open_; }
294
// We keep the rest around until deleted, as some queries are allowed
295
// on closed fonts (which is rather strange).
298
void DoState(PointerWrap &p) {
299
auto s = p.Section("LoadedFont", 1, 3);
303
int numInternalFonts = (int)internalFonts.size();
304
p.Do(numInternalFonts);
305
if (numInternalFonts != (int)internalFonts.size()) {
306
ERROR_LOG(SCEFONT, "Unable to load state: different internal font count.");
307
p.SetError(p.ERROR_FAILURE);
312
int internalFont = GetInternalFontIndex(font_);
314
if (internalFont == -1) {
316
} else if (p.mode == p.MODE_READ) {
317
font_ = internalFonts[internalFont];
323
open_ = fontLibID_ != (u32)-1;
328
mode_ = FONT_OPEN_INTERNAL_FULL;
338
DISALLOW_COPY_AND_ASSIGN(LoadedFont);
341
class PostAllocCallback : public Action {
343
PostAllocCallback() {}
344
static Action *Create() { return new PostAllocCallback(); }
345
void DoState(PointerWrap &p) override {
346
auto s = p.Section("PostAllocCallback", 1, 2);
355
void run(MipsCall &call) override;
356
void SetFontLib(u32 fontLibID, u32 errorCodePtr) { fontLibID_ = fontLibID; errorCodePtr_ = errorCodePtr; }
363
class PostOpenCallback : public Action {
365
PostOpenCallback() {}
366
static Action *Create() { return new PostOpenCallback(); }
367
void DoState(PointerWrap &p) override {
368
auto s = p.Section("PostOpenCallback", 1);
374
void run(MipsCall &call) override;
375
void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
381
struct NativeFontLib {
382
FontNewLibParams params;
390
u32_le internalFontCount;
391
u32_le internalFontInfo;
396
struct FontImageRect {
401
// A "fontLib" is a container of loaded fonts.
402
// One can open either "internal" fonts or custom fonts into a fontlib.
406
// For save states only.
409
FontLib(u32 paramPtr, u32 errorCodePtr) : fontHRes_(128.0f), fontVRes_(128.0f), altCharCode_(0x5F) {
411
Memory::ReadStruct(paramPtr, ¶ms_);
412
if (params_.numFonts > 9) {
413
params_.numFonts = 9;
416
// Technically, this should be four separate allocations.
417
u32 allocSize = 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230 + (u32)internalFonts.size() * 0xA8;
418
PostAllocCallback *action = (PostAllocCallback *) __KernelCreateAction(actionPostAllocCallback);
419
action->SetFontLib(GetListID(), errorCodePtr);
421
u32 args[2] = { params_.userDataAddr, allocSize };
422
__KernelDirectMipsCall(params_.allocFuncAddr, action, args, 2, true);
426
return (u32)(std::find(fontLibList.begin(), fontLibList.end(), this) - fontLibList.begin());
430
for (size_t i = 0; i < fonts_.size(); i++) {
431
if (isfontopen_[i] == FONT_IS_OPEN) {
432
fontMap[fonts_[i]]->Close();
433
delete fontMap[fonts_[i]];
434
fontMap.erase(fonts_[i]);
437
u32 args[2] = { params_.userDataAddr, (u32)handle_ };
438
// TODO: The return value of this is leaking.
439
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
445
void AllocDone(u32 allocatedAddr) {
446
handle_ = allocatedAddr;
447
fonts_.resize(params_.numFonts);
448
isfontopen_.resize(params_.numFonts);
449
for (size_t i = 0; i < fonts_.size(); i++) {
450
u32 addr = allocatedAddr + 0x4C + (u32)i * 0x4C;
455
// Let's write out the native struct to make tests easier.
456
// It's possible games may depend on this staying in ram, e.g. copying it, we may move to that.
457
nfl_ = allocatedAddr;
458
nfl_->params = params_;
459
nfl_->fontInfo1 = allocatedAddr + 0x4C;
460
nfl_->fontInfo2 = allocatedAddr + 0x4C + params_.numFonts * 0x4C;
463
nfl_->hRes = fontHRes_;
464
nfl_->vRes = fontVRes_;
465
nfl_->internalFontCount = (u32)internalFonts.size();
466
nfl_->internalFontInfo = allocatedAddr + 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230;
467
nfl_->altCharCode = altCharCode_;
470
u32 handle() const { return handle_; }
471
int numFonts() const { return params_.numFonts; }
473
void SetResolution(float hres, float vres) {
476
if (nfl_.IsValid()) {
482
float FontHRes() const { return fontHRes_; }
483
float FontVRes() const { return fontVRes_; }
485
void SetAltCharCode(int charCode) {
486
altCharCode_ = charCode;
488
nfl_->altCharCode = charCode;
491
int GetFontHandle(int index) const {
492
return fonts_[index];
495
// For FONT_OPEN_USER* modes, the font will automatically be freed.
496
LoadedFont *OpenFont(Font *font, FontOpenMode mode, int &error) {
497
// TODO: Do something with mode, possibly save it where the PSP does in the struct.
498
// Maybe needed in Font, though? Handlers seem... difficult to emulate.
499
int freeFontIndex = -1;
500
for (size_t i = 0; i < fonts_.size(); i++) {
501
if (isfontopen_[i] == 0) {
502
freeFontIndex = (int)i;
506
if (freeFontIndex < 0) {
507
ERROR_LOG(SCEFONT, "Too many fonts opened in FontLib");
508
error = ERROR_FONT_TOO_MANY_OPEN_FONTS;
511
if (!font->IsValid()) {
512
ERROR_LOG(SCEFONT, "Invalid font data");
513
error = ERROR_FONT_INVALID_FONT_DATA;
516
LoadedFont *loadedFont = new LoadedFont(font, mode, GetListID(), fonts_[freeFontIndex]);
517
isfontopen_[freeFontIndex] = 1;
519
auto prevFont = fontMap.find(loadedFont->Handle());
520
if (prevFont != fontMap.end()) {
521
// Before replacing it and forgetting about it, let's free it.
522
delete prevFont->second;
524
fontMap[loadedFont->Handle()] = loadedFont;
528
void CloseFont(LoadedFont *font) {
529
for (size_t i = 0; i < fonts_.size(); i++) {
530
if (fonts_[i] == font->Handle()) {
538
void DoState(PointerWrap &p) {
539
auto s = p.Section("FontLib", 1, 2);
548
p.Do(fileFontHandle_);
558
void SetFileFontHandle(u32 handle) {
559
fileFontHandle_ = handle;
562
u32 GetAltCharCode() const { return altCharCode_; }
565
std::vector<u32> fonts_;
566
std::vector<u32> isfontopen_;
568
FontNewLibParams params_;
574
PSPPointer<NativeFontLib> nfl_;
576
DISALLOW_COPY_AND_ASSIGN(FontLib);
580
void PostAllocCallback::run(MipsCall &call) {
581
INFO_LOG(SCEFONT, "Entering PostAllocCallback::run");
582
u32 v0 = currentMIPS->r[MIPS_REG_V0];
584
// TODO: Who deletes fontLib?
585
Memory::Write_U32(ERROR_FONT_OUT_OF_MEMORY, errorCodePtr_);
586
call.setReturnValue(0);
588
FontLib *fontLib = fontLibList[fontLibID_];
589
fontLib->AllocDone(v0);
590
fontLibMap[fontLib->handle()] = fontLibID_;
591
call.setReturnValue(fontLib->handle());
593
INFO_LOG(SCEFONT, "Leaving PostAllocCallback::run");
596
void PostOpenCallback::run(MipsCall &call) {
597
FontLib *fontLib = fontLibList[fontLibID_];
598
u32 v0 = currentMIPS->r[MIPS_REG_V0];
599
fontLib->SetFileFontHandle(v0);
602
inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {
603
auto fontLib = GetFontLib();
604
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
605
return GetPGF()->GetCharInfo(charCode, charInfo, altCharCode, glyphType);
608
inline void LoadedFont::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const {
609
auto fontLib = GetFontLib();
610
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
611
GetPGF()->DrawCharacter(image, clipX, clipY, clipWidth, clipHeight, charCode, altCharCode, glyphType);
614
static FontLib *GetFontLib(u32 handle) {
615
if (fontLibMap.find(handle) != fontLibMap.end()) {
616
return fontLibList[fontLibMap[handle]];
618
ERROR_LOG(SCEFONT, "No fontlib with handle %08x", handle);
623
static LoadedFont *GetLoadedFont(u32 handle, bool allowClosed) {
624
auto iter = fontMap.find(handle);
625
if (iter != fontMap.end()) {
626
if (iter->second->IsOpen() || allowClosed) {
627
return fontMap[handle];
629
ERROR_LOG(SCEFONT, "Font exists but is closed, which was not allowed in this call.");
633
ERROR_LOG(SCEFONT, "No font with handle %08x", handle);
638
static void __LoadInternalFonts() {
639
if (internalFonts.size()) {
640
// Fonts already loaded.
643
const std::string fontPath = "flash0:/font/";
644
const std::string fontOverridePath = "ms0:/PSP/flash0/font/";
645
const std::string userfontPath = "disc0:/PSP_GAME/USRDIR/";
647
if (!pspFileSystem.GetFileInfo(fontPath).exists) {
648
pspFileSystem.MkDir(fontPath);
650
if ((pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/zh_gb.pgf").exists) && (pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/oldfont.prx").exists)) {
651
for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {
652
const FontRegistryEntry &entry = fontRegistry[i];
653
std::string fontFilename = userfontPath + entry.fileName;
654
PSPFileInfo info = pspFileSystem.GetFileInfo(fontFilename);
655
DEBUG_LOG(SCEFONT, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
656
std::vector<u8> buffer;
657
if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {
658
ERROR_LOG(SCEFONT, "Failed opening font");
661
internalFonts.push_back(new Font(buffer, entry));
662
DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
667
for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {
668
const FontRegistryEntry &entry = fontRegistry[i];
669
std::string fontFilename = userfontPath + entry.fileName;
670
PSPFileInfo info = pspFileSystem.GetFileInfo(fontFilename);
673
// No user font, let's try override path.
674
fontFilename = fontOverridePath + entry.fileName;
675
info = pspFileSystem.GetFileInfo(fontFilename);
679
// No override, let's use the default path.
680
fontFilename = fontPath + entry.fileName;
681
info = pspFileSystem.GetFileInfo(fontFilename);
685
DEBUG_LOG(SCEFONT, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
686
std::vector<u8> buffer;
687
if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {
688
ERROR_LOG(SCEFONT, "Failed opening font");
692
internalFonts.push_back(new Font(buffer, entry));
694
DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
695
} else if (!entry.ignoreIfMissing) {
696
WARN_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str());
701
int GetInternalFontIndex(Font *font) {
702
for (size_t i = 0; i < internalFonts.size(); i++) {
703
if (internalFonts[i] == font)
710
actionPostAllocCallback = __KernelRegisterActionType(PostAllocCallback::Create);
711
actionPostOpenCallback = __KernelRegisterActionType(PostOpenCallback::Create);
714
void __FontShutdown() {
715
for (auto iter = fontMap.begin(); iter != fontMap.end(); iter++) {
716
FontLib *fontLib = iter->second->GetFontLib();
718
fontLib->CloseFont(iter->second);
722
for (auto iter = fontLibList.begin(); iter != fontLibList.end(); iter++) {
727
for (auto iter = internalFonts.begin(); iter != internalFonts.end(); ++iter) {
730
internalFonts.clear();
733
void __FontDoState(PointerWrap &p) {
734
auto s = p.Section("sceFont", 1);
738
__LoadInternalFonts();
744
p.Do(actionPostAllocCallback);
745
__KernelRestoreActionType(actionPostAllocCallback, PostAllocCallback::Create);
746
p.Do(actionPostOpenCallback);
747
__KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);
750
static u32 sceFontNewLib(u32 paramPtr, u32 errorCodePtr) {
751
// Lazy load internal fonts, only when font library first inited.
752
__LoadInternalFonts();
754
auto params = PSPPointer<FontNewLibParams>::Create(paramPtr);
755
auto errorCode = PSPPointer<u32>::Create(errorCodePtr);
757
if (!params.IsValid() || !errorCode.IsValid()) {
758
ERROR_LOG_REPORT(SCEFONT, "sceFontNewLib(%08x, %08x): invalid addresses", paramPtr, errorCodePtr);
759
// The PSP would crash in this situation, not a real error code.
760
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
762
if (!Memory::IsValidAddress(params->allocFuncAddr) || !Memory::IsValidAddress(params->freeFuncAddr)) {
763
ERROR_LOG_REPORT(SCEFONT, "sceFontNewLib(%08x, %08x): missing alloc func", paramPtr, errorCodePtr);
764
*errorCode = ERROR_FONT_INVALID_PARAMETER;
768
INFO_LOG(SCEFONT, "sceFontNewLib(%08x, %08x)", paramPtr, errorCodePtr);
771
FontLib *newLib = new FontLib(paramPtr, errorCodePtr);
772
fontLibList.push_back(newLib);
773
// The game should never see this value, the return value is replaced
774
// by the action. Except if we disable the alloc, in this case we return
775
// the handle correctly here.
776
return hleDelayResult(newLib->handle(), "new fontlib", 30000);
779
static int sceFontDoneLib(u32 fontLibHandle) {
780
INFO_LOG(SCEFONT, "sceFontDoneLib(%08x)", fontLibHandle);
781
FontLib *fl = GetFontLib(fontLibHandle);
788
// Open internal font into a FontLib
789
static u32 sceFontOpen(u32 libHandle, u32 index, u32 mode, u32 errorCodePtr) {
790
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
791
if (!errorCode.IsValid()) {
792
// Would crash on the PSP.
793
ERROR_LOG(SCEFONT, "sceFontOpen(%x, %x, %x, %x): invalid pointer", libHandle, index, mode, errorCodePtr);
797
DEBUG_LOG(SCEFONT, "sceFontOpen(%x, %x, %x, %x)", libHandle, index, mode, errorCodePtr);
798
FontLib *fontLib = GetFontLib(libHandle);
799
if (fontLib == NULL) {
800
*errorCode = ERROR_FONT_INVALID_LIBID;
803
if (index >= internalFonts.size()) {
804
*errorCode = ERROR_FONT_INVALID_PARAMETER;
808
FontOpenMode openMode = mode == 0 ? FONT_OPEN_INTERNAL_STINGY : FONT_OPEN_INTERNAL_FULL;
809
LoadedFont *font = fontLib->OpenFont(internalFonts[index], openMode, *errorCode);
812
return hleDelayResult(font->Handle(), "font open", 10000);
818
// Open a user font in RAM into a FontLib
819
static u32 sceFontOpenUserMemory(u32 libHandle, u32 memoryFontAddrPtr, u32 memoryFontLength, u32 errorCodePtr) {
820
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
821
if (!errorCode.IsValid()) {
822
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserMemory(%08x, %08x, %08x, %08x): invalid error address", libHandle, memoryFontAddrPtr, memoryFontLength, errorCodePtr);
825
if (!Memory::IsValidAddress(memoryFontAddrPtr)) {
826
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserMemory(%08x, %08x, %08x, %08x): invalid address", libHandle, memoryFontAddrPtr, memoryFontLength, errorCodePtr);
827
*errorCode = ERROR_FONT_INVALID_PARAMETER;
831
FontLib *fontLib = GetFontLib(libHandle);
833
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserMemory(%08x, %08x, %08x, %08x): bad font lib", libHandle, memoryFontAddrPtr, memoryFontLength, errorCodePtr);
834
*errorCode = ERROR_FONT_INVALID_LIBID;
837
if (memoryFontLength == 0) {
838
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserMemory(%08x, %08x, %08x, %08x): invalid size", libHandle, memoryFontAddrPtr, memoryFontLength, errorCodePtr);
839
*errorCode = ERROR_FONT_INVALID_PARAMETER;
843
DEBUG_LOG(SCEFONT, "sceFontOpenUserMemory(%08x, %08x, %08x, %08x)", libHandle, memoryFontAddrPtr, memoryFontLength, errorCodePtr);
844
const u8 *fontData = Memory::GetPointer(memoryFontAddrPtr);
845
// Games are able to overstate the size of a font. Let's avoid crashing when we memcpy() it.
846
// Unsigned 0xFFFFFFFF is treated as max, but that's impossible, so let's clamp to 64MB.
847
if (memoryFontLength > 0x03FFFFFF)
848
memoryFontLength = 0x03FFFFFF;
849
while (!Memory::IsValidAddress(memoryFontAddrPtr + memoryFontLength - 1)) {
852
Font *f = new Font(fontData, memoryFontLength);
853
LoadedFont *font = fontLib->OpenFont(f, FONT_OPEN_USERBUFFER, *errorCode);
856
return font->Handle();
863
// Open a user font in a file into a FontLib
864
static u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u32 errorCodePtr) {
865
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
867
if (!errorCode.IsValid()) {
868
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserFile(%08x, %s, %08x, %08x): invalid error address", libHandle, fileName, mode, errorCodePtr);
869
return ERROR_FONT_INVALID_PARAMETER;
872
if (fileName == NULL) {
873
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserFile(%08x, %s, %08x, %08x): invalid filename", libHandle, fileName, mode, errorCodePtr);
874
*errorCode = ERROR_FONT_INVALID_PARAMETER;
878
FontLib *fontLib = GetFontLib(libHandle);
880
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserFile(%08x, %s, %08x, %08x): invalid font lib", libHandle, fileName, mode, errorCodePtr);
881
*errorCode = ERROR_FONT_INVALID_LIBID;
885
// TODO: Technically, we only do this if mode = 1. Mode 0 uses the handlers.
887
WARN_LOG_REPORT(SCEFONT, "Loading file directly instead of using handlers: %s", fileName);
889
PSPFileInfo info = pspFileSystem.GetFileInfo(fileName);
891
ERROR_LOG_REPORT(SCEFONT, "sceFontOpenUserFile(%08x, %s, %08x, %08x): file does not exist", libHandle, fileName, mode, errorCodePtr);
892
*errorCode = ERROR_FONT_HANDLER_OPEN_FAILED;
896
INFO_LOG(SCEFONT, "sceFontOpenUserFile(%08x, %s, %08x, %08x)", libHandle, fileName, mode, errorCodePtr);
897
std::vector<u8> buffer;
898
pspFileSystem.ReadEntireFile(fileName, buffer);
899
Font *f = new Font(buffer);
900
FontOpenMode openMode = mode == 0 ? FONT_OPEN_USERFILE_HANDLERS : FONT_OPEN_USERFILE_FULL;
901
LoadedFont *font = fontLib->OpenFont(f, openMode, *errorCode);
904
return font->Handle();
911
static int sceFontClose(u32 fontHandle) {
912
LoadedFont *font = GetLoadedFont(fontHandle, false);
915
DEBUG_LOG(SCEFONT, "sceFontClose(%x)", fontHandle);
916
FontLib *fontLib = font->GetFontLib();
918
fontLib->CloseFont(font);
921
ERROR_LOG(SCEFONT, "sceFontClose(%x) - font not open?", fontHandle);
925
static int sceFontFindOptimumFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {
926
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
927
if (!errorCode.IsValid()) {
928
ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid error address", libHandle, fontStylePtr, errorCodePtr);
929
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
932
FontLib *fontLib = GetFontLib(libHandle);
934
ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid font lib", libHandle, fontStylePtr, errorCodePtr);
935
*errorCode = ERROR_FONT_INVALID_LIBID;
939
if (!Memory::IsValidAddress(fontStylePtr)) {
940
ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid style address", libHandle, fontStylePtr, errorCodePtr);
941
// Yes, actually. Must've been a typo in the library.
942
*errorCode = ERROR_FONT_INVALID_LIBID;
946
DEBUG_LOG(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x)", libHandle, fontStylePtr, errorCodePtr);
948
auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
950
// Find the first nearest match for H/V, OR the last exact match for others.
951
float hRes = requestedStyle->fontHRes > 0.0f ? requestedStyle->fontHRes : fontLib->FontHRes();
952
float vRes = requestedStyle->fontVRes > 0.0f ? requestedStyle->fontVRes : fontLib->FontVRes();
953
Font *optimumFont = 0;
954
Font *nearestFont = 0;
955
float nearestDist = std::numeric_limits<float>::infinity();
956
for (size_t i = 0; i < internalFonts.size(); i++) {
957
MatchQuality q = internalFonts[i]->MatchesStyle(*requestedStyle);
958
if (q != MATCH_NONE) {
959
auto matchStyle = internalFonts[i]->GetFontStyle();
960
if (requestedStyle->fontH > 0.0f) {
961
float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);
962
if (hDist < nearestDist) {
964
nearestFont = internalFonts[i];
967
if (requestedStyle->fontV > 0.0f) {
968
// Appears to be a bug? It seems to match H instead of V.
969
float vDist = fabs(matchStyle.fontVRes * matchStyle.fontV - vRes * requestedStyle->fontH);
970
if (vDist < nearestDist) {
972
nearestFont = internalFonts[i];
976
if (q == MATCH_GOOD) {
977
optimumFont = internalFonts[i];
981
optimumFont = nearestFont;
985
return GetInternalFontIndex(optimumFont);
992
// Returns the font index, not handle
993
static int sceFontFindFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {
994
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
995
if (!errorCode.IsValid()) {
996
ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%x, %x, %x): invalid error address", libHandle, fontStylePtr, errorCodePtr);
997
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
1000
FontLib *fontLib = GetFontLib(libHandle);
1002
ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%08x, %08x, %08x): invalid font lib", libHandle, fontStylePtr, errorCodePtr);
1003
*errorCode = ERROR_FONT_INVALID_LIBID;
1007
if (!Memory::IsValidAddress(fontStylePtr)) {
1008
ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%08x, %08x, %08x): invalid style address", libHandle, fontStylePtr, errorCodePtr);
1009
*errorCode = ERROR_FONT_INVALID_PARAMETER;
1013
DEBUG_LOG(SCEFONT, "sceFontFindFont(%x, %x, %x)", libHandle, fontStylePtr, errorCodePtr);
1015
auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
1017
// Find the closest exact match for the fields specified.
1018
float hRes = requestedStyle->fontHRes > 0.0f ? requestedStyle->fontHRes : fontLib->FontHRes();
1019
float vRes = requestedStyle->fontVRes > 0.0f ? requestedStyle->fontVRes : fontLib->FontVRes();
1020
for (size_t i = 0; i < internalFonts.size(); i++) {
1021
if (internalFonts[i]->MatchesStyle(*requestedStyle) != MATCH_NONE) {
1022
auto matchStyle = internalFonts[i]->GetFontStyle();
1023
if (requestedStyle->fontH > 0.0f) {
1024
float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);
1025
if (hDist > 0.001f) {
1028
} else if (requestedStyle->fontV > 0.0f) {
1029
// V seems to be ignored, unless H isn't specified.
1030
// If V is specified alone, the match always fails.
1041
static int sceFontGetFontInfo(u32 fontHandle, u32 fontInfoPtr) {
1042
if (!Memory::IsValidAddress(fontInfoPtr)) {
1043
ERROR_LOG(SCEFONT, "sceFontGetFontInfo(%x, %x): bad fontInfo pointer", fontHandle, fontInfoPtr);
1044
return ERROR_FONT_INVALID_PARAMETER;
1046
LoadedFont *font = GetLoadedFont(fontHandle, true);
1048
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfo(%x, %x): bad font", fontHandle, fontInfoPtr);
1049
return ERROR_FONT_INVALID_PARAMETER;
1052
DEBUG_LOG(SCEFONT, "sceFontGetFontInfo(%x, %x)", fontHandle, fontInfoPtr);
1053
auto fi = PSPPointer<PGFFontInfo>::Create(fontInfoPtr);
1054
font->GetPGF()->GetFontInfo(fi);
1055
fi->fontStyle = font->GetFont()->GetFontStyle();
1060
// It says FontInfo but it means Style - this is like sceFontGetFontList().
1061
static int sceFontGetFontInfoByIndexNumber(u32 libHandle, u32 fontInfoPtr, u32 index) {
1062
auto fontStyle = PSPPointer<PGFFontStyle>::Create(fontInfoPtr);
1063
FontLib *fl = GetFontLib(libHandle);
1064
if (!fl || fl->handle() == 0) {
1065
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font lib", libHandle, fontInfoPtr, index);
1066
return !fl ? ERROR_FONT_INVALID_LIBID : ERROR_FONT_INVALID_PARAMETER;
1068
if (index >= internalFonts.size()) {
1069
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font index", libHandle, fontInfoPtr, index);
1070
return ERROR_FONT_INVALID_PARAMETER;
1072
if (!fontStyle.IsValid()) {
1073
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid info pointer", libHandle, fontInfoPtr, index);
1074
return ERROR_FONT_INVALID_PARAMETER;
1077
DEBUG_LOG(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i)", libHandle, fontInfoPtr, index);
1078
auto font = internalFonts[index];
1079
*fontStyle = font->GetFontStyle();
1084
static int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
1086
if (!Memory::IsValidAddress(charInfoPtr)) {
1087
ERROR_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);
1088
return ERROR_FONT_INVALID_PARAMETER;
1090
LoadedFont *font = GetLoadedFont(fontHandle, true);
1092
// The PSP crashes, but we assume it'd work like sceFontGetFontInfo(), and not touch charInfo.
1093
ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);
1094
return ERROR_FONT_INVALID_PARAMETER;
1097
DEBUG_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
1098
auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);
1099
font->GetCharInfo(charCode, charInfo);
1104
static int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
1106
if (!Memory::IsValidAddress(charInfoPtr)) {
1107
ERROR_LOG(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);
1108
return ERROR_FONT_INVALID_PARAMETER;
1110
LoadedFont *font = GetLoadedFont(fontHandle, true);
1112
ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);
1113
return ERROR_FONT_INVALID_PARAMETER;
1116
DEBUG_LOG(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
1117
auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);
1118
font->GetCharInfo(charCode, charInfo, FONT_PGF_SHADOWGLYPH);
1123
static int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
1125
auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);
1126
LoadedFont *font = GetLoadedFont(fontHandle, true);
1128
ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);
1129
return ERROR_FONT_INVALID_PARAMETER;
1131
if (!charRect.IsValid()) {
1132
ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);
1133
return ERROR_FONT_INVALID_PARAMETER;
1136
DEBUG_LOG(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
1137
PGFCharInfo charInfo;
1138
font->GetCharInfo(charCode, &charInfo);
1139
charRect->width = charInfo.bitmapWidth;
1140
charRect->height = charInfo.bitmapHeight;
1144
static int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
1146
auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);
1147
LoadedFont *font = GetLoadedFont(fontHandle, true);
1149
ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);
1150
return ERROR_FONT_INVALID_PARAMETER;
1152
if (!charRect.IsValid()) {
1153
ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);
1154
return ERROR_FONT_INVALID_PARAMETER;
1157
DEBUG_LOG(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
1158
PGFCharInfo charInfo;
1159
font->GetCharInfo(charCode, &charInfo, FONT_PGF_SHADOWGLYPH);
1160
charRect->width = charInfo.bitmapWidth;
1161
charRect->height = charInfo.bitmapHeight;
1165
static int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {
1167
if (!Memory::IsValidAddress(glyphImagePtr)) {
1168
ERROR_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);
1169
return ERROR_FONT_INVALID_PARAMETER;
1171
LoadedFont *font = GetLoadedFont(fontHandle, true);
1173
ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);
1174
return ERROR_FONT_INVALID_PARAMETER;
1177
DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);
1178
auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1179
font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_CHARGLYPH);
1183
static int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {
1185
if (!Memory::IsValidAddress(glyphImagePtr)) {
1186
ERROR_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1187
return ERROR_FONT_INVALID_PARAMETER;
1189
LoadedFont *font = GetLoadedFont(fontHandle, true);
1191
ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1192
return ERROR_FONT_INVALID_PARAMETER;
1195
DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1196
auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1197
font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_CHARGLYPH);
1201
static int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode) {
1203
FontLib *fl = GetFontLib(fontLibHandle);
1205
ERROR_LOG_REPORT(SCEFONT, "sceFontSetAltCharacterCode(%08x, %08x): invalid font lib", fontLibHandle, charCode);
1206
return ERROR_FONT_INVALID_LIBID;
1209
INFO_LOG(SCEFONT, "sceFontSetAltCharacterCode(%08x, %08x)", fontLibHandle, charCode);
1210
fl->SetAltCharCode(charCode & 0xFFFF);
1214
static int sceFontFlush(u32 fontHandle) {
1215
INFO_LOG(SCEFONT, "sceFontFlush(%i)", fontHandle);
1216
// Probably don't need to do anything here.
1220
// One would think that this should loop through the fonts loaded in the fontLibHandle,
1221
// but it seems not.
1222
static int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, int numFonts) {
1223
auto fontStyles = PSPPointer<PGFFontStyle>::Create(fontStylePtr);
1224
FontLib *fl = GetFontLib(fontLibHandle);
1226
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontList(%08x, %08x, %i): invalid font lib", fontLibHandle, fontStylePtr, numFonts);
1227
return ERROR_FONT_INVALID_LIBID;
1229
if (!fontStyles.IsValid()) {
1230
ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontList(%08x, %08x, %i): invalid style pointer", fontLibHandle, fontStylePtr, numFonts);
1231
return ERROR_FONT_INVALID_PARAMETER;
1234
DEBUG_LOG(SCEFONT, "sceFontGetFontList(%08x, %08x, %i)", fontLibHandle, fontStylePtr, numFonts);
1235
if (fl->handle() != 0) {
1236
numFonts = std::min(numFonts, (int)internalFonts.size());
1237
for (int i = 0; i < numFonts; i++)
1238
fontStyles[i] = internalFonts[i]->GetFontStyle();
1241
return hleDelayResult(0, "font list read", 100);
1244
static int sceFontGetNumFontList(u32 fontLibHandle, u32 errorCodePtr) {
1245
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
1246
if (!errorCode.IsValid()) {
1247
ERROR_LOG_REPORT(SCEFONT, "sceFontGetNumFontList(%08x, %08x): invalid error address", fontLibHandle, errorCodePtr);
1248
return ERROR_FONT_INVALID_PARAMETER;
1250
FontLib *fl = GetFontLib(fontLibHandle);
1252
ERROR_LOG_REPORT(SCEFONT, "sceFontGetNumFontList(%08x, %08x): invalid font lib", fontLibHandle, errorCodePtr);
1253
*errorCode = ERROR_FONT_INVALID_LIBID;
1256
DEBUG_LOG(SCEFONT, "sceFontGetNumFontList(%08x, %08x)", fontLibHandle, errorCodePtr);
1258
return fl->handle() == 0 ? 0 : (int)internalFonts.size();
1261
static int sceFontSetResolution(u32 fontLibHandle, float hRes, float vRes) {
1262
FontLib *fl = GetFontLib(fontLibHandle);
1264
ERROR_LOG_REPORT(SCEFONT, "sceFontSetResolution(%08x, %f, %f): invalid font lib", fontLibHandle, hRes, vRes);
1265
return ERROR_FONT_INVALID_LIBID;
1267
if (hRes <= 0.0f || vRes <= 0.0f) {
1268
ERROR_LOG_REPORT(SCEFONT, "sceFontSetResolution(%08x, %f, %f): negative value", fontLibHandle, hRes, vRes);
1269
return ERROR_FONT_INVALID_PARAMETER;
1271
INFO_LOG(SCEFONT, "sceFontSetResolution(%08x, %f, %f)", fontLibHandle, hRes, vRes);
1272
fl->SetResolution(hRes, vRes);
1276
static float sceFontPixelToPointH(int fontLibHandle, float fontPixelsH, u32 errorCodePtr) {
1277
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
1278
if (!errorCode.IsValid()) {
1279
ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsH, errorCodePtr);
1282
FontLib *fl = GetFontLib(fontLibHandle);
1284
ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsH, errorCodePtr);
1285
*errorCode = ERROR_FONT_INVALID_LIBID;
1288
DEBUG_LOG(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x)", fontLibHandle, fontPixelsH, errorCodePtr);
1290
return fontPixelsH * pointDPI / fl->FontHRes();
1293
static float sceFontPixelToPointV(int fontLibHandle, float fontPixelsV, u32 errorCodePtr) {
1294
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
1295
if (!errorCode.IsValid()) {
1296
ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsV, errorCodePtr);
1299
FontLib *fl = GetFontLib(fontLibHandle);
1301
ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsV, errorCodePtr);
1302
*errorCode = ERROR_FONT_INVALID_LIBID;
1305
DEBUG_LOG(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x)", fontLibHandle, fontPixelsV, errorCodePtr);
1307
return fontPixelsV * pointDPI / fl->FontVRes();
1310
static float sceFontPointToPixelH(int fontLibHandle, float fontPointsH, u32 errorCodePtr) {
1311
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
1312
if (!errorCode.IsValid()) {
1313
ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsH, errorCodePtr);
1316
FontLib *fl = GetFontLib(fontLibHandle);
1318
ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsH, errorCodePtr);
1319
*errorCode = ERROR_FONT_INVALID_LIBID;
1322
DEBUG_LOG(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x)", fontLibHandle, fontPointsH, errorCodePtr);
1324
return fontPointsH * fl->FontHRes() / pointDPI;
1327
static float sceFontPointToPixelV(int fontLibHandle, float fontPointsV, u32 errorCodePtr) {
1328
auto errorCode = PSPPointer<int>::Create(errorCodePtr);
1329
if (!errorCode.IsValid()) {
1330
ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsV, errorCodePtr);
1333
FontLib *fl = GetFontLib(fontLibHandle);
1335
ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsV, errorCodePtr);
1336
*errorCode = ERROR_FONT_INVALID_LIBID;
1339
DEBUG_LOG(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x)", fontLibHandle, fontPointsV, errorCodePtr);
1341
return fontPointsV * fl->FontVRes() / pointDPI;
1344
static int sceFontCalcMemorySize() {
1345
ERROR_LOG_REPORT(SCEFONT, "UNIMPL sceFontCalcMemorySize()");
1349
static int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {
1351
if (!Memory::IsValidAddress(glyphImagePtr)) {
1352
ERROR_LOG(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);
1353
return ERROR_FONT_INVALID_PARAMETER;
1355
LoadedFont *font = GetLoadedFont(fontHandle, true);
1357
ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);
1358
return ERROR_FONT_INVALID_PARAMETER;
1361
DEBUG_LOG(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);
1362
auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1363
font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_SHADOWGLYPH);
1367
static int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {
1369
if (!Memory::IsValidAddress(glyphImagePtr)) {
1370
ERROR_LOG(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1371
return ERROR_FONT_INVALID_PARAMETER;
1373
LoadedFont *font = GetLoadedFont(fontHandle, true);
1375
ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1376
return ERROR_FONT_INVALID_PARAMETER;
1379
DEBUG_LOG(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1380
auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1381
font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_SHADOWGLYPH);
1385
// sceLibFont is a user level library so it can touch the stack. Some games appear to rely a bit of stack
1386
// being wiped - although in reality, it won't be wiped with just zeroes..
1387
const HLEFunction sceLibFont[] = {
1388
{0X67F17ED7, &WrapU_UU<sceFontNewLib>, "sceFontNewLib", 'x', "xx", HLE_CLEAR_STACK_BYTES, 0x5A0 },
1389
{0X574B6FBC, &WrapI_U<sceFontDoneLib>, "sceFontDoneLib", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x2C },
1390
{0X48293280, &WrapI_UFF<sceFontSetResolution>, "sceFontSetResolution", 'i', "xff" },
1391
{0X27F6E642, &WrapI_UU<sceFontGetNumFontList>, "sceFontGetNumFontList", 'i', "xx" },
1392
{0XBC75D85B, &WrapI_UUI<sceFontGetFontList>, "sceFontGetFontList", 'i', "xxi", HLE_CLEAR_STACK_BYTES, 0x31C },
1393
{0X099EF33C, &WrapI_UUU<sceFontFindOptimumFont>, "sceFontFindOptimumFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0xF0 },
1394
{0X681E61A7, &WrapI_UUU<sceFontFindFont>, "sceFontFindFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x40 },
1395
{0X2F67356A, &WrapI_V<sceFontCalcMemorySize>, "sceFontCalcMemorySize", 'i', "" },
1396
{0X5333322D, &WrapI_UUU<sceFontGetFontInfoByIndexNumber>, "sceFontGetFontInfoByIndexNumber", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x20 },
1397
{0XA834319D, &WrapU_UUUU<sceFontOpen>, "sceFontOpen", 'x', "xxxx", HLE_CLEAR_STACK_BYTES, 0x460 },
1398
{0X57FCB733, &WrapU_UCUU<sceFontOpenUserFile>, "sceFontOpenUserFile", 'x', "xsxx" },
1399
{0XBB8E7FE6, &WrapU_UUUU<sceFontOpenUserMemory>, "sceFontOpenUserMemory", 'x', "xxxx", HLE_CLEAR_STACK_BYTES, 0x440 /*from JPCSP*/ },
1400
{0X3AEA8CB6, &WrapI_U<sceFontClose>, "sceFontClose", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x54 },
1401
{0X0DA7535E, &WrapI_UU<sceFontGetFontInfo>, "sceFontGetFontInfo", 'i', "xx" },
1402
{0XDCC80C2F, &WrapI_UUU<sceFontGetCharInfo>, "sceFontGetCharInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x110 },
1403
{0XAA3DE7B5, &WrapI_UUU<sceFontGetShadowInfo>, "sceFontGetShadowInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },
1404
{0X5C3E4A9E, &WrapI_UUU<sceFontGetCharImageRect>, "sceFontGetCharImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },
1405
{0X48B06520, &WrapI_UUU<sceFontGetShadowImageRect>, "sceFontGetShadowImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },
1406
{0X980F4895, &WrapI_UUU<sceFontGetCharGlyphImage>, "sceFontGetCharGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },
1407
{0XCA1E6945, &WrapI_UUUIIII<sceFontGetCharGlyphImage_Clip>, "sceFontGetCharGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x130 },
1408
{0X74B21701, &WrapF_IFU<sceFontPixelToPointH>, "sceFontPixelToPointH", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },
1409
{0XF8F0752E, &WrapF_IFU<sceFontPixelToPointV>, "sceFontPixelToPointV", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },
1410
{0X472694CD, &WrapF_IFU<sceFontPointToPixelH>, "sceFontPointToPixelH", 'f', "ifx" },
1411
{0X3C4B7E82, &WrapF_IFU<sceFontPointToPixelV>, "sceFontPointToPixelV", 'f', "ifx" },
1412
{0XEE232411, &WrapI_UU<sceFontSetAltCharacterCode>, "sceFontSetAltCharacterCode", 'i', "xx" },
1413
{0X568BE516, &WrapI_UUU<sceFontGetShadowGlyphImage>, "sceFontGetShadowGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x160 },
1414
{0X5DCF6858, &WrapI_UUUIIII<sceFontGetShadowGlyphImage_Clip>, "sceFontGetShadowGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x170 },
1415
{0X02D7F94B, &WrapI_U<sceFontFlush>, "sceFontFlush", 'i', "x" },
1418
void Register_sceFont() {
1419
RegisterModule("sceLibFont", ARRAY_SIZE(sceLibFont), sceLibFont);
1422
void Register_sceLibFttt() {
1423
RegisterModule("sceLibFttt", ARRAY_SIZE(sceLibFont), sceLibFont);