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

102 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.