exe: Support PAK v1.6 self-extracting archives
[deark.git] / src / deark-data.c
blob147232303d9142d8699cb0e253dca0da8f2fdb40
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // deark-data.c
6 //
7 // Data lookup and conversion.
9 #define DE_NOT_IN_MODULE
10 #include "deark-config.h"
12 #include "deark-private.h"
14 static const char *g_hexchars = "0123456789abcdef";
16 char de_get_hexchar(int n)
18 if(n>=0 && n<16) return g_hexchars[n];
19 return '0';
22 static char de_get_hexcharUC(int n)
24 static const char *hexcharsUC = "0123456789ABCDEF";
25 if(n>=0 && n<16) return hexcharsUC[n];
26 return '0';
29 u8 de_decode_hex_digit(u8 x, int *errorflag)
31 if(errorflag) *errorflag = 0;
32 if(x>='0' && x<='9') return x-48;
33 if(x>='A' && x<='F') return x-55;
34 if(x>='a' && x<='f') return x-87;
35 if(errorflag) *errorflag = 1;
36 return 0;
39 struct ext_ascii_pvt_data {
40 const u16 *tbl; // array[128]
43 static const u16 cp437table[256] = {
44 0x00a0,0x263a,0x263b,0x2665,0x2666,0x2663,0x2660,0x2022,0x25d8,0x25cb,0x25d9,0x2642,0x2640,0x266a,0x266b,0x263c,
45 0x25ba,0x25c4,0x2195,0x203c,0x00b6,0x00a7,0x25ac,0x21a8,0x2191,0x2193,0x2192,0x2190,0x221f,0x2194,0x25b2,0x25bc,
46 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
47 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
48 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
49 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
50 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
51 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x2302,
52 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
53 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
54 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
55 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
56 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
57 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
58 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
59 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
62 static const u16 latin2table[32] = { // 0xa0 to 0xbf
63 0x00a0,0x0104,0x02d8,0x0141,0x00a4,0x013d,0x015a,0x00a7,0x00a8,0x0160,0x015e,0x0164,0x0179,0x00ad,0x017d,0x017b,
64 0x00b0,0x0105,0x02db,0x0142,0x00b4,0x013e,0x015b,0x02c7,0x00b8,0x0161,0x015f,0x0165,0x017a,0x02dd,0x017e,0x017c
67 static const u16 windows1250table[128] = {
68 0x20ac,0xffff,0x201a,0xffff,0x201e,0x2026,0x2020,0x2021,0xffff,0x2030,0x0160,0x2039,0x015a,0x0164,0x017d,0x0179,
69 0xffff,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,0xffff,0x2122,0x0161,0x203a,0x015b,0x0165,0x017e,0x017a,
70 0x00a0,0x02c7,0x02d8,0x0141,0x00a4,0x0104,0x00a6,0x00a7,0x00a8,0x00a9,0x015e,0x00ab,0x00ac,0x00ad,0x00ae,0x017b,
71 0x00b0,0x00b1,0x02db,0x0142,0x00b4,0x00b5,0x00b6,0x00b7,0x00b8,0x0105,0x015f,0x00bb,0x013d,0x02dd,0x013e,0x017c,
72 0x0154,0x00c1,0x00c2,0x0102,0x00c4,0x0139,0x0106,0x00c7,0x010c,0x00c9,0x0118,0x00cb,0x011a,0x00cd,0x00ce,0x010e,
73 0x0110,0x0143,0x0147,0x00d3,0x00d4,0x0150,0x00d6,0x00d7,0x0158,0x016e,0x00da,0x0170,0x00dc,0x00dd,0x0162,0x00df,
74 0x0155,0x00e1,0x00e2,0x0103,0x00e4,0x013a,0x0107,0x00e7,0x010d,0x00e9,0x0119,0x00eb,0x011b,0x00ed,0x00ee,0x010f,
75 0x0111,0x0144,0x0148,0x00f3,0x00f4,0x0151,0x00f6,0x00f7,0x0159,0x016f,0x00fa,0x0171,0x00fc,0x00fd,0x0163,0x02d9
77 static const struct ext_ascii_pvt_data windows1250_pvt_data = { windows1250table };
79 static const u16 windows1251table[128] = {
80 0x0402,0x0403,0x201a,0x0453,0x201e,0x2026,0x2020,0x2021,0x20ac,0x2030,0x0409,0x2039,0x040a,0x040c,0x040b,0x040f,
81 0x0452,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,0xffff,0x2122,0x0459,0x203a,0x045a,0x045c,0x045b,0x045f,
82 0x00a0,0x040e,0x045e,0x0408,0x00a4,0x0490,0x00a6,0x00a7,0x0401,0x00a9,0x0404,0x00ab,0x00ac,0x00ad,0x00ae,0x0407,
83 0x00b0,0x00b1,0x0406,0x0456,0x0491,0x00b5,0x00b6,0x00b7,0x0451,0x2116,0x0454,0x00bb,0x0458,0x0405,0x0455,0x0457,
84 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
85 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
86 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
87 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f
89 static const struct ext_ascii_pvt_data windows1251_pvt_data = { windows1251table };
91 static const u16 windows1252table[32] = {
92 0x20ac,0xffff,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,0x02c6,0x2030,0x0160,0x2039,0x0152,0xffff,0x017d,0xffff,
93 0xffff,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,0x02dc,0x2122,0x0161,0x203a,0x0153,0xffff,0x017e,0x0178
96 static const u16 windows1253table[128] = {
97 0x20ac,0xffff,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,0xffff,0x2030,0xffff,0x2039,0xffff,0xffff,0xffff,0xffff,
98 0xffff,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,0xffff,0x2122,0xffff,0x203a,0xffff,0xffff,0xffff,0xffff,
99 0x00a0,0x0385,0x0386,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,0x00a8,0x00a9,0xffff,0x00ab,0x00ac,0x00ad,0x00ae,0x2015,
100 0x00b0,0x00b1,0x00b2,0x00b3,0x0384,0x00b5,0x00b6,0x00b7,0x0388,0x0389,0x038a,0x00bb,0x038c,0x00bd,0x038e,0x038f,
101 0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,
102 0x03a0,0x03a1,0xffff,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03aa,0x03ab,0x03ac,0x03ad,0x03ae,0x03af,
103 0x03b0,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,
104 0x03c0,0x03c1,0x03c2,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,0x03c9,0x03ca,0x03cb,0x03cc,0x03cd,0x03ce,0xffff
106 static const struct ext_ascii_pvt_data windows1253_pvt_data = { windows1253table };
108 static const u16 windows1254table[128] = {
109 0x20ac,0xffff,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,0x02c6,0x2030,0x0160,0x2039,0x0152,0xffff,0xffff,0xffff,
110 0xffff,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,0x02dc,0x2122,0x0161,0x203a,0x0153,0xffff,0xffff,0x0178,
111 0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
112 0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
113 0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
114 0x011e,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x0130,0x015e,0x00df,
115 0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
116 0x011f,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x0131,0x015f,0x00ff
118 static const struct ext_ascii_pvt_data windows1254_pvt_data = { windows1254table };
120 static const i32 atarist_table_lo[32] = { // [0..31]
121 0x0000, 0x21e7, 0x21e9, 0x21e8, 0x21e6,0x1fbbd,0x1fbbe,0x1fbbf,
122 0x2713,0x1f552,0x1f514, 0x266a, 0x240c, 0x240d, 0xffff, 0xffff,
123 0x1fbf0,0x1fbf1,0x1fbf2,0x1fbf3,0x1fbf4,0x1fbf5,0x1fbf6,0x1fbf7,
124 0x1fbf8,0x1fbf9, 0x0259, 0x241b, 0xffff, 0xffff, 0xffff, 0xffff
127 static const u16 atarist_table_hi[80] = { // [176..255]
128 0x00e3,0x00f5,0x00d8,0x00f8,0x0153,0x0152,0x00c0,0x00c3,0x00d5,0x00a8,0x00b4,0x2020,0x00b6,0x00a9,0x00ae,0x2122,
129 0x0133,0x0132,0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,0x05d8,0x05d9,0x05db,0x05dc,0x05de,0x05e0,
130 0x05e1,0x05e2,0x05e4,0x05e6,0x05e7,0x05e8,0x05e9,0x05ea,0x05df,0x05da,0x05dd,0x05e3,0x05e5,0x00a7,0x2227,0x221e,
131 0x03b1,0x03b2,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x222e,0x03d5,0x2208,0x2229,
132 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2022,0x00b7,0x221a,0x207f,0x00b2,0x00b3,0x00af
135 // Trivia: This table maps the heart and diamond suits to the BLACK Unicode
136 // characters. Some sources map them to the WHITE characters instead.
137 static const u16 palmcstable[4] = {
138 0x2666,0x2663,0x2665,0x2660
141 static const u16 riscostable[32] = {
142 0x20ac,0x0174,0x0175,0xffff,0xffff,0x0176,0x0177,0xffff,0xffff,0xffff,0xffff,0xffff,0x2026,0x2122,0x2030,0x2022,
143 0x2018,0x2019,0x2039,0x203a,0x201c,0x201d,0x201e,0x2013,0x2014,0x2212,0x0152,0x0153,0x2020,0x2021,0xfb01,0xfb02
146 // MacRoman, a.k.a "Mac OS Roman", "Macintosh"
147 static const u16 macromantable[128] = {
148 0x00c4,0x00c5,0x00c7,0x00c9,0x00d1,0x00d6,0x00dc,0x00e1,0x00e0,0x00e2,0x00e4,0x00e3,0x00e5,0x00e7,0x00e9,0x00e8,
149 0x00ea,0x00eb,0x00ed,0x00ec,0x00ee,0x00ef,0x00f1,0x00f3,0x00f2,0x00f4,0x00f6,0x00f5,0x00fa,0x00f9,0x00fb,0x00fc,
150 0x2020,0x00b0,0x00a2,0x00a3,0x00a7,0x2022,0x00b6,0x00df,0x00ae,0x00a9,0x2122,0x00b4,0x00a8,0x2260,0x00c6,0x00d8,
151 0x221e,0x00b1,0x2264,0x2265,0x00a5,0x00b5,0x2202,0x2211,0x220f,0x03c0,0x222b,0x00aa,0x00ba,0x03a9,0x00e6,0x00f8,
152 0x00bf,0x00a1,0x00ac,0x221a,0x0192,0x2248,0x2206,0x00ab,0x00bb,0x2026,0x00a0,0x00c0,0x00c3,0x00d5,0x0152,0x0153,
153 0x2013,0x2014,0x201c,0x201d,0x2018,0x2019,0x00f7,0x25ca,0x00ff,0x0178,0x2044,0x20ac,0x2039,0x203a,0xfb01,0xfb02,
154 0x2021,0x00b7,0x201a,0x201e,0x2030,0x00c2,0x00ca,0x00c1,0x00cb,0x00c8,0x00cd,0x00ce,0x00cf,0x00cc,0x00d3,0x00d4,
155 0xf8ff,0x00d2,0x00da,0x00db,0x00d9,0x0131,0x02c6,0x02dc,0x00af,0x02d8,0x02d9,0x02da,0x00b8,0x02dd,0x02db,0x02c7
157 static const struct ext_ascii_pvt_data macroman_pvt_data = { macromantable };
159 // Note: This is not an official or canonical mapping.
160 static const i32 petscii1table[256] = {
161 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x000d,0x000e,0xffff,
162 0xffff,0xffff,0xffff,0xffff,0x007f,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
163 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
164 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
165 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
166 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x00a3,0x005d,0x2191,0x2190,
167 0x2500,0x2660,0x2502,0x2500,0x1fb77,0x1fb76,0x1fb7a,0x1fb71,0x1fb74,0x256e,0x2570,0x256f,0x1fb7c,0x2572,0x2571,0x1fb7d,
168 0x1fb7e,0x25cf,0x1fb7b,0x2665,0x1fb70,0x256d,0x2573,0x25cb,0x2663,0x1fb75,0x2666,0x253c,0x1fb8c,0x2502,0x03c0,0x25e5,
169 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x000a,0x000f,0xffff,
170 0xffff,0xffff,0xffff,0x000c,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0x0008,0xffff,0xffff,
171 0x00a0,0x258c,0x2584,0x2594,0x2581,0x258e,0x2592,0x2595,0x1fb8f,0x25e4,0x1fb87,0x251c,0x2597,0x2514,0x2510,0x2582,
172 0x250c,0x2534,0x252c,0x2524,0x258e,0x258d,0x1fb88,0x1fb82,0x1fb83,0x2583,0x1fb7f,0x2596,0x259d,0x2518,0x2598,0x259a,
173 0x2500,0x2660,0x2502,0x2500,0x1fb77,0x1fb76,0x1fb7a,0x1fb71,0x1fb74,0x256e,0x2570,0x256f,0x1fb7c,0x2572,0x2571,0x1fb7d,
174 0x1fb7e,0x25cf,0x1fb7b,0x2665,0x1fb70,0x256d,0x2573,0x25cb,0x2663,0x1fb75,0x2666,0x253c,0x1fb8c,0x2502,0x03c0,0x25e5,
175 0x00a0,0x258c,0x2584,0x2594,0x2581,0x258e,0x2592,0x2595,0x1fb8f,0x25e4,0x1fb87,0x251c,0x2597,0x2514,0x2510,0x2582,
176 0x250c,0x2534,0x252c,0x2524,0x258e,0x258d,0x1fb88,0x1fb82,0x1fb83,0x2583,0x1fb7f,0x2596,0x259d,0x2518,0x2598,0x03c0
179 // Derived from VT100 Series Technical manual, Table A-9: Special Graphics Characters (p. A-12)
180 static const u16 decspecialgraphicstable[32] = {
181 0x00a0,0x25c6,0x2592,0x2409,0x240c,0x240d,0x240a,0x00b0,0x00b1,0x2424,0x240b,0x2518,0x2510,0x250c,0x2514,0x253c,
182 0x23ba,0x23bb,0x2500,0x23bc,0x23bd,0x251c,0x2524,0x2534,0x252c,0x2502,0x2264,0x2265,0x03c0,0x2260,0x00a3,0x00b7
185 // Code page 437, with screen code graphics characters.
186 static de_rune de_cp437g_to_unicode(struct de_encconv_state *es, i32 a)
188 de_rune n;
189 if(a<=0xff) n = (de_rune)cp437table[a];
190 else n = DE_CODEPOINT_INVALID;
191 if(n==0xffff) n = DE_CODEPOINT_INVALID;
192 return n;
195 // Code page 437, with control characters.
196 static de_rune de_cp437c_to_unicode(struct de_encconv_state *es, i32 a)
198 de_rune n;
199 if(a<=0x7f) n = a;
200 else if(a>=0x80 && a<=0xff) n = (de_rune)cp437table[a];
201 else n = DE_CODEPOINT_INVALID;
202 if(n==0xffff) n = DE_CODEPOINT_INVALID;
203 return n;
206 // Code page 437, with only selected control characters.
207 static de_rune de_cp437h_to_unicode(struct de_encconv_state *es, i32 a)
209 de_rune n;
211 if(a==0 || a==9 || a==10 || a==13) n = a;
212 else n = de_cp437g_to_unicode(NULL, a);
213 return n;
216 static de_rune de_latin2_to_unicode(struct de_encconv_state *es, i32 a)
218 de_rune n;
219 if(a<=0x9f) n = a;
220 else if(a>=0xa0 && a<=0xbf) n = (de_rune)latin2table[a-0xa0];
221 else if(a>=0x0c0 && a<=0xff) n = (de_rune)windows1250table[a-0x80];
222 else n = DE_CODEPOINT_INVALID;
223 if(n==0xffff) n = DE_CODEPOINT_INVALID;
224 return n;
227 static de_rune de_windows1252_to_unicode(struct de_encconv_state *es, i32 a)
229 de_rune n;
230 if(a>=0x80 && a<=0x9f) n = (de_rune)windows1252table[a-0x80];
231 else if(a<=0xff) n = a;
232 else n = DE_CODEPOINT_INVALID;
233 if(n==0xffff) n = DE_CODEPOINT_INVALID;
234 return n;
237 static de_rune de_windows874_to_unicode(struct de_encconv_state *es, i32 a)
239 de_rune n = 0xffff;
240 if(a<=0x7f || a==0xa0) n = a;
241 else if(a==0x80 || a==0x85 || (a>=0x91 && a<=0x97)) n = (de_rune)windows1252table[a-0x80];
242 else if((a>=0xa1 && a<=0xda) || (a>=0xdf && a<=0xfb)) n = a + (0xe01 - 0xa1);
243 if(n==0xffff) n = DE_CODEPOINT_INVALID;
244 return n;
247 static de_rune de_atarist_to_unicode(struct de_encconv_state *es, i32 a)
249 de_rune n;
251 if(a<=0x1f || a==0x7f) {
252 int st = DE_EXTENC_GET_SUBTYPE(es->ee);
254 if (st==DE_ENCSUBTYPE_HYBRID || st==DE_ENCSUBTYPE_CONTROLS) {
255 return a;
258 if(a<=0x1f) n = atarist_table_lo[a];
259 else if(a>=0xb0 && a<=0xff) n = (de_rune)atarist_table_hi[a-0xb0];
260 else if(a==0x7f) n = 0x0394;
261 else if(a==0x9e) n = 0x00df;
262 else n = de_cp437g_to_unicode(NULL, a);
263 if(n==0xffff) n = DE_CODEPOINT_INVALID;
264 return n;
267 static de_rune de_palmcs_to_unicode(struct de_encconv_state *es, i32 a)
269 de_rune n;
270 // This is not perfect, but the diamond/club/heart/spade characters seem to
271 // be about the only printable characters common to all versions of this
272 // encoding, that differ from Windows-1252.
273 if(a>=0x8d && a<=0x90) n = (de_rune)palmcstable[a-0x8d];
274 else n = de_windows1252_to_unicode(NULL, a);
275 return n;
278 static de_rune de_riscos_to_unicode(struct de_encconv_state *es, i32 a)
280 de_rune n;
281 if(a>=0x80 && a<=0x9f) n = (de_rune)riscostable[a-0x80];
282 else if(a<=0xff) n = a;
283 else n = DE_CODEPOINT_INVALID;
284 if(n==0xffff) n = DE_CODEPOINT_INVALID;
285 return n;
288 static de_rune de_petscii_to_unicode(struct de_encconv_state *es, i32 a)
290 de_rune n;
291 if(a<=0xff) n = petscii1table[a];
292 else n = DE_CODEPOINT_INVALID;
293 if(n==0xffff) n = DE_CODEPOINT_INVALID;
294 if(a==0x0a) {
295 // This is a hack to make "-m plaintext -inenc petscii" work with the
296 // output from the basic_c64 module.
297 if(DE_EXTENC_GET_SUBTYPE(es->ee)==DE_ENCSUBTYPE_HYBRID) {
298 n = 0x0a;
301 return n;
304 static de_rune de_appleii_to_unicode(struct de_encconv_state *es, i32 a)
306 de_rune n;
308 // This suffices to support some text files I've seen, but I really don't know
309 // what all is needed for Apple II text.
310 n = (de_rune)(a & 0x7f);
311 if(n==0x0d) n = 0x0a;
312 return n;
315 static de_rune de_decspecialgraphics_to_unicode(struct de_encconv_state *es, i32 a)
317 de_rune n;
318 if(a>=95 && a<=126) n = (de_rune)decspecialgraphicstable[a-95];
319 else n = DE_CODEPOINT_INVALID;
320 if(n==0xffff) n = DE_CODEPOINT_INVALID;
321 return n;
324 // Latin-1 + ROT-13.
325 // Intended for testing, as an easy way to check that encoding translation is
326 // working, even when the source data is plain ASCII.
327 static de_rune de_rot13_to_unicode(struct de_encconv_state *es, i32 a)
329 de_rune n;
331 if((a>='A' && a<='M') || (a>='a' && a<='m')) {
332 n = (de_rune)a+13;
334 else if((a>='N' && a<='Z') || (a>='n' && a<='z')) {
335 n = (de_rune)a-13;
337 else {
338 n = (de_rune)a;
341 return n;
344 // For any charset that uses 128 ASCII chars + 128 custom chars.
345 static de_rune de_ext_ascii_to_unicode(struct de_encconv_state *es, i32 a)
347 de_rune n;
349 if(a<=0x7f) n = a;
350 else if(a>=0x80 && a<=0xff) n = (de_rune)((struct ext_ascii_pvt_data*)es->fn_pvt_data)->tbl[a-0x80];
351 else n = DE_CODEPOINT_INVALID;
352 if(n==0xffff) n = DE_CODEPOINT_INVALID;
353 return n;
356 void de_encconv_init(struct de_encconv_state *es, de_ext_encoding ee)
358 de_encoding enc = DE_EXTENC_GET_BASE(ee);
360 de_zeromem(es, sizeof(struct de_encconv_state));
361 es->ee = ee;
363 if(enc==DE_ENCODING_LATIN1 || enc==DE_ENCODING_UTF8 ||
364 enc==DE_ENCODING_ASCII)
366 return;
369 switch(enc) {
370 case DE_ENCODING_LATIN2:
371 es->fn = de_latin2_to_unicode;
372 break;
373 case DE_ENCODING_CP437:
374 switch(DE_EXTENC_GET_SUBTYPE(es->ee)) {
375 case DE_ENCSUBTYPE_CONTROLS:
376 es->fn = de_cp437c_to_unicode;
377 break;
378 case DE_ENCSUBTYPE_HYBRID:
379 es->fn = de_cp437h_to_unicode;
380 break;
381 default:
382 es->fn = de_cp437g_to_unicode;
384 break;
385 case DE_ENCODING_PETSCII:
386 es->fn = de_petscii_to_unicode;
387 break;
388 case DE_ENCODING_WINDOWS1252:
389 es->fn = de_windows1252_to_unicode;
390 break;
391 case DE_ENCODING_MACROMAN:
392 es->fn = de_ext_ascii_to_unicode;
393 es->fn_pvt_data = (const void*)&macroman_pvt_data;
394 break;
395 case DE_ENCODING_WINDOWS1250:
396 es->fn = de_ext_ascii_to_unicode;
397 es->fn_pvt_data = (const void*)&windows1250_pvt_data;
398 break;
399 case DE_ENCODING_WINDOWS1251:
400 es->fn = de_ext_ascii_to_unicode;
401 es->fn_pvt_data = (const void*)&windows1251_pvt_data;
402 break;
403 case DE_ENCODING_WINDOWS1253:
404 es->fn = de_ext_ascii_to_unicode;
405 es->fn_pvt_data = (const void*)&windows1253_pvt_data;
406 break;
407 case DE_ENCODING_WINDOWS1254:
408 es->fn = de_ext_ascii_to_unicode;
409 es->fn_pvt_data = (const void*)&windows1254_pvt_data;
410 break;
411 case DE_ENCODING_WINDOWS874:
412 es->fn = de_windows874_to_unicode;
413 break;
414 case DE_ENCODING_ATARIST:
415 es->fn = de_atarist_to_unicode;
416 break;
417 case DE_ENCODING_PALM:
418 es->fn = de_palmcs_to_unicode;
419 break;
420 case DE_ENCODING_RISCOS:
421 es->fn = de_riscos_to_unicode;
422 break;
423 case DE_ENCODING_APPLEII:
424 es->fn = de_appleii_to_unicode;
425 break;
426 case DE_ENCODING_DEC_SPECIAL_GRAPHICS:
427 es->fn = de_decspecialgraphics_to_unicode;
428 break;
429 case DE_ENCODING_ROT13:
430 es->fn = de_rot13_to_unicode;
431 break;
432 default:
433 break;
437 de_rune de_char_to_unicode_ex(i32 a, struct de_encconv_state *es)
439 if(a<0) return DE_CODEPOINT_INVALID;
440 if(es->fn) {
441 return es->fn(es, a);
444 switch(DE_EXTENC_GET_BASE(es->ee)) {
445 case DE_ENCODING_ASCII:
446 if(DE_EXTENC_GET_SUBTYPE(es->ee)==DE_ENCSUBTYPE_PRINTABLE) {
447 return (a>=32 && a<=126)?a:DE_CODEPOINT_INVALID;
449 return (a<128)?a:DE_CODEPOINT_INVALID;
450 case DE_ENCODING_LATIN1:
451 return (a<256)?a:DE_CODEPOINT_INVALID;
452 default:
453 break;
455 return a;
458 de_rune de_char_to_unicode(deark *c, i32 a, de_ext_encoding ee)
460 struct de_encconv_state es;
462 de_encconv_init(&es, ee);
463 return de_char_to_unicode_ex(a, &es);
466 // Encode a Unicode char in UTF-8.
467 // Caller supplies utf8buf[4].
468 // Sets *p_utf8len to the number of bytes used (1-4).
469 void de_uchar_to_utf8(de_rune u1, u8 *utf8buf, i64 *p_utf8len)
471 u32 u = (u32)u1;
473 // TODO: Maybe there should be a flag to tell what to do with
474 // our special codepoints (DE_CODEPOINT_BYTE00, ...).
475 if(u1<0 || u1>0x10ffff) {
476 u=0xfffd;
479 if(u<=0x7f) {
480 *p_utf8len = 1;
481 utf8buf[0] = (u8)u;
483 else if(u>=0x80 && u<=0x7ff) {
484 *p_utf8len = 2;
485 utf8buf[0] = 0xc0 | (u8)(u>>6);
486 utf8buf[1] = 0x80 | (u&0x3f);
488 else if(u>=0x800 && u<=0xffff) {
489 *p_utf8len = 3;
490 utf8buf[0] = 0xe0 | (u8)(u>>12);
491 utf8buf[1] = 0x80 | ((u>>6)&0x3f);
492 utf8buf[2] = 0x80 | (u&0x3f);
494 else {
495 *p_utf8len = 4;
496 utf8buf[0] = 0xf0 | (u8)(u>>18);
497 utf8buf[1] = 0x80 | ((u>>12)&0x3f);
498 utf8buf[2] = 0x80 | ((u>>6)&0x3f);
499 utf8buf[3] = 0x80 | (u&0x3f);
503 // Write a unicode code point to a file, encoded as UTF-8.
504 void dbuf_write_uchar_as_utf8(dbuf *outf, de_rune u)
506 u8 utf8buf[4];
507 i64 utf8len;
509 de_uchar_to_utf8(u, utf8buf, &utf8len);
510 dbuf_write(outf, utf8buf, utf8len);
513 // Convert a UTF-8 character to UTF-32.
514 // Returns 1 if a valid character was converted, 0 otherwise.
515 // buflen = the max number of bytes to read (but regardless of buflen, this
516 // will not read past a byte whose value is < 0x80).
518 // TODO?: There is another UTF-8 decoder in ucstring_append_bytes_ex(). Maybe
519 // should be consolidated in some way.
520 int de_utf8_to_uchar(const u8 *utf8buf, i64 buflen,
521 de_rune *p_uchar, i64 *p_utf8len)
523 i32 u0=0;
524 i32 u1=0;
525 i32 u2=0;
526 i32 u3=0;
528 if(buflen<1) return 0;
529 u0 = (i32)utf8buf[0];
530 if(u0<=0x7f) { // 1-byte UTF-8 char
531 *p_utf8len = 1;
532 *p_uchar = u0;
533 return 1;
535 if(buflen<2) return 0;
536 if((utf8buf[1]&0xc0)!=0x80) return 0;
537 u1 = (i32)utf8buf[1];
538 if(u0<=0xdf) { // 2-byte UTF-8 char
539 *p_utf8len = 2;
540 *p_uchar = ((u0&0x1f)<<6) | (u1&0x3f);
541 return 1;
543 if(buflen<3) return 0;
544 if((utf8buf[2]&0xc0)!=0x80) return 0;
545 u2 = (i32)utf8buf[2];
546 if(u0<=0xef) { // 3-byte UTF-8 char
547 *p_utf8len = 3;
548 *p_uchar = ((u0&0x0f)<<12) | ((u1&0x3f)<<6) | (u2&0x3f);
549 return 1;
551 if(buflen<4) return 0;
552 if((utf8buf[3]&0xc0)!=0x80) return 0;
553 u3 = (i32)utf8buf[3];
554 if(u0<=0xf7) { // 4-byte UTF-8 char
555 *p_utf8len = 4;
556 *p_uchar = ((u0&0x07)<<18) | ((u1&0x3f)<<12) | ((u2&0x3f)<<6) | (u3&0x3f);
557 return 1;
559 return 0;
562 // Copy a string, converting from UTF-8 to ASCII.
563 // Non-ASCII characters will be replaced, one way or another.
564 void de_utf8_to_ascii(const char *src, char *dst, size_t dstlen, unsigned int flags)
566 size_t srcpos = 0;
567 size_t dstpos = 0;
568 unsigned char ch;
569 i32 uchar;
570 i64 code_len;
571 int ret;
573 while(1) {
574 char sc; // substitution character 1
575 char sc2 = 0; // substitution character 2
577 if(dstpos >= dstlen-1) {
578 dst[dstlen-1] = '\0';
579 break;
582 ch = (unsigned char)src[srcpos];
583 if(ch<0x80) {
584 dst[dstpos++] = src[srcpos++];
585 if(ch=='\0')
586 break;
588 else { // Start of a multi-byte UTF8 char
590 ret = de_utf8_to_uchar((const u8*)&src[srcpos], 4, &uchar, &code_len);
591 if(ret) {
592 srcpos += (size_t)code_len;
593 switch(uchar) {
594 case 0x00d7: sc='x'; break; // Multiplication sign
595 case 0x2018: case 0x2019: sc='\''; break; // single quotes
596 case 0x201c: case 0x201d: sc='"'; break; // double quotes
597 case 0x2192: sc='-'; sc2='>'; break; // Rightwards arrow
598 case 0x2264: sc='<'; sc2='='; break;
599 case 0x2265: sc='>'; sc2='='; break;
600 case 0x2502: sc='|'; break; // Box drawings light vertical
601 default: sc = '_';
604 else {
605 srcpos += 1;
606 sc = '?';
608 dst[dstpos++] = sc;
609 if(sc2 && dstpos<dstlen-1) dst[dstpos++] = sc2;
614 // Given a buffer, return 1 if it has no bytes 0x80 or higher.
615 int de_is_ascii(const u8 *buf, i64 buflen)
617 i64 i;
619 for(i=0; i<buflen; i++) {
620 if(buf[i]>=128) return 0;
622 return 1;
625 static const u8 stdpal_vga256_colors[256*3] = {
626 0x00,0x00,0x00,0x00,0x00,0xaa,0x00,0xaa,0x00,0x00,0xaa,0xaa,0xaa,0x00,0x00,0xaa,0x00,0xaa,
627 0xaa,0x55,0x00,0xaa,0xaa,0xaa,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0xff,0x55,0x55,0xff,0xff,
628 0xff,0x55,0x55,0xff,0x55,0xff,0xff,0xff,0x55,0xff,0xff,0xff,0x00,0x00,0x00,0x14,0x14,0x14,
629 0x20,0x20,0x20,0x2d,0x2d,0x2d,0x39,0x39,0x39,0x45,0x45,0x45,0x51,0x51,0x51,0x61,0x61,0x61,
630 0x71,0x71,0x71,0x82,0x82,0x82,0x92,0x92,0x92,0xa2,0xa2,0xa2,0xb6,0xb6,0xb6,0xca,0xca,0xca,
631 0xe3,0xe3,0xe3,0xff,0xff,0xff,0x00,0x00,0xff,0x41,0x00,0xff,0x7d,0x00,0xff,0xbe,0x00,0xff,
632 0xff,0x00,0xff,0xff,0x00,0xbe,0xff,0x00,0x7d,0xff,0x00,0x41,0xff,0x00,0x00,0xff,0x41,0x00,
633 0xff,0x7d,0x00,0xff,0xbe,0x00,0xff,0xff,0x00,0xbe,0xff,0x00,0x7d,0xff,0x00,0x41,0xff,0x00,
634 0x00,0xff,0x00,0x00,0xff,0x41,0x00,0xff,0x7d,0x00,0xff,0xbe,0x00,0xff,0xff,0x00,0xbe,0xff,
635 0x00,0x7d,0xff,0x00,0x41,0xff,0x7d,0x7d,0xff,0x9e,0x7d,0xff,0xbe,0x7d,0xff,0xdf,0x7d,0xff,
636 0xff,0x7d,0xff,0xff,0x7d,0xdf,0xff,0x7d,0xbe,0xff,0x7d,0x9e,0xff,0x7d,0x7d,0xff,0x9e,0x7d,
637 0xff,0xbe,0x7d,0xff,0xdf,0x7d,0xff,0xff,0x7d,0xdf,0xff,0x7d,0xbe,0xff,0x7d,0x9e,0xff,0x7d,
638 0x7d,0xff,0x7d,0x7d,0xff,0x9e,0x7d,0xff,0xbe,0x7d,0xff,0xdf,0x7d,0xff,0xff,0x7d,0xdf,0xff,
639 0x7d,0xbe,0xff,0x7d,0x9e,0xff,0xb6,0xb6,0xff,0xc6,0xb6,0xff,0xdb,0xb6,0xff,0xeb,0xb6,0xff,
640 0xff,0xb6,0xff,0xff,0xb6,0xeb,0xff,0xb6,0xdb,0xff,0xb6,0xc6,0xff,0xb6,0xb6,0xff,0xc6,0xb6,
641 0xff,0xdb,0xb6,0xff,0xeb,0xb6,0xff,0xff,0xb6,0xeb,0xff,0xb6,0xdb,0xff,0xb6,0xc6,0xff,0xb6,
642 0xb6,0xff,0xb6,0xb6,0xff,0xc6,0xb6,0xff,0xdb,0xb6,0xff,0xeb,0xb6,0xff,0xff,0xb6,0xeb,0xff,
643 0xb6,0xdb,0xff,0xb6,0xc6,0xff,0x00,0x00,0x71,0x1c,0x00,0x71,0x39,0x00,0x71,0x55,0x00,0x71,
644 0x71,0x00,0x71,0x71,0x00,0x55,0x71,0x00,0x39,0x71,0x00,0x1c,0x71,0x00,0x00,0x71,0x1c,0x00,
645 0x71,0x39,0x00,0x71,0x55,0x00,0x71,0x71,0x00,0x55,0x71,0x00,0x39,0x71,0x00,0x1c,0x71,0x00,
646 0x00,0x71,0x00,0x00,0x71,0x1c,0x00,0x71,0x39,0x00,0x71,0x55,0x00,0x71,0x71,0x00,0x55,0x71,
647 0x00,0x39,0x71,0x00,0x1c,0x71,0x39,0x39,0x71,0x45,0x39,0x71,0x55,0x39,0x71,0x61,0x39,0x71,
648 0x71,0x39,0x71,0x71,0x39,0x61,0x71,0x39,0x55,0x71,0x39,0x45,0x71,0x39,0x39,0x71,0x45,0x39,
649 0x71,0x55,0x39,0x71,0x61,0x39,0x71,0x71,0x39,0x61,0x71,0x39,0x55,0x71,0x39,0x45,0x71,0x39,
650 0x39,0x71,0x39,0x39,0x71,0x45,0x39,0x71,0x55,0x39,0x71,0x61,0x39,0x71,0x71,0x39,0x61,0x71,
651 0x39,0x55,0x71,0x39,0x45,0x71,0x51,0x51,0x71,0x59,0x51,0x71,0x61,0x51,0x71,0x69,0x51,0x71,
652 0x71,0x51,0x71,0x71,0x51,0x69,0x71,0x51,0x61,0x71,0x51,0x59,0x71,0x51,0x51,0x71,0x59,0x51,
653 0x71,0x61,0x51,0x71,0x69,0x51,0x71,0x71,0x51,0x69,0x71,0x51,0x61,0x71,0x51,0x59,0x71,0x51,
654 0x51,0x71,0x51,0x51,0x71,0x59,0x51,0x71,0x61,0x51,0x71,0x69,0x51,0x71,0x71,0x51,0x69,0x71,
655 0x51,0x61,0x71,0x51,0x59,0x71,0x00,0x00,0x41,0x10,0x00,0x41,0x20,0x00,0x41,0x31,0x00,0x41,
656 0x41,0x00,0x41,0x41,0x00,0x31,0x41,0x00,0x20,0x41,0x00,0x10,0x41,0x00,0x00,0x41,0x10,0x00,
657 0x41,0x20,0x00,0x41,0x31,0x00,0x41,0x41,0x00,0x31,0x41,0x00,0x20,0x41,0x00,0x10,0x41,0x00,
658 0x00,0x41,0x00,0x00,0x41,0x10,0x00,0x41,0x20,0x00,0x41,0x31,0x00,0x41,0x41,0x00,0x31,0x41,
659 0x00,0x20,0x41,0x00,0x10,0x41,0x20,0x20,0x41,0x28,0x20,0x41,0x31,0x20,0x41,0x39,0x20,0x41,
660 0x41,0x20,0x41,0x41,0x20,0x39,0x41,0x20,0x31,0x41,0x20,0x28,0x41,0x20,0x20,0x41,0x28,0x20,
661 0x41,0x31,0x20,0x41,0x39,0x20,0x41,0x41,0x20,0x39,0x41,0x20,0x31,0x41,0x20,0x28,0x41,0x20,
662 0x20,0x41,0x20,0x20,0x41,0x28,0x20,0x41,0x31,0x20,0x41,0x39,0x20,0x41,0x41,0x20,0x39,0x41,
663 0x20,0x31,0x41,0x20,0x28,0x41,0x2d,0x2d,0x41,0x31,0x2d,0x41,0x35,0x2d,0x41,0x3d,0x2d,0x41,
664 0x41,0x2d,0x41,0x41,0x2d,0x3d,0x41,0x2d,0x35,0x41,0x2d,0x31,0x41,0x2d,0x2d,0x41,0x31,0x2d,
665 0x41,0x35,0x2d,0x41,0x3d,0x2d,0x41,0x41,0x2d,0x3d,0x41,0x2d,0x35,0x41,0x2d,0x31,0x41,0x2d,
666 0x2d,0x41,0x2d,0x2d,0x41,0x31,0x2d,0x41,0x35,0x2d,0x41,0x3d,0x2d,0x41,0x41,0x2d,0x3d,0x41,
667 0x2d,0x35,0x41,0x2d,0x31,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
668 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
671 static const u8 stdpal_ega64_colors[64*3] = {
672 0x00,0x00,0x00,0x00,0x00,0xaa,0x00,0xaa,0x00,0x00,0xaa,0xaa,0xaa,0x00,0x00,0xaa,0x00,0xaa,
673 0xaa,0xaa,0x00,0xaa,0xaa,0xaa,0x00,0x00,0x55,0x00,0x00,0xff,0x00,0xaa,0x55,0x00,0xaa,0xff,
674 0xaa,0x00,0x55,0xaa,0x00,0xff,0xaa,0xaa,0x55,0xaa,0xaa,0xff,0x00,0x55,0x00,0x00,0x55,0xaa,
675 0x00,0xff,0x00,0x00,0xff,0xaa,0xaa,0x55,0x00,0xaa,0x55,0xaa,0xaa,0xff,0x00,0xaa,0xff,0xaa,
676 0x00,0x55,0x55,0x00,0x55,0xff,0x00,0xff,0x55,0x00,0xff,0xff,0xaa,0x55,0x55,0xaa,0x55,0xff,
677 0xaa,0xff,0x55,0xaa,0xff,0xff,0x55,0x00,0x00,0x55,0x00,0xaa,0x55,0xaa,0x00,0x55,0xaa,0xaa,
678 0xff,0x00,0x00,0xff,0x00,0xaa,0xff,0xaa,0x00,0xff,0xaa,0xaa,0x55,0x00,0x55,0x55,0x00,0xff,
679 0x55,0xaa,0x55,0x55,0xaa,0xff,0xff,0x00,0x55,0xff,0x00,0xff,0xff,0xaa,0x55,0xff,0xaa,0xff,
680 0x55,0x55,0x00,0x55,0x55,0xaa,0x55,0xff,0x00,0x55,0xff,0xaa,0xff,0x55,0x00,0xff,0x55,0xaa,
681 0xff,0xff,0x00,0xff,0xff,0xaa,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0xff,0x55,0x55,0xff,0xff,
682 0xff,0x55,0x55,0xff,0x55,0xff,0xff,0xff,0x55,0xff,0xff,0xff
685 static const u8 stdpal_pc16_colors[16*3] = {
686 0x00,0x00,0x00,0x00,0x00,0xaa,0x00,0xaa,0x00,0x00,0xaa,0xaa,0xaa,0x00,0x00,0xaa,0x00,0xaa,
687 0xaa,0x55,0x00,0xaa,0xaa,0xaa,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0xff,0x55,0x55,0xff,0xff,
688 0xff,0x55,0x55,0xff,0x55,0xff,0xff,0xff,0x55,0xff,0xff,0xff
691 // This is a widely-used color set, but there seem to many different possible
692 // orders for the colors.
693 static const u8 stdpal_win16_colors_0[16*3] = {
694 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x80,
695 0x00,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0,0xff,0x00,0x00,0x00,0xff,0x00,0xff,0xff,0x00,
696 0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0xff,0xff
699 static const u8 stdpal_win16_colors_1[16*3] = {
700 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x80,
701 0x00,0x80,0x80,0xc0,0xc0,0xc0,0x80,0x80,0x80,0xff,0x00,0x00,0x00,0xff,0x00,0xff,0xff,0x00,
702 0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0xff,0xff
705 static const u8 stdpal_win16_colors_2[16*3] = {
706 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x80,0x00,0x80,
707 0x80,0x80,0x00,0x80,0x80,0x80,0xc0,0xc0,0xc0,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,
708 0xff,0x00,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff
711 static const u8 stdpals_cga[6][4*3] = {
712 { 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0xaa, 0xaa, 0xaa, 0xaa }, // 0 = palette 1 low
713 { 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x00, 0xaa, 0x55, 0x00 }, // 1 = palette 0 low
714 { 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xaa, 0xaa, 0xaa }, // 2 = 3rd palette low
715 { 0x00, 0x00, 0x00, 0x55, 0xff, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff, 0xff }, // 3 = palette 1 high
716 { 0x00, 0x00, 0x00, 0x55, 0xff, 0x55, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55 }, // 4 = palette 0 high
717 { 0x00, 0x00, 0x00, 0x55, 0xff, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0xff } // 5 = 3rd palette high
720 static const u8 *get_stdpal_colors(int pal_id, int pal_subid, i64 *pncolors)
722 const u8 *p = NULL;
724 *pncolors = 0;
726 switch(pal_id) {
727 case DE_PALID_CGA:
728 *pncolors = 4;
729 if(pal_subid>=0 && pal_subid<=5) {
730 p = stdpals_cga[pal_subid];
732 else {
733 p = stdpals_cga[2];
735 break;
736 case DE_PALID_PC16:
737 *pncolors = 16;
738 p = stdpal_pc16_colors;
739 break;
740 case DE_PALID_WIN16:
741 *pncolors = 16;
742 switch(pal_subid) {
743 case 1: p = stdpal_win16_colors_1; break;
744 case 2: p = stdpal_win16_colors_2; break;
745 default: p = stdpal_win16_colors_0; break;
747 break;
748 case DE_PALID_EGA64:
749 *pncolors = 64;
750 p = stdpal_ega64_colors;
751 break;
752 case DE_PALID_VGA256:
753 *pncolors = 256;
754 p = stdpal_vga256_colors;
755 break;
757 return p;
760 // May be inefficient. de_copy_std_palette() is preferred.
761 de_color de_get_std_palette_entry(int pal_id, int pal_subid, int index)
763 const u8 *pal;
764 i64 stdpal_ncolors;
766 pal = get_stdpal_colors(pal_id, pal_subid, &stdpal_ncolors);
767 if(!pal || index<0 || index>=(int)stdpal_ncolors) {
768 return DE_STOCKCOLOR_BLACK;
770 return DE_MAKE_RGB(pal[index*3], pal[index*3+1], pal[index*3+2]);
773 // starting_idx: The index of the color in the standard palette to be copied
774 // to dstpal[0].
775 // dstpal is indexed from 0...(dstpal_capacity-1).
776 // flags:
777 // DE_COPYPALFLAG_INITPAL: Ensure all items in dstpal are set to something,
778 // even if the source palette is too short.
779 void de_copy_std_palette(int pal_id, int pal_subid, i64 starting_idx,
780 de_color *dstpal, size_t dstpal_capacity, UI flags)
782 const u8 *pal;
783 i64 n_to_copy;
784 i64 stdpal_ncolors;
786 if(flags & DE_COPYPALFLAG_INITPAL) {
787 de_zeromem(dstpal, dstpal_capacity*sizeof(de_color));
790 pal = get_stdpal_colors(pal_id, pal_subid, &stdpal_ncolors);
791 if(!pal) goto done;
792 if(starting_idx >= stdpal_ncolors) goto done;
794 n_to_copy = de_min_int((i64)dstpal_capacity, stdpal_ncolors - starting_idx);
795 if(n_to_copy<=0) goto done;
796 de_copy_palette_from_rgb24(&pal[starting_idx*3], dstpal, (size_t)n_to_copy);
797 done:
801 void de_copy_palette_from_rgb24(const u8 *src, de_color *dst, size_t ncolors)
803 size_t i;
805 for(i=0; i<ncolors; i++) {
806 dst[i] = DE_MAKE_RGB(src[i*3], src[i*3+1], src[i*3+2]);
810 // Only codepoints 32-127 are included here.
811 static const u8 cga_8x8_font_data[96*8] = {
812 0,0,0,0,0,0,0,0,
813 48,120,120,48,48,0,48,0,
814 108,108,108,0,0,0,0,0,
815 108,108,254,108,254,108,108,0,
816 48,124,192,120,12,248,48,0,
817 0,198,204,24,48,102,198,0,
818 56,108,56,118,220,204,118,0,
819 96,96,192,0,0,0,0,0,
820 24,48,96,96,96,48,24,0,
821 96,48,24,24,24,48,96,0,
822 0,102,60,255,60,102,0,0,
823 0,48,48,252,48,48,0,0,
824 0,0,0,0,0,48,48,96,
825 0,0,0,252,0,0,0,0,
826 0,0,0,0,0,48,48,0,
827 6,12,24,48,96,192,128,0,
828 124,198,206,222,246,230,124,0,
829 48,112,48,48,48,48,252,0,
830 120,204,12,56,96,204,252,0,
831 120,204,12,56,12,204,120,0,
832 28,60,108,204,254,12,30,0,
833 252,192,248,12,12,204,120,0,
834 56,96,192,248,204,204,120,0,
835 252,204,12,24,48,48,48,0,
836 120,204,204,120,204,204,120,0,
837 120,204,204,124,12,24,112,0,
838 0,48,48,0,0,48,48,0,
839 0,48,48,0,0,48,48,96,
840 24,48,96,192,96,48,24,0,
841 0,0,252,0,0,252,0,0,
842 96,48,24,12,24,48,96,0,
843 120,204,12,24,48,0,48,0,
844 124,198,222,222,222,192,120,0,
845 48,120,204,204,252,204,204,0,
846 252,102,102,124,102,102,252,0,
847 60,102,192,192,192,102,60,0,
848 248,108,102,102,102,108,248,0,
849 254,98,104,120,104,98,254,0,
850 254,98,104,120,104,96,240,0,
851 60,102,192,192,206,102,62,0,
852 204,204,204,252,204,204,204,0,
853 120,48,48,48,48,48,120,0,
854 30,12,12,12,204,204,120,0,
855 230,102,108,120,108,102,230,0,
856 240,96,96,96,98,102,254,0,
857 198,238,254,254,214,198,198,0,
858 198,230,246,222,206,198,198,0,
859 56,108,198,198,198,108,56,0,
860 252,102,102,124,96,96,240,0,
861 120,204,204,204,220,120,28,0,
862 252,102,102,124,108,102,230,0,
863 120,204,96,48,24,204,120,0,
864 252,180,48,48,48,48,120,0,
865 204,204,204,204,204,204,252,0,
866 204,204,204,204,204,120,48,0,
867 198,198,198,214,254,238,198,0,
868 198,198,108,56,56,108,198,0,
869 204,204,204,120,48,48,120,0,
870 254,198,140,24,50,102,254,0,
871 120,96,96,96,96,96,120,0,
872 192,96,48,24,12,6,2,0,
873 120,24,24,24,24,24,120,0,
874 16,56,108,198,0,0,0,0,
875 0,0,0,0,0,0,0,255,
876 48,48,24,0,0,0,0,0,
877 0,0,120,12,124,204,118,0,
878 224,96,96,124,102,102,220,0,
879 0,0,120,204,192,204,120,0,
880 28,12,12,124,204,204,118,0,
881 0,0,120,204,252,192,120,0,
882 56,108,96,240,96,96,240,0,
883 0,0,118,204,204,124,12,248,
884 224,96,108,118,102,102,230,0,
885 48,0,112,48,48,48,120,0,
886 12,0,12,12,12,204,204,120,
887 224,96,102,108,120,108,230,0,
888 112,48,48,48,48,48,120,0,
889 0,0,204,254,254,214,198,0,
890 0,0,248,204,204,204,204,0,
891 0,0,120,204,204,204,120,0,
892 0,0,220,102,102,124,96,240,
893 0,0,118,204,204,124,12,30,
894 0,0,220,118,102,96,240,0,
895 0,0,124,192,120,12,248,0,
896 16,48,124,48,48,52,24,0,
897 0,0,204,204,204,204,118,0,
898 0,0,204,204,204,120,48,0,
899 0,0,198,214,254,254,108,0,
900 0,0,198,108,56,108,198,0,
901 0,0,204,204,204,124,12,248,
902 0,0,252,152,48,100,252,0,
903 28,48,48,224,48,48,28,0,
904 24,24,24,0,24,24,24,0,
905 224,48,48,28,48,48,224,0,
906 118,220,0,0,0,0,0,0,
907 0,16,56,108,198,198,254,0
910 const u8 *de_get_8x8ascii_font_ptr(void)
912 return cga_8x8_font_data;
915 static const u8 vga_cp437_font_data[256*16] = {
916 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
917 0,0,126,129,165,129,129,189,153,129,129,126,0,0,0,0,
918 0,0,126,255,219,255,255,195,231,255,255,126,0,0,0,0,
919 0,0,0,0,108,254,254,254,254,124,56,16,0,0,0,0,
920 0,0,0,0,16,56,124,254,124,56,16,0,0,0,0,0,
921 0,0,0,24,60,60,231,231,231,24,24,60,0,0,0,0,
922 0,0,0,24,60,126,255,255,126,24,24,60,0,0,0,0,
923 0,0,0,0,0,0,24,60,60,24,0,0,0,0,0,0,
924 255,255,255,255,255,255,231,195,195,231,255,255,255,255,255,255,
925 0,0,0,0,0,60,102,66,66,102,60,0,0,0,0,0,
926 255,255,255,255,255,195,153,189,189,153,195,255,255,255,255,255,
927 0,0,30,14,26,50,120,204,204,204,204,120,0,0,0,0,
928 0,0,60,102,102,102,102,60,24,126,24,24,0,0,0,0,
929 0,0,63,51,63,48,48,48,48,112,240,224,0,0,0,0,
930 0,0,127,99,127,99,99,99,99,103,231,230,192,0,0,0,
931 0,0,0,24,24,219,60,231,60,219,24,24,0,0,0,0,
932 0,128,192,224,240,248,254,248,240,224,192,128,0,0,0,0,
933 0,2,6,14,30,62,254,62,30,14,6,2,0,0,0,0,
934 0,0,24,60,126,24,24,24,126,60,24,0,0,0,0,0,
935 0,0,102,102,102,102,102,102,102,0,102,102,0,0,0,0,
936 0,0,127,219,219,219,123,27,27,27,27,27,0,0,0,0,
937 0,124,198,96,56,108,198,198,108,56,12,198,124,0,0,0,
938 0,0,0,0,0,0,0,0,254,254,254,254,0,0,0,0,
939 0,0,24,60,126,24,24,24,126,60,24,126,0,0,0,0,
940 0,0,24,60,126,24,24,24,24,24,24,24,0,0,0,0,
941 0,0,24,24,24,24,24,24,24,126,60,24,0,0,0,0,
942 0,0,0,0,0,24,12,254,12,24,0,0,0,0,0,0,
943 0,0,0,0,0,48,96,254,96,48,0,0,0,0,0,0,
944 0,0,0,0,0,0,192,192,192,254,0,0,0,0,0,0,
945 0,0,0,0,0,40,108,254,108,40,0,0,0,0,0,0,
946 0,0,0,0,16,56,56,124,124,254,254,0,0,0,0,0,
947 0,0,0,0,254,254,124,124,56,56,16,0,0,0,0,0,
948 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
949 0,0,24,60,60,60,24,24,24,0,24,24,0,0,0,0,
950 0,102,102,102,36,0,0,0,0,0,0,0,0,0,0,0,
951 0,0,0,108,108,254,108,108,108,254,108,108,0,0,0,0,
952 24,24,124,198,194,192,124,6,6,134,198,124,24,24,0,0,
953 0,0,0,0,194,198,12,24,48,96,198,134,0,0,0,0,
954 0,0,56,108,108,56,118,220,204,204,204,118,0,0,0,0,
955 0,48,48,48,96,0,0,0,0,0,0,0,0,0,0,0,
956 0,0,12,24,48,48,48,48,48,48,24,12,0,0,0,0,
957 0,0,48,24,12,12,12,12,12,12,24,48,0,0,0,0,
958 0,0,0,0,0,102,60,255,60,102,0,0,0,0,0,0,
959 0,0,0,0,0,24,24,126,24,24,0,0,0,0,0,0,
960 0,0,0,0,0,0,0,0,0,24,24,24,48,0,0,0,
961 0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,
962 0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,
963 0,0,0,0,2,6,12,24,48,96,192,128,0,0,0,0,
964 0,0,56,108,198,198,214,214,198,198,108,56,0,0,0,0,
965 0,0,24,56,120,24,24,24,24,24,24,126,0,0,0,0,
966 0,0,124,198,6,12,24,48,96,192,198,254,0,0,0,0,
967 0,0,124,198,6,6,60,6,6,6,198,124,0,0,0,0,
968 0,0,12,28,60,108,204,254,12,12,12,30,0,0,0,0,
969 0,0,254,192,192,192,252,6,6,6,198,124,0,0,0,0,
970 0,0,56,96,192,192,252,198,198,198,198,124,0,0,0,0,
971 0,0,254,198,6,6,12,24,48,48,48,48,0,0,0,0,
972 0,0,124,198,198,198,124,198,198,198,198,124,0,0,0,0,
973 0,0,124,198,198,198,126,6,6,6,12,120,0,0,0,0,
974 0,0,0,0,24,24,0,0,0,24,24,0,0,0,0,0,
975 0,0,0,0,24,24,0,0,0,24,24,48,0,0,0,0,
976 0,0,0,6,12,24,48,96,48,24,12,6,0,0,0,0,
977 0,0,0,0,0,126,0,0,126,0,0,0,0,0,0,0,
978 0,0,0,96,48,24,12,6,12,24,48,96,0,0,0,0,
979 0,0,124,198,198,12,24,24,24,0,24,24,0,0,0,0,
980 0,0,0,124,198,198,222,222,222,220,192,124,0,0,0,0,
981 0,0,16,56,108,198,198,254,198,198,198,198,0,0,0,0,
982 0,0,252,102,102,102,124,102,102,102,102,252,0,0,0,0,
983 0,0,60,102,194,192,192,192,192,194,102,60,0,0,0,0,
984 0,0,248,108,102,102,102,102,102,102,108,248,0,0,0,0,
985 0,0,254,102,98,104,120,104,96,98,102,254,0,0,0,0,
986 0,0,254,102,98,104,120,104,96,96,96,240,0,0,0,0,
987 0,0,60,102,194,192,192,222,198,198,102,58,0,0,0,0,
988 0,0,198,198,198,198,254,198,198,198,198,198,0,0,0,0,
989 0,0,60,24,24,24,24,24,24,24,24,60,0,0,0,0,
990 0,0,30,12,12,12,12,12,204,204,204,120,0,0,0,0,
991 0,0,230,102,102,108,120,120,108,102,102,230,0,0,0,0,
992 0,0,240,96,96,96,96,96,96,98,102,254,0,0,0,0,
993 0,0,198,238,254,254,214,198,198,198,198,198,0,0,0,0,
994 0,0,198,230,246,254,222,206,198,198,198,198,0,0,0,0,
995 0,0,124,198,198,198,198,198,198,198,198,124,0,0,0,0,
996 0,0,252,102,102,102,124,96,96,96,96,240,0,0,0,0,
997 0,0,124,198,198,198,198,198,198,214,222,124,12,14,0,0,
998 0,0,252,102,102,102,124,108,102,102,102,230,0,0,0,0,
999 0,0,124,198,198,96,56,12,6,198,198,124,0,0,0,0,
1000 0,0,126,126,90,24,24,24,24,24,24,60,0,0,0,0,
1001 0,0,198,198,198,198,198,198,198,198,198,124,0,0,0,0,
1002 0,0,198,198,198,198,198,198,198,108,56,16,0,0,0,0,
1003 0,0,198,198,198,198,214,214,214,254,238,108,0,0,0,0,
1004 0,0,198,198,108,124,56,56,124,108,198,198,0,0,0,0,
1005 0,0,102,102,102,102,60,24,24,24,24,60,0,0,0,0,
1006 0,0,254,198,134,12,24,48,96,194,198,254,0,0,0,0,
1007 0,0,60,48,48,48,48,48,48,48,48,60,0,0,0,0,
1008 0,0,0,128,192,224,112,56,28,14,6,2,0,0,0,0,
1009 0,0,60,12,12,12,12,12,12,12,12,60,0,0,0,0,
1010 16,56,108,198,0,0,0,0,0,0,0,0,0,0,0,0,
1011 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,
1012 0,48,24,12,0,0,0,0,0,0,0,0,0,0,0,0,
1013 0,0,0,0,0,120,12,124,204,204,204,118,0,0,0,0,
1014 0,0,224,96,96,120,108,102,102,102,102,124,0,0,0,0,
1015 0,0,0,0,0,124,198,192,192,192,198,124,0,0,0,0,
1016 0,0,28,12,12,60,108,204,204,204,204,118,0,0,0,0,
1017 0,0,0,0,0,124,198,254,192,192,198,124,0,0,0,0,
1018 0,0,28,54,50,48,120,48,48,48,48,120,0,0,0,0,
1019 0,0,0,0,0,118,204,204,204,204,204,124,12,204,120,0,
1020 0,0,224,96,96,108,118,102,102,102,102,230,0,0,0,0,
1021 0,0,24,24,0,56,24,24,24,24,24,60,0,0,0,0,
1022 0,0,6,6,0,14,6,6,6,6,6,6,102,102,60,0,
1023 0,0,224,96,96,102,108,120,120,108,102,230,0,0,0,0,
1024 0,0,56,24,24,24,24,24,24,24,24,60,0,0,0,0,
1025 0,0,0,0,0,236,254,214,214,214,214,198,0,0,0,0,
1026 0,0,0,0,0,220,102,102,102,102,102,102,0,0,0,0,
1027 0,0,0,0,0,124,198,198,198,198,198,124,0,0,0,0,
1028 0,0,0,0,0,220,102,102,102,102,102,124,96,96,240,0,
1029 0,0,0,0,0,118,204,204,204,204,204,124,12,12,30,0,
1030 0,0,0,0,0,220,118,102,96,96,96,240,0,0,0,0,
1031 0,0,0,0,0,124,198,96,56,12,198,124,0,0,0,0,
1032 0,0,16,48,48,252,48,48,48,48,54,28,0,0,0,0,
1033 0,0,0,0,0,204,204,204,204,204,204,118,0,0,0,0,
1034 0,0,0,0,0,198,198,198,198,198,108,56,0,0,0,0,
1035 0,0,0,0,0,198,198,214,214,214,254,108,0,0,0,0,
1036 0,0,0,0,0,198,108,56,56,56,108,198,0,0,0,0,
1037 0,0,0,0,0,198,198,198,198,198,198,126,6,12,248,0,
1038 0,0,0,0,0,254,204,24,48,96,198,254,0,0,0,0,
1039 0,0,14,24,24,24,112,24,24,24,24,14,0,0,0,0,
1040 0,0,24,24,24,24,24,24,24,24,24,24,0,0,0,0,
1041 0,0,112,24,24,24,14,24,24,24,24,112,0,0,0,0,
1042 0,118,220,0,0,0,0,0,0,0,0,0,0,0,0,0,
1043 0,0,0,0,16,56,108,198,198,198,254,0,0,0,0,0,
1044 0,0,60,102,194,192,192,192,192,194,102,60,24,112,0,0,
1045 0,0,204,0,0,204,204,204,204,204,204,118,0,0,0,0,
1046 0,12,24,48,0,124,198,254,192,192,198,124,0,0,0,0,
1047 0,16,56,108,0,120,12,124,204,204,204,118,0,0,0,0,
1048 0,0,204,0,0,120,12,124,204,204,204,118,0,0,0,0,
1049 0,96,48,24,0,120,12,124,204,204,204,118,0,0,0,0,
1050 0,56,108,56,0,120,12,124,204,204,204,118,0,0,0,0,
1051 0,0,0,0,0,124,198,192,192,192,198,124,24,112,0,0,
1052 0,16,56,108,0,124,198,254,192,192,198,124,0,0,0,0,
1053 0,0,198,0,0,124,198,254,192,192,198,124,0,0,0,0,
1054 0,96,48,24,0,124,198,254,192,192,198,124,0,0,0,0,
1055 0,0,102,0,0,56,24,24,24,24,24,60,0,0,0,0,
1056 0,24,60,102,0,56,24,24,24,24,24,60,0,0,0,0,
1057 0,96,48,24,0,56,24,24,24,24,24,60,0,0,0,0,
1058 0,198,0,16,56,108,198,198,254,198,198,198,0,0,0,0,
1059 56,108,56,16,56,108,198,254,198,198,198,198,0,0,0,0,
1060 12,24,0,254,102,98,104,120,104,98,102,254,0,0,0,0,
1061 0,0,0,0,0,236,54,54,126,216,216,110,0,0,0,0,
1062 0,0,62,108,204,204,254,204,204,204,204,206,0,0,0,0,
1063 0,16,56,108,0,124,198,198,198,198,198,124,0,0,0,0,
1064 0,0,198,0,0,124,198,198,198,198,198,124,0,0,0,0,
1065 0,96,48,24,0,124,198,198,198,198,198,124,0,0,0,0,
1066 0,48,120,204,0,204,204,204,204,204,204,118,0,0,0,0,
1067 0,96,48,24,0,204,204,204,204,204,204,118,0,0,0,0,
1068 0,0,198,0,0,198,198,198,198,198,198,126,6,12,120,0,
1069 0,198,0,124,198,198,198,198,198,198,198,124,0,0,0,0,
1070 0,198,0,198,198,198,198,198,198,198,198,124,0,0,0,0,
1071 0,24,24,124,198,192,192,192,198,124,24,24,0,0,0,0,
1072 0,56,108,100,96,240,96,96,96,96,230,252,0,0,0,0,
1073 0,0,102,102,60,24,126,24,126,24,24,24,0,0,0,0,
1074 0,248,204,204,248,196,204,222,204,204,204,198,0,0,0,0,
1075 0,14,27,24,24,24,126,24,24,24,216,112,0,0,0,0,
1076 0,24,48,96,0,120,12,124,204,204,204,118,0,0,0,0,
1077 0,12,24,48,0,56,24,24,24,24,24,60,0,0,0,0,
1078 0,24,48,96,0,124,198,198,198,198,198,124,0,0,0,0,
1079 0,24,48,96,0,204,204,204,204,204,204,118,0,0,0,0,
1080 0,0,118,220,0,220,102,102,102,102,102,102,0,0,0,0,
1081 118,220,0,198,230,246,254,222,206,198,198,198,0,0,0,0,
1082 0,0,60,108,108,62,0,126,0,0,0,0,0,0,0,0,
1083 0,0,56,108,108,56,0,124,0,0,0,0,0,0,0,0,
1084 0,0,48,48,0,48,48,96,192,198,198,124,0,0,0,0,
1085 0,0,0,0,0,0,254,192,192,192,192,0,0,0,0,0,
1086 0,0,0,0,0,0,254,6,6,6,6,0,0,0,0,0,
1087 0,96,224,98,102,108,24,48,96,220,134,12,24,62,0,0,
1088 0,96,224,98,102,108,24,48,102,206,154,63,6,6,0,0,
1089 0,0,24,24,0,24,24,24,60,60,60,24,0,0,0,0,
1090 0,0,0,0,0,54,108,216,108,54,0,0,0,0,0,0,
1091 0,0,0,0,0,216,108,54,108,216,0,0,0,0,0,0,
1092 17,68,17,68,17,68,17,68,17,68,17,68,17,68,17,68,
1093 85,170,85,170,85,170,85,170,85,170,85,170,85,170,85,170,
1094 221,119,221,119,221,119,221,119,221,119,221,119,221,119,221,119,
1095 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
1096 24,24,24,24,24,24,24,248,24,24,24,24,24,24,24,24,
1097 24,24,24,24,24,248,24,248,24,24,24,24,24,24,24,24,
1098 54,54,54,54,54,54,54,246,54,54,54,54,54,54,54,54,
1099 0,0,0,0,0,0,0,254,54,54,54,54,54,54,54,54,
1100 0,0,0,0,0,248,24,248,24,24,24,24,24,24,24,24,
1101 54,54,54,54,54,246,6,246,54,54,54,54,54,54,54,54,
1102 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
1103 0,0,0,0,0,254,6,246,54,54,54,54,54,54,54,54,
1104 54,54,54,54,54,246,6,254,0,0,0,0,0,0,0,0,
1105 54,54,54,54,54,54,54,254,0,0,0,0,0,0,0,0,
1106 24,24,24,24,24,248,24,248,0,0,0,0,0,0,0,0,
1107 0,0,0,0,0,0,0,248,24,24,24,24,24,24,24,24,
1108 24,24,24,24,24,24,24,31,0,0,0,0,0,0,0,0,
1109 24,24,24,24,24,24,24,255,0,0,0,0,0,0,0,0,
1110 0,0,0,0,0,0,0,255,24,24,24,24,24,24,24,24,
1111 24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,24,
1112 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,
1113 24,24,24,24,24,24,24,255,24,24,24,24,24,24,24,24,
1114 24,24,24,24,24,31,24,31,24,24,24,24,24,24,24,24,
1115 54,54,54,54,54,54,54,55,54,54,54,54,54,54,54,54,
1116 54,54,54,54,54,55,48,63,0,0,0,0,0,0,0,0,
1117 0,0,0,0,0,63,48,55,54,54,54,54,54,54,54,54,
1118 54,54,54,54,54,247,0,255,0,0,0,0,0,0,0,0,
1119 0,0,0,0,0,255,0,247,54,54,54,54,54,54,54,54,
1120 54,54,54,54,54,55,48,55,54,54,54,54,54,54,54,54,
1121 0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,
1122 54,54,54,54,54,247,0,247,54,54,54,54,54,54,54,54,
1123 24,24,24,24,24,255,0,255,0,0,0,0,0,0,0,0,
1124 54,54,54,54,54,54,54,255,0,0,0,0,0,0,0,0,
1125 0,0,0,0,0,255,0,255,24,24,24,24,24,24,24,24,
1126 0,0,0,0,0,0,0,255,54,54,54,54,54,54,54,54,
1127 54,54,54,54,54,54,54,63,0,0,0,0,0,0,0,0,
1128 24,24,24,24,24,31,24,31,0,0,0,0,0,0,0,0,
1129 0,0,0,0,0,31,24,31,24,24,24,24,24,24,24,24,
1130 0,0,0,0,0,0,0,63,54,54,54,54,54,54,54,54,
1131 54,54,54,54,54,54,54,255,54,54,54,54,54,54,54,54,
1132 24,24,24,24,24,255,24,255,24,24,24,24,24,24,24,24,
1133 24,24,24,24,24,24,24,248,0,0,0,0,0,0,0,0,
1134 0,0,0,0,0,0,0,31,24,24,24,24,24,24,24,24,
1135 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1136 0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,
1137 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
1138 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
1139 255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,
1140 0,0,0,0,0,118,220,216,216,216,220,118,0,0,0,0,
1141 0,0,120,204,204,204,216,204,198,198,198,204,0,0,0,0,
1142 0,0,254,198,198,192,192,192,192,192,192,192,0,0,0,0,
1143 0,0,0,0,0,254,108,108,108,108,108,108,0,0,0,0,
1144 0,0,254,198,96,48,24,24,48,96,198,254,0,0,0,0,
1145 0,0,0,0,0,126,216,216,216,216,216,112,0,0,0,0,
1146 0,0,0,0,0,102,102,102,102,102,102,124,96,96,192,0,
1147 0,0,0,0,118,220,24,24,24,24,24,24,0,0,0,0,
1148 0,0,126,24,60,102,102,102,102,60,24,126,0,0,0,0,
1149 0,0,56,108,198,198,254,198,198,198,108,56,0,0,0,0,
1150 0,0,56,108,198,198,198,108,108,108,108,238,0,0,0,0,
1151 0,0,30,48,24,12,62,102,102,102,102,60,0,0,0,0,
1152 0,0,0,0,0,126,219,219,219,126,0,0,0,0,0,0,
1153 0,0,0,3,6,126,219,219,243,126,96,192,0,0,0,0,
1154 0,0,28,48,96,96,124,96,96,96,48,28,0,0,0,0,
1155 0,0,0,124,198,198,198,198,198,198,198,198,0,0,0,0,
1156 0,0,0,0,254,0,0,254,0,0,254,0,0,0,0,0,
1157 0,0,0,0,24,24,126,24,24,0,0,126,0,0,0,0,
1158 0,0,0,48,24,12,6,12,24,48,0,126,0,0,0,0,
1159 0,0,0,12,24,48,96,48,24,12,0,126,0,0,0,0,
1160 0,0,14,27,27,24,24,24,24,24,24,24,24,24,24,24,
1161 24,24,24,24,24,24,24,24,24,216,216,216,112,0,0,0,
1162 0,0,0,0,0,24,0,126,0,24,0,0,0,0,0,0,
1163 0,0,0,0,0,118,220,0,118,220,0,0,0,0,0,0,
1164 0,56,108,108,56,0,0,0,0,0,0,0,0,0,0,0,
1165 0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,
1166 0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,
1167 0,15,12,12,12,12,12,236,108,108,60,28,0,0,0,0,
1168 0,108,54,54,54,54,54,0,0,0,0,0,0,0,0,0,
1169 0,60,102,12,24,50,126,0,0,0,0,0,0,0,0,0,
1170 0,0,0,0,126,126,126,126,126,126,126,0,0,0,0,0,
1171 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1174 const u8 *de_get_vga_cp437_font_ptr(void)
1176 return vga_cp437_font_data;
1179 void de_color_to_css(de_color color, char *buf, int buflen)
1181 u8 r, g, b;
1183 buf[0] = '#';
1184 r = DE_COLOR_R(color);
1185 g = DE_COLOR_G(color);
1186 b = DE_COLOR_B(color);
1188 if(r%17==0 && g%17==0 && b%17==0) {
1189 // Can use short form.
1190 buf[1] = g_hexchars[r/17];
1191 buf[2] = g_hexchars[g/17];
1192 buf[3] = g_hexchars[b/17];
1193 buf[4] = '\0';
1194 return;
1197 buf[1] = g_hexchars[r/16];
1198 buf[2] = g_hexchars[r%16];
1199 buf[3] = g_hexchars[g/16];
1200 buf[4] = g_hexchars[g%16];
1201 buf[5] = g_hexchars[b/16];
1202 buf[6] = g_hexchars[b%16];
1203 buf[7] = '\0';
1206 u8 de_sample_nbit_to_8bit(i64 n, unsigned int x)
1208 unsigned int maxval;
1210 if(x==0) return 0;
1211 if(n<1 || n>16) return 0;
1212 maxval = (1<<n)-1;
1213 if(x>=maxval) return 255;
1214 return (u8)(0.5+((((double)x)/(double)maxval)*255.0));
1217 u8 de_scale_63_to_255(u8 x)
1219 if(x>=63) return 255;
1220 return (u8)(0.5+(((double)x)*(255.0/63.0)));
1223 u8 de_scale_1000_to_255(i64 x)
1225 if(x>=1000) return 255;
1226 if(x<=0) return 0;
1227 return (u8)(0.5+(((double)x)*(255.0/1000.0)));
1230 u8 de_scale_n_to_255(i64 n, i64 x)
1232 if(x>=n) return 255;
1233 if(x<=0) return 0;
1234 return (u8)(0.5+(((double)x)*(255.0/(double)n)));
1237 void de_scale_n_to_16bit(int n, int x_in, u8 *x_out_hi, u8 *x_out_lo)
1239 double tmp1;
1240 UI tmp2;
1242 if(x_in<0) x_in = 0;
1243 if(x_in>n) x_in = n;
1244 tmp1 = ((double)x_in / (double)n) * 65535.0;
1245 tmp2 = (UI)(tmp1 + 0.5);
1246 *x_out_hi = (tmp2 & 0xff00)>>8;
1247 *x_out_lo = (tmp2 & 0xff);
1250 de_color de_rgb565_to_888(u32 x)
1252 u8 cr, cg, cb;
1253 cr = (u8)(x>>11);
1254 cg = (u8)((x>>5)&0x3f);
1255 cb = (u8)(x&0x1f);
1256 cr = (u8)(0.5+((double)cr)*(255.0/31.0));
1257 cg = (u8)(0.5+((double)cg)*(255.0/63.0));
1258 cb = (u8)(0.5+((double)cb)*(255.0/31.0));
1259 return DE_MAKE_RGB(cr, cg, cb);
1262 de_color de_bgr555_to_888(u32 x)
1264 u8 cr, cg, cb;
1265 cb = (u8)((x>>10)&0x1f);
1266 cg = (u8)((x>>5)&0x1f);
1267 cr = (u8)(x&0x1f);
1268 cb = (u8)(0.5+((double)cb)*(255.0/31.0));
1269 cg = (u8)(0.5+((double)cg)*(255.0/31.0));
1270 cr = (u8)(0.5+((double)cr)*(255.0/31.0));
1271 return DE_MAKE_RGB(cr, cg, cb);
1274 de_color de_rgb555_to_888(u32 x)
1276 u8 cr, cg, cb;
1277 cr = (u8)((x>>10)&0x1f);
1278 cg = (u8)((x>>5)&0x1f);
1279 cb = (u8)(x&0x1f);
1280 cr = (u8)(0.5+((double)cr)*(255.0/31.0));
1281 cg = (u8)(0.5+((double)cg)*(255.0/31.0));
1282 cb = (u8)(0.5+((double)cb)*(255.0/31.0));
1283 return DE_MAKE_RGB(cr, cg, cb);
1286 char de_byte_to_printable_char(u8 b)
1288 if(b>=32 && b<=126) return (char)b;
1289 return '_';
1292 // This function has been largely replaced by other functions, and should
1293 // rarely be used. See the comment in the header file.
1294 // s1 is not NUL terminated, but s2 will be.
1295 // s2_size includes the NUL terminator.
1296 // Supported conv_flags: DE_CONVFLAG_STOP_AT_NUL, DE_CONVFLAG_ALLOW_HL
1297 // src_encoding: Only DE_ENCODING_ASCII is supported.
1298 void de_bytes_to_printable_sz(const u8 *s1, i64 s1_len,
1299 char *s2, i64 s2_size, unsigned int conv_flags, de_ext_encoding src_ee)
1301 i64 i;
1302 i64 s2_pos = 0;
1303 de_ext_encoding src_encoding = DE_EXTENC_GET_BASE(src_ee);
1305 if(src_encoding!=DE_ENCODING_ASCII) {
1306 s2[0] = '\0';
1307 return;
1310 for(i=0; i<s1_len; i++) {
1311 int is_printable = 0;
1313 if(s1[i]=='\0' && (conv_flags & DE_CONVFLAG_STOP_AT_NUL)) {
1314 break;
1317 if(s1[i]>=32 && s1[i]<=126) {
1318 is_printable = 1;
1321 if(is_printable) {
1322 if(s2_pos < s2_size-1) {
1323 s2[s2_pos++] = (char)s1[i];
1326 else if(conv_flags & DE_CONVFLAG_ALLOW_HL) {
1327 if(s2_pos < s2_size-6) {
1328 s2[s2_pos++] = 0x01; // DE_CODEPOINT_HL
1329 s2[s2_pos++] = '<';
1330 s2[s2_pos++] = de_get_hexcharUC((int)(s1[i]/16));
1331 s2[s2_pos++] = de_get_hexcharUC((int)(s1[i]%16));
1332 s2[s2_pos++] = '>';
1333 s2[s2_pos++] = 0x02; // DE_CODEPOINT_UNHL
1336 else {
1337 if(s2_pos < s2_size-1) {
1338 s2[s2_pos++] = '_';
1343 s2[s2_pos] = '\0';
1346 void de_write_codepoint_to_html(deark *c, dbuf *f, de_rune ch)
1348 int e; // How to encode this codepoint
1350 if(ch<0 || ch>0x10ffff || ch==DE_CODEPOINT_INVALID) ch=0xfffd;
1352 if(ch=='&' || ch=='<' || ch=='>') {
1353 e = 1; // HTML entity
1355 else if(ch>=32 && ch<=126) {
1356 e = 2; // raw byte
1358 else if(c->ascii_html) {
1359 e = 1; // HTML entity
1361 else {
1362 e = 3; // UTF-8
1365 if(e==2) {
1366 dbuf_writebyte(f, (u8)ch);
1368 else if(e==3) {
1369 dbuf_write_uchar_as_utf8(f, ch);
1371 else {
1372 dbuf_printf(f, "&#%d;", (int)ch);
1376 struct de_encmap_item {
1377 unsigned int reserved;
1378 int n;
1379 const char *encname;
1382 static const struct de_encmap_item de_encmap_arr[] = {
1383 { 0x01, DE_ENCODING_ASCII, "ascii" },
1384 { 0x01, DE_ENCODING_UTF8, "utf8" },
1385 { 0x01, DE_ENCODING_LATIN1, "latin1" },
1386 { 0x01, DE_ENCODING_LATIN2, "latin2" },
1387 { 0x01, DE_ENCODING_CP437, "cp437" },
1388 { 0x01, DE_ENCODING_WINDOWS1250, "windows1250" },
1389 { 0x01, DE_ENCODING_WINDOWS1251, "windows1251" },
1390 { 0x01, DE_ENCODING_WINDOWS1252, "windows1252" },
1391 { 0x01, DE_ENCODING_WINDOWS1253, "windows1253" },
1392 { 0x01, DE_ENCODING_WINDOWS1254, "windows1254" },
1393 { 0x01, DE_ENCODING_WINDOWS874, "windows874" },
1394 { 0x01, DE_ENCODING_MACROMAN, "macroman" },
1395 { 0x01, DE_ENCODING_PALM, "palm" },
1396 { 0x01, DE_ENCODING_RISCOS, "riscos" },
1397 { 0x01, DE_ENCODING_PETSCII, "petscii" },
1398 { 0x01, DE_ENCODING_ATARIST, "atarist" },
1399 { 0x01, DE_ENCODING_APPLEII, "appleii" },
1400 { 0x01, DE_ENCODING_ROT13, "rot13" },
1401 { 0x01, DE_ENCODING_UTF16BE, "utf16be" },
1402 { 0x01, DE_ENCODING_UTF16LE, "utf16le" }
1405 de_encoding de_encoding_name_to_code(const char *encname)
1407 size_t k;
1409 for(k=0; k<DE_ARRAYCOUNT(de_encmap_arr); k++) {
1410 if(!de_strcasecmp(encname, de_encmap_arr[k].encname)) {
1411 return de_encmap_arr[k].n;
1414 return DE_ENCODING_UNKNOWN;
1417 struct de_encmapwin_item {
1418 unsigned int flags; // 0x1=supported
1419 int wincodepage;
1420 de_encoding enc;
1421 const char *encname;
1422 const char *encname_note;
1425 static const struct de_encmapwin_item de_encmapwin_arr[] = {
1426 { 0x01, 1200, DE_ENCODING_UTF16LE, "UTF-16LE", NULL },
1427 { 0x01, 1250, DE_ENCODING_WINDOWS1250, "Windows-1250", "Central/Eastern European" },
1428 { 0x01, 1251, DE_ENCODING_WINDOWS1251, "Windows-1251", "Cyrillic" },
1429 { 0x01, 1252, DE_ENCODING_WINDOWS1252, "Windows-1252", NULL },
1430 { 0x01, 1253, DE_ENCODING_WINDOWS1253, "Windows-1253", "Greek" },
1431 { 0x01, 1254, DE_ENCODING_WINDOWS1254, "Windows-1254", "Turkish" },
1432 { 0x01, 10000, DE_ENCODING_MACROMAN, "MacRoman", NULL },
1433 { 0x01, 65001, DE_ENCODING_UTF8, "UTF-8", NULL },
1434 { 0x01, 874, DE_ENCODING_WINDOWS874, "Windows-874", "Thai" },
1435 { 0x00, 932, DE_ENCODING_UNKNOWN, "Windows-932", "Japanese" },
1436 { 0x00, 936, DE_ENCODING_UNKNOWN, "Windows-936", "simplified Chinese" },
1437 { 0x00, 1255, DE_ENCODING_UNKNOWN, "Windows-1255", "Hebrew" },
1438 { 0x00, 1256, DE_ENCODING_UNKNOWN, "Windows-1256", "Arabic" },
1439 { 0x00, 1257, DE_ENCODING_UNKNOWN, "Windows-1257", "Baltic" },
1440 { 0x00, 1258, DE_ENCODING_UNKNOWN, "Windows-1258", "Vietnamese" }
1443 // Returns a DE_ENCODING_* code.
1444 // Returns DE_ENCODING_UNKNOWN if unsupported or unknown.
1445 // encname can be NULL.
1446 // flags:
1447 // 0x1: If encoding is known but unsupported, append "(unsupported)" to the
1448 // description.
1449 de_encoding de_windows_codepage_to_encoding(deark *c, int wincodepage,
1450 char *encname, size_t encname_len, unsigned int flags)
1452 size_t k;
1453 const struct de_encmapwin_item *cpinfo = NULL;
1455 for(k=0; k<DE_ARRAYCOUNT(de_encmapwin_arr); k++) {
1456 if(de_encmapwin_arr[k].wincodepage == wincodepage) {
1457 cpinfo = &de_encmapwin_arr[k];
1458 break;
1462 if(cpinfo) {
1463 // Code page is known, though not necessarily supported.
1464 if(encname) {
1465 char note_tmp[80];
1466 if(cpinfo->encname_note) {
1467 de_snprintf(note_tmp, sizeof(note_tmp), " (%s)", cpinfo->encname_note);
1469 else {
1470 note_tmp[0] = '\0';
1472 de_snprintf(encname, encname_len, "%s%s%s", cpinfo->encname, note_tmp,
1473 ((cpinfo->flags&0x1)==0 && (flags&0x1)!=0)?" (unsupported)":"");
1475 return (cpinfo->flags&0x1) ? cpinfo->enc : DE_ENCODING_UNKNOWN;
1478 if(encname) {
1479 de_strlcpy(encname, "?", encname_len);
1481 return DE_ENCODING_UNKNOWN;
1484 void de_decode_base16(deark *c, dbuf *inf, i64 pos1, i64 len,
1485 dbuf *outf, unsigned int flags)
1487 i64 pos = pos1;
1488 u8 b;
1489 int bad_warned = 0;
1490 struct base16_ctx {
1491 int cbuf_count;
1492 u8 cbuf[5];
1494 struct base16_ctx *d = NULL;
1496 d = de_malloc(c, sizeof(struct base16_ctx));
1497 pos = pos1;
1498 d->cbuf_count = 0;
1499 while(pos<pos1+len) {
1500 b = dbuf_getbyte_p(inf, &pos);
1501 if(b>='0' && b<='9') {
1502 d->cbuf[d->cbuf_count++] = b-48;
1504 else if(b>='A' && b<='F') {
1505 d->cbuf[d->cbuf_count++] = b-55;
1507 else if(b>='a' && b<='f') {
1508 d->cbuf[d->cbuf_count++] = b-87;
1510 else if(b==9 || b==10 || b==13 || b==32) {
1511 ; // ignore whitespace
1513 else {
1514 if(!bad_warned) {
1515 de_warn(c, "Bad hex character(s) found (offset %d)", (int)pos);
1516 bad_warned = 1;
1520 if(d->cbuf_count>=2) {
1521 dbuf_writebyte(outf, (d->cbuf[0]<<4)|(d->cbuf[1]));
1522 d->cbuf_count=0;
1526 if(d->cbuf_count>0) {
1527 de_warn(c, "Unexpected end of hex data");
1530 de_free(c, d);