[8cfde7e] | 1 | #include <map>
|
---|
| 2 | #include <vector>
|
---|
| 3 | #include <stdint.h>
|
---|
| 4 |
|
---|
| 5 | #include <arpa/inet.h>
|
---|
| 6 |
|
---|
| 7 | struct __attribute__((packed)) BAS_Data {
|
---|
| 8 | uint8_t type;
|
---|
| 9 | uint16_t length;
|
---|
| 10 | std::vector<uint8_t> data;
|
---|
| 11 | };
|
---|
| 12 |
|
---|
| 13 | bool BAS_ReadChunk(FILE* in, BAS_Data& out) {
|
---|
| 14 | // Read the chunk header
|
---|
| 15 | int value = fread(&out, 3, 1, in);
|
---|
| 16 | if (value == 0)
|
---|
| 17 | return false;
|
---|
| 18 |
|
---|
| 19 | // 6809 is little endian, take that into account...
|
---|
| 20 | out.length = ntohs(out.length);
|
---|
| 21 |
|
---|
| 22 | // Resize the data member to the proper size and read the data to it.
|
---|
| 23 | out.data.reserve(out.length);
|
---|
| 24 | fread(&out.data[0], out.length, 1, in);
|
---|
| 25 |
|
---|
| 26 | return true;
|
---|
| 27 | };
|
---|
| 28 |
|
---|
| 29 | struct __attribute__((packed)) BAS_Line {
|
---|
| 30 | uint16_t offset;
|
---|
| 31 | uint16_t number;
|
---|
| 32 | uint8_t data[];
|
---|
| 33 | };
|
---|
| 34 |
|
---|
| 35 | void BAStoASCII(BAS_Data& data)
|
---|
| 36 | {
|
---|
| 37 | std::map<uint8_t, const char*> Opcodes;
|
---|
| 38 | std::map<uint8_t, const char*> Functions;
|
---|
| 39 |
|
---|
| 40 | // FLOW CONTROL
|
---|
| 41 | Opcodes[0x80] = "END";
|
---|
| 42 | Opcodes[0x81] = "FOR";
|
---|
| 43 | Opcodes[0x82] = "NEXT";
|
---|
| 44 | Opcodes[0x83] = "DATA";
|
---|
| 45 | Opcodes[0x84] = "DIM";
|
---|
| 46 | Opcodes[0x85] = "READ";
|
---|
| 47 | //
|
---|
| 48 | Opcodes[0x87] = "GO";
|
---|
| 49 | //
|
---|
| 50 | Opcodes[0x89] = "IF";
|
---|
| 51 | Opcodes[0x8A] = "RESTORE";
|
---|
| 52 | Opcodes[0x8B] = "RETURN";
|
---|
| 53 | //
|
---|
| 54 | Opcodes[0x93] = "DEFINT";
|
---|
| 55 | // CURSOR
|
---|
| 56 | Opcodes[0x9C] = "LOCATE";
|
---|
| 57 | Opcodes[0x9D] = "CLS";
|
---|
| 58 | // MACHINE
|
---|
| 59 | Opcodes[0xA2] = "EXEC";
|
---|
| 60 | // DISPLAY
|
---|
| 61 | Opcodes[0xA4] = "COLOR";
|
---|
| 62 | Opcodes[0xA5] = "LINE";
|
---|
| 63 | Opcodes[0xA6] = "BOX";
|
---|
| 64 | //
|
---|
| 65 | Opcodes[0xA8] = "ATTRB";
|
---|
| 66 | Opcodes[0xA9] = "DEF"; // FIXME DEFGR$
|
---|
| 67 | Opcodes[0xAA] = "POKE";
|
---|
| 68 | Opcodes[0xAB] = "PRINT";
|
---|
| 69 | //
|
---|
| 70 | Opcodes[0xAE] = "CLEAR";
|
---|
| 71 |
|
---|
| 72 | // SOUND
|
---|
| 73 | Opcodes[0xB9] = "PLAY";
|
---|
| 74 |
|
---|
| 75 | // SUB-CODES
|
---|
| 76 | Opcodes[0xBB] = "TO";
|
---|
| 77 | Opcodes[0xBC] = "SUB";
|
---|
| 78 | //
|
---|
| 79 | Opcodes[0xBF] = "USING";
|
---|
| 80 | //
|
---|
| 81 | Opcodes[0xC4] = "THEN";
|
---|
| 82 | //
|
---|
| 83 | Opcodes[0xC6] = "STEP";
|
---|
| 84 |
|
---|
| 85 | // OPERATORS
|
---|
| 86 | Opcodes[0xC7] = "+";
|
---|
| 87 | Opcodes[0xC8] = "-";
|
---|
| 88 | Opcodes[0xC9] = "*";
|
---|
| 89 | Opcodes[0xCA] = "/";
|
---|
| 90 | //
|
---|
| 91 | Opcodes[0xCC] = "AND";
|
---|
| 92 | Opcodes[0xCD] = "OR";
|
---|
| 93 | //
|
---|
| 94 | Opcodes[0xD3] = ">";
|
---|
| 95 | Opcodes[0xD4] = "=";
|
---|
| 96 | Opcodes[0xD5] = "<";
|
---|
| 97 |
|
---|
| 98 |
|
---|
| 99 | Functions[0x81] = "INT";
|
---|
| 100 | Functions[0x82] = "ABS";
|
---|
| 101 | Functions[0x8B] = "LEN";
|
---|
| 102 | Functions[0x8E] = "ASC";
|
---|
| 103 | Functions[0x8F] = "CHR$";
|
---|
| 104 | Functions[0x99] = "GR$";
|
---|
| 105 | Functions[0x9A] = "LEFT$";
|
---|
| 106 | Functions[0x9C] = "MID$";
|
---|
| 107 | Functions[0x9F] = "RND";
|
---|
| 108 | Functions[0xA0] = "INKEY$";
|
---|
| 109 | Functions[0xA1] = "INPUT$";
|
---|
| 110 | Functions[0xA4] = "SCREEN";
|
---|
| 111 |
|
---|
| 112 | /* ################################ */
|
---|
| 113 |
|
---|
| 114 | BAS_Line* currentLine;
|
---|
| 115 | currentLine = (BAS_Line*)&data.data[0];
|
---|
| 116 |
|
---|
| 117 | bool func = false;
|
---|
| 118 | while(currentLine->offset) {
|
---|
| 119 | // Endianness fixup
|
---|
| 120 | currentLine->offset = ntohs(currentLine->offset);
|
---|
| 121 | currentLine->number = ntohs(currentLine->number);
|
---|
| 122 |
|
---|
| 123 | printf("%d ", currentLine->number);
|
---|
| 124 |
|
---|
| 125 | for (int i = 0; currentLine->data[i]; i++) {
|
---|
| 126 | uint8_t c = currentLine->data[i];
|
---|
| 127 | if (c < 128 && isprint(c))
|
---|
| 128 | putchar(c);
|
---|
| 129 | else if (c == 0xFF) {
|
---|
| 130 | func = true;
|
---|
| 131 | continue;
|
---|
| 132 | } else if ((!func) && (Opcodes.find(c) != Opcodes.end()))
|
---|
| 133 | printf("\x1B[31m%s\x1B[0m", Opcodes[c]);
|
---|
| 134 | else if (func && (Functions.find(c) != Functions.end()))
|
---|
| 135 | printf("\x1B[32m%s\x1B[0m", Functions[c]);
|
---|
| 136 | else {
|
---|
| 137 | printf("\n*** UNKNOWN %s %x ***\n", func?"FUNCTION":"OPCODE", c);
|
---|
| 138 | for (int k = 0; currentLine->data[k]; k++)
|
---|
| 139 | printf("%02X ", currentLine->data[k]);
|
---|
| 140 | puts("");
|
---|
| 141 | exit(EXIT_FAILURE);
|
---|
| 142 | }
|
---|
| 143 | func = false;
|
---|
| 144 | }
|
---|
| 145 | currentLine = (BAS_Line*)&data.data[currentLine->offset - 0x25A4];
|
---|
| 146 | puts("");
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | int main(int argc, char* argv[])
|
---|
| 151 | {
|
---|
| 152 | if (argc < 2)
|
---|
| 153 | {
|
---|
| 154 | fprintf(stderr, "%s file.bas\n", argv[0]);
|
---|
| 155 | return 1;
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | FILE* in;
|
---|
| 159 | BAS_Data h;
|
---|
| 160 |
|
---|
| 161 | in = fopen(argv[1], "rb");
|
---|
| 162 |
|
---|
| 163 | while(BAS_ReadChunk(in, h))
|
---|
| 164 | {
|
---|
| 165 | BAStoASCII(h);
|
---|
| 166 | };
|
---|
| 167 |
|
---|
| 168 | }
|
---|