diff --git a/README.md b/README.md index 6b6b821..695e312 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | ZLIB | `application/zlib` | [`patterns/zlib.hexpat`](patterns/zlib.hexpat) | ZLIB compressed data format | | ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format | | MOD | `3d-model/mod` | [`patterns/DMC3HD-Mod.hexpat`](patterns/dmc3_hd_mod.hexpat) | 3D Model files used in Devil May Cry 3 HD Collection | +| CBM BASIC | | [`commodore_basic.hexpat`](patterns/commodore_basic.hexpat) | Commodore BASIC | ### Scripts diff --git a/patterns/commodore_basic.hexpat b/patterns/commodore_basic.hexpat new file mode 100644 index 0000000..5f4cf02 --- /dev/null +++ b/patterns/commodore_basic.hexpat @@ -0,0 +1,158 @@ +#pragma description Commodore BASIC +#pragma author Stephen Hewitt + +import std.io; +import std.mem; + +bool in_quotes = false; + +le u16 LoadAddress @0 [[color("ff0000")]]; + +fn formatll(u16 offset) { + if (offset&0xff00 == 0) + return "No next line"; + u16 fo = offset-LoadAddress+2; + return std::format("Next line: ${:04X} (offset ${:04X})", offset, fo); +}; + +enum Token : u8 { + END = 0x80, + FOR = 0x81, + NEXT = 0x82, + DATA = 0x83, + INPUT_ = 0x84, + INPUT = 0x85, + DIM = 0x86, + READ = 0x87, + LET = 0x88, + GOTO = 0x89, + RUN = 0x8a, + IF = 0x8b, + RESTORE = 0x8c, + GOSUB = 0x8d, + RETURN = 0x8e, + REM = 0x8f, + STOP = 0x90, + ON = 0x91, + WAIT = 0x92, + LOAD = 0x93, + SAVE = 0x94, + VERIFY = 0x95, + DEF = 0x96, + POKE = 0x97, + PRINT_ = 0x98, + PRINT = 0x99, + CONT = 0x9a, + LIST = 0x9b, + CLR = 0x9c, + CMD = 0x9d, + SYS = 0x9e, + OPEN = 0x9f, + CLOSE = 0xa0, + GET = 0xa1, + NEW = 0xa2, + TAB_ = 0xa3, + TO = 0xa4, + FN = 0xa5, + SPC_ = 0xa6, + THEN = 0xa7, + NOT = 0xa8, + STEP = 0xa9, + PLUS_ = 0xaa, + MINUS_ = 0xab, + TIMES_ = 0xac, + DIVIDE_ = 0xad, + POW_ = 0xae, + AND = 0xaf, + OR = 0xb0, + GT_ = 0xb1, + EQ_ = 0xb2, + LT_ = 0xb3, + SGN = 0xb4, + INT = 0xb5, + ABS = 0xb6, + USR = 0xb7, + FRE = 0xb7, + POS = 0xb9, + SQR = 0xba, + RND = 0xbb, + LOG = 0xbc, + EXP = 0xbd, + COS = 0xbe, + SIN = 0xbf, + TAN = 0xc0, + ATN = 0xc1, + PEEK = 0xc2, + LEN = 0xc3, + STR_ = 0xc4, + VAL = 0xc5, + ASC = 0xc6, + CHR_ = 0xc7, + LEFT_ = 0xc8, + RIGHT_ = 0xc9, + MID_ = 0xca, + PI_ = 0xff +} [[format("formate")]]; + +// Can't seem to put attributes on enum members. Hack around it. +fn formate(Token t) { + match (t) { + (Token::INPUT_): return "INPUT#"; // $84 + (Token::PRINT_): return "PRINT#"; // $98 + (Token::TAB_): return "TAB("; // $a3 + (Token::SPC_): return "SPC("; // $a6 + (Token::PLUS_): return "+"; // $aa + (Token::MINUS_): return "-"; // $ab + (Token::TIMES_): return "*"; // $ac + (Token::DIVIDE_): return "/"; // $ad + //(Token::POW_): return "↑"; // $ae + (Token::GT_): return ">"; // $b1 + (Token::EQ_): return "="; // $b2 + (Token::LT_): return "<"; // $b3 + (Token::STR_): return "STR$"; // $c4 + (Token::CHR_): return "CHR$"; // $c7 + (Token::LEFT_): return "LEFT$"; // $c8 + (Token::RIGHT_): return "RIGHT$"; // $c9 + (Token::MID_): return "MID$"; // $ca + //(Token::PI_): return "π"; // $ff + } + + return t; +}; + +fn NotZero() { + u8 b = std::mem::read_unsigned($, 1); + return b!=0; +}; + +fn IsToken() { + u8 b = std::mem::read_unsigned($, 1); + return b&0x80!=0; +}; + +fn IsPETSCII() { + u8 b = std::mem::read_unsigned($, 1); + if (b == '"') + in_quotes = !in_quotes; + return (b!=0) && (in_quotes || (b&0x80)==0); +}; + +struct LineSegment +{ + Token tokens[while(IsToken())] [[color("a040a0")]]; + char petscii[while(IsPETSCII())] [[color("a0a0a0")]]; +}; + +struct Line +{ + in_quotes = false; + + u16 next [[color("8080ff"), format("formatll")]]; + if (next&0xff00 == 0) + break; + le u16 line_number [[color("00FF00")]]; + LineSegment contents[while(NotZero())]; + u8 eol [[color("00ffff")]]; +}; + +Line Lines[while(!std::mem::eof())] @ 2; \ No newline at end of file diff --git a/tests/patterns/test_data/commodore_basic.hexpat.prg b/tests/patterns/test_data/commodore_basic.hexpat.prg new file mode 100644 index 0000000..9ad2826 Binary files /dev/null and b/tests/patterns/test_data/commodore_basic.hexpat.prg differ