| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- IMPLEMENTATION MODULE Loader2 ;
- FROM SYSTEM IMPORT ADR ;
- IMPORT FIO ;
- FROM FIO IMPORT OpenToRead, ReadNBytes, Close, IsNoError ;
- FROM Memory IMPORT ArenaBase, LoadImage, ReadByte, ReadWord, ReadSlot,
- FillBytes, ReadLong ;
- FROM Global IMPORT SetModuleBase, SetModuleProcs, SetModuleFlag,
- SetCurrentModule, GetModuleBase, GetModuleFlag ;
- FROM Local IMPORT Init, SetGP, SetIP ;
- FROM Instruction IMPORT ProcedureAddress ;
- FROM Interpreter IMPORT Run ;
- FROM Extended IMPORT SetHeapBase ;
- FROM Console IMPORT Fatal ;
- CONST
- HeaderSize = 64 ;
- DescDeps = 0 ;
- DescLink = 256 ;
- DescName = 264 ;
- DescLoadAddr = 280 ;
- DescChecksum = 288 ;
- DescFlags = 292 ;
- DescVarCount = 293 ;
- DescDepCount = 294 ;
- DescPad = 295 ;
- DescProcs = 296 ;
- DescVarSizes = 304 ;
- MaxDeps = 32 ;
- VAR
- buf : ARRAY [0 .. 65535] OF CHAR ;
- f : FIO.File ;
- (* Load one translated .MC4 image into module `slot`. The image and its
- zero-filled data window (plus globals) are placed at `next` and `next` is
- advanced past them, so several modules share the arena without overlap
- (multi-window arena). The requested module lives at MTBL slot `dcnt`,
- its dependencies at slots 0..dcnt-1 (the 16-bit source references the
- first import as mod 0). *)
- PROCEDURE LoadOne (slot: CARDINAL; name: ARRAY OF CHAR; VAR next: LONGCARD ;
- allowDeps: BOOLEAN) ;
- VAR
- got : CARDINAL ;
- i : CARDINAL ;
- imgLen, desc, procsAbs, dataWin, vnext, sz : LONGCARD ;
- chk, sum : CARDINAL ;
- fl, vcnt, dcnt : CARDINAL ;
- j : CARDINAL ;
- BEGIN
- f := OpenToRead (name) ;
- IF NOT IsNoError (f) THEN
- Fatal ("loader: cannot open module file") ;
- END ;
- got := ReadNBytes (f, HIGH (buf) + 1, ADR (buf)) ;
- Close (f) ;
- IF got <= 64 THEN
- Fatal ("loader: file too short") ;
- END ;
- imgLen := VAL (LONGCARD, got) - HeaderSize ;
- desc := next ;
- LoadImage (buf, HeaderSize, desc, got - HeaderSize) ;
- dcnt := ReadByte (desc + VAL (LONGCARD, DescDepCount)) ;
- IF (dcnt # 0) AND NOT allowDeps THEN
- Fatal ("loader: nested dependencies not supported yet") ;
- END ;
- chk := ReadLong (desc + VAL (LONGCARD, DescChecksum)) ;
- sum := 0 ;
- FOR i := HeaderSize TO got - 1 DO
- IF NOT ((i >= 352) AND (i <= 355)) THEN
- sum := sum + ORD (buf [i]) ;
- END ;
- END ;
- IF chk # sum THEN
- Fatal ("loader: checksum mismatch") ;
- END ;
- procsAbs := desc + ReadSlot (desc + VAL (LONGCARD, DescProcs)) ;
- fl := ReadByte (desc + VAL (LONGCARD, DescFlags)) ;
- vcnt := ReadByte (desc + VAL (LONGCARD, DescVarCount)) ;
- dataWin := desc + imgLen ;
- IF (dataWin MOD 8) # 0 THEN
- dataWin := dataWin + 8 - (dataWin MOD 8) ;
- END ;
- vnext := dataWin ;
- FOR j := 1 TO vcnt DO
- sz := ReadSlot (desc + (VAL (LONGCARD, DescVarSizes) +
- (VAL (LONGCARD, j) - 1) * 8)) ;
- IF (sz MOD 8) # 0 THEN
- sz := sz + 8 - (sz MOD 8) ;
- END ;
- FillBytes (vnext, sz, 0) ;
- vnext := vnext + sz ;
- END ;
- SetModuleBase (slot, dataWin) ;
- SetModuleProcs (slot, procsAbs) ;
- SetModuleFlag (slot, fl) ;
- next := vnext ;
- END LoadOne ;
- PROCEDURE Call (name: ARRAY OF CHAR) ;
- VAR
- got : CARDINAL ;
- imgLen, next : LONGCARD ;
- dcnt : CARDINAL ;
- j, k : CARDINAL ;
- mainDataWin : LONGCARD ;
- fl : CARDINAL ;
- depName : ARRAY [0 .. MaxDeps - 1] OF ARRAY [0 .. 15] OF CHAR ;
- fname : ARRAY [0 .. 255] OF CHAR ;
- BEGIN
- f := OpenToRead (name) ;
- IF NOT IsNoError (f) THEN
- Fatal ("loader: cannot open module file") ;
- END ;
- got := ReadNBytes (f, HIGH (buf) + 1, ADR (buf)) ;
- Close (f) ;
- IF got <= 64 THEN
- Fatal ("loader: file too short") ;
- END ;
- imgLen := VAL (LONGCARD, got) - HeaderSize ;
- dcnt := ORD (buf [HeaderSize + DescDepCount]) ;
- IF dcnt > MaxDeps THEN
- Fatal ("loader: too many dependencies") ;
- END ;
- (* dependency names are the last dcnt*8 bytes of the image (file tail) *)
- FOR j := 1 TO dcnt DO
- FOR k := 0 TO 7 DO
- depName [j - 1] [k] :=
- buf [got - dcnt * 8 + (j - 1) * 8 + k] ;
- END ;
- depName [j - 1] [8] := 0C ;
- END ;
- next := ArenaBase () ;
- (* dependencies first (slots 0..dcnt-1), then the requested module
- (slot dcnt). In the 16-bit source, extern references use mod 0 for
- the first import, so MTBL slot 0 must be the first dependency. *)
- FOR j := 1 TO dcnt DO
- k := 0 ;
- WHILE (k < 16) AND (depName [j - 1] [k] # 0C) DO
- fname [k] := depName [j - 1] [k] ;
- INC (k) ;
- END ;
- fname [k] := '.' ;
- fname [k + 1] := 'M' ;
- fname [k + 2] := 'C' ;
- fname [k + 3] := '4' ;
- fname [k + 4] := 0C ;
- LoadOne (j - 1, fname, next, FALSE) ;
- END ;
- LoadOne (dcnt, name, next, TRUE) ;
- SetHeapBase (next) ;
- mainDataWin := GetModuleBase (dcnt) ;
- fl := GetModuleFlag (dcnt) ;
- SetCurrentModule (dcnt) ;
- Init () ;
- SetGP (mainDataWin) ;
- (* initializers run dependency-first, the requested module last *)
- FOR j := 1 TO dcnt DO
- IF (GetModuleFlag (j - 1) DIV 4) MOD 2 # 0 THEN
- Init () ;
- SetGP (GetModuleBase (j - 1)) ;
- SetCurrentModule (j - 1) ;
- SetIP (ProcedureAddress (j - 1, 0)) ;
- Run () ;
- END ;
- END ;
- IF (fl DIV 4) MOD 2 # 0 THEN (* TOINIT : run the module initializer *)
- Init () ;
- SetGP (mainDataWin) ;
- SetCurrentModule (dcnt) ;
- SetIP (ProcedureAddress (dcnt, 0)) ;
- Run () ;
- END ;
- END Call ;
- END Loader2.
|