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