Files
MZBAS/ANALYSIS.md
T
2026-10-08 16:52:36 +03:00

5.3 KiB
Raw Blame History

Ghidra project analysis — Orion-MSXBASIC / MZBAS$.BRU

Program: MZBAS$ — MSX BASIC for the Orion-128 (Z80), tape image loaded at 0x0000. Banner in the image: MSX system / version 1.2/M / MSX BASIC / Copyright 1983,1993 by Microsoft,OBERON Inc i.e. the MSX BASIC 2.1 codebase ported to Orion-128 (64K RAM, Z80).

Source file format (MZBAS$.BRU)

Cassette-style image, 33664 (0x8380) bytes:

Offset Size Content
0x0000 8 name MZBAS$··
0x0008 2 load address 0x0000 (LE)
0x000A 2 length field 0x8300 (LE; payload is actually 0x8370)
0x000C 4 unknown/reserved (00 49 53 D4)
0x0010 0x8370 program image → ram:0x0000–0x836F

Mapping verified: file offset 0x10 = ram:0000, banner at file 0x8251 = ram:08241. The tape image contains only the BASIC program (0x0000–0x836F); high memory in the Ghidra project was modeled separately.

Memory map (as modeled in Ghidra)

Block Range Size Notes
MB 0000–BFFF 48K BASIC program image (real data ends at 0x836F)
SCREEN C000–EFFF 12K MSX screen RAM (uninitialized in image)
MON_RAM F000–F2FF 768B character generator (MON_CHARGEN)
ORI_F300_CODE F300–F3FF 256B Orion I/O patch code — duplicated in the project from its in-image home at 0x0C22 (bytes identical)
IOPORTS F400–F7FF 1K PORT_F400_KBD (keyboard, 10 xrefs), USR1 F500, USR2 F600, EXT F700, FDC regs F701–F708
MONITOR F800–FFFF 2K zeroed in the image; real monitor lives in Orion ROM. SYSINIT does CALL 0xF830 into it
PORTS (io space) 0000–00FE 255B e.g. P_SW_MEM io:00F9 (14 xrefs), P_SW_SCR io:00FA

Entry point and startup

  • Entry: SYSINIT at 0x0000 = JP 0x24A2.
  • 0x24A2: CALL 0xF830 (Orion monitor), sets SP, saves it to 0x8D01, then initializes the keyboard port (LD A,0xAA / LD HL,0xF400 ...), calls 0x0C0A, does a wait-loop on BC/DE counters, and hands control onward.

Major structures found

1. Vector table, 0x0000–~0x00EC

~78 entries of JP nn. The first ~15 slots are 3-byte-aligned with NOP padding (0x0000 JP 24A2, 0x0008 JP 24C6, 0x0010 JP 24C9, 0x0018 JP 2111, 0x0020 JP 1B55, 0x0028 JP 24CC, …), then densely packed JPs from 0x0038 (JP 03AB, 1AA1, 0228, 022E, 028D, 01EB, 0207, 0241, 1B5B, 04AC, 04F6, 0CE8, …). This is the built-in command/statement dispatch table; real code starts at ~0x00ED.

2. Command-prefix table, 0x1AAD–~0x1B50

Fixed 16-byte records: 8-byte text + 8 zero bytes: LOAD", AUTO , GOTO , LIST , RUN␍, SAVE", CLOAD", CONT␍, LIST.␍, … Used to recognize whole-line commands. Table is pointed to from code at 0x1AA1 (LD HL,0x1AAD / CALL 0x0FF0).

3. Keyword/function lookup table, ~0x3AF5–0x3DA8

Variable-length entries: a short distinguishing fragment of the keyword (1–5 chars) followed by a 2-byte handler address. Fragments include: NKEY(INKEY$), PRIN(PRINT), ETUR(RETURN), ESTOR(RESTORE), ESUM(RESUME), IGHT(RIGHT$), CREE(DECLARE), TRING(STRING), PACE(SPACE$), ARPT(VARPTR), EFST/EFIN/EFSN/EFDB, ELET, OCAT, FILE, RESE, …

4. Error table, 0x3DAB–~0x4070 (MB_ERRTAB)

Zero-terminated messages, indexed by error code — matches errors.inc: 1 NEXT without FOR, 2 Syntax error, … 19 Line buffer overflow, 0x32 FIELD overflow, 0x33 Internal error, 0x34–0x3B file errors, plus Orion-specific additions. Followed by " in ", "Ok␍␊", "Break".

5. Character tables, 0x07E2–0x089A

Digit/upper/lower case conversion tables (;1234567890-:, -@abcdefghijklmn, …).

6. Banner & workspace, ~0x8200–0x836F

Code for memory allocation/stack setup (refs to 0x8CC2/0x8CC4, 0x8EAF/0x8EB0/0x8EB2) immediately followed by the banner strings at 0x8241 and end-of-image code at 0x836F.

7. Orion patch code, image copy at 0x0C22 (= project block F300)

Small I/O routines writing port 0xF9 (LD A,1 / OUT (F9),A) with HL-based loops — the Orion-128 hardware glue that replaces MSX I/O calls.

Project state / gaps

  • 2006 symbols (original Microsoft label names) are present, but:
    • 0 functions defined, and no instruction listing outside the few ranges disassembled in this session (0x0000–0x005F, 0x1A80–0x1B47, 0x24A2–0x2501, 0xF830–0xF86F).
    • Auto-analysis is marked complete (nothing left to run); scripts are disabled (GHIDRA_MCP_ALLOW_SCRIPTS not set), so bulk work must go through individual tools.
  • High memory (SCREEN/MON_RAM/MONITOR) is placeholder; only F300 patch code and port labels carry real content.

Suggested next steps (for the reconstruction in mzbas.asm)

  1. Run reanalyze or create functions at the vector-table targets to get call graphs.
  2. Walk the dispatch table at 0x0038+ — each JP target is a statement handler; naming them from the MSX BASIC 2.1 source (MB_* labels) will anchor the rest.
  3. Reconstruct the global variable block around 0x8C00–0x8F60 (pointers seen: 0x8CC2/0x8CC4, 0x8D01, 0x8EAF/0x8EB0/0x8EB2) — these are the BASIC workspace (MB_BASLIM, program pointer, stack, etc. in the original).
  4. The 16-byte command records at 0x1AAD and the fragment table at 0x3AF5 translate directly into assembler tables for sjasmplus.