%begin
%include "i:util.inc"

!MPROM (RWT Aug 83)
!Convert Igor Microword format to Motorola Object format

! Bit N corresponds to 1<<(N&31) in longword N>>5

%constinteger maxword=4095, maxbit=96
%constinteger usedbit=1<<((maxbit)&31), usedword=(maxbit+31)>>5
%recordformat mw(%integerarray a(0:usedword) %c
             %or %byteintegerarray b(0:(maxbit+7)>>3))
%record(mw)%array m(0:maxword)
%owninteger fields=0, bits=0, loc=-1
%string(255) filename
%byteintegerarray size(1:128)

%routine PRINT REST
%integer k
  %if loc >= 0 %start
    print string(" at microword ");  phex4(loc)
  %finish
  print string(": ") %if next symbol # nl
  read symbol(k) %and print symbol(k) %until k = nl
%end

%routine SKIP SEPARATOR
  skip symbol %while next symbol = ' '
  %if next symbol = ',' %start
    skip symbol
    skip symbol %if next symbol = nl
    skip symbol %while next symbol = ' '
  %finish
%end

%routine READ FIELD SIZES
%integer n
  m(n) = 0 %for n=0,1,maxword
  skip symbol %while next symbol <= ' '
  bits = 0
  %cycle
    %unless '0' <= next symbol <= '9' %start
      printstring("* Faulty format declaration: ")
      print rest
      %stop
    %finish
    fields = fields+1;  read(n)
    %unless 0 < n <= 16 %start
      print string("*Field sizes must be in range 1..16")
      newline
      %stop
    %finish
    bits = bits+n
    %if bits > maxbit %start
      printstring("* Field widths exceed");  write(maxbit,1)
      printstring(" bits");  newline
      %stop
    %finish
    size(fields) = n
    skip separator
  %repeat %until next symbol = nl
  skip symbol
%end;  !read sizes

%routine READ HEX(%integername v)
%integer k
  v = 0
  %cycle
    %if '0' <= next symbol <= '9' %start
      read symbol(k)
    %else %if 'A' <= next symbol&95 <= 'F'
      read symbol(k);  k = k&95-7
    %else
      printstring("* Faulty hex value")
      print rest
      %stop
    %finish
    v = v<<4+k-'0'
  %repeat %until next symbol < '0'
%end

%routine READ FIELD VALUES
%record(mw)%name mword == m(loc)
%integer f,n,m,p,q,pos
  %routine insert(%integer value,position)
  %integer index = position>>5, shift=position&31
  %integer this = value<<shift, other = value>>(32-shift)
    mword_a(index) = mword_a(index)!this %if this#0
    mword_a(index+1) = mword_a(index+1)!other %if other#0
  %end
  %if mword_a(usedword)&usedbit#0 %start
    printstring("* Duplicate entry for microword "); phex4(loc)
    newline
  %finish
  mword = 0; pos = 0; insert(1,maxbit)
  %for f = 1,1,fields %cycle
    %if next symbol = nl %start
      print string("?Too few field values");  print rest
      %exit
    %finish
    read hex(n)
    m = (\0)>>(32-size(f))
    %if n&(\m) # 0 %start
      print string("* Value for field");  write(f,1)
      print string(" exceeds field size at microword ");  phex4(loc)
      newline
      n = n&m
    %finish
    insert(n,pos)
    pos = pos+size(f)
    skip separator
  %repeat
%end;  !READ FIELD VALUES

%routine LOAD MICROCODE
  %on %event 9 %start
    %return
  %finish
  loc = 0
  %cycle
    skip symbol %while next symbol <= ' '
    %if next symbol = '@' %start
      skip symbol;  read hex(loc)
    %finish %else %start
      read field values; loc = loc+1
    %finish
  %repeat
%end;  !LOAD MICROCODE

%routine EJECT FILES
%record(mw)%name w
%integer file,loc
%integer open=0,nextloc,p,checksum

%routine dump(%integer byte)
%constinteger max=16
%ownintegerarray buf(1:max)

    %routine put(%integer byte)
       phex2(byte)
       checksum=checksum+byte
    %end
    %routine flush
    %integer i
       printstring("S1"); checksum=0
       put(p+3); put((nextloc-p)>>8); put((nextloc-p)&255)
       put(buf(i)) %for i=1,1,p
       phex2(\checksum)
       newline
       p=0
    %end
    %if open=0 %start
       open=1
       printstring("S00600004844521B"); newline
       nextloc=loc; p=0
    %finish
    %if byte<0 %start; ! Closing
       flush %unless p=0
       printstring("S9030000FC"); newline
       open = 0
       %return
    %finish
    flush %if p=max %or nextloc#loc
    nextloc=loc+1
    p=p+1; buf(p)=byte
  %end

  %for file = 0,1,(bits+7)>>3-1 %cycle
    filename = "$byte".tostring(file+'0')
    selectoutput(0); printstring("Writing ".filename); newline
    openoutput(1,filename); selectoutput(1)
    %for loc = 0,1,maxword %cycle
      w == m(loc)
      dump(w_b(file!!3)) %unless w_a(usedword)&usedbit=0
    %repeat
    dump(-1)
    closeoutput
  %repeat
  selectoutput(0); printstring("Writing $list"); newline
  openoutput(1,"$list"); selectoutput(1)
  nextloc = -1
  %for loc = 0,1,maxword %cycle
    w == m(loc)
    %unless w_a(usedword)&usedbit=0 %start
      newline %unless nextloc=loc %or nextloc<0; nextloc = loc+1
      printsymbol('@'); phex4(loc); space
      %for file = (bits+7)>>3-1,-1,0 %cycle
        space; phex2(w_b(file!!3))
      %repeat
      newline
    %finish
  %repeat
%end

  prompt("File:")
  open input(1,cliparam);  select input(1)
  prompt(":")
  read field sizes
  print string("Converting");  write(bits,1)
  print string("-bit microcode")
  newline
  loc = 0
  load microcode
  eject files
%endofprogram
