CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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