~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/HLE/sceFont.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

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