Branch data Line data Source code
1 : : #include "std-includes.h"
2 : : #include "libstr.h"
3 : : #include "virtualfile.h"
4 : : #include "asar.h"
5 : : #include "warnings.h"
6 : :
7 : : #define typed_malloc(type, count) (type*)malloc(sizeof(type)*(count))
8 : : #define typed_realloc(type, ptr, count) (type*)realloc(ptr, sizeof(type)*(count))
9 : :
10 : :
11 : : // RPG Hacker: Functions below are copied over from Asar 2.0 branch for the sole purpose of generating
12 : : // non-UTF-8 deprecation warnings in 1.9. Don't know if there's a better way to handle this, but it means
13 : : // we should delete all of this again once we merge branches.
14 : :
15 : : // vvvvvvvvvvvvvvvvvvvvvv
16 : :
17 : : // Detects if str starts with a UTF-8 byte order mark.
18 : : // If so, throws a warning, then returns the number of bytes we should skip ahead in the string.
19 : 300 : size_t check_bom(const char* str)
20 : : {
21 : : // RPG Hacker: We could also check for BoMs of incompatible encodings here (like UTF-16)
22 : : // and throw errors, but not sure if that's worth adding. Asar never supported any wide
23 : : // encodings to begin with, so it's unreasonable to assume that any UTF-16 patches currently
24 : : // exist for it. As for future patches, those should be caught by the "must be UTF-8" checks
25 : : // I have already implemented further below.
26 : : // I think UTF-8 + BoM is the only case that could lead to confusion if we didn't handle it,
27 : : // so that's why I have added this.
28 [ - + - - : 300 : if (str[0u] == '\xEF' && str[1u] == '\xBB' && str[2u] == '\xBF')
- - ]
29 : : {
30 : 0 : asar_throw_warning(0, warning_id_byte_order_mark_utf8);
31 : 0 : return 3u;
32 : : }
33 : :
34 : : return 0u;
35 : : }
36 : :
37 : :
38 : 88855 : size_t utf8_val(int* codepoint, const char* inp) {
39 : 88855 : unsigned char c = *inp++;
40 : : int val;
41 [ + - ]: 88855 : if (c < 0x80) {
42 : : // plain ascii
43 : 88855 : *codepoint = c;
44 : 88855 : return 1u;
45 : : }
46 : : // RPG Hacker: Byte sequences starting with 0xC0 or 0xC1 are invalid.
47 : : // So are byte sequences starting with anything >= 0xF5.
48 : : // And anything below 0xC0 indicates a follow-up byte and should never be at the start of a sequence.
49 [ # # ]: 0 : else if (c > 0xC1 && c < 0xF5) {
50 : : // 1, 2 or 3 continuation bytes
51 [ # # # # ]: 0 : int cont_byte_count = (c >= 0xF0) ? 3 : (c >= 0xE0) ? 2 : 1;
52 : : // bit hack to extract the significant bits from the start byte
53 : 0 : val = (c & ((1 << (6 - cont_byte_count)) - 1));
54 [ # # ]: 0 : for (int i = 0; i < cont_byte_count; i++) {
55 : 0 : unsigned char next = *inp++;
56 [ # # ]: 0 : if ((next & 0xC0) != 0x80) {
57 : 0 : *codepoint = -1;
58 : 0 : return 0u;
59 : : }
60 : 0 : val = (val << 6) | (next & 0x3F);
61 : : }
62 : 0 : if (// too many cont.bytes
63 [ # # # # ]: 0 : (*inp & 0xC0) == 0x80 ||
64 : :
65 : : // invalid codepoints
66 : 0 : val > 0x10FFFF ||
67 : :
68 : : // check overlong encodings
69 [ # # ]: 0 : (cont_byte_count == 3 && val < 0x1000) ||
70 [ # # ]: 0 : (cont_byte_count == 2 && val < 0x800) ||
71 [ # # ]: 0 : (cont_byte_count == 1 && val < 0x80) ||
72 : :
73 : : // UTF16 surrogates
74 [ # # ]: 0 : (val >= 0xD800 && val <= 0xDFFF)
75 : : ) {
76 : 0 : *codepoint = -1;
77 : 0 : return 0u;
78 : : };
79 : 0 : *codepoint = val;
80 : 0 : return 1u + cont_byte_count;
81 : : }
82 : :
83 : : // if none of the above, this couldn't possibly be a valid encoding
84 : 0 : *codepoint = -1;
85 : 0 : return 0u;
86 : : }
87 : :
88 : 300 : bool is_valid_utf8(const char* inp) {
89 [ + + ]: 89155 : while (*inp != '\0') {
90 : : int codepoint;
91 : 88855 : inp += utf8_val(&codepoint, inp);
92 : :
93 [ - + ]: 88855 : if (codepoint == -1) return false;
94 : : }
95 : :
96 : : return true;
97 : : }
98 : :
99 : : // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100 : :
101 : :
102 : 110 : char * readfile(const char * fname, const char * basepath)
103 : : {
104 : 110 : virtual_file_handle myfile = filesystem->open_file(fname, basepath);
105 [ + - ]: 110 : if (myfile == INVALID_VIRTUAL_FILE_HANDLE) return nullptr;
106 : 110 : size_t datalen = filesystem->get_file_size(myfile);
107 : 110 : char * data= typed_malloc(char, datalen+1);
108 : 110 : data[filesystem->read_file(myfile, data, 0u, datalen)] = 0;
109 : 110 : filesystem->close_file(myfile);
110 : : int inpos=0;
111 : : int outpos=0;
112 : 110 : inpos += check_bom(data + inpos);
113 [ + + ]: 76900 : while (data[inpos])
114 : : {
115 [ + - ]: 76790 : if (data[inpos]!='\r') data[outpos++]=data[inpos];
116 : 76790 : inpos++;
117 : : }
118 : 110 : data[outpos]=0;
119 [ - + ]: 110 : if (!is_valid_utf8(data)) asar_throw_warning(0, warning_id_feature_deprecated, "non-UTF-8 source files", "Re-save the file as UTF-8 in a text editor of choice and avoid using non-ASCII characters in Asar versions < 2.0");
120 : : return data;
121 : : }
122 : :
123 : : // RPG Hacker: like readfile(), but doesn't use virtual file system
124 : : // and instead read our file directly.
125 : 190 : char * readfilenative(const char * fname)
126 : : {
127 : 190 : FILE* myfile = fopen(fname, "rb");
128 [ + - ]: 190 : if (myfile == nullptr) return nullptr;
129 : 190 : fseek(myfile, 0, SEEK_END);
130 : 190 : size_t datalen = (size_t)ftell(myfile);
131 : 190 : fseek(myfile, 0, SEEK_SET);
132 : 190 : char * data = typed_malloc(char, datalen + 1);
133 : 190 : data[fread(data, 1u, datalen, myfile)] = 0;
134 : 190 : fclose(myfile);
135 : : int inpos = 0;
136 : : int outpos = 0;
137 : 190 : inpos += check_bom(data + inpos);
138 [ + + ]: 12255 : while (data[inpos])
139 : : {
140 [ + - ]: 12065 : if (data[inpos] != '\r') data[outpos++] = data[inpos];
141 : 12065 : inpos++;
142 : : }
143 : 190 : data[outpos] = 0;
144 [ - + ]: 190 : if (!is_valid_utf8(data)) asar_throw_warning(0, warning_id_feature_deprecated, "non-UTF-8 source files", "Re-save the file as UTF-8 in a text editor of choice and avoid using non-ASCII characters in Asar versions < 2.0");
145 : : return data;
146 : : }
147 : :
148 : 111 : bool readfile(const char * fname, const char * basepath, char ** data, int * len)
149 : : {
150 : 111 : virtual_file_handle myfile = filesystem->open_file(fname, basepath);
151 [ + + ]: 111 : if (!myfile) return false;
152 : 108 : size_t datalen = filesystem->get_file_size(myfile);
153 : 108 : *data= typed_malloc(char, datalen);
154 : 108 : *len = (int)filesystem->read_file(myfile, *data, 0, datalen);
155 : 108 : filesystem->close_file(myfile);
156 : 108 : return true;
157 : : }
158 : :
159 : : #define dequote(var, next, error) if (var=='"') do { next; while (var!='"' && var != '\0') { if (!var) error; next; } if (var == '\0') error; next; } while(0); else if (var=='\'') do { next; if (!var) error; /* ''' special case hack */ if (var=='\'') { next; if (var!='\'') error; next; } else { next; while (var!='\'' && var != '\0') { if (!var) error; next; } if (var == '\0') error; next; } } while(0)
160 : : #define skippar(var, next, error) dequote(var, next, error); else if (var=='(') { int par=1; next; while (par) { dequote(var, next, error); else { \
161 : : if (var=='(') par++; if (var==')') par--; if (!var) error; next; } } } else if (var==')') error
162 : :
163 : 484 : string& string::replace(const char * instr, const char * outstr, bool all)
164 : : {
165 : : string& thisstring=*this;
166 [ - + ]: 484 : if (!all)
167 : : {
168 : : const char * ptr=strstr(thisstring, instr);
169 [ # # ]: 0 : if (!ptr) return thisstring;
170 : 0 : string out=STR substr(thisstring, (int)(ptr-thisstring.data()))+outstr+(ptr+strlen(instr));
171 : : thisstring =out;
172 : : return thisstring;
173 : 0 : }
174 : : //performance hack (obviously for ", "->"," in asar, but who cares, it's a performance booster)
175 [ + + - + ]: 484 : if (strlen(instr)==strlen(outstr)+1 && !memcmp(instr, outstr, strlen(outstr)))
176 : : {
177 : : const char * indat= thisstring;
178 : 469 : char * trueoutdat= typed_malloc(char, strlen(indat)+1);
179 : : char * outdat=trueoutdat;
180 : 469 : int thelen=(int)strlen(outstr);
181 : : //nested hack
182 [ + + ]: 469 : if (thelen==0)
183 : : {
184 : 1 : char thechar=instr[0];
185 [ + + ]: 31 : while (*indat)
186 : : {
187 [ + + ]: 30 : if (*indat==thechar) indat++;
188 : 27 : else *outdat++=*indat++;
189 : : }
190 : 1 : *outdat=0;
191 : : thisstring =trueoutdat;
192 : 1 : free(trueoutdat);
193 : 1 : return thisstring;
194 : : }
195 [ + - ]: 468 : else if (thelen==1)
196 : : {
197 : 468 : char firstchar=instr[0];
198 : 468 : char secondchar=instr[1];
199 [ + + ]: 7025 : while (*indat)
200 : : {
201 [ + + ]: 6557 : if (*indat==firstchar)
202 : : {
203 : 527 : *outdat++=*indat++;
204 [ + + ]: 1052 : while (*indat==secondchar) indat++;
205 : : }
206 : 6030 : else *outdat++=*indat++;
207 : : }
208 : 468 : *outdat=0;
209 : : thisstring =trueoutdat;
210 : 468 : free(trueoutdat);
211 : 468 : return thisstring;
212 : : }
213 : : else
214 : : //end hack
215 : : {
216 : 0 : char thehatedchar=instr[thelen];
217 [ # # ]: 0 : while (*indat)
218 : : {
219 [ # # ]: 0 : if (!memcmp(indat, outstr, (size_t)thelen))
220 : : {
221 : 0 : memcpy(outdat, outstr, (size_t)thelen);
222 : 0 : outdat+=thelen;
223 : 0 : indat+=thelen;
224 [ # # ]: 0 : while (*indat==thehatedchar) indat++;
225 : : }
226 : 0 : else *outdat++=*indat++;
227 : : }
228 : : }
229 : 0 : *outdat=0;
230 : : thisstring =trueoutdat;
231 : 0 : free(trueoutdat);
232 : 0 : return thisstring;
233 : : }
234 : : //end hack
235 : : bool replaced=true;
236 [ + + ]: 45 : while (replaced)
237 : : {
238 : : replaced=false;
239 : 30 : string out;
240 : : const char * in= thisstring;
241 : 30 : int inlen=(int)strlen(instr);
242 [ + + ]: 537 : while (*in)
243 : : {
244 [ + + ]: 507 : if (!strncmp(in, instr, (size_t)inlen))
245 : : {
246 : : replaced=true;
247 : 15 : out+=outstr;
248 : 15 : in+=inlen;
249 : : }
250 : 492 : else out+=*in++;
251 : : }
252 : : thisstring =out;
253 : 30 : }
254 : : return thisstring;
255 : : }
256 : :
257 : 2062214 : string& string::qreplace(const char * instr, const char * outstr, bool all)
258 : : {
259 : : string& thisstring =*this;
260 [ + + ]: 2062214 : if (!strstr(thisstring, instr)) return thisstring;
261 [ + + - + ]: 604 : if (!strchr(thisstring, '"') && !strchr(thisstring, '\''))
262 : : {
263 : 484 : thisstring.replace(instr, outstr, all);
264 : 484 : return thisstring;
265 : : }
266 : : bool replaced=true;
267 [ + + ]: 345 : while (replaced)
268 : : {
269 : : replaced=false;
270 : 225 : string out;
271 [ + + ]: 5970 : for (int i=0;thisstring[i];)
272 : : {
273 : 12087 : dequote(thisstring[i], out+= thisstring[i++], return thisstring);
274 : : else
275 : : {
276 [ + + ]: 5214 : if (!strncmp((const char*)thisstring + i, instr, strlen(instr)))
277 : : {
278 : : replaced = true;
279 : 186 : out += outstr;
280 : 186 : i += (int)strlen(instr);
281 [ - + ]: 186 : if (!all)
282 : : {
283 : 0 : out += ((const char*)thisstring) + i;
284 : : thisstring = out;
285 : 0 : return thisstring;
286 : : }
287 : : }
288 : : // randomdude999: prevent appending the null terminator to the output
289 : 5028 : else if (thisstring[i]) out += thisstring[i++];
290 : : }
291 : : }
292 : : thisstring =out;
293 : 225 : }
294 : : return thisstring;
295 : : }
296 : :
297 : 440694 : bool confirmquotes(const char * str)
298 : : {
299 [ + + ]: 3779634 : for (int i=0;str[i];)
300 : : {
301 : 3352145 : dequote(str[i], i++, return false);
302 : 3337798 : else i++;
303 : : }
304 : : return true;
305 : : }
306 : :
307 : 107211 : bool confirmqpar(const char * str)
308 : : {
309 [ + + ]: 222679 : for (int i=0;str[i];)
310 : : {
311 : 124307 : skippar(str[i], i++, return false);
312 : 114584 : else i++;
313 : : }
314 : : return true;
315 : : }
316 : :
317 : 872273 : char ** nsplit(char * str, const char * key, int maxlen, int * len)
318 : : {
319 [ + + ]: 872273 : if (!strstr(str, key))
320 : : {
321 : 653199 : char ** out= typed_malloc(char*, 2);
322 : 653199 : out[0]=str;
323 : 653199 : out[1]=nullptr;
324 [ + + ]: 653199 : if (len) *len=1;
325 : 653199 : return out;
326 : : }
327 : 219074 : int keylen=(int)strlen(key);
328 : : int count=7; //makes the default alloc 8 elements, sounds fair.
329 [ - + ]: 219074 : if (maxlen && count>maxlen) count=maxlen;
330 : 219074 : char ** outdata= typed_malloc(char*, (size_t)count+1);
331 : :
332 : : int newcount=0;
333 : : char *thisentry=str;
334 : 219074 : outdata[newcount++]=thisentry;
335 [ + + ]: 654952 : while((thisentry = strstr(thisentry, key))){
336 : 435878 : *thisentry = 0;
337 : 435878 : thisentry += keylen;
338 : 435878 : outdata[newcount++]=thisentry;
339 [ + + ]: 435878 : if(newcount >= count)
340 : : {
341 : 276 : outdata = typed_realloc(char *, outdata, count * 2);
342 : : count *= 2;
343 : : }
344 : : }
345 : :
346 : 219074 : outdata[newcount]= nullptr;
347 [ + + ]: 219074 : if (len) *len=newcount;
348 : : return outdata;
349 : : }
350 : :
351 : 873228 : char ** qnsplit(char * str, const char * key, int maxlen, int * len)
352 : : {
353 [ + + + + ]: 873228 : if (!strchr(str, '"') && !strchr(str, '\'')) return nsplit(str, key, maxlen, len);
354 : 1518 : int keylen=(int)strlen(key);
355 : : int count=7;
356 [ - + ]: 1518 : if (maxlen && count>maxlen) count=maxlen;
357 : 1518 : char ** outdata= typed_malloc(char*, (size_t)count+1);
358 : : int newcount=0;
359 : : char * thisentry=str;
360 : 1518 : outdata[newcount++]=thisentry;
361 [ + + ]: 19218 : while (*thisentry) /*todo fix*/
362 : : {
363 : 38572 : dequote(*thisentry, thisentry++, return nullptr);
364 [ + + ]: 15864 : else if (!strncmp(thisentry, key, (size_t)keylen))
365 : : {
366 : 858 : *thisentry=0;
367 : 858 : thisentry+=keylen;
368 : 858 : outdata[newcount++]=thisentry;
369 [ - + ]: 858 : if(newcount >= count)
370 : : {
371 : 0 : outdata = typed_realloc(char *, outdata, count * 2);
372 : : count *= 2;
373 : : }
374 : : }
375 : 15006 : else thisentry++;
376 : : }
377 : 1518 : outdata[newcount]= nullptr;
378 [ + + ]: 1518 : if (len) *len=newcount;
379 : : return outdata;
380 : : }
381 : :
382 : 110033 : char ** qpnsplit(char * str, const char * key, int maxlen, int * len)
383 : : {
384 : 110033 : int keylen=(int)strlen(key);
385 : : int count=7;
386 [ - + ]: 110033 : if (maxlen && count>maxlen) count=maxlen;
387 : 110033 : char ** outdata= typed_malloc(char*, (size_t)count+1);
388 : :
389 : : int newcount=0;
390 : : char * thisentry=str;
391 : 110033 : outdata[newcount++]=thisentry;
392 [ + + ]: 236478 : while (*thisentry)
393 : : {
394 : 136738 : skippar(*thisentry, thisentry++, return nullptr);
395 [ + + ]: 125110 : else if (!strncmp(thisentry, key, (size_t)keylen))
396 : : {
397 : 1748 : *thisentry=0;
398 : 1748 : thisentry+=keylen;
399 : 1748 : outdata[newcount++]=thisentry;
400 [ + + ]: 1748 : if(newcount >= count)
401 : : {
402 : 21 : outdata = typed_realloc(char *, outdata, count * 2);
403 : : count *= 2;
404 : : }
405 : : }
406 : 123362 : else thisentry++;
407 : : }
408 : 110033 : outdata[newcount]= nullptr;
409 [ + + ]: 110033 : if (len) *len=newcount;
410 : : return outdata;
411 : : }
412 : :
413 : 438141 : string &strip_prefix(string &str, char c, bool multi)
414 : : {
415 [ + + ]: 438141 : if(!multi){
416 [ + + ]: 1149 : if(str.data()[0] == c){
417 : 579 : str = string(str.data() + 1, str.length() - 1);
418 : : }
419 : 1149 : return str;
420 : : }
421 : : int length = str.length();
422 [ + + ]: 436992 : for(int i = 0; i < length; i++){
423 [ + - ]: 326485 : if(str.data()[i] != c){
424 : 326485 : str = string(str.data() + i, str.length() - i);
425 : 326485 : return str;
426 : : }
427 : : }
428 : : return str;
429 : : }
430 : :
431 : 437055 : string &strip_suffix(string &str, char c, bool multi)
432 : : {
433 [ + + ]: 437055 : if(!multi){
434 [ + - ]: 63 : if(str.data()[str.length() - 1] == c){
435 : 63 : str.truncate(str.length() - 1);
436 : : }
437 : 63 : return str;
438 : : }
439 [ + + ]: 437013 : for(int i = str.length() - 1; i >= 0; i--){
440 [ + + ]: 326506 : if(str.data()[i] != c){
441 : 326485 : str.truncate(i + 1);
442 : 326485 : return str;
443 : : }
444 : : }
445 : : return str;
446 : : }
447 : :
448 : 436992 : string &strip_both(string &str, char c, bool multi)
449 : : {
450 : 436992 : return strip_suffix(strip_prefix(str, c, multi), c, multi);
451 : : }
452 : :
453 : 543010 : string &strip_whitespace(string &str)
454 : : {
455 [ + + ]: 543399 : for(int i = str.length() - 1; i >= 0; i--){
456 [ + + + - ]: 538317 : if(str.data()[i] != ' ' && str.data()[i] != '\t'){
457 : 537928 : str.truncate(i + 1);
458 : : break;
459 : : }
460 : : }
461 : :
462 : : int length = str.length();
463 [ + + ]: 543295 : for(int i = 0; i < length; i++){
464 [ + + - + ]: 538213 : if(str.data()[i] != ' ' && str.data()[i] != '\t'){
465 : 537928 : str = string(str.data() + i, str.length() - i);
466 : 537928 : return str;
467 : : }
468 : : }
469 : : return str;
470 : : }
471 : :
472 : 4506 : char * itrim(char * str, const char * left, const char * right, bool multi)
473 : : {
474 : 4506 : string tmp(str);
475 : 4506 : return strcpy(str, itrim(tmp, left, right, multi).data());
476 : 4506 : }
477 : :
478 : : //todo merge above with this
479 : 4929 : string &itrim(string &input, const char * left, const char * right, bool multi)
480 : : {
481 : : bool nukeright=true;
482 : : int totallen=input.length();
483 : 4929 : int rightlen=(int)strlen(right);
484 [ + + ]: 4929 : if (rightlen && rightlen<=totallen)
485 : : {
486 : : do
487 : : {
488 : 10919 : const char * rightend=right+rightlen;
489 : 10919 : const char * strend=input.data()+totallen;
490 [ + + ]: 22411 : while (right!=rightend)
491 : : {
492 : 11492 : rightend--;
493 : 11492 : strend--;
494 [ + + ]: 11492 : if (to_lower(*strend)!=to_lower(*rightend)) nukeright=false;
495 : : }
496 [ + + ]: 10919 : if (nukeright)
497 : : {
498 : 8024 : totallen-=rightlen;
499 : : input.truncate(totallen);
500 : : }
501 [ + + + + ]: 10919 : } while (multi && nukeright && rightlen<=totallen);
502 : : }
503 : : bool nukeleft=true;
504 : 4929 : int leftlen = strlen(left);
505 [ + + + - ]: 4929 : if(!multi && leftlen == 1 && input.data()[0] == left[0])
506 : : {
507 : 102 : return input = string(input.data()+1, (input.length()-1));
508 : : }
509 : : else
510 : : {
511 : : do
512 : : {
513 : :
514 [ + + ]: 10847 : for (int i = 0; i < leftlen; i++)
515 : : {
516 [ + + ]: 5263 : if (to_lower(input.data()[i])!=to_lower(left[i])) nukeleft=false;
517 : : }
518 [ + + ]: 6662 : if (nukeleft) input = string(input.data()+leftlen, (input.length()-leftlen));
519 [ + + ]: 5584 : } while (multi && nukeleft);
520 : : }
521 : : return input;
522 : : }
523 : :
524 : 3 : char* strqpchr(const char* str, char key)
525 : : {
526 [ + - ]: 12 : while (*str)
527 : : {
528 : 36 : skippar(*str, str++, return nullptr);
529 [ + + ]: 6 : else if (*str == key) return const_cast<char*>(str);
530 : : else if (!*str) return nullptr;
531 : 3 : else str++;
532 : : }
533 : : return nullptr;
534 : : }
535 : :
536 : :
537 : 81 : char* strqpstr(const char* str, const char* key)
538 : : {
539 : 81 : size_t keylen = strlen(key);
540 [ + + ]: 411 : while (*str)
541 : : {
542 : 450 : skippar(*str, str++, return nullptr);
543 [ + + ]: 399 : else if (!strncmp(str, key, keylen)) return const_cast<char*>(str);
544 : : else if (!*str) return nullptr;
545 : 321 : else str++;
546 : : }
547 : : return nullptr;
548 : : }
549 : :
550 : : extern const uint8_t char_props[256] = {
551 : : //x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
552 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, // 0x
553 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1x
554 : : 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2x !"#$%&'()*+,-./
555 : : 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, // 3x 0123456789:;<=>?
556 : : 0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, // 4x @ABCDEFGHIJKLMNO
557 : : 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, // 5x PQRSTUVWXYZ[\]^_
558 : : 0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, // 6x `abcdefghijklmno
559 : : 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, // 7x pqrstuvwxyz{|}~
560 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8x
561 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9x
562 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ax
563 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Bx
564 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Cx
565 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Dx
566 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ex
567 : : 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Fx
568 : : };
|