[Oberon] Standalone BootLoader format

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Thu May 14 17:54:22 CEST 2020

    > Your first word of the bootfile should be the length of the first
    > section, the second word should be the address, and then the subsequent
    > words should be the data you want to put at that address.  Any  subsequent
    > section must also be like this.  You need to finish with a section with
    > a word len of zero.
    > From section 14.1 of the book:
    >  BootFile = {block}.
    > block = size address {byte}. (size and address are words)
    > and size = 0 indicates the end of the file.  {} means possibly repeated.

Maybe the procedure MakeStream and the command WriteStream below
is useful. MakeStream generates just that format.



  VAR W: Texts.Writer;

  PROCEDURE MakeStream(VAR Rf, Rg: Files.Rider; blksize, destadr: INTEGER);
    VAR i, a: INTEGER; b: BYTE;
  BEGIN Files.ReadByte(Rf, b); i := 0; a := destadr;
    WHILE ~Rf.eof DO
      IF i MOD blksize = 0 THEN Files.WriteInt(Rg, blksize); Files.WriteInt(Rg, a); INC(a, blksize); i := 0 END ;
      Files.WriteByte(Rg, b); INC(i); Files.ReadByte(Rf, b)
    END ;
    WHILE i < blksize DO Files.WriteByte(Rg, 0); INC(i) END ;
    Files.WriteInt(Rg, 0)  (*size of last block*)
  END MakeStream;

  PROCEDURE WriteStream*;  (*convert file to stream format with specified block size and dest adr*)
    VAR f, g: Files.File; Rf, Rg: Files.Rider;
      filelen, blksize, res: INTEGER;
      name, name1: ARRAY 32 OF CHAR;
      S: Texts.Scanner;
  BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); res := -1;
    IF S.class = Texts.Name THEN name := S.s; Texts.Scan(S);
      IF S.class = Texts.Name THEN name1 := S.s; Texts.Scan(S);
        IF S.class = Texts.Int THEN blksize := S.i; Texts.Scan(S);
          IF S.class = Texts.Int THEN res := 0; Texts.WriteString(W, "  WriteStream ");
            Texts.WriteString(W, name); Texts.Write(W, " "); Texts.WriteString(W, name1);
            Texts.WriteInt(W, blksize, 5); Texts.WriteInt(W, S.i, 5);
            IF blksize >= 0 THEN
              IF S.i >= 0 THEN f := Files.Old(name);
                IF f # NIL THEN filelen := Files.Length(f);
                  IF filelen > 0 THEN g := Files.New(name1);
                    IF blksize = 0 THEN blksize := filelen END ;
                    Files.Set(Rf, f, 0); Files.Set(Rg, g, 0); MakeStream(Rf, Rg, blksize, S.i);
                    Files.Register(g); Texts.WriteString(W, "  done")
                  ELSE Texts.WriteString(W, "  input file empty")
                ELSE Texts.WriteString(W, "  input file not found")
              ELSE Texts.WriteString(W, "  destaddr must be >= 0")
            ELSE Texts.WriteString(W, "  blocksize must be >= 0")
    END ;
    IF res = -1 THEN Texts.WriteString(W, "Usage: ORX.WriteStream inputfile M.stream blocksize destadr") END ;
    Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  END WriteStream;

More information about the Oberon mailing list