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