1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/config-manager.h"
24 #include "common/translation.h"
25 #include "gui/gui-manager.h"
26 #include "gui/message.h"
27 #include "graphics/fonts/amigafont.h"
28
29 #include "agi/agi.h"
30 #include "agi/font.h"
31 #include "agi/text.h"
32
33 namespace Agi {
34
GfxFont(AgiBase * vm)35 GfxFont::GfxFont(AgiBase *vm) {
36 _vm = vm;
37
38 _fontData = nullptr;
39 _fontDataAllocated = nullptr;
40 _fontIsHires = false;
41 }
42
~GfxFont()43 GfxFont::~GfxFont() {
44 free(_fontDataAllocated);
45 }
46
47 // Arrow to the right character, used for original saved game dialogs
48 // Needs to get patched into at least the Apple IIgs font, because the font didn't support
49 // that character and original AGI on Apple IIgs used Apple II menus for saving/restoring.
50 static const uint8 fontData_ArrowRightCharacter[8] = {
51 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
52 };
53
54 // 8x8 font patterns
55
56 // this is basically the standard PC BIOS font, taken from Dos-Box, with a few modifications
57 static const uint8 fontData_PCBIOS[] = {
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
60 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
61 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00,
62 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
63 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C,
64 0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C,
65 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
66 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
67 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
68 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF,
69 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
70 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
71 0x08, 0x0C, 0x0A, 0x0A, 0x08, 0x78, 0xF0, 0x00, // 0x0D changed
72 0x18, 0x14, 0x1A, 0x16, 0x72, 0xE2, 0x0E, 0x1C, // 0x0E changed
73 0x10, 0x54, 0x38, 0xEE, 0x38, 0x54, 0x10, 0x00, // 0x0F changed
74 //0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, // 0x0D original
75 //0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, // 0x0E original
76 //0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, // 0x0F original
77 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
78 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
79 0x18, 0x3C, 0x5A, 0x18, 0x5A, 0x3C, 0x18, 0x00, // 0x12 changed
80 //0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, // 0x12 original
81 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
82 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x00, // 0x14 changed
83 0x1C, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70, // 0x14 changed
84 //0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, // 0x14 original
85 //0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78, // 0x15 original
86 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
87 0x18, 0x3C, 0x5A, 0x18, 0x5A, 0x3C, 0x18, 0x7E, // 0x17 changed
88 0x18, 0x3C, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x00, // 0x18 changed
89 0x18, 0x18, 0x18, 0x18, 0x5A, 0x3C, 0x18, 0x00, // 0x19 changed
90 //0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, // 0x17 original
91 //0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, // 0x18 original
92 //0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, // 0x19 original
93 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
94 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
95 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
96 0x00, 0x24, 0x42, 0xFF, 0x42, 0x24, 0x00, 0x00, // 0x1D changed
97 0x00, 0x10, 0x38, 0x7C, 0xFE, 0xFE, 0x00, 0x00, // 0x1E changed
98 0x00, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, // 0x1F changed
99 //0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, // 0x1D original
100 //0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, // 0x1E original
101 //0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, // 0x1F original
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20
103 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
104 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
106 0x30, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x30, 0x00,
107 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
108 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
109 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
111 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
112 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
113 0x00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
115 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
117 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
118 0x7C, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0x7C, 0x00, // 0x30
119 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
120 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
121 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
122 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
123 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
124 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
125 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
126 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
127 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
128 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
129 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
130 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
131 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00,
132 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
133 0x78, 0xCC, 0x0C, 0x18, 0x30, 0x00, 0x30, 0x00,
134 0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x78, 0x00, // 0x40
135 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
136 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
137 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
138 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
139 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
140 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
141 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00,
142 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
143 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
144 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
145 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
146 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
147 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
148 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
149 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
150 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, // 0x50
151 0x78, 0xCC, 0xCC, 0xCC, 0xDC, 0x78, 0x1C, 0x00,
152 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
153 0x78, 0xCC, 0xE0, 0x70, 0x1C, 0xCC, 0x78, 0x00,
154 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
155 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
156 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
157 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00,
158 0xC6, 0xC6, 0x6C, 0x38, 0x38, 0x6C, 0xC6, 0x00,
159 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
160 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
161 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
162 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
163 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
164 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
166 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60
167 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
168 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
169 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
170 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
171 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
172 0x38, 0x6C, 0x60, 0xF0, 0x60, 0x60, 0xF0, 0x00,
173 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
174 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
175 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
176 0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
177 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
178 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
179 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
180 0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
181 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
182 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, // 0x70
183 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
184 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00,
185 0x00, 0x00, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x00,
186 0x10, 0x30, 0x7C, 0x30, 0x30, 0x34, 0x18, 0x00,
187 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
188 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
189 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00,
190 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
191 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
192 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
193 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
194 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
195 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
196 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
198 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x18, 0x0C, 0x78, // 0x80
199 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
200 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
201 0x7E, 0xC3, 0x3C, 0x06, 0x3E, 0x66, 0x3F, 0x00,
202 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
203 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
204 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
205 0x00, 0x00, 0x78, 0xC0, 0xC0, 0x78, 0x0C, 0x38,
206 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
207 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
208 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
209 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
210 0x7C, 0xC6, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
211 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
212 0xC6, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00,
213 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00,
214 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00,
215 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00,
216 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00,
217 0x78, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
218 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
219 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
220 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
221 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
222 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
223 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00,
224 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
225 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18,
226 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00,
227 0xCC, 0xCC, 0x78, 0xFC, 0x30, 0xFC, 0x30, 0x30,
228 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC7,
229 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70,
230 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
231 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
232 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
233 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
234 0x00, 0xF8, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0x00,
235 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00,
236 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00,
237 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00,
238 0x30, 0x00, 0x30, 0x60, 0xC0, 0xCC, 0x78, 0x00,
239 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00,
241 0xC3, 0xC6, 0xCC, 0xDE, 0x33, 0x66, 0xCC, 0x0F,
242 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6F, 0xCF, 0x03,
243 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
244 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00,
245 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00,
246 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
247 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
248 0xDB, 0x77, 0xDB, 0xEE, 0xDB, 0x77, 0xDB, 0xEE,
249 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
250 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18,
251 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
252 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36,
253 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36,
254 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
255 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36,
256 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
257 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36,
258 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00,
259 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00,
260 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18,
262 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00,
263 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18,
265 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18,
266 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
267 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18,
268 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
269 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
270 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36,
272 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36,
274 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
275 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
276 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36,
277 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
278 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18,
280 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36,
281 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00,
282 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
284 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36,
285 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36,
286 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18,
287 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18,
289 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
290 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
291 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
292 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
293 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00,
295 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0,
296 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00,
297 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
298 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00,
299 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00,
300 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0,
301 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00,
302 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC,
303 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00,
304 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00,
305 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00,
306 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00,
307 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0,
308 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00,
309 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
310 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x00,
311 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0xFC, 0x00,
312 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00,
313 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00,
314 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
315 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
316 0x30, 0x30, 0x00, 0xFC, 0x00, 0x30, 0x30, 0x00,
317 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
318 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
321 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C,
322 0x78, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
323 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
326 };
327
328 // Extended set (0x80-0xFF) for Russian versions of games
329 static const uint8 fontData_ExtendedRussian[] = {
330 0x1E, 0x36, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00, // 0x80
331 0x7C, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
332 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00,
333 0x7E, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
334 0x38, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xFE, 0xC6,
335 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00,
336 0xDB, 0xDB, 0x7E, 0x3C, 0x7E, 0xDB, 0xDB, 0x00,
337 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00,
338 0x66, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00,
339 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00,
340 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00,
341 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00,
342 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
343 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00,
344 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00,
345 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00,
346 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x00,
347 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00,
348 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
349 0x66, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C, 0x00,
350 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x00,
351 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00,
352 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7F, 0x03,
353 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00,
354 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x00,
355 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x03,
356 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
357 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00,
358 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
359 0x78, 0x8C, 0x06, 0x3E, 0x06, 0x8C, 0x78, 0x00,
360 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00,
361 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x00,
362 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3A, 0x00,
363 0x00, 0x3C, 0x60, 0x3C, 0x66, 0x66, 0x3C, 0x00,
364 0x00, 0x00, 0x7C, 0x66, 0x7C, 0x66, 0x7C, 0x00,
365 0x00, 0x00, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x00,
366 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x6C, 0xFE, 0xC6,
367 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
368 0x00, 0x00, 0xDB, 0x7E, 0x3C, 0x7E, 0xDB, 0x00,
369 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x66, 0x3C, 0x00,
370 0x00, 0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x00,
371 0x00, 0x18, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x00,
372 0x00, 0x00, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00,
373 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x00,
374 0x00, 0x00, 0xC6, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
375 0x00, 0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00,
376 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00,
377 0x00, 0x00, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00,
378 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
379 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
380 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
381 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
382 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
383 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
384 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36,
385 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36,
386 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
387 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36,
388 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
389 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36,
390 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00,
391 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00,
392 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18,
394 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00,
395 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18,
397 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
398 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
399 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
400 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
401 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36,
402 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
404 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36,
406 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
407 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
408 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36,
409 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
410 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18,
412 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36,
413 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00,
414 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
416 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36,
417 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36,
418 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
419 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18,
421 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
422 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
423 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
424 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
425 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00,
427 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00,
428 0x00, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
429 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x7C, 0x00,
430 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x18, 0x00,
431 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00,
432 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7F, 0x03,
433 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x00,
434 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x00,
435 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x03,
436 0x00, 0x00, 0xE0, 0x60, 0x7C, 0x66, 0x7C, 0x00,
437 0x00, 0x00, 0xC6, 0xC6, 0xF6, 0xDE, 0xF6, 0x00,
438 0x00, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x7C, 0x00,
439 0x00, 0x00, 0x7C, 0x06, 0x3E, 0x06, 0x7C, 0x00,
440 0x00, 0x00, 0xCE, 0xDB, 0xFB, 0xDB, 0xCE, 0x00,
441 0x00, 0x00, 0x3E, 0x66, 0x3E, 0x36, 0x66, 0x00,
442 0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
443 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x7C, 0x00,
444 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30,
445 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C,
446 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
447 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
448 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18,
449 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
450 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00,
453 0x03, 0x02, 0x06, 0x04, 0xCC, 0x68, 0x38, 0x10,
454 0x3C, 0x42, 0x99, 0xA1, 0xA1, 0x99, 0x42, 0x3C,
455 0x30, 0x48, 0x10, 0x20, 0x78, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x7E, 0x00
458 };
459
init()460 void GfxFont::init() {
461 if (ConfMan.getBool("herculesfont")) {
462 // User wants, that we use Hercules hires font, try to load it
463 loadFontHercules();
464 } else {
465 switch (_vm->_renderMode) {
466 case Common::kRenderHercA:
467 case Common::kRenderHercG:
468 // Render mode is Hercules, we try to load Hercules hires font
469 loadFontHercules();
470 break;
471 default:
472 break;
473 }
474 }
475
476 if (!_fontData) {
477 switch (_vm->_renderMode) {
478 case Common::kRenderAmiga:
479 // Try user-file first, if that fails use our internal inaccurate topaz font
480 loadFontScummVMFile("agi-font-amiga.bin");
481 if (!_fontData) {
482 loadFontAmigaPseudoTopaz();
483 }
484 break;
485 case Common::kRenderApple2GS:
486 // Special font, stored in file AGIFONT
487 loadFontAppleIIgs();
488 break;
489 case Common::kRenderAtariST:
490 // TODO: Atari ST uses another font
491 // Seems to be the standard Atari ST 8x8 system font
492 loadFontScummVMFile("agi-font-atarist.bin");
493 if (!_fontData) {
494 loadFontAtariST("agi-font-atarist-system.fnt");
495 if (!_fontData) {
496 // TODO: in case we find a recreation of the font, add it in here
497 }
498 }
499 break;
500 case Common::kRenderHercA:
501 case Common::kRenderHercG:
502 case Common::kRenderCGA:
503 case Common::kRenderEGA:
504 case Common::kRenderVGA:
505 switch (_vm->getGameID()) {
506 case GID_MICKEY:
507 // load mickey mouse font from interpreter file
508 loadFontMickey();
509 break;
510 default:
511 loadFontScummVMFile("agi-font-dos.bin");
512 break;
513 }
514 break;
515
516 default:
517 break;
518 }
519
520 if (!_fontData) {
521 // no font assigned?
522 // use regular PC-BIOS font (taken from Dos-Box with a few modifications)
523 _fontData = fontData_PCBIOS;
524 debug("AGI: Using PC-BIOS font");
525 }
526 }
527
528 if (_vm->getLanguage() == Common::RU_RUS) {
529 // Russian versions need special extended set
530 overwriteExtendedWithRussianSet();
531 }
532 }
533
getFontData()534 const byte *GfxFont::getFontData() {
535 assert(_fontData);
536 return _fontData;
537 }
538
isFontHires()539 bool GfxFont::isFontHires() {
540 return _fontIsHires;
541 }
542
overwriteSaveRestoreDialogCharacter()543 void GfxFont::overwriteSaveRestoreDialogCharacter() {
544 // overwrite character 0x1A with the standard Sierra arrow to the right character
545 // required for the original save/restore dialogs
546 memcpy(_fontDataAllocated + (0x1A * 8), fontData_ArrowRightCharacter, sizeof(fontData_ArrowRightCharacter));
547 }
548
549 // Overwrite extended character set (0x80-0xFF) with Russian characters
overwriteExtendedWithRussianSet()550 void GfxFont::overwriteExtendedWithRussianSet() {
551 if (_fontIsHires) {
552 // TODO: Implement overwriting hires font characters too
553 return;
554 }
555
556 if (!_fontDataAllocated) {
557 // nothing allocated, we need to allocate space ourselves to be able to modify an internal font
558 _fontDataAllocated = (uint8 *)calloc(256, 8);
559 memcpy(_fontDataAllocated, _fontData, 128 * 8); // copy ASCII set over
560 _fontData = _fontDataAllocated;
561 }
562 // Overwrite extended set with Russian characters
563 memcpy(_fontDataAllocated + (128 * 8), fontData_ExtendedRussian, 128 * 8);
564
565 debug("AGI: Using Russian extended font set");
566 }
567
568 // This code loads a ScummVM-specific user-supplied binary font file
569 // It's assumed that it's a plain binary file, that contains 256 characters. 8 bytes per character.
570 // 8x8 pixels per character. File size 2048 bytes.
571 //
572 // Currently used for:
573 // Atari ST - "agi-font-atarist.bin" -> should be the Atari ST 8x8 system font
574 // Amiga - "agi-font-amiga.bin" -> should be the Amiga 8x8 Topaz font
575 // DOS - "agi-font-dos.bin"
loadFontScummVMFile(Common::String fontFilename)576 void GfxFont::loadFontScummVMFile(Common::String fontFilename) {
577 Common::File fontFile;
578 int32 fontFileSize = 0;
579
580 if (!fontFile.open(fontFilename)) {
581 // Continue, if file not found
582 // These ScummVM font files are totally optional, so don't show a warning
583 return;
584 }
585
586 fontFileSize = fontFile.size();
587 if (fontFileSize != (256 * 8)) {
588 // unexpected file size
589 fontFile.close();
590 warning("Fontfile '%s': unexpected file size", fontFilename.c_str());
591 return;
592 }
593
594 // allocate space for font bitmap data
595 _fontDataAllocated = (uint8 *)calloc(256, 8);
596 _fontData = _fontDataAllocated;
597
598 // read font data, is already in the format that we need (plain bitmap 8x8)
599 fontFile.read(_fontDataAllocated, 256 * 8);
600 fontFile.close();
601
602 overwriteSaveRestoreDialogCharacter();
603
604 debug("AGI: Using user-supplied font");
605 }
606
607 // We load the Mickey Mouse font from MICKEY.EXE
loadFontMickey()608 void GfxFont::loadFontMickey() {
609 Common::File interpreterFile;
610 int32 interpreterFileSize = 0;
611 byte *fontData = nullptr;
612
613 if (!interpreterFile.open("mickey.exe")) {
614 // Continue, if file not found
615 warning("Could not open file 'mickey.exe' for Mickey Mouse font");
616 return;
617 }
618
619 interpreterFileSize = interpreterFile.size();
620 if (interpreterFileSize != 55136) {
621 // unexpected file size
622 interpreterFile.close();
623 warning("File 'mickey.exe': unexpected file size");
624 return;
625 }
626 interpreterFile.seek(32476); // offset of font data
627
628 // allocate space for font bitmap data
629 fontData = (uint8 *)calloc(256, 8);
630 _fontData = fontData;
631 _fontDataAllocated = fontData;
632
633 // read font data, is already in the format that we need (plain bitmap 8x8)
634 interpreterFile.read(fontData, 256 * 8);
635 interpreterFile.close();
636
637 debug("AGI: Using Mickey Mouse font");
638 }
639
640 // we create a bitmap out of the topaz data used in parallaction (which is normally found in staticres.cpp)
641 // it's a recreation of the Amiga Topaz font but not really accurate
loadFontAmigaPseudoTopaz()642 void GfxFont::loadFontAmigaPseudoTopaz() {
643 Graphics::Surface surf;
644 surf.create(8, 8, Graphics::PixelFormat::createFormatCLUT8());
645 byte *fontData = (uint8 *)calloc(256, 8);
646
647 _fontData = fontData;
648 _fontDataAllocated = fontData;
649
650 // copy first 32 PC-BIOS characters over
651 memcpy(fontData, fontData_PCBIOS, FONT_DISPLAY_WIDTH * 32);
652 fontData += FONT_DISPLAY_WIDTH * 32;
653
654 Graphics::AmigaFont topaz;
655
656 for (uint16 curChar = topaz.getLoChar(); curChar <= topaz.getHiChar(); curChar++) {
657 topaz.drawChar(&surf, curChar, 0, 0, 0xff);
658
659 // Turn it into 1bpp
660 for (int y = 0; y < 8; y++) {
661 byte line = 0;
662 byte *ptr = (byte *)surf.getBasePtr(0, y);
663 for (int x = 0; x < 8; x++, ptr++) {
664 line <<= 1;
665 line |= *ptr & 0x1;
666 }
667 *fontData++ = line;
668 }
669 memset(surf.getPixels(), 0, 8 * 8);
670 }
671
672 surf.free();
673
674 debug("AGI: Using recreation of Amiga Topaz font");
675 }
676
loadFontAppleIIgs()677 void GfxFont::loadFontAppleIIgs() {
678 Common::File fontFile;
679 uint16 headerIIgs_OffsetMacHeader = 0;
680 uint16 headerIIgs_Version = 0;
681 uint16 macRecord_FirstChar = 0;
682 uint16 macRecord_LastChar = 0;
683 int16 macRecord_MaxKern = 0;
684 uint16 macRecord_RectHeight = 0;
685 uint16 macRecord_StrikeWidth = 0;
686 uint16 strikeDataLen = 0;
687 byte *strikeDataPtr = nullptr;
688 uint16 actualCharacterCount = 0;
689 uint16 totalCharacterCount = 0;
690 uint16 *locationTablePtr = nullptr;
691 uint16 *offsetWidthTablePtr = nullptr;
692
693 uint16 curCharNr = 0;
694 uint16 curRow = 0;
695 uint16 curLocation = 0;
696 uint16 curLocationBytes = 0;
697 uint16 curLocationBits = 0;
698 uint16 curCharOffsetWidth = 0;
699 uint16 curCharOffset = 0;
700 uint16 curCharWidth = 0;
701 uint16 curStrikeWidth = 0;
702
703 uint16 curPixelNr = 0;
704 uint16 curBitMask = 0;
705 int16 positionAdjust = 0;
706 byte curByte = 0;
707 byte fontByte = 0;
708
709 uint16 strikeRowOffset = 0;
710 uint16 strikeCurOffset = 0;
711
712 byte *fontData = nullptr;
713
714 if (!fontFile.open("agifont")) {
715 // Continue,
716 // This also happens when the user selected Apple IIgs as render for the palette for non-AppleIIgs games
717 warning("Could not open file 'agifont' for Apple IIgs font");
718 return;
719 }
720
721 // Apple IIgs header
722 headerIIgs_OffsetMacHeader = fontFile.readUint16LE();
723 fontFile.skip(2); // font family
724 fontFile.skip(2); // font style
725 fontFile.skip(2); // point size
726 headerIIgs_Version = fontFile.readUint16LE();
727 fontFile.skip(2); // bounds type
728 // end of Apple IIgs header
729 // Macintosh font record
730 fontFile.skip(2); // font type
731 macRecord_FirstChar = fontFile.readUint16LE();
732 macRecord_LastChar = fontFile.readUint16LE();
733 fontFile.skip(2); // max width
734 macRecord_MaxKern = fontFile.readSint16LE();
735 fontFile.skip(2); // negative descent
736 fontFile.skip(2); // rect width
737 macRecord_RectHeight = fontFile.readUint16LE();
738 fontFile.skip(2); // low word ptr table
739 fontFile.skip(2); // font ascent
740 fontFile.skip(2); // font descent
741 fontFile.skip(2); // leading
742 macRecord_StrikeWidth = fontFile.readUint16LE();
743
744 // security-checks
745 if (headerIIgs_OffsetMacHeader != 6)
746 error("AppleIIgs-font: unexpected header");
747 if (headerIIgs_Version != 0x0101)
748 error("AppleIIgs-font: not a 1.1 font");
749 if ((macRecord_FirstChar != 0) || (macRecord_LastChar != 255))
750 error("AppleIIgs-font: unexpected characters");
751 if (macRecord_RectHeight != 8)
752 error("AppleIIgs-font: expected 8x8 font");
753
754 // Calculate table sizes
755 strikeDataLen = macRecord_StrikeWidth * macRecord_RectHeight * 2;
756 actualCharacterCount = (macRecord_LastChar - macRecord_FirstChar + 1);
757 totalCharacterCount = actualCharacterCount + 2; // replacement-char + extra character
758
759 // Allocate memory for tables
760 strikeDataPtr = (byte *)calloc(strikeDataLen, 1);
761 locationTablePtr = (uint16 *)calloc(totalCharacterCount, 2); // 1 word per character
762 offsetWidthTablePtr = (uint16 *)calloc(totalCharacterCount, 2); // ditto
763
764 // read tables
765 fontFile.read(strikeDataPtr, strikeDataLen);
766 for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
767 locationTablePtr[curCharNr] = fontFile.readUint16LE();
768 }
769 for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
770 offsetWidthTablePtr[curCharNr] = fontFile.readUint16LE();
771 }
772 fontFile.close();
773
774 // allocate space for font bitmap data
775 fontData = (uint8 *)calloc(256, 8);
776 _fontData = fontData;
777 _fontDataAllocated = fontData;
778
779 // extract font bitmap data
780 for (curCharNr = 0; curCharNr < actualCharacterCount; curCharNr++) {
781 curCharOffsetWidth = offsetWidthTablePtr[curCharNr];
782 curLocation = locationTablePtr[curCharNr];
783 if (curCharOffsetWidth == 0xFFFF) {
784 // character does not exist in font, use replacement character instead
785 curCharOffsetWidth = offsetWidthTablePtr[actualCharacterCount];
786 curLocation = locationTablePtr[actualCharacterCount];
787 curStrikeWidth = locationTablePtr[actualCharacterCount + 1] - curLocation;
788 } else {
789 curStrikeWidth = locationTablePtr[curCharNr + 1] - curLocation;
790 }
791
792 // Figure out bytes + bits location
793 curLocationBytes = curLocation >> 3;
794 curLocationBits = curLocation & 0x0007;
795 curCharWidth = curCharOffsetWidth & 0x00FF; // isolate width
796 curCharOffset = curCharOffsetWidth >> 8; // isolate offset
797
798 if (!curCharWidth) {
799 fontData += 8; // skip over this character
800 continue;
801 }
802
803 if (curCharWidth != 8) {
804 if (curCharNr != 0x3B)
805 error("AppleIIgs-font: expected 8x8 font");
806 }
807
808 // Get all rows of the current character
809 strikeRowOffset = 0;
810 for (curRow = 0; curRow < macRecord_RectHeight; curRow++) {
811 strikeCurOffset = strikeRowOffset + curLocationBytes;
812
813 // Copy over bits
814 fontByte = 0;
815 curByte = strikeDataPtr[strikeCurOffset];
816 curBitMask = 0x80 >> curLocationBits;
817
818 for (curPixelNr = 0; curPixelNr < curStrikeWidth; curPixelNr++) {
819 fontByte = fontByte << 1;
820 if (curByte & curBitMask) {
821 fontByte |= 0x01;
822 }
823 curBitMask = curBitMask >> 1;
824 if (!curBitMask) {
825 curByte = strikeDataPtr[strikeCurOffset + 1];
826 curBitMask = 0x80;
827 }
828 }
829
830 // adjust, so that it's aligned to the left (starting at 0x80 bit)
831 fontByte = fontByte << (8 - curStrikeWidth);
832
833 // now adjust according to offset + MaxKern
834 positionAdjust = macRecord_MaxKern + curCharOffset;
835
836 // adjust may be negative for space, or 8 for "empty" characters
837 if (positionAdjust > 8)
838 error("AppleIIgs-font: invalid character spacing");
839
840 if (positionAdjust < 0) {
841 // negative adjust strangely happens for empty characters like space
842 if (curStrikeWidth)
843 error("AppleIIgs-font: invalid character spacing");
844 }
845
846 if (positionAdjust > 0) {
847 // move the amount of pixels to the right
848 fontByte = fontByte >> positionAdjust;
849 }
850
851 *fontData = fontByte;
852 fontData++;
853
854 strikeRowOffset += macRecord_StrikeWidth * 2;
855 }
856 }
857
858 free(offsetWidthTablePtr);
859 free(locationTablePtr);
860 free(strikeDataPtr);
861
862 overwriteSaveRestoreDialogCharacter();
863
864 debug("AGI: Using Apple IIgs font");
865 }
866
867 // Loads Atari ST font file
868 // It's found inside Atari ST ROMs. Just search for "8x8 system font". Font starts 4 bytes before that.
loadFontAtariST(Common::String fontFilename)869 void GfxFont::loadFontAtariST(Common::String fontFilename) {
870 Common::File fontFile;
871 uint16 header_FirstChar = 0;
872 uint16 header_LastChar = 0;
873 uint16 header_MaxWidth = 0;
874 uint16 header_MaxHeight = 0;
875 uint16 header_Flags = 0;
876 //uint32 header_OffsetOfCharOffsets = 0;
877 //uint32 header_OffsetOfFontData = 0;
878 uint16 header_FormWidth = 0;
879 uint16 header_FormHeight = 0;
880 uint16 totalCharacterCount = 0;
881 uint16 *charOffsetTablePtr = nullptr;
882 byte *rawDataTablePtr = nullptr;
883
884 uint16 curCharNr = 0;
885 uint16 curCharRawOffset = 0;
886 uint16 curCharDestOffset = 0;
887 uint16 curRow = 0;
888
889 byte *fontData = nullptr;
890
891 if (!fontFile.open(fontFilename)) {
892 // Continue, if file not found
893 warning("Could not open file 'agi-font-atarist-system.bin' for Atari ST 8x8 system font");
894 return;
895 }
896
897 // Atari ST font header
898 fontFile.skip(2); // face identifier
899 fontFile.skip(2); // point size
900 fontFile.skip(32); // font name
901 header_FirstChar = fontFile.readUint16BE();
902 header_LastChar = fontFile.readUint16BE();
903 fontFile.skip(10); // aligntment of cells
904 header_MaxWidth = fontFile.readUint16BE();
905 header_MaxHeight = fontFile.readUint16BE();
906 fontFile.skip(2); // left offset cel
907 fontFile.skip(2); // right offset cel
908 fontFile.skip(2); // number of pixels to thicken pixels
909 fontFile.skip(2); // underline width
910 fontFile.skip(2); // lightening mask
911 fontFile.skip(2); // skewing mask
912 header_Flags = fontFile.readUint16BE();
913 // bit 0 - default system font
914 // bit 1 - horizontal offset table (not supported)
915 // bit 2 - byte orientation word is high->low
916 // bit 3 - mono spaced font
917 fontFile.skip(4); // horizontal table offset
918 fontFile.skip(4); // header_OffsetOfCharOffsets = fontFile.readUint32BE();
919 fontFile.skip(4); // header_OffsetOfFontData = fontFile.readUint32BE();
920 header_FormWidth = fontFile.readUint16BE();
921 header_FormHeight = fontFile.readUint16BE();
922 fontFile.skip(4); // pointer to next font
923
924 totalCharacterCount = header_LastChar - header_FirstChar + 1;
925
926 // security-checks
927 if (header_MaxWidth > 8)
928 error("AtariST-font: not a 8x8 font");
929 if (header_MaxHeight != 8)
930 error("AtariST-font: not a 8x8 font");
931 if (header_FormHeight != 8)
932 error("AtariST-font: not a 8x8 font");
933 if ((header_FirstChar != 0) || (header_LastChar != 255))
934 error("AtariST-font: unexpected characters");
935 if (header_FormWidth != totalCharacterCount)
936 error("AtariST-font: header inconsistency");
937 if (!(header_Flags & 0x04))
938 error("AtariST-font: font data not in high->low order");
939 if (!(header_Flags & 0x08))
940 error("AtariST-font: not a mono-spaced font");
941
942 // Now we should normally use the offsets, but they don't make sense to me
943 // So I just read the data directly. For the 8x8 system font that works
944 fontFile.skip(2); // extra bytes
945
946 // Allocate memory for tables
947 charOffsetTablePtr = (uint16 *)calloc(totalCharacterCount, 2); // 1 word per character
948 rawDataTablePtr = (byte *)calloc(header_FormWidth, header_FormHeight);
949
950 // Char-Offset Table (2 * total number of characters)
951 for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
952 charOffsetTablePtr[curCharNr] = fontFile.readUint16BE();
953 }
954
955 // Followed by actual font data
956 // Attention: Atari ST fonts contain every same row of all characters after each other.
957 // So it's basically like this:
958 // [character data of first row of first character]
959 // [character data of first row of second character]
960 // ...
961 // [character data of first row of last character]
962 // [character data of second row of first character]
963 fontFile.skip(2); // extra bytes
964 fontFile.read(rawDataTablePtr, header_FormWidth * header_FormHeight);
965 fontFile.close();
966
967 // allocate space for font bitmap data
968 fontData = (uint8 *)calloc(256, 8);
969 _fontData = fontData;
970 _fontDataAllocated = fontData;
971
972 // extract font bitmap data
973 for (curCharNr = 0; curCharNr < totalCharacterCount; curCharNr++) {
974 // Figure out base offset from char offset table
975 curCharRawOffset = charOffsetTablePtr[curCharNr] >> 3;
976 curCharDestOffset = curCharNr * 8; // destination offset into our font data
977
978 // now copy over every row of the character
979 for (curRow = 0; curRow < header_FormHeight; curRow++) {
980 fontData[curCharDestOffset] = rawDataTablePtr[curCharRawOffset];
981 curCharDestOffset++;
982 curCharRawOffset += header_FormWidth;
983 }
984 }
985
986 free(rawDataTablePtr);
987 free(charOffsetTablePtr);
988
989 overwriteSaveRestoreDialogCharacter();
990
991 debug("AGI: Using Atari ST 8x8 system font");
992 }
993
994 // Loads a Sierra Hercules font file
loadFontHercules()995 void GfxFont::loadFontHercules() {
996
997 if (_vm->getLanguage() == Common::RU_RUS) {
998 warning("Hercules font does not contain Russian characters, switching to default");
999
1000 return;
1001 }
1002
1003 Common::File fontFile;
1004 int32 fontFileSize = 0;
1005 byte *fontData = nullptr;
1006 byte *rawData = nullptr;
1007
1008 uint16 rawDataPos = 0;
1009 uint16 curCharNr = 0;
1010 uint16 curCharLine = 0;
1011
1012 if (fontFile.open("hgc_font")) {
1013 // hgc_font file found, this is interleaved font data 16x12, should be 3072 bytes
1014 // 24 bytes per character, 128 characters
1015 fontFileSize = fontFile.size();
1016 if (fontFileSize == (128 * 24)) {
1017 // size seems to be fine
1018 fontData = (uint8 *)calloc(256, 32);
1019 _fontDataAllocated = fontData;
1020
1021 rawData = (byte *)calloc(128, 24);
1022 fontFile.read(rawData, 128 * 24);
1023
1024 // convert interleaved 16x12 -> non-interleaved 16x16
1025 for (curCharNr = 0; curCharNr < 128; curCharNr++) {
1026 fontData += 4; // skip the first 2 lines
1027 for (curCharLine = 0; curCharLine < 6; curCharLine++) {
1028 fontData[0] = rawData[rawDataPos + 2 + 0];
1029 fontData[1] = rawData[rawDataPos + 2 + 1];
1030 fontData[2] = rawData[rawDataPos + 0 + 0];
1031 fontData[3] = rawData[rawDataPos + 0 + 1];
1032 rawDataPos += 4;
1033 fontData += 4;
1034 }
1035 fontData += 4; // skip the last 2 lines
1036 }
1037
1038 free(rawData);
1039 } else {
1040 warning("Fontfile 'hgc_font': unexpected file size");
1041 }
1042 fontFile.close();
1043
1044 }
1045
1046 // It seems hgc_graf.ovl holds a low-res font. It makes no real sense to use it.
1047 // This was only done to AGI3 games and those rendered differently (2 pixel lines -> 3 pixel lines instead of 4)
1048 // User could copy hgc_font from another AGI game over to get the hires font working.
1049 #if 0
1050 if (!_fontDataAllocated) {
1051 if (fontFile.open("hgc_graf.ovl")) {
1052 // hgc_graf.ovl file found, this is font data + code. non-interleaved font data, should be 3075 bytes
1053 // 16 bytes per character, 128 characters, 2048 bytes of font data, starting offset 21
1054 fontFileSize = fontFile.size();
1055 if (fontFileSize == 3075) {
1056 // size seems to be fine
1057 fontData = (uint8 *)calloc(256, 32);
1058 _fontDataAllocated = fontData;
1059
1060 fontFile.seek(21);
1061 rawData = (byte *)calloc(128, 16);
1062 fontFile.read(rawData, 128 * 16);
1063
1064 // repeat every line 2 times to get 16x16 pixels
1065 for (curCharNr = 0; curCharNr < 128; curCharNr++) {
1066 for (curCharLine = 0; curCharLine < 8; curCharLine++) {
1067 fontData[0] = rawData[rawDataPos + 0];
1068 fontData[1] = rawData[rawDataPos + 1];
1069 fontData[2] = rawData[rawDataPos + 0];
1070 fontData[3] = rawData[rawDataPos + 1];
1071 rawDataPos += 2;
1072 fontData += 4;
1073 }
1074 }
1075
1076 free(rawData);
1077
1078 } else {
1079 warning("Fontfile 'hgc_graf.ovl': unexpected file size");
1080 }
1081 fontFile.close();
1082 }
1083 }
1084 #endif
1085
1086 if (_fontDataAllocated) {
1087 // font loaded
1088 _fontData = _fontDataAllocated;
1089 _fontIsHires = true;
1090
1091 debug("AGI: Using Hercules hires font");
1092
1093 } else {
1094 // Continue, if no file was not found
1095 warning("Could not open/use file 'hgc_font' for Hercules hires font");
1096 if (GUI::GuiManager::hasInstance()) {
1097 GUI::MessageDialog dialog(_("Could not open/use file 'hgc_font' for Hercules hires font.\nIf you have such file in other AGI (Sierra) game, you can copy it to the game directory"));
1098 dialog.runModal();
1099 };
1100
1101 }
1102 }
1103
1104 } // End of namespace Agi
1105