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, &params_);
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