|
| 1 | +#include <stdio.h> |
| 2 | +#include <stdint.h> |
| 3 | + |
| 4 | +static const char *petscii_to_utf8[256] = { |
| 5 | + /* 0x00 - 0x0F */ |
| 6 | + " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\n", " ", " ", "\r", " ", " ", |
| 7 | + |
| 8 | + /* 0x10 - 0x1F */ |
| 9 | + " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", |
| 10 | + |
| 11 | + /* 0x20 - 0x2F */ |
| 12 | + " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", |
| 13 | + |
| 14 | + /* 0x30 - 0x3F */ |
| 15 | + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", |
| 16 | + |
| 17 | + /* 0x40 - 0x4F */ |
| 18 | + "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", |
| 19 | + |
| 20 | + /* 0x50 - 0x5F */ |
| 21 | + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "£", "]", "↑", "←", |
| 22 | + |
| 23 | + /* 0x60 - 0x6F */ |
| 24 | + "─", "♠", "│", "─", "🭰", "🭯", "🭲", "🭱", "🭴", "╮", "╰", "╯", "🭵", "╲", "╱", "🭶", |
| 25 | + |
| 26 | + /* 0x70 - 0x7F */ |
| 27 | + "🭷", "●", "🭸", "♥", "🭹", "╭", "╳", "○", "♣", "🭺", "♦", "┼", "🭻", "│", "π", "◥", |
| 28 | + |
| 29 | + /* 0x80 - 0x8F reversed/control in real PETSCII, approximated here */ |
| 30 | + " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "\n", " ", " ", "\r", " ", " ", |
| 31 | + |
| 32 | + /* 0x90 - 0x9F */ |
| 33 | + " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", |
| 34 | + |
| 35 | + /* 0xA0 - 0xAF */ |
| 36 | + " ", "▌", "▄", "▔", "▁", "▏", "▎", "▕", "🮂", "🮃", "🭿", "🮌", "🮊", "🮈", "🮄", "▖", |
| 37 | + |
| 38 | + /* 0xB0 - 0xBF */ |
| 39 | + "▗", "▘", "▝", "▚", "▞", "▙", "▛", "▜", "▟", "🮅", "🮆", "🮇", "🮉", "🮋", "🮍", "█", |
| 40 | + |
| 41 | + /* 0xC0 - 0xCF lowercase/graphics bank depending on mode */ |
| 42 | + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", |
| 43 | + |
| 44 | + /* 0xD0 - 0xDF */ |
| 45 | + "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "┌", "🮎", "│", "🮏", "🮐", "🮑", |
| 46 | + |
| 47 | + /* 0xE0 - 0xEF */ |
| 48 | + " ", "♠", "│", "─", "🭰", "🭯", "🭲", "🭱", "🭴", "╮", "╰", "╯", "🭵", "╲", "╱", "🭶", |
| 49 | + |
| 50 | + /* 0xF0 - 0xFF */ |
| 51 | + "🭷", "●", "🭸", "♥", "🭹", "╭", "╳", "○", "♣", "🭺", "♦", "┼", "🭻", "│", "π", "█" |
| 52 | +}; |
| 53 | + |
| 54 | +static const char *petscii_safe_to_utf8[256] = { |
| 55 | + [0 ... 255] = "?", |
| 56 | + |
| 57 | + [' '] = " ", |
| 58 | + ['!'] = "!", |
| 59 | + ['"'] = "\"", |
| 60 | + ['#'] = "#", |
| 61 | + ['$'] = "$", |
| 62 | + ['%'] = "%", |
| 63 | + ['&'] = "&", |
| 64 | + ['\''] = "'", |
| 65 | + ['('] = "(", |
| 66 | + [')'] = ")", |
| 67 | + ['*'] = "*", |
| 68 | + ['+'] = "+", |
| 69 | + [','] = ",", |
| 70 | + ['-'] = "-", |
| 71 | + ['.'] = ".", |
| 72 | + ['/'] = "/", |
| 73 | + |
| 74 | + ['0'] = "0", ['1'] = "1", ['2'] = "2", ['3'] = "3", ['4'] = "4", |
| 75 | + ['5'] = "5", ['6'] = "6", ['7'] = "7", ['8'] = "8", ['9'] = "9", |
| 76 | + |
| 77 | + [0x3A] = ":", [0x3B] = ";", [0x3C] = "<", [0x3D] = "=", [0x3E] = ">", [0x3F] = "?", |
| 78 | + |
| 79 | + [0x40] = "@", |
| 80 | + [0x41] = "A", [0x42] = "B", [0x43] = "C", [0x44] = "D", [0x45] = "E", |
| 81 | + [0x46] = "F", [0x47] = "G", [0x48] = "H", [0x49] = "I", [0x4A] = "J", |
| 82 | + [0x4B] = "K", [0x4C] = "L", [0x4D] = "M", [0x4E] = "N", [0x4F] = "O", |
| 83 | + [0x50] = "P", [0x51] = "Q", [0x52] = "R", [0x53] = "S", [0x54] = "T", |
| 84 | + [0x55] = "U", [0x56] = "V", [0x57] = "W", [0x58] = "X", [0x59] = "Y", [0x5A] = "Z", |
| 85 | + |
| 86 | + [0x5B] = "[", |
| 87 | + [0x5C] = "£", |
| 88 | + [0x5D] = "]", |
| 89 | + [0x5E] = "↑", |
| 90 | + [0x5F] = "←", |
| 91 | + |
| 92 | + [0x60] = "-", |
| 93 | + [0x61] = "♠", |
| 94 | + [0x62] = "|", |
| 95 | + [0x63] = "-", |
| 96 | + [0x6A] = "+", |
| 97 | + [0x6B] = "+", |
| 98 | + [0x6D] = "\\", |
| 99 | + [0x6E] = "/", |
| 100 | + [0x71] = "●", |
| 101 | + [0x73] = "♥", |
| 102 | + [0x75] = "+", |
| 103 | + [0x76] = "x", |
| 104 | + [0x77] = "○", |
| 105 | + [0x78] = "♣", |
| 106 | + [0x7A] = "♦", |
| 107 | + [0x7B] = "+", |
| 108 | + [0x7C] = "+", |
| 109 | + [0x7D] = "|", |
| 110 | + [0x7E] = "π", |
| 111 | + [0x7F] = "#", |
| 112 | + |
| 113 | + [0xA1] = "▌", |
| 114 | + [0xA2] = "▄", |
| 115 | + [0xA3] = "▀", |
| 116 | + [0xAF] = "▖", |
| 117 | + [0xB0] = "▗", |
| 118 | + [0xB1] = "▘", |
| 119 | + [0xB2] = "▝", |
| 120 | + [0xB5] = "▙", |
| 121 | + [0xB6] = "▛", |
| 122 | + [0xB7] = "▜", |
| 123 | + [0xB8] = "▟", |
| 124 | + [0xBF] = "█", |
| 125 | + |
| 126 | + [0xC1] = "a", [0xC2] = "b", [0xC3] = "c", [0xC4] = "d", [0xC5] = "e", |
| 127 | + [0xC6] = "f", [0xC7] = "g", [0xC8] = "h", [0xC9] = "i", [0xCA] = "j", |
| 128 | + [0xCB] = "k", [0xCC] = "l", [0xCD] = "m", [0xCE] = "n", [0xCF] = "o", |
| 129 | + [0xD0] = "p", [0xD1] = "q", [0xD2] = "r", [0xD3] = "s", [0xD4] = "t", |
| 130 | + [0xD5] = "u", [0xD6] = "v", [0xD7] = "w", [0xD8] = "x", [0xD9] = "y", [0xDA] = "z", |
| 131 | + |
| 132 | + [0xDB] = "+", |
| 133 | + [0xDC] = "+", |
| 134 | + [0xDD] = "|", |
| 135 | + [0xDE] = "+", |
| 136 | + [0xDF] = "#" |
| 137 | +}; |
| 138 | + |
| 139 | +const char *petscii_char_to_utf8(uint8_t c) { |
| 140 | + const char *s = petscii_safe_to_utf8[c]; |
| 141 | + return s ? s : "?"; |
| 142 | +} |
| 143 | + |
| 144 | +void print_petscii(const uint8_t *data, size_t len) { |
| 145 | + for (size_t i = 0; i < len; i++) { |
| 146 | + fputs(petscii_char_to_utf8(data[i]), stdout); |
| 147 | + } |
| 148 | +} |
| 149 | + |
| 150 | +int main(void) { |
| 151 | + uint8_t demo[] = { |
| 152 | + 0x48, 0x45, 0x4C, 0x4C, 0x4F, 0x20, |
| 153 | + 0x61, 0x20, 0x73, 0x20, 0x7A, 0x20, |
| 154 | + 0x5E, 0x20, 0x5F, 0x0D |
| 155 | + }; |
| 156 | + |
| 157 | + print_petscii(demo, sizeof(demo)); |
| 158 | + printf(petscii_char_to_utf8(65)); |
| 159 | + return 0; |
| 160 | +} |
| 161 | + |
0 commit comments