MODULE mkdemo ; (* Generates boot.MC4, a single-module MC64 image that prints "Hello MC64!" via the SYSTEM write-string service (ยง9.3). *) FROM FileIO IMPORT WriteFile ; FROM Console IMPORT Fatal ; FROM SYSTEM IMPORT ADR ; CONST HeaderSize = 64 ; DescDeps = 0 ; DescLink = 256 ; DescName = 264 ; DescLoadAddr = 280 ; DescChecksum = 288 ; DescFlags = 292 ; DescVarCount = 293 ; DescDepCount = 294 ; DescPad = 295 ; DescProcs = 296 ; ProcTable = 304 ; CodeOff = 312 ; FileSize = 396 ; StrOff = 314 ; (* image offset of the string *) StrLen = 14 ; (* 11 chars + CR + LF + NUL *) VAR buf : ARRAY [0 .. FileSize - 1] OF CHAR ; i : CARDINAL ; sum : CARDINAL ; PROCEDURE Put32 (off, v : CARDINAL) ; BEGIN buf [off] := CHR (v MOD 256) ; buf [off + 1] := CHR ((v DIV 256) MOD 256) ; buf [off + 2] := CHR ((v DIV 65536) MOD 256) ; buf [off + 3] := CHR (v DIV 16777216) ; END Put32 ; PROCEDURE Put64 (off : CARDINAL; v : LONGCARD) ; VAR j : CARDINAL ; BEGIN FOR j := 0 TO 7 DO buf [off + j] := CHR (VAL (CARDINAL, v MOD 256)) ; v := v DIV 256 ; END ; END Put64 ; BEGIN FOR i := 0 TO FileSize - 1 DO buf [i] := 0C ; END ; (* file header (64 bytes) : magic *) buf [0] := 'M' ; buf [1] := 'C' ; buf [2] := '6' ; buf [3] := '4' ; (* descriptor *) buf [HeaderSize + DescName] := 'd' ; buf [HeaderSize + DescName + 1] := 'e' ; buf [HeaderSize + DescName + 2] := 'm' ; buf [HeaderSize + DescName + 3] := 'o' ; buf [HeaderSize + DescFlags] := CHR (4) ; (* TOINIT *) buf [HeaderSize + DescVarCount] := CHR (0) ; buf [HeaderSize + DescDepCount] := CHR (0) ; Put64 (HeaderSize + DescProcs, 304) ; (* proc table image offset *) (* procedure table : proc0 at image offset 312 *) Put64 (HeaderSize + ProcTable, 8) ; (* code : call_rel 14 ; "Hello MC64!\r\n\0" ; load_imm_byte 1 ; system ; end *) buf [HeaderSize + CodeOff] := CHR (8CH) ; (* call_rel *) buf [HeaderSize + CodeOff + 1] := CHR (14) ; buf [HeaderSize + StrOff] := 'H' ; buf [HeaderSize + StrOff + 1] := 'e' ; buf [HeaderSize + StrOff + 2] := 'l' ; buf [HeaderSize + StrOff + 3] := 'l' ; buf [HeaderSize + StrOff + 4] := 'o' ; buf [HeaderSize + StrOff + 5] := ' ' ; buf [HeaderSize + StrOff + 6] := 'M' ; buf [HeaderSize + StrOff + 7] := 'C' ; buf [HeaderSize + StrOff + 8] := '6' ; buf [HeaderSize + StrOff + 9] := '4' ; buf [HeaderSize + StrOff + 10] := '!' ; buf [HeaderSize + StrOff + 11] := 13C ; (* CR *) buf [HeaderSize + StrOff + 12] := 12C ; (* LF *) buf [HeaderSize + StrOff + 13] := 0C ; (* NUL *) buf [HeaderSize + CodeOff + 16] := CHR (8DH) ; (* load_imm_byte *) buf [HeaderSize + CodeOff + 17] := CHR (1) ; buf [HeaderSize + CodeOff + 18] := CHR (0C3H) ; (* system *) buf [HeaderSize + CodeOff + 19] := CHR (50H) ; (* end_program *) (* checksum over the image, excluding the checksum field itself *) sum := 0 ; FOR i := HeaderSize TO FileSize - 1 DO IF NOT ((i >= 352) AND (i <= 355)) THEN sum := sum + ORD (buf [i]) ; END ; END ; Put32 (HeaderSize + DescChecksum, sum) ; IF NOT WriteFile ("boot.MC4", buf, FileSize) THEN Fatal ("mkdemo: cannot write boot.MC4") ; END ; END mkdemo.