1 #include "sceFont.h"
2
3 #include "Common/TimeUtil.h"
4
5 #include <cmath>
6 #include <vector>
7 #include <map>
8 #include <algorithm>
9
10 #include "Common/Serialize/Serializer.h"
11 #include "Common/Serialize/SerializeFuncs.h"
12 #include "Common/Serialize/SerializeMap.h"
13 #include "Core/HLE/HLE.h"
14 #include "Core/HLE/FunctionWrappers.h"
15 #include "Core/HLE/sceFont.h"
16 #include "Core/HLE/sceKernel.h"
17 #include "Core/HLE/sceKernelThread.h"
18 #include "Core/MIPS/MIPS.h"
19 #include "Core/FileSystems/FileSystem.h"
20 #include "Core/FileSystems/MetaFileSystem.h"
21 #include "Core/MemMapHelpers.h"
22 #include "Core/Reporting.h"
23 #include "Core/System.h"
24 #include "Core/Font/PGF.h"
25
26 enum {
27 ERROR_FONT_OUT_OF_MEMORY = 0x80460001,
28 ERROR_FONT_INVALID_LIBID = 0x80460002,
29 ERROR_FONT_INVALID_PARAMETER = 0x80460003,
30 ERROR_FONT_HANDLER_OPEN_FAILED = 0x80460005,
31 ERROR_FONT_TOO_MANY_OPEN_FONTS = 0x80460009,
32 ERROR_FONT_INVALID_FONT_DATA = 0x8046000a,
33 };
34
35 constexpr int MAX_FONT_REFS = 4;
36
37 // For the save states.
38 static bool useAllocCallbacks = true;
39
40 // Actions
41 static int actionPostAllocCallback;
42 static int actionPostOpenCallback;
43 static int actionPostOpenAllocCallback;
44 static int actionPostCharInfoAllocCallback;
45 static int actionPostCharInfoFreeCallback;
46
47 // Monster Hunter sequence:
48 // 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:469 E[HLE]: sceFontNewLib 89ad4a0, 9fff5cc
49 // 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:699 E[HLE]: UNIMPL sceFontGetNumFontList 1, 9fff5cc
50 // 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:526 E[HLE]: sceFontFindOptimumFont 1, 9fff524, 9fff5cc
51 // 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:490 E[HLE]: sceFontOpenFont 1, 1, 0, 9fff5cc
52 // 36:46:999 c:\dev\ppsspp\core\hle\scefont.cpp:542 E[HLE]: sceFontGetFontInfo 1, 997140c
53
54 typedef u32 FontLibraryHandle;
55 typedef u32 FontHandle;
56
57 struct FontNewLibParams {
58 u32_le userDataAddr;
59 u32_le numFonts;
60 u32_le cacheDataAddr;
61
62 // Driver callbacks.
63 u32_le allocFuncAddr;
64 u32_le freeFuncAddr;
65 u32_le openFuncAddr;
66 u32_le closeFuncAddr;
67 u32_le readFuncAddr;
68 u32_le seekFuncAddr;
69 u32_le errorFuncAddr;
70 u32_le ioFinishFuncAddr;
71 };
72
73 struct FontRegistryEntry {
74 int hSize;
75 int vSize;
76 int hResolution;
77 int vResolution;
78 int extraAttributes;
79 int weight;
80 int familyCode;
81 int style;
82 int styleSub;
83 int languageCode;
84 int regionCode;
85 int countryCode;
86 const char *fileName;
87 const char *fontName;
88 int expireDate;
89 int shadow_option;
90 u32 fontFileSize;
91 u32 stingySize; // for the FONT_OPEN_INTERNAL_STINGY mode, from pspautotests.
92 bool ignoreIfMissing;
93 };
94
95 static const FontRegistryEntry fontRegistry[] = {
96 // This was added for Chinese translations and is not normally loaded on a PSP.
97 { 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 },
98 { 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 },
99 { 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 },
100 { 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 },
101 { 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 },
102 { 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 },
103 { 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 },
104 { 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 },
105 { 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 },
106 { 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 },
107 { 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 },
108 { 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 },
109 { 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 },
110 { 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 },
111 { 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 },
112 { 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 },
113 { 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 },
114 { 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 },
115 { 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 },
116 };
117
118 static const float pointDPI = 72.f;
119
120 class LoadedFont;
121 class FontLib;
122 class Font;
123 int GetInternalFontIndex(Font *font);
124
125 // These should not need to be state saved.
126 static std::vector<Font *> internalFonts;
127 // However, these we must save - but we could take a shortcut
128 // for LoadedFonts that point to internal fonts.
129 static std::map<u32, LoadedFont *> fontMap;
130 static std::map<u32, u32> fontLibMap;
131 // We keep this list to avoid ptr references, even before alloc is called.
132 static std::vector<FontLib *> fontLibList;
133
134 enum MatchQuality {
135 MATCH_UNKNOWN,
136 MATCH_NONE,
137 MATCH_GOOD,
138 };
139
140 enum FontOpenMode {
141 FONT_OPEN_INTERNAL_STINGY = 0,
142 FONT_OPEN_INTERNAL_FULL = 1,
143 // Calls open/seek/read/close handlers to read the file partially.
144 FONT_OPEN_USERFILE_HANDLERS = 2,
145 // Reads directly from filesystem.
146 FONT_OPEN_USERFILE_FULL = 3,
147 FONT_OPEN_USERBUFFER = 4,
148 };
149
150 // TODO: Merge this class with PGF? That'd make it harder to support .bwfon
151 // fonts though, unless that's added directly to PGF.
152 class Font {
153 public:
154 // For savestates only.
Font()155 Font() {
156 }
157
Font(const u8 * data,size_t dataSize)158 Font(const u8 *data, size_t dataSize) {
159 Init(data, dataSize);
160 }
161
Font(const u8 * data,size_t dataSize,const FontRegistryEntry & entry)162 Font(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
163 Init(data, dataSize, entry);
164 }
165
Font(const std::vector<u8> & data)166 Font(const std::vector<u8> &data) {
167 Init(&data[0], data.size());
168 }
169
Font(const std::vector<u8> & data,const FontRegistryEntry & entry)170 Font(const std::vector<u8> &data, const FontRegistryEntry &entry) {
171 Init(&data[0], data.size(), entry);
172 }
173
GetFontStyle() const174 const PGFFontStyle &GetFontStyle() const { return style_; }
175
MatchesStyle(const PGFFontStyle & style) const176 MatchQuality MatchesStyle(const PGFFontStyle &style) const {
177 // If no field matches, it doesn't match.
178 MatchQuality match = MATCH_UNKNOWN;
179
180 #define CHECK_FIELD(f, m) \
181 if (style.f != 0) { \
182 if (style.f != style_.f) { \
183 return MATCH_NONE; \
184 } \
185 if (match < m) { \
186 match = m; \
187 } \
188 }
189 #define CHECK_FIELD_STR(f, m) \
190 if (style.f[0] != '\0') { \
191 if (strcmp(style.f, style_.f) != 0) { \
192 return MATCH_NONE; \
193 } \
194 if (match < m) { \
195 match = m; \
196 } \
197 }
198
199 CHECK_FIELD(fontFamily, MATCH_GOOD);
200 CHECK_FIELD(fontStyle, MATCH_GOOD);
201 CHECK_FIELD(fontLanguage, MATCH_GOOD);
202 CHECK_FIELD(fontCountry, MATCH_GOOD);
203
204 CHECK_FIELD_STR(fontName, MATCH_GOOD);
205 CHECK_FIELD_STR(fontFileName, MATCH_GOOD);
206
207 #undef CHECK_FIELD_STR
208 #undef CHECK_FIELD
209 return match;
210 }
211
GetPGF()212 PGF *GetPGF() { return &pgf_; }
GetPGF() const213 const PGF *GetPGF() const { return &pgf_; }
getSize() const214 u32 getSize() const { return dataSize_; }
getStingySize() const215 u32 getStingySize() const { return stingySize_; }
IsValid() const216 bool IsValid() const { return valid_; }
217
DoState(PointerWrap & p)218 void DoState(PointerWrap &p) {
219 auto s = p.Section("Font", 1, 2);
220 if (!s)
221 return;
222
223 Do(p, pgf_);
224 Do(p, style_);
225 if (s < 2) {
226 valid_ = true;
227 } else {
228 Do(p, valid_);
229 }
230 }
231
232 private:
Init(const u8 * data,size_t dataSize)233 void Init(const u8 *data, size_t dataSize) {
234 valid_ = pgf_.ReadPtr(data, dataSize);
235 memset(&style_, 0, sizeof(style_));
236 style_.fontH = (float)pgf_.header.hSize / 64.0f;
237 style_.fontV = (float)pgf_.header.vSize / 64.0f;
238 style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;
239 style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;
240 this->dataSize_ = (u32)dataSize;
241 this->stingySize_ = 0; // Unused
242 }
243
Init(const u8 * data,size_t dataSize,const FontRegistryEntry & entry)244 void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
245 valid_ = pgf_.ReadPtr(data, dataSize);
246 style_.fontH = entry.hSize / 64.f;
247 style_.fontV = entry.vSize / 64.f;
248 style_.fontHRes = entry.hResolution / 64.f;
249 style_.fontVRes = entry.vResolution / 64.f;
250 style_.fontWeight = (float)entry.weight;
251 style_.fontFamily = (u16)entry.familyCode;
252 style_.fontStyle = (u16)entry.style;
253 style_.fontStyleSub = (u16)entry.styleSub;
254 style_.fontLanguage = (u16)entry.languageCode;
255 style_.fontRegion = (u16)entry.regionCode;
256 style_.fontCountry = (u16)entry.countryCode;
257 strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName));
258 strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));
259 style_.fontAttributes = entry.extraAttributes;
260 style_.fontExpire = entry.expireDate;
261 this->dataSize_ = entry.fontFileSize;
262 this->stingySize_ = entry.stingySize;
263 }
264
265 PGF pgf_;
266 PGFFontStyle style_;
267 bool valid_;
268 u32 dataSize_;
269 u32 stingySize_;
270 DISALLOW_COPY_AND_ASSIGN(Font);
271 };
272
273 class LoadedFont {
274 public:
275 // For savestates only.
LoadedFont()276 LoadedFont() : font_(NULL) {
277 }
278
LoadedFont(Font * font,FontOpenMode mode,u32 fontLibID,u32 handle)279 LoadedFont(Font *font, FontOpenMode mode, u32 fontLibID, u32 handle)
280 : fontLibID_(fontLibID), font_(font), handle_(handle), mode_(mode), open_(true) {}
281
~LoadedFont()282 ~LoadedFont() {
283 switch (mode_) {
284 case FONT_OPEN_USERBUFFER:
285 case FONT_OPEN_USERFILE_FULL:
286 case FONT_OPEN_USERFILE_HANDLERS:
287 // For these types, it's our responsibility to delete.
288 delete font_;
289 font_ = NULL;
290 break;
291 default:
292 // Otherwise, it's an internal font, we keep those.
293 break;
294 }
295 }
296
GetFont() const297 const Font *GetFont() const { return font_; }
GetPGF() const298 const PGF *GetPGF() const { return font_->GetPGF(); }
GetFontLib() const299 const FontLib *GetFontLib() const { return fontLibList[fontLibID_]; }
GetFontLib()300 FontLib *GetFontLib() { return fontLibList[fontLibID_]; }
Handle() const301 u32 Handle() const { return handle_; }
302
303 bool GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType = FONT_PGF_CHARGLYPH) const;
304 void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const;
305
IsOpen() const306 bool IsOpen() const { return open_; }
Close()307 void Close() {
308 open_ = false;
309 // We keep the rest around until deleted, as some queries are allowed
310 // on closed fonts (which is rather strange).
311 }
312
DoState(PointerWrap & p)313 void DoState(PointerWrap &p) {
314 auto s = p.Section("LoadedFont", 1, 3);
315 if (!s)
316 return;
317
318 int numInternalFonts = (int)internalFonts.size();
319 Do(p, numInternalFonts);
320 if (numInternalFonts != (int)internalFonts.size()) {
321 ERROR_LOG(SCEFONT, "Unable to load state: different internal font count.");
322 p.SetError(p.ERROR_FAILURE);
323 return;
324 }
325
326 Do(p, fontLibID_);
327 int internalFont = GetInternalFontIndex(font_);
328 Do(p, internalFont);
329 if (internalFont == -1) {
330 Do(p, font_);
331 } else if (p.mode == p.MODE_READ) {
332 font_ = internalFonts[internalFont];
333 }
334 Do(p, handle_);
335 if (s >= 2) {
336 Do(p, open_);
337 } else {
338 open_ = fontLibID_ != (u32)-1;
339 }
340 if (s >= 3) {
341 Do(p, mode_);
342 } else {
343 mode_ = FONT_OPEN_INTERNAL_FULL;
344 }
345 }
346
347 private:
348 u32 fontLibID_;
349 Font *font_;
350 u32 handle_;
351 FontOpenMode mode_;
352 bool open_;
353 DISALLOW_COPY_AND_ASSIGN(LoadedFont);
354 };
355
356 class PostAllocCallback : public PSPAction {
357 public:
PostAllocCallback()358 PostAllocCallback() {}
Create()359 static PSPAction *Create() { return new PostAllocCallback(); }
DoState(PointerWrap & p)360 void DoState(PointerWrap &p) override {
361 auto s = p.Section("PostAllocCallback", 1, 2);
362 if (!s)
363 return;
364
365 Do(p, fontLibID_);
366 if (s >= 2) {
367 Do(p, errorCodePtr_);
368 } else {
369 errorCodePtr_ = 0;
370 }
371 }
372 void run(MipsCall &call) override;
SetFontLib(u32 fontLibID,u32 errorCodePtr)373 void SetFontLib(u32 fontLibID, u32 errorCodePtr) { fontLibID_ = fontLibID; errorCodePtr_ = errorCodePtr; }
374
375 private:
376 u32 fontLibID_;
377 u32 errorCodePtr_;
378 };
379
380 class PostOpenCallback : public PSPAction {
381 public:
PostOpenCallback()382 PostOpenCallback() {}
Create()383 static PSPAction *Create() { return new PostOpenCallback(); }
DoState(PointerWrap & p)384 void DoState(PointerWrap &p) override {
385 auto s = p.Section("PostOpenCallback", 1);
386 if (!s)
387 return;
388
389 Do(p, fontLibID_);
390 }
391 void run(MipsCall &call) override;
SetFontLib(u32 fontLibID)392 void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
393
394 private:
395 u32 fontLibID_;
396 };
397
398 class PostOpenAllocCallback : public PSPAction {
399 public:
PostOpenAllocCallback()400 PostOpenAllocCallback() {}
Create()401 static PSPAction *Create() { return new PostOpenAllocCallback(); }
DoState(PointerWrap & p)402 void DoState(PointerWrap &p) override {
403 auto s = p.Section("PostOpenAllocCallback", 1);
404 if (!s)
405 return;
406
407 Do(p, fontLibID_);
408 Do(p, fontHandle_);
409 Do(p, fontIndex_);
410 }
411 void run(MipsCall &call) override;
SetFontLib(u32 fontLibID)412 void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
SetFont(u32 handle,int index)413 void SetFont(u32 handle, int index) { fontHandle_ = handle; fontIndex_ = index; }
414
415 private:
416 u32 fontLibID_;
417 u32 fontHandle_;
418 int fontIndex_;
419 };
420
421 class PostCharInfoAllocCallback : public PSPAction {
422 public:
PostCharInfoAllocCallback()423 PostCharInfoAllocCallback() {}
Create()424 static PSPAction *Create() { return new PostCharInfoAllocCallback(); }
DoState(PointerWrap & p)425 void DoState(PointerWrap &p) override {
426 auto s = p.Section("PostCharInfoAllocCallback", 1);
427 if (!s)
428 return;
429
430 Do(p, fontLibID_);
431 }
432 void run(MipsCall &call) override;
SetFontLib(u32 fontLibID)433 void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
434
435 private:
436 u32 fontLibID_;
437 };
438
439 class PostCharInfoFreeCallback : public PSPAction {
440 public:
PostCharInfoFreeCallback()441 PostCharInfoFreeCallback() {}
Create()442 static PSPAction *Create() { return new PostCharInfoFreeCallback(); }
DoState(PointerWrap & p)443 void DoState(PointerWrap &p) override {
444 auto s = p.Section("PostCharInfoFreeCallback", 1);
445 if (!s)
446 return;
447
448 Do(p, fontLibID_);
449 Do(p, charInfo_);
450 }
451 void run(MipsCall &call) override;
SetFontLib(u32 fontLibID)452 void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
SetCharInfo(PSPPointer<PGFCharInfo> charInfo)453 void SetCharInfo(PSPPointer<PGFCharInfo> charInfo) { charInfo_ = charInfo; }
454
455 private:
456 u32 fontLibID_;
457 PSPPointer<PGFCharInfo> charInfo_;
458 };
459
460
461 struct NativeFontLib {
462 FontNewLibParams params;
463 // TODO
464 u32_le fontInfo1;
465 u32_le fontInfo2;
466 u16_le unk1;
467 u16_le unk2;
468 float_le hRes;
469 float_le vRes;
470 u32_le internalFontCount;
471 u32_le internalFontInfo;
472 u16_le altCharCode;
473 u16_le unk5;
474 };
475
476 struct FontImageRect {
477 s16_le width;
478 s16_le height;
479 };
480
481 // A "fontLib" is a container of loaded fonts.
482 // One can open either "internal" fonts or custom fonts into a fontlib.
483 class FontLib {
484 public:
FontLib()485 FontLib() {
486 // For save states only.
487 }
488
FontLib(u32 paramPtr,u32 errorCodePtr)489 FontLib(u32 paramPtr, u32 errorCodePtr) : fontHRes_(128.0f), fontVRes_(128.0f), altCharCode_(0x5F), charInfoBitmapAddress_(0) {
490 nfl_ = 0;
491 Memory::ReadStruct(paramPtr, ¶ms_);
492 if (params_.numFonts > 9) {
493 params_.numFonts = 9;
494 }
495
496 // Technically, this should be four separate allocations.
497 u32 allocSize = 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230 + (u32)internalFonts.size() * 0xA8;
498 PostAllocCallback *action = (PostAllocCallback *) __KernelCreateAction(actionPostAllocCallback);
499 action->SetFontLib(GetListID(), errorCodePtr);
500
501 u32 args[2] = { userDataAddr(), allocSize };
502 hleEnqueueCall(allocFuncAddr(), 2, args, action);
503 }
504
GetListID()505 u32 GetListID() {
506 return (u32)(std::find(fontLibList.begin(), fontLibList.end(), this) - fontLibList.begin());
507 }
508
Done()509 void Done() {
510 for (size_t i = 0; i < fonts_.size(); i++) {
511 if (fontRefCount_[i] > 0) {
512 CloseFont(fontMap[fonts_[i]], true);
513 delete fontMap[fonts_[i]];
514 fontMap.erase(fonts_[i]);
515 }
516 }
517 u32 args[2] = { userDataAddr(), (u32)handle_ };
518 // TODO: The return value of this is leaking.
519 if (handle_) { // Avoid calling free-callback on double-free
520 if (coreState != CORE_POWERDOWN) {
521 hleEnqueueCall(freeFuncAddr(), 2, args);
522 }
523 }
524 handle_ = 0;
525 fonts_.clear();
526 fontRefCount_.clear();
527 openAllocatedAddresses_.clear();
528 }
529
AllocDone(u32 allocatedAddr)530 void AllocDone(u32 allocatedAddr) {
531 handle_ = allocatedAddr;
532 fonts_.resize(params_.numFonts);
533 fontRefCount_.resize(params_.numFonts);
534 openAllocatedAddresses_.resize(params_.numFonts);
535 for (size_t i = 0; i < fonts_.size(); i++) {
536 u32 addr = allocatedAddr + 0x4C + (u32)i * 0x4C;
537 fontRefCount_[i] = 0;
538 fonts_[i] = addr;
539 }
540
541 // Let's write out the native struct to make tests easier.
542 // It's possible games may depend on this staying in ram, e.g. copying it, we may move to that.
543 nfl_ = allocatedAddr;
544 nfl_->params = params_;
545 nfl_->fontInfo1 = allocatedAddr + 0x4C;
546 nfl_->fontInfo2 = allocatedAddr + 0x4C + params_.numFonts * 0x4C;
547 nfl_->unk1 = 0;
548 nfl_->unk2 = 0;
549 nfl_->hRes = fontHRes_;
550 nfl_->vRes = fontVRes_;
551 nfl_->internalFontCount = (u32)internalFonts.size();
552 nfl_->internalFontInfo = allocatedAddr + 0x4C + params_.numFonts * 0x4C + params_.numFonts * 0x230;
553 nfl_->altCharCode = altCharCode_;
554 }
555
handle() const556 u32 handle() const { return handle_; }
numFonts() const557 int numFonts() const { return params_.numFonts; }
userDataAddr() const558 u32_le userDataAddr() const{ return params_.userDataAddr; }
allocFuncAddr() const559 u32_le allocFuncAddr() const { return params_.allocFuncAddr; }
freeFuncAddr() const560 u32_le freeFuncAddr() const { return params_.freeFuncAddr; }
561
SetResolution(float hres,float vres)562 void SetResolution(float hres, float vres) {
563 fontHRes_ = hres;
564 fontVRes_ = vres;
565 if (nfl_.IsValid()) {
566 nfl_->hRes = hres;
567 nfl_->vRes = vres;
568 }
569 }
570
FontHRes() const571 float FontHRes() const { return fontHRes_; }
FontVRes() const572 float FontVRes() const { return fontVRes_; }
573
SetAltCharCode(int charCode)574 void SetAltCharCode(int charCode) {
575 altCharCode_ = charCode;
576 if (nfl_.IsValid())
577 nfl_->altCharCode = charCode;
578 }
579
GetFontHandle(int index) const580 int GetFontHandle(int index) const {
581 return fonts_[index];
582 }
583
GetFontRefCount(Font * font) const584 int GetFontRefCount(Font *font) const {
585 int foundFontIndex = FindExistingIndex(font);
586 if (foundFontIndex >= 0)
587 return fontRefCount_.at(foundFontIndex);
588 return 0;
589 }
590
591 // For FONT_OPEN_USER* modes, the font will automatically be freed.
OpenFont(Font * font,FontOpenMode mode,int & error)592 LoadedFont *OpenFont(Font *font, FontOpenMode mode, int &error) {
593 // TODO: Do something with mode, possibly save it where the PSP does in the struct.
594 // Maybe needed in Font, though? Handlers seem... difficult to emulate.
595
596 // First, check if the font is already open. We need to refcount, see font/open test.
597 int foundFontIndex = FindExistingIndex(font);
598 if (foundFontIndex < 0)
599 foundFontIndex = FindFreeIndex();
600
601 if (foundFontIndex < 0 || fontRefCount_[foundFontIndex] >= MAX_FONT_REFS) {
602 error = ERROR_FONT_TOO_MANY_OPEN_FONTS;
603 hleLogError(SCEFONT, 0, "Too many fonts opened in FontLib");
604 return nullptr;
605 }
606 if (!font->IsValid()) {
607 error = ERROR_FONT_INVALID_FONT_DATA;
608 hleLogError(SCEFONT, 0, "Invalid font data");
609 return nullptr;
610 }
611
612 LoadedFont *loadedFont = nullptr;
613 if (fontRefCount_[foundFontIndex] == 0) {
614 loadedFont = new LoadedFont(font, mode, GetListID(), fonts_[foundFontIndex]);
615
616 auto prevFont = fontMap.find(loadedFont->Handle());
617 if (prevFont != fontMap.end()) {
618 // Before replacing it and forgetting about it, let's free it.
619 delete prevFont->second;
620 }
621 fontMap[loadedFont->Handle()] = loadedFont;
622 } else {
623 loadedFont = fontMap[fonts_[foundFontIndex]];
624 }
625 fontRefCount_[foundFontIndex]++;
626
627 // Only need to allocate the first time.
628 if (!useAllocCallbacks || fontRefCount_[foundFontIndex] > 1)
629 return loadedFont;
630
631 u32 allocSize = 12;
632 if (mode == FONT_OPEN_INTERNAL_STINGY) {
633 allocSize = loadedFont->GetFont()->getStingySize();
634 } else if (mode == FONT_OPEN_INTERNAL_FULL) {
635 allocSize += loadedFont->GetFont()->getSize();
636 }
637
638 PostOpenAllocCallback *action = (PostOpenAllocCallback *)__KernelCreateAction(actionPostOpenAllocCallback);
639 action->SetFontLib(GetListID());
640 action->SetFont(loadedFont->Handle(), foundFontIndex);
641
642 u32 args[2] = { userDataAddr(), allocSize };
643 hleEnqueueCall(allocFuncAddr(), 2, args, action);
644
645 return loadedFont;
646 }
647
CloseFont(LoadedFont * font,bool releaseAll)648 void CloseFont(LoadedFont *font, bool releaseAll) {
649 bool allowClose = true;
650 for (size_t i = 0; i < fonts_.size(); i++) {
651 if (fonts_[i] == font->Handle() && fontRefCount_[i] > 0) {
652 if (releaseAll)
653 fontRefCount_[i] = 0;
654 else
655 fontRefCount_[i]--;
656
657 allowClose = fontRefCount_[i] == 0;
658 bool deallocate = allowClose && openAllocatedAddresses_[i] != 0;
659 if (deallocate && coreState != CORE_POWERDOWN) {
660 u32 args[2] = { userDataAddr(), openAllocatedAddresses_[i] };
661 hleEnqueueCall(freeFuncAddr(), 2, args);
662 openAllocatedAddresses_[i] = 0;
663 }
664 break;
665 }
666 }
667 flushFont();
668 if (allowClose)
669 font->Close();
670 }
671
flushFont()672 void flushFont() {
673 if (charInfoBitmapAddress_ != 0 && coreState != CORE_POWERDOWN) {
674 u32 args[2] = { userDataAddr(), charInfoBitmapAddress_ };
675 hleEnqueueCall(freeFuncAddr(), 2, args);
676 charInfoBitmapAddress_ = 0;
677 }
678 }
679
DoState(PointerWrap & p)680 void DoState(PointerWrap &p) {
681 auto s = p.Section("FontLib", 1, 3);
682 if (!s)
683 return;
684
685 Do(p, fonts_);
686 Do(p, fontRefCount_);
687 Do(p, params_);
688 Do(p, fontHRes_);
689 Do(p, fontVRes_);
690 Do(p, fileFontHandle_);
691 Do(p, handle_);
692 Do(p, altCharCode_);
693 if (s >= 2) {
694 Do(p, nfl_);
695 } else {
696 nfl_ = 0;
697 }
698
699 if (s >= 3) {
700 Do(p, openAllocatedAddresses_);
701 Do(p, charInfoBitmapAddress_);
702 } else {
703 openAllocatedAddresses_.resize(params_.numFonts);
704 charInfoBitmapAddress_ = 0;
705 }
706 }
707
SetFileFontHandle(u32 handle)708 void SetFileFontHandle(u32 handle) {
709 fileFontHandle_ = handle;
710 }
711
GetAltCharCode() const712 u32 GetAltCharCode() const { return altCharCode_; }
713
GetOpenAllocatedAddress(int index) const714 u32 GetOpenAllocatedAddress(int index) const {
715 if(index < numFonts())
716 return openAllocatedAddresses_[index];
717 return 0;
718 }
719
SetOpenAllocatedAddress(int index,u32 addr)720 void SetOpenAllocatedAddress(int index, u32 addr) {
721 if (index < numFonts())
722 openAllocatedAddresses_[index] = addr;
723 }
724
GetCharInfoBitmapAddress() const725 u32 GetCharInfoBitmapAddress() const { return charInfoBitmapAddress_; }
SetCharInfoBitmapAddress(u32 addr)726 void SetCharInfoBitmapAddress(u32 addr) { charInfoBitmapAddress_ = addr; }
727
728 private:
FindExistingIndex(Font * font) const729 int FindExistingIndex(Font *font) const {
730 // TODO: Should this also match for memory fonts, or only internal fonts?
731 for (auto it : fontMap) {
732 if (it.second->GetFont() != font || it.second->GetFontLib() != this)
733 continue;
734 for (size_t i = 0; i < fonts_.size(); i++) {
735 if (fonts_[i] == it.first) {
736 return (int)i;
737 }
738 }
739 }
740 return -1;
741 }
742
FindFreeIndex() const743 int FindFreeIndex() const {
744 for (size_t i = 0; i < fonts_.size(); i++) {
745 if (fontRefCount_[i] == 0) {
746 return (int)i;
747 }
748 }
749 return -1;
750 }
751
752 std::vector<u32> fonts_;
753 std::vector<u32> fontRefCount_;
754
755 FontNewLibParams params_;
756 float fontHRes_;
757 float fontVRes_;
758 int fileFontHandle_;
759 int handle_;
760 int altCharCode_;
761 std::vector<u32> openAllocatedAddresses_;
762 u32 charInfoBitmapAddress_;
763 PSPPointer<NativeFontLib> nfl_;
764
765 DISALLOW_COPY_AND_ASSIGN(FontLib);
766 };
767
768
run(MipsCall & call)769 void PostAllocCallback::run(MipsCall &call) {
770 INFO_LOG(SCEFONT, "Entering PostAllocCallback::run");
771 u32 v0 = currentMIPS->r[MIPS_REG_V0];
772 if (v0 == 0) {
773 // TODO: Who deletes fontLib?
774 if (errorCodePtr_)
775 Memory::Write_U32(ERROR_FONT_OUT_OF_MEMORY, errorCodePtr_);
776 call.setReturnValue(0);
777 } else {
778 FontLib *fontLib = fontLibList[fontLibID_];
779 fontLib->AllocDone(v0);
780 fontLibMap[fontLib->handle()] = fontLibID_;
781 // This is the same as v0 above.
782 call.setReturnValue(fontLib->handle());
783 }
784 INFO_LOG(SCEFONT, "Leaving PostAllocCallback::run");
785 }
786
run(MipsCall & call)787 void PostOpenCallback::run(MipsCall &call) {
788 FontLib *fontLib = fontLibList[fontLibID_];
789 u32 v0 = currentMIPS->r[MIPS_REG_V0];
790 fontLib->SetFileFontHandle(v0);
791 }
792
run(MipsCall & call)793 void PostOpenAllocCallback::run(MipsCall &call) {
794 FontLib *fontLib = fontLibList[fontLibID_];
795 u32 v0 = currentMIPS->r[MIPS_REG_V0];
796 fontLib->SetOpenAllocatedAddress(fontIndex_, v0);
797 }
798
run(MipsCall & call)799 void PostCharInfoAllocCallback::run(MipsCall &call) {
800 FontLib *fontLib = fontLibList[fontLibID_];
801 u32 v0 = currentMIPS->r[MIPS_REG_V0];
802 if (v0 == 0) {
803 call.setReturnValue(ERROR_FONT_OUT_OF_MEMORY); // From JPCSP, if alloc size is 0, still this error value?
804 } else {
805 fontLib->SetCharInfoBitmapAddress(v0);
806 }
807 }
808
run(MipsCall & call)809 void PostCharInfoFreeCallback::run(MipsCall &call) {
810 FontLib *fontLib = fontLibList[fontLibID_];
811 fontLib->SetCharInfoBitmapAddress(0);
812
813 u32 allocSize = charInfo_->bitmapWidth * charInfo_->bitmapHeight;
814 PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);
815 action->SetFontLib(fontLibID_);
816
817 u32 args[2] = { fontLib->userDataAddr(), allocSize };
818 hleEnqueueCall(fontLib->allocFuncAddr(), 2, args, action);
819 }
820
GetCharInfo(int charCode,PGFCharInfo * charInfo,int glyphType) const821 inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {
822 auto fontLib = GetFontLib();
823 int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
824 return GetPGF()->GetCharInfo(charCode, charInfo, altCharCode, glyphType);
825 }
826
DrawCharacter(const GlyphImage * image,int clipX,int clipY,int clipWidth,int clipHeight,int charCode,int glyphType) const827 inline void LoadedFont::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int glyphType) const {
828 auto fontLib = GetFontLib();
829 int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
830 GetPGF()->DrawCharacter(image, clipX, clipY, clipWidth, clipHeight, charCode, altCharCode, glyphType);
831 }
832
GetFontLib(u32 handle)833 static FontLib *GetFontLib(u32 handle) {
834 if (fontLibMap.find(handle) != fontLibMap.end()) {
835 return fontLibList[fontLibMap[handle]];
836 }
837 return nullptr;
838 }
839
GetLoadedFont(u32 handle,bool allowClosed)840 static LoadedFont *GetLoadedFont(u32 handle, bool allowClosed) {
841 auto iter = fontMap.find(handle);
842 if (iter != fontMap.end()) {
843 if (iter->second->IsOpen() || allowClosed) {
844 return fontMap[handle];
845 } else {
846 ERROR_LOG(SCEFONT, "Font exists but is closed, which was not allowed in this call.");
847 return 0;
848 }
849 } else {
850 ERROR_LOG(SCEFONT, "No font with handle %08x", handle);
851 return 0;
852 }
853 }
854
__LoadInternalFonts()855 static void __LoadInternalFonts() {
856 if (internalFonts.size()) {
857 // Fonts already loaded.
858 return;
859 }
860 const std::string fontPath = "flash0:/font/";
861 const std::string fontOverridePath = "ms0:/PSP/flash0/font/";
862 const std::string userfontPath = "disc0:/PSP_GAME/USRDIR/";
863
864 if (!pspFileSystem.GetFileInfo(fontPath).exists) {
865 pspFileSystem.MkDir(fontPath);
866 }
867 if ((pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/zh_gb.pgf").exists) && (pspFileSystem.GetFileInfo("disc0:/PSP_GAME/USRDIR/oldfont.prx").exists)) {
868 for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {
869 const FontRegistryEntry &entry = fontRegistry[i];
870 std::string fontFilename = userfontPath + entry.fileName;
871 PSPFileInfo info = pspFileSystem.GetFileInfo(fontFilename);
872 DEBUG_LOG(SCEFONT, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
873 std::vector<u8> buffer;
874 if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {
875 ERROR_LOG(SCEFONT, "Failed opening font");
876 continue;
877 }
878 internalFonts.push_back(new Font(buffer, entry));
879 DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
880 return;
881 }
882 }
883
884 for (size_t i = 0; i < ARRAY_SIZE(fontRegistry); i++) {
885 const FontRegistryEntry &entry = fontRegistry[i];
886 std::string fontFilename = userfontPath + entry.fileName;
887 PSPFileInfo info = pspFileSystem.GetFileInfo(fontFilename);
888
889 if (!info.exists) {
890 // No user font, let's try override path.
891 fontFilename = fontOverridePath + entry.fileName;
892 info = pspFileSystem.GetFileInfo(fontFilename);
893 }
894
895 if (!info.exists) {
896 // No override, let's use the default path.
897 fontFilename = fontPath + entry.fileName;
898 info = pspFileSystem.GetFileInfo(fontFilename);
899 }
900
901 if (info.exists) {
902 DEBUG_LOG(SCEFONT, "Loading internal font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
903 std::vector<u8> buffer;
904 if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {
905 ERROR_LOG(SCEFONT, "Failed opening font");
906 continue;
907 }
908
909 internalFonts.push_back(new Font(buffer, entry));
910
911 DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
912 } else if (!entry.ignoreIfMissing) {
913 WARN_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str());
914 }
915 }
916 }
917
GetInternalFontIndex(Font * font)918 int GetInternalFontIndex(Font *font) {
919 for (size_t i = 0; i < internalFonts.size(); i++) {
920 if (internalFonts[i] == font)
921 return (int)i;
922 }
923 return -1;
924 }
925
__FontInit()926 void __FontInit() {
927 useAllocCallbacks = true;
928 actionPostAllocCallback = __KernelRegisterActionType(PostAllocCallback::Create);
929 actionPostOpenCallback = __KernelRegisterActionType(PostOpenCallback::Create);
930 actionPostOpenAllocCallback = __KernelRegisterActionType(PostOpenAllocCallback::Create);
931 actionPostCharInfoAllocCallback = __KernelRegisterActionType(PostCharInfoAllocCallback::Create);
932 actionPostCharInfoFreeCallback = __KernelRegisterActionType(PostCharInfoFreeCallback::Create);
933 }
934
__FontShutdown()935 void __FontShutdown() {
936 for (auto iter = fontMap.begin(); iter != fontMap.end(); iter++) {
937 FontLib *fontLib = iter->second->GetFontLib();
938 if (fontLib)
939 fontLib->CloseFont(iter->second, true);
940 delete iter->second;
941 }
942 fontMap.clear();
943 for (auto iter = fontLibList.begin(); iter != fontLibList.end(); iter++) {
944 delete *iter;
945 }
946 fontLibList.clear();
947 fontLibMap.clear();
948 for (auto iter = internalFonts.begin(); iter != internalFonts.end(); ++iter) {
949 delete *iter;
950 }
951 internalFonts.clear();
952 }
953
__FontDoState(PointerWrap & p)954 void __FontDoState(PointerWrap &p) {
955 auto s = p.Section("sceFont", 1, 2);
956 if (!s)
957 return;
958
959 __LoadInternalFonts();
960
961 Do(p, fontLibList);
962 Do(p, fontLibMap);
963 Do(p, fontMap);
964
965 Do(p, actionPostAllocCallback);
966 __KernelRestoreActionType(actionPostAllocCallback, PostAllocCallback::Create);
967 Do(p, actionPostOpenCallback);
968 __KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);
969 if (s >= 2) {
970 Do(p, actionPostOpenAllocCallback);
971 __KernelRestoreActionType(actionPostOpenAllocCallback, PostOpenAllocCallback::Create);
972 Do(p, actionPostCharInfoAllocCallback);
973 __KernelRestoreActionType(actionPostCharInfoAllocCallback, PostCharInfoAllocCallback::Create);
974 Do(p, actionPostCharInfoFreeCallback);
975 __KernelRestoreActionType(actionPostCharInfoFreeCallback, PostCharInfoFreeCallback::Create);
976 } else {
977 useAllocCallbacks = false;
978 }
979 }
980
sceFontNewLib(u32 paramPtr,u32 errorCodePtr)981 static u32 sceFontNewLib(u32 paramPtr, u32 errorCodePtr) {
982 // Lazy load internal fonts, only when font library first inited.
983 __LoadInternalFonts();
984
985 auto params = PSPPointer<FontNewLibParams>::Create(paramPtr);
986 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
987
988 if (!params.IsValid() || !errorCode.IsValid()) {
989 ERROR_LOG_REPORT(SCEFONT, "sceFontNewLib(%08x, %08x): invalid addresses", paramPtr, errorCodePtr);
990 // The PSP would crash in this situation, not a real error code.
991 return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
992 }
993 if (!Memory::IsValidAddress(params->allocFuncAddr) || !Memory::IsValidAddress(params->freeFuncAddr)) {
994 ERROR_LOG_REPORT(SCEFONT, "sceFontNewLib(%08x, %08x): missing alloc func", paramPtr, errorCodePtr);
995 *errorCode = ERROR_FONT_INVALID_PARAMETER;
996 return 0;
997 }
998
999 INFO_LOG(SCEFONT, "sceFontNewLib(%08x, %08x)", paramPtr, errorCodePtr);
1000 *errorCode = 0;
1001
1002 FontLib *newLib = new FontLib(paramPtr, errorCodePtr);
1003 fontLibList.push_back(newLib);
1004 // The game should never see this value, the return value is replaced
1005 // by the action. Except if we disable the alloc, in this case we return
1006 // the handle correctly here.
1007 return hleDelayResult(newLib->handle(), "new fontlib", 30000);
1008 }
1009
sceFontDoneLib(u32 fontLibHandle)1010 static int sceFontDoneLib(u32 fontLibHandle) {
1011 FontLib *fl = GetFontLib(fontLibHandle);
1012 if (fl) {
1013 fl->Done();
1014 return hleLogSuccessInfoI(SCEFONT, 0);
1015 }
1016
1017 return hleLogWarning(SCEFONT, 0, "invalid font lib");
1018 }
1019
1020 // Open internal font into a FontLib
sceFontOpen(u32 libHandle,u32 index,u32 mode,u32 errorCodePtr)1021 static u32 sceFontOpen(u32 libHandle, u32 index, u32 mode, u32 errorCodePtr) {
1022 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1023 if (!errorCode.IsValid()) {
1024 // Would crash on the PSP.
1025 return hleLogError(SCEFONT, -1, "invalid error address");
1026 }
1027
1028 FontLib *fontLib = GetFontLib(libHandle);
1029 if (!fontLib) {
1030 *errorCode = ERROR_FONT_INVALID_LIBID;
1031 return hleLogDebug(SCEFONT, 0, "invalid font lib");
1032 }
1033 if (index >= internalFonts.size()) {
1034 *errorCode = ERROR_FONT_INVALID_PARAMETER;
1035 return hleLogDebug(SCEFONT, 0, "invalid font index");
1036 }
1037
1038 FontOpenMode openMode = mode != 1 ? FONT_OPEN_INTERNAL_STINGY : FONT_OPEN_INTERNAL_FULL;
1039 LoadedFont *font = fontLib->OpenFont(internalFonts[index], openMode, *errorCode);
1040 if (font) {
1041 *errorCode = 0;
1042 // Delay only on the first open.
1043 if (fontLib->GetFontRefCount(internalFonts[index]) == 1)
1044 return hleDelayResult(hleLogSuccessX(SCEFONT, font->Handle()), "font open", 10000);
1045 return hleLogSuccessX(SCEFONT, font->Handle());
1046 }
1047 return 0;
1048 }
1049
1050 // Open a user font in RAM into a FontLib
sceFontOpenUserMemory(u32 libHandle,u32 memoryFontPtr,u32 memoryFontLength,u32 errorCodePtr)1051 static u32 sceFontOpenUserMemory(u32 libHandle, u32 memoryFontPtr, u32 memoryFontLength, u32 errorCodePtr) {
1052 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1053 if (!errorCode.IsValid()) {
1054 return hleReportError(SCEFONT, -1, "invalid error address");
1055 }
1056 if (!Memory::IsValidAddress(memoryFontPtr)) {
1057 *errorCode = ERROR_FONT_INVALID_PARAMETER;
1058 return hleReportError(SCEFONT, 0, "invalid address");
1059 }
1060
1061 FontLib *fontLib = GetFontLib(libHandle);
1062 if (!fontLib) {
1063 *errorCode = ERROR_FONT_INVALID_LIBID;
1064 return hleReportError(SCEFONT, 0, "invalid font lib");
1065 }
1066 if (memoryFontLength == 0) {
1067 *errorCode = ERROR_FONT_INVALID_PARAMETER;
1068 return hleReportError(SCEFONT, 0, "invalid size");
1069 }
1070
1071 const u8 *fontData = Memory::GetPointer(memoryFontPtr);
1072 // Games are able to overstate the size of a font. Let's avoid crashing when we memcpy() it.
1073 // Unsigned 0xFFFFFFFF is treated as max, but that's impossible, so let's clamp to 64MB.
1074 if (memoryFontLength > 0x03FFFFFF)
1075 memoryFontLength = 0x03FFFFFF;
1076 while (!Memory::IsValidAddress(memoryFontPtr + memoryFontLength - 1)) {
1077 --memoryFontLength;
1078 }
1079 Font *f = new Font(fontData, memoryFontLength);
1080 LoadedFont *font = fontLib->OpenFont(f, FONT_OPEN_USERBUFFER, *errorCode);
1081 if (font) {
1082 *errorCode = 0;
1083 return hleLogSuccessX(SCEFONT, font->Handle());
1084 }
1085 delete f;
1086 return 0;
1087 }
1088
1089 // Open a user font in a file into a FontLib
sceFontOpenUserFile(u32 libHandle,const char * fileName,u32 mode,u32 errorCodePtr)1090 static u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u32 errorCodePtr) {
1091 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1092 if (!errorCode.IsValid()) {
1093 return hleReportError(SCEFONT, ERROR_FONT_INVALID_PARAMETER, "invalid error address");
1094 }
1095
1096 if (!fileName) {
1097 *errorCode = ERROR_FONT_INVALID_PARAMETER;
1098 return hleReportError(SCEFONT, 0, "invalid filename");
1099 }
1100
1101 FontLib *fontLib = GetFontLib(libHandle);
1102 if (!fontLib) {
1103 *errorCode = ERROR_FONT_INVALID_LIBID;
1104 return hleReportError(SCEFONT, 0, "invalid font lib");
1105 }
1106
1107 // TODO: Technically, we only do this if mode = 1. Mode 0 uses the handlers.
1108 if (mode != 1) {
1109 WARN_LOG_REPORT(SCEFONT, "Loading file directly instead of using handlers: %s", fileName);
1110 }
1111
1112 std::vector<u8> buffer;
1113 if (pspFileSystem.ReadEntireFile(fileName, buffer) != 0) {
1114 *errorCode = ERROR_FONT_HANDLER_OPEN_FAILED;
1115 return hleLogError(SCEFONT, 0, "file does not exist");
1116 }
1117
1118 Font *f = new Font(buffer);
1119 FontOpenMode openMode = mode == 0 ? FONT_OPEN_USERFILE_HANDLERS : FONT_OPEN_USERFILE_FULL;
1120 LoadedFont *font = fontLib->OpenFont(f, openMode, *errorCode);
1121 if (font) {
1122 *errorCode = 0;
1123 return hleLogSuccessInfoX(SCEFONT, font->Handle());
1124 }
1125
1126 delete f;
1127 // Message was already logged.
1128 return 0;
1129 }
1130
sceFontClose(u32 fontHandle)1131 static int sceFontClose(u32 fontHandle) {
1132 LoadedFont *font = GetLoadedFont(fontHandle, false);
1133 if (font) {
1134 DEBUG_LOG(SCEFONT, "sceFontClose(%x)", fontHandle);
1135 FontLib *fontLib = font->GetFontLib();
1136 if (fontLib) {
1137 fontLib->CloseFont(font, false);
1138 }
1139 } else
1140 ERROR_LOG(SCEFONT, "sceFontClose(%x) - font not open?", fontHandle);
1141 return 0;
1142 }
1143
sceFontFindOptimumFont(u32 libHandle,u32 fontStylePtr,u32 errorCodePtr)1144 static int sceFontFindOptimumFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {
1145 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1146 if (!errorCode.IsValid()) {
1147 ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid error address", libHandle, fontStylePtr, errorCodePtr);
1148 return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
1149 }
1150
1151 FontLib *fontLib = GetFontLib(libHandle);
1152 if (!fontLib) {
1153 ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid font lib", libHandle, fontStylePtr, errorCodePtr);
1154 *errorCode = ERROR_FONT_INVALID_LIBID;
1155 return 0;
1156 }
1157
1158 if (!Memory::IsValidAddress(fontStylePtr)) {
1159 ERROR_LOG_REPORT(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x): invalid style address", libHandle, fontStylePtr, errorCodePtr);
1160 // Yes, actually. Must've been a typo in the library.
1161 *errorCode = ERROR_FONT_INVALID_LIBID;
1162 return 0;
1163 }
1164
1165 DEBUG_LOG(SCEFONT, "sceFontFindOptimumFont(%08x, %08x, %08x)", libHandle, fontStylePtr, errorCodePtr);
1166
1167 auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
1168
1169 // Find the first nearest match for H/V, OR the last exact match for others.
1170 float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();
1171 float vRes = requestedStyle->fontVRes > 0.0f ? (float)requestedStyle->fontVRes : fontLib->FontVRes();
1172 Font *optimumFont = 0;
1173 Font *nearestFont = 0;
1174 float nearestDist = std::numeric_limits<float>::infinity();
1175 for (size_t i = 0; i < internalFonts.size(); i++) {
1176 MatchQuality q = internalFonts[i]->MatchesStyle(*requestedStyle);
1177 if (q != MATCH_NONE) {
1178 auto matchStyle = internalFonts[i]->GetFontStyle();
1179 if (requestedStyle->fontH > 0.0f) {
1180 float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);
1181 if (hDist < nearestDist) {
1182 nearestDist = hDist;
1183 nearestFont = internalFonts[i];
1184 }
1185 }
1186 if (requestedStyle->fontV > 0.0f) {
1187 // Appears to be a bug? It seems to match H instead of V.
1188 float vDist = fabs(matchStyle.fontVRes * matchStyle.fontV - vRes * requestedStyle->fontH);
1189 if (vDist < nearestDist) {
1190 nearestDist = vDist;
1191 nearestFont = internalFonts[i];
1192 }
1193 }
1194 }
1195 if (q == MATCH_GOOD) {
1196 optimumFont = internalFonts[i];
1197 }
1198 }
1199 if (nearestFont) {
1200 optimumFont = nearestFont;
1201 }
1202 if (optimumFont) {
1203 *errorCode = 0;
1204 return GetInternalFontIndex(optimumFont);
1205 } else {
1206 *errorCode = 0;
1207 return 0;
1208 }
1209 }
1210
1211 // Returns the font index, not handle
sceFontFindFont(u32 libHandle,u32 fontStylePtr,u32 errorCodePtr)1212 static int sceFontFindFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {
1213 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1214 if (!errorCode.IsValid()) {
1215 ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%x, %x, %x): invalid error address", libHandle, fontStylePtr, errorCodePtr);
1216 return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
1217 }
1218
1219 FontLib *fontLib = GetFontLib(libHandle);
1220 if (!fontLib) {
1221 ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%08x, %08x, %08x): invalid font lib", libHandle, fontStylePtr, errorCodePtr);
1222 *errorCode = ERROR_FONT_INVALID_LIBID;
1223 return 0;
1224 }
1225
1226 if (!Memory::IsValidAddress(fontStylePtr)) {
1227 ERROR_LOG_REPORT(SCEFONT, "sceFontFindFont(%08x, %08x, %08x): invalid style address", libHandle, fontStylePtr, errorCodePtr);
1228 *errorCode = ERROR_FONT_INVALID_PARAMETER;
1229 return 0;
1230 }
1231
1232 DEBUG_LOG(SCEFONT, "sceFontFindFont(%x, %x, %x)", libHandle, fontStylePtr, errorCodePtr);
1233
1234 auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
1235
1236 // Find the closest exact match for the fields specified.
1237 float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();
1238 for (size_t i = 0; i < internalFonts.size(); i++) {
1239 if (internalFonts[i]->MatchesStyle(*requestedStyle) != MATCH_NONE) {
1240 auto matchStyle = internalFonts[i]->GetFontStyle();
1241 if (requestedStyle->fontH > 0.0f) {
1242 float hDist = fabs(matchStyle.fontHRes * matchStyle.fontH - hRes * requestedStyle->fontH);
1243 if (hDist > 0.001f) {
1244 continue;
1245 }
1246 } else if (requestedStyle->fontV > 0.0f) {
1247 // V seems to be ignored, unless H isn't specified.
1248 // If V is specified alone, the match always fails.
1249 continue;
1250 }
1251 *errorCode = 0;
1252 return (int)i;
1253 }
1254 }
1255 *errorCode = 0;
1256 return -1;
1257 }
1258
sceFontGetFontInfo(u32 fontHandle,u32 fontInfoPtr)1259 static int sceFontGetFontInfo(u32 fontHandle, u32 fontInfoPtr) {
1260 if (!Memory::IsValidAddress(fontInfoPtr)) {
1261 ERROR_LOG(SCEFONT, "sceFontGetFontInfo(%x, %x): bad fontInfo pointer", fontHandle, fontInfoPtr);
1262 return ERROR_FONT_INVALID_PARAMETER;
1263 }
1264 LoadedFont *font = GetLoadedFont(fontHandle, true);
1265 if (!font) {
1266 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfo(%x, %x): bad font", fontHandle, fontInfoPtr);
1267 return ERROR_FONT_INVALID_PARAMETER;
1268 }
1269
1270 DEBUG_LOG(SCEFONT, "sceFontGetFontInfo(%x, %x)", fontHandle, fontInfoPtr);
1271 auto fi = PSPPointer<PGFFontInfo>::Create(fontInfoPtr);
1272 font->GetPGF()->GetFontInfo(fi);
1273 fi->fontStyle = font->GetFont()->GetFontStyle();
1274
1275 return 0;
1276 }
1277
1278 // It says FontInfo but it means Style - this is like sceFontGetFontList().
sceFontGetFontInfoByIndexNumber(u32 libHandle,u32 fontInfoPtr,u32 index)1279 static int sceFontGetFontInfoByIndexNumber(u32 libHandle, u32 fontInfoPtr, u32 index) {
1280 auto fontStyle = PSPPointer<PGFFontStyle>::Create(fontInfoPtr);
1281 FontLib *fl = GetFontLib(libHandle);
1282 if (!fl || fl->handle() == 0) {
1283 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font lib", libHandle, fontInfoPtr, index);
1284 return !fl ? ERROR_FONT_INVALID_LIBID : ERROR_FONT_INVALID_PARAMETER;
1285 }
1286 if (index >= internalFonts.size()) {
1287 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid font index", libHandle, fontInfoPtr, index);
1288 return ERROR_FONT_INVALID_PARAMETER;
1289 }
1290 if (!fontStyle.IsValid()) {
1291 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i): invalid info pointer", libHandle, fontInfoPtr, index);
1292 return ERROR_FONT_INVALID_PARAMETER;
1293 }
1294
1295 DEBUG_LOG(SCEFONT, "sceFontGetFontInfoByIndexNumber(%08x, %08x, %i)", libHandle, fontInfoPtr, index);
1296 auto font = internalFonts[index];
1297 *fontStyle = font->GetFontStyle();
1298
1299 return 0;
1300 }
1301
sceFontGetCharInfo(u32 fontHandle,u32 charCode,u32 charInfoPtr)1302 static int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
1303 charCode &= 0xffff;
1304 if (!Memory::IsValidAddress(charInfoPtr)) {
1305 ERROR_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);
1306 return ERROR_FONT_INVALID_PARAMETER;
1307 }
1308 LoadedFont *font = GetLoadedFont(fontHandle, true);
1309 if (!font) {
1310 // The PSP crashes, but we assume it'd work like sceFontGetFontInfo(), and not touch charInfo.
1311 ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);
1312 return ERROR_FONT_INVALID_PARAMETER;
1313 }
1314
1315 DEBUG_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
1316 auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);
1317 font->GetCharInfo(charCode, charInfo);
1318
1319 if (!useAllocCallbacks)
1320 return 0;
1321
1322 u32 allocSize = charInfo->bitmapWidth * charInfo->bitmapHeight;
1323 if (font->GetFontLib() && (charInfo->sfp26AdvanceH != 0 || charInfo->sfp26AdvanceV != 0)) {
1324 if (font->GetFontLib()->GetCharInfoBitmapAddress() != 0) {
1325 PostCharInfoFreeCallback *action = (PostCharInfoFreeCallback *)__KernelCreateAction(actionPostCharInfoFreeCallback);
1326 action->SetFontLib(font->GetFontLib()->GetListID());
1327 action->SetCharInfo(charInfo);
1328
1329 u32 args[2] = { font->GetFontLib()->userDataAddr(), font->GetFontLib()->GetCharInfoBitmapAddress() };
1330 hleEnqueueCall(font->GetFontLib()->freeFuncAddr(), 2, args, action);
1331 } else {
1332 PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);
1333 action->SetFontLib(font->GetFontLib()->GetListID());
1334
1335 u32 args[2] = { font->GetFontLib()->userDataAddr(), allocSize };
1336 hleEnqueueCall(font->GetFontLib()->allocFuncAddr(), 2, args, action);
1337 }
1338 }
1339
1340 return 0;
1341 }
1342
sceFontGetShadowInfo(u32 fontHandle,u32 charCode,u32 charInfoPtr)1343 static int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
1344 charCode &= 0xffff;
1345 if (!Memory::IsValidAddress(charInfoPtr)) {
1346 ERROR_LOG(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr);
1347 return ERROR_FONT_INVALID_PARAMETER;
1348 }
1349 LoadedFont *font = GetLoadedFont(fontHandle, true);
1350 if (!font) {
1351 ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr);
1352 return ERROR_FONT_INVALID_PARAMETER;
1353 }
1354
1355 DEBUG_LOG(SCEFONT, "sceFontGetShadowInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
1356 auto charInfo = PSPPointer<PGFCharInfo>::Create(charInfoPtr);
1357 font->GetCharInfo(charCode, charInfo, FONT_PGF_SHADOWGLYPH);
1358
1359 return 0;
1360 }
1361
sceFontGetCharImageRect(u32 fontHandle,u32 charCode,u32 charRectPtr)1362 static int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
1363 charCode &= 0xffff;
1364 auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);
1365 LoadedFont *font = GetLoadedFont(fontHandle, true);
1366 if (!font) {
1367 ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);
1368 return ERROR_FONT_INVALID_PARAMETER;
1369 }
1370 if (!charRect.IsValid()) {
1371 ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);
1372 return ERROR_FONT_INVALID_PARAMETER;
1373 }
1374
1375 DEBUG_LOG(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
1376 PGFCharInfo charInfo;
1377 font->GetCharInfo(charCode, &charInfo);
1378 charRect->width = charInfo.bitmapWidth;
1379 charRect->height = charInfo.bitmapHeight;
1380 return 0;
1381 }
1382
sceFontGetShadowImageRect(u32 fontHandle,u32 charCode,u32 charRectPtr)1383 static int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
1384 charCode &= 0xffff;
1385 auto charRect = PSPPointer<FontImageRect>::Create(charRectPtr);
1386 LoadedFont *font = GetLoadedFont(fontHandle, true);
1387 if (!font) {
1388 ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x): bad font", fontHandle, charCode, charRectPtr);
1389 return ERROR_FONT_INVALID_PARAMETER;
1390 }
1391 if (!charRect.IsValid()) {
1392 ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x): invalid rect pointer", fontHandle, charCode, charRectPtr);
1393 return ERROR_FONT_INVALID_PARAMETER;
1394 }
1395
1396 DEBUG_LOG(SCEFONT, "sceFontGetShadowImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
1397 PGFCharInfo charInfo;
1398 font->GetCharInfo(charCode, &charInfo, FONT_PGF_SHADOWGLYPH);
1399 charRect->width = charInfo.bitmapWidth;
1400 charRect->height = charInfo.bitmapHeight;
1401 return 0;
1402 }
1403
sceFontGetCharGlyphImage(u32 fontHandle,u32 charCode,u32 glyphImagePtr)1404 static int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {
1405 charCode &= 0xffff;
1406 if (!Memory::IsValidAddress(glyphImagePtr)) {
1407 ERROR_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);
1408 return ERROR_FONT_INVALID_PARAMETER;
1409 }
1410 LoadedFont *font = GetLoadedFont(fontHandle, true);
1411 if (!font) {
1412 ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);
1413 return ERROR_FONT_INVALID_PARAMETER;
1414 }
1415
1416 DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);
1417 auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1418 font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_CHARGLYPH);
1419 return 0;
1420 }
1421
sceFontGetCharGlyphImage_Clip(u32 fontHandle,u32 charCode,u32 glyphImagePtr,int clipXPos,int clipYPos,int clipWidth,int clipHeight)1422 static int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {
1423 charCode &= 0xffff;
1424 if (!Memory::IsValidAddress(glyphImagePtr)) {
1425 ERROR_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1426 return ERROR_FONT_INVALID_PARAMETER;
1427 }
1428 LoadedFont *font = GetLoadedFont(fontHandle, true);
1429 if (!font) {
1430 ERROR_LOG_REPORT(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1431 return ERROR_FONT_INVALID_PARAMETER;
1432 }
1433
1434 DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1435 auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1436 font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_CHARGLYPH);
1437 return 0;
1438 }
1439
sceFontSetAltCharacterCode(u32 fontLibHandle,u32 charCode)1440 static int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode) {
1441 charCode &= 0xffff;
1442 FontLib *fl = GetFontLib(fontLibHandle);
1443 if (!fl) {
1444 ERROR_LOG_REPORT(SCEFONT, "sceFontSetAltCharacterCode(%08x, %08x): invalid font lib", fontLibHandle, charCode);
1445 return ERROR_FONT_INVALID_LIBID;
1446 }
1447
1448 INFO_LOG(SCEFONT, "sceFontSetAltCharacterCode(%08x, %08x)", fontLibHandle, charCode);
1449 fl->SetAltCharCode(charCode & 0xFFFF);
1450 return 0;
1451 }
1452
sceFontFlush(u32 fontHandle)1453 static int sceFontFlush(u32 fontHandle) {
1454 INFO_LOG(SCEFONT, "sceFontFlush(%i)", fontHandle);
1455
1456 LoadedFont *font = GetLoadedFont(fontHandle, true);
1457 if (!font) {
1458 ERROR_LOG_REPORT(SCEFONT, "sceFontFlush(%08x): bad font", fontHandle);
1459 return ERROR_FONT_INVALID_PARAMETER;
1460 }
1461
1462 if (font->GetFontLib())
1463 font->GetFontLib()->flushFont();
1464
1465 return 0;
1466 }
1467
1468 // One would think that this should loop through the fonts loaded in the fontLibHandle,
1469 // but it seems not.
sceFontGetFontList(u32 fontLibHandle,u32 fontStylePtr,int numFonts)1470 static int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, int numFonts) {
1471 auto fontStyles = PSPPointer<PGFFontStyle>::Create(fontStylePtr);
1472 FontLib *fl = GetFontLib(fontLibHandle);
1473 if (!fl) {
1474 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontList(%08x, %08x, %i): invalid font lib", fontLibHandle, fontStylePtr, numFonts);
1475 return ERROR_FONT_INVALID_LIBID;
1476 }
1477 if (!fontStyles.IsValid()) {
1478 ERROR_LOG_REPORT(SCEFONT, "sceFontGetFontList(%08x, %08x, %i): invalid style pointer", fontLibHandle, fontStylePtr, numFonts);
1479 return ERROR_FONT_INVALID_PARAMETER;
1480 }
1481
1482 DEBUG_LOG(SCEFONT, "sceFontGetFontList(%08x, %08x, %i)", fontLibHandle, fontStylePtr, numFonts);
1483 if (fl->handle() != 0) {
1484 numFonts = std::min(numFonts, (int)internalFonts.size());
1485 for (int i = 0; i < numFonts; i++)
1486 fontStyles[i] = internalFonts[i]->GetFontStyle();
1487 }
1488
1489 return hleDelayResult(0, "font list read", 100);
1490 }
1491
sceFontGetNumFontList(u32 fontLibHandle,u32 errorCodePtr)1492 static int sceFontGetNumFontList(u32 fontLibHandle, u32 errorCodePtr) {
1493 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1494 if (!errorCode.IsValid()) {
1495 ERROR_LOG_REPORT(SCEFONT, "sceFontGetNumFontList(%08x, %08x): invalid error address", fontLibHandle, errorCodePtr);
1496 return ERROR_FONT_INVALID_PARAMETER;
1497 }
1498 FontLib *fl = GetFontLib(fontLibHandle);
1499 if (!fl) {
1500 ERROR_LOG_REPORT(SCEFONT, "sceFontGetNumFontList(%08x, %08x): invalid font lib", fontLibHandle, errorCodePtr);
1501 *errorCode = ERROR_FONT_INVALID_LIBID;
1502 return 0;
1503 }
1504 DEBUG_LOG(SCEFONT, "sceFontGetNumFontList(%08x, %08x)", fontLibHandle, errorCodePtr);
1505 *errorCode = 0;
1506 return fl->handle() == 0 ? 0 : (int)internalFonts.size();
1507 }
1508
sceFontSetResolution(u32 fontLibHandle,float hRes,float vRes)1509 static int sceFontSetResolution(u32 fontLibHandle, float hRes, float vRes) {
1510 FontLib *fl = GetFontLib(fontLibHandle);
1511 if (!fl) {
1512 ERROR_LOG_REPORT(SCEFONT, "sceFontSetResolution(%08x, %f, %f): invalid font lib", fontLibHandle, hRes, vRes);
1513 return ERROR_FONT_INVALID_LIBID;
1514 }
1515 if (hRes <= 0.0f || vRes <= 0.0f) {
1516 ERROR_LOG_REPORT(SCEFONT, "sceFontSetResolution(%08x, %f, %f): negative value", fontLibHandle, hRes, vRes);
1517 return ERROR_FONT_INVALID_PARAMETER;
1518 }
1519 INFO_LOG(SCEFONT, "sceFontSetResolution(%08x, %f, %f)", fontLibHandle, hRes, vRes);
1520 fl->SetResolution(hRes, vRes);
1521 return 0;
1522 }
1523
sceFontPixelToPointH(int fontLibHandle,float fontPixelsH,u32 errorCodePtr)1524 static float sceFontPixelToPointH(int fontLibHandle, float fontPixelsH, u32 errorCodePtr) {
1525 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1526 if (!errorCode.IsValid()) {
1527 ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsH, errorCodePtr);
1528 return 0.0f;
1529 }
1530 FontLib *fl = GetFontLib(fontLibHandle);
1531 if (!fl) {
1532 ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsH, errorCodePtr);
1533 *errorCode = ERROR_FONT_INVALID_LIBID;
1534 return 0.0f;
1535 }
1536 DEBUG_LOG(SCEFONT, "sceFontPixelToPointH(%08x, %f, %08x)", fontLibHandle, fontPixelsH, errorCodePtr);
1537 *errorCode = 0;
1538 return fontPixelsH * pointDPI / fl->FontHRes();
1539 }
1540
sceFontPixelToPointV(int fontLibHandle,float fontPixelsV,u32 errorCodePtr)1541 static float sceFontPixelToPointV(int fontLibHandle, float fontPixelsV, u32 errorCodePtr) {
1542 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1543 if (!errorCode.IsValid()) {
1544 ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPixelsV, errorCodePtr);
1545 return 0.0f;
1546 }
1547 FontLib *fl = GetFontLib(fontLibHandle);
1548 if (!fl) {
1549 ERROR_LOG_REPORT(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPixelsV, errorCodePtr);
1550 *errorCode = ERROR_FONT_INVALID_LIBID;
1551 return 0.0f;
1552 }
1553 DEBUG_LOG(SCEFONT, "sceFontPixelToPointV(%08x, %f, %08x)", fontLibHandle, fontPixelsV, errorCodePtr);
1554 *errorCode = 0;
1555 return fontPixelsV * pointDPI / fl->FontVRes();
1556 }
1557
sceFontPointToPixelH(int fontLibHandle,float fontPointsH,u32 errorCodePtr)1558 static float sceFontPointToPixelH(int fontLibHandle, float fontPointsH, u32 errorCodePtr) {
1559 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1560 if (!errorCode.IsValid()) {
1561 ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsH, errorCodePtr);
1562 return 0.0f;
1563 }
1564 FontLib *fl = GetFontLib(fontLibHandle);
1565 if (!fl) {
1566 ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsH, errorCodePtr);
1567 *errorCode = ERROR_FONT_INVALID_LIBID;
1568 return 0.0f;
1569 }
1570 DEBUG_LOG(SCEFONT, "sceFontPointToPixelH(%08x, %f, %08x)", fontLibHandle, fontPointsH, errorCodePtr);
1571 *errorCode = 0;
1572 return fontPointsH * fl->FontHRes() / pointDPI;
1573 }
1574
sceFontPointToPixelV(int fontLibHandle,float fontPointsV,u32 errorCodePtr)1575 static float sceFontPointToPixelV(int fontLibHandle, float fontPointsV, u32 errorCodePtr) {
1576 auto errorCode = PSPPointer<s32_le>::Create(errorCodePtr);
1577 if (!errorCode.IsValid()) {
1578 ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x): invalid error address", fontLibHandle, fontPointsV, errorCodePtr);
1579 return 0.0f;
1580 }
1581 FontLib *fl = GetFontLib(fontLibHandle);
1582 if (!fl) {
1583 ERROR_LOG_REPORT(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x): invalid font lib", fontLibHandle, fontPointsV, errorCodePtr);
1584 *errorCode = ERROR_FONT_INVALID_LIBID;
1585 return 0.0f;
1586 }
1587 DEBUG_LOG(SCEFONT, "sceFontPointToPixelV(%08x, %f, %08x)", fontLibHandle, fontPointsV, errorCodePtr);
1588 *errorCode = 0;
1589 return fontPointsV * fl->FontVRes() / pointDPI;
1590 }
1591
sceFontCalcMemorySize()1592 static int sceFontCalcMemorySize() {
1593 ERROR_LOG_REPORT(SCEFONT, "UNIMPL sceFontCalcMemorySize()");
1594 return 0;
1595 }
1596
sceFontGetShadowGlyphImage(u32 fontHandle,u32 charCode,u32 glyphImagePtr)1597 static int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {
1598 charCode &= 0xffff;
1599 if (!Memory::IsValidAddress(glyphImagePtr)) {
1600 ERROR_LOG(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr);
1601 return ERROR_FONT_INVALID_PARAMETER;
1602 }
1603 LoadedFont *font = GetLoadedFont(fontHandle, true);
1604 if (!font) {
1605 ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr);
1606 return ERROR_FONT_INVALID_PARAMETER;
1607 }
1608
1609 DEBUG_LOG(SCEFONT, "sceFontGetShadowGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);
1610 auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1611 font->DrawCharacter(glyph, -1, -1, -1, -1, charCode, FONT_PGF_SHADOWGLYPH);
1612 return 0;
1613 }
1614
sceFontGetShadowGlyphImage_Clip(u32 fontHandle,u32 charCode,u32 glyphImagePtr,int clipXPos,int clipYPos,int clipWidth,int clipHeight)1615 static int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) {
1616 charCode &= 0xffff;
1617 if (!Memory::IsValidAddress(glyphImagePtr)) {
1618 ERROR_LOG(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1619 return ERROR_FONT_INVALID_PARAMETER;
1620 }
1621 LoadedFont *font = GetLoadedFont(fontHandle, true);
1622 if (!font) {
1623 ERROR_LOG_REPORT(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1624 return ERROR_FONT_INVALID_PARAMETER;
1625 }
1626
1627 DEBUG_LOG(SCEFONT, "sceFontGetShadowGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
1628 auto glyph = PSPPointer<const GlyphImage>::Create(glyphImagePtr);
1629 font->DrawCharacter(glyph, clipXPos, clipYPos, clipWidth, clipHeight, charCode, FONT_PGF_SHADOWGLYPH);
1630 return 0;
1631 }
1632
1633 // sceLibFont is a user level library so it can touch the stack. Some games appear to rely a bit of stack
1634 // being wiped - although in reality, it won't be wiped with just zeroes..
1635 const HLEFunction sceLibFont[] = {
1636 {0X67F17ED7, &WrapU_UU<sceFontNewLib>, "sceFontNewLib", 'x', "xx", HLE_CLEAR_STACK_BYTES, 0x5A0 },
1637 {0X574B6FBC, &WrapI_U<sceFontDoneLib>, "sceFontDoneLib", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x2C },
1638 {0X48293280, &WrapI_UFF<sceFontSetResolution>, "sceFontSetResolution", 'i', "xff" },
1639 {0X27F6E642, &WrapI_UU<sceFontGetNumFontList>, "sceFontGetNumFontList", 'i', "xx" },
1640 {0XBC75D85B, &WrapI_UUI<sceFontGetFontList>, "sceFontGetFontList", 'i', "xxi", HLE_CLEAR_STACK_BYTES, 0x31C },
1641 {0X099EF33C, &WrapI_UUU<sceFontFindOptimumFont>, "sceFontFindOptimumFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0xF0 },
1642 {0X681E61A7, &WrapI_UUU<sceFontFindFont>, "sceFontFindFont", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x40 },
1643 {0X2F67356A, &WrapI_V<sceFontCalcMemorySize>, "sceFontCalcMemorySize", 'i', "" },
1644 {0X5333322D, &WrapI_UUU<sceFontGetFontInfoByIndexNumber>, "sceFontGetFontInfoByIndexNumber", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x20 },
1645 {0XA834319D, &WrapU_UUUU<sceFontOpen>, "sceFontOpen", 'x', "xxxp", HLE_CLEAR_STACK_BYTES, 0x460 },
1646 {0X57FCB733, &WrapU_UCUU<sceFontOpenUserFile>, "sceFontOpenUserFile", 'x', "xsxp" },
1647 {0XBB8E7FE6, &WrapU_UUUU<sceFontOpenUserMemory>, "sceFontOpenUserMemory", 'x', "xxxp", HLE_CLEAR_STACK_BYTES, 0x440 /*from JPCSP*/ },
1648 {0X3AEA8CB6, &WrapI_U<sceFontClose>, "sceFontClose", 'i', "x", HLE_CLEAR_STACK_BYTES, 0x54 },
1649 {0X0DA7535E, &WrapI_UU<sceFontGetFontInfo>, "sceFontGetFontInfo", 'i', "xx" },
1650 {0XDCC80C2F, &WrapI_UUU<sceFontGetCharInfo>, "sceFontGetCharInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x110 },
1651 {0XAA3DE7B5, &WrapI_UUU<sceFontGetShadowInfo>, "sceFontGetShadowInfo", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },
1652 {0X5C3E4A9E, &WrapI_UUU<sceFontGetCharImageRect>, "sceFontGetCharImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },
1653 {0X48B06520, &WrapI_UUU<sceFontGetShadowImageRect>, "sceFontGetShadowImageRect", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x150 },
1654 {0X980F4895, &WrapI_UUU<sceFontGetCharGlyphImage>, "sceFontGetCharGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x120 },
1655 {0XCA1E6945, &WrapI_UUUIIII<sceFontGetCharGlyphImage_Clip>, "sceFontGetCharGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x130 },
1656 {0X74B21701, &WrapF_IFU<sceFontPixelToPointH>, "sceFontPixelToPointH", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },
1657 {0XF8F0752E, &WrapF_IFU<sceFontPixelToPointV>, "sceFontPixelToPointV", 'f', "ifx", HLE_CLEAR_STACK_BYTES, 0x10 },
1658 {0X472694CD, &WrapF_IFU<sceFontPointToPixelH>, "sceFontPointToPixelH", 'f', "ifx" },
1659 {0X3C4B7E82, &WrapF_IFU<sceFontPointToPixelV>, "sceFontPointToPixelV", 'f', "ifx" },
1660 {0XEE232411, &WrapI_UU<sceFontSetAltCharacterCode>, "sceFontSetAltCharacterCode", 'i', "xx" },
1661 {0X568BE516, &WrapI_UUU<sceFontGetShadowGlyphImage>, "sceFontGetShadowGlyphImage", 'i', "xxx", HLE_CLEAR_STACK_BYTES, 0x160 },
1662 {0X5DCF6858, &WrapI_UUUIIII<sceFontGetShadowGlyphImage_Clip>, "sceFontGetShadowGlyphImage_Clip", 'i', "xxxiiii", HLE_CLEAR_STACK_BYTES, 0x170 },
1663 {0X02D7F94B, &WrapI_U<sceFontFlush>, "sceFontFlush", 'i', "x" },
1664 };
1665
Register_sceFont()1666 void Register_sceFont() {
1667 RegisterModule("sceLibFont", ARRAY_SIZE(sceLibFont), sceLibFont);
1668 }
1669
Register_sceLibFttt()1670 void Register_sceLibFttt() {
1671 RegisterModule("sceLibFttt", ARRAY_SIZE(sceLibFont), sceLibFont);
1672 }
1673