!Microware Eprom Blowing Program
!Common source file for model 32 and model 33 versions
!To be compiled into two different object files

%include "inc:util.imp"
%begin

%constinteger model=33

%integer start of PROM, end of PROM, PROM size, PROM type, t, check sum
%string(5) PROM name
%constant %integer no PROM types = 6
%constant %string(4) %array PROM types(0:no PROM types) = %c
  "?", "1702", "2704", "2708", "2758", "2716", "2732"
%constant %integer %array PROM sizes(1:no PROM types) = %c
  512, 512, 1024, 1024, 2048, 4096
%integerarray line(0:15)

  %routine next sig(%integer %name sym)
    read symbol(sym) %and sym = sym&127 %until sym>' '
  %end

  %routine read number(%integer %name number)
  %integer sym
  %integer radix
    number = 0
    next sig(sym)
    %if sym='$' %start
      next sig(sym)
      radix = 16
    %finish %else %if sym='@' %start
      next sig(sym)
      radix = 8
    %finish %else %if sym='%' %start
      next sig(sym)
      radix = 2
    %else
      radix = 10
    %finish
    %cycle
      %if '0'<=sym<='9' %start
        sym = sym-'0'
      %finish %else %if 'A'<=sym<='F' %start
        sym = sym-'A'+10
      %finish %else %if 'a'<=sym<='f' %start
        sym = sym-'a'+10
      %else
        sym = 16
      %finish
      %exit %unless sym<radix
      number = number*radix+sym
      read symbol(sym)
      sym = sym&127
    %repeat
  %end

  %routine read type(%integer %name PROM type, %string(5) %name PROM name)
  %integer sym
    next sig(sym)
    PROM name = to string(sym)
    %cycle
      read symbol(sym)
      sym = sym&127
      %exit %unless '0'<=sym<='9'
      PROM name = PROM name.to string(sym)
    %repeat
    PROM type = 0
    %while PROM type<=no PROM types %cycle
      %exit %if PROM name=PROM types(PROM type)
      PROM type = PROM type+1
    %repeat
  %end

  %routine read nibble(%integer %name nib)
    read symbol(nib)
    nib = nib&127
    %if '0'<=nib<='9' %start
      nib = nib-'0'
    %finish %else %if 'A'<=nib<='F' %start
      nib = nib-'A'+10
    %finish %else %if 'a'<=nib<='f' %start
      nib = nib-'a'+10
    %else
      print string("Invalid hex digit.")
      new line
      %stop
    %finish
  %end

  %routine read byte(%integer %name byte, check sum)
  %integer msnib
    read nibble(msnib)
    read nibble(byte)
    byte = byte+msnib<<4
    check sum = check sum+byte
  %end

  %routine read line(%integer %name type, length, addr)
!               %integer %array %name line)
  %integer sym
  %integer check sum, i
    next sig(sym)
    %unless sym='S' %or sym='s' %start
      print string("Invalid header in input.")
      new line
      %stop
    %finish
    read nibble(type)
    check sum = 0
    read byte(length, check sum)
    %if length>0 %start
      %if length>1 %start
        read byte(sym, check sum)
        addr = sym
        %if length>2 %start
          read byte(sym, check sum)
          addr = addr<<8+sym
          %if length>3 %start
            read byte(line(i), check sum) %for i = 0, 1, length-4
          %finish
        %finish
      %finish
      read byte(sym, check sum)
      %unless (check sum+1)&255=0 %start
        print string("Check sum failure.")
        new line
        %stop
      %finish
    %finish
  %end

  %routine print nibble (%integer F)
    F = F&15
    F = F+'A'-10-'0' %if F>9 %and model=33
    print symbol (F + '0')
  %end
  
  %routine print byte(%integer byte)
    print nibble(byte>>4)
    print nibble(byte)
    check sum = check sum+byte
  %end

  %predicate you have opened(%string(255)s)
    %onevent 3,4,9 %start
      %false
    %finish
    openinput(1,s)
    %true
  %end

  %routine setup
  %string(255)parm
    parm = cliparam
    %unless you have opened(parm.".obj") %start
      %unless you have opened(parm) %start
        printstring(event_message); newline; %stop
      %finish
    %finish
    select input(0)
    prompt("PROM type :")
    read type(PROM type, PROM name)
    %if PROM type>no PROM types %start
      print string("I don't know what a ".PROM name." is.")
      new line
      PROM type = 0
    %finish
    %if PROM type=0 %start
      prompt("How big is the PROM? :")
      read number(PROM size)
      %stop %if PROM size=0
    %else
      PROM size = PROM sizes(PROM type)
    %finish
    prompt("PROM start address :")
    read number(start of PROM)
    end of PROM = start of PROM+PROM size-1
    %if start of PROM>end of PROM %start
      t = start of PROM
      start of PROM = end of PROM
      end of PROM = t
    %finish
  %end

  %routine begin
  %byte %integer %array contents(start of PROM:end of PROM)
! %integer %array line(0:15)
  %integer line type, length
  %integer no bytes, no errors, i, addr

    %on %event 9 %start
      print string("Unexpected end of data.")
      new line
      -> output contents
    %finish

    contents(i) = 16_FF %for i = start of PROM, 1, end of PROM
    no errors = 0
    no bytes = 0

    select input(1)

    read line(line type, length, addr{, line})
    %unless line type=0 %start
      print string("Invalid header record.")
      new line
      %stop
    %finish

    %cycle
      read line(line type, length, addr{, line})
      %exit %if line type=9
      %unless line type=1 %start
        print string("Invalid record type.")
        new line
        %stop
      %finish
      %if length>3 %start
        %for i = 0, 1, length-4 %cycle
          %if start of PROM<=addr+i<=end of PROM %start
            %unless line(i)=16_FF %start
              no bytes = no bytes+1
              contents(addr+i) = line(i)&255
            %finish
          %else
            no errors = no errors+1
          %finish
        %repeat
      %finish
    %repeat

output contents:
    %if no errors>0 %start
      write(no errors, 0)
      print string(" byte")
      print symbol('s') %unless no errors=1
      print string(" not in PROM.")
      new line
    %finish
    %if no bytes=0 %start
      print string("No bytes to be programmed.")
      new line
    %else
      printsymbol(27); printsymbol('W');  ! V200 Transparent mode on
      set terminal mode(8);           ! no auto freeze
      new line
      addr = 10000; addr = addr-1 %until addr=0; ! Crap hardware
      addr = start of PROM
      %while addr<=end of PROM %cycle
        %if end of PROM-addr<16 %start
          no bytes = end of PROM-addr+1
        %else
          no bytes = 16
        %finish
        check sum = 0
        %if model=32 %start
          print string("S1")
          print byte((no bytes+3)&255)
          print byte((addr-start of PROM+16_2000)>>8)
          print byte((addr-start of PROM+16_2000)&255)
          print byte(contents(addr+i)) %for i = 0, 1, no bytes-1
          print byte((\check sum)&255)
        %elseif model=33
          print symbol (':')
          print byte((no bytes{+4})&255)
          print byte((addr-start of PROM{+16_2000})>>8)
          print byte((addr-start of PROM{+16_2000})&255)
          print byte (0)
          print byte(contents(addr+i)) %for i = 0, 1, no bytes-1
          print byte((-check sum)&255)
        %finish
        new line
        addr = addr+no bytes
      %repeat
      printstring("S9") %if model=32
      new line
      printsymbol(27); printsymbol('X'); ! Transparent mode off
    %finish
  %end

  setup
  begin

%end %of %program
