GET "b.cgd"
.

SECTION "Diss"

GET "b.CGheader"

LET PrintingCharacter(n) = #x20<n<#x7f

AND PrintHexAndChars(loc, n, fnname) BE
$( WriteF(" & &%x8", n);
   StartComment();
   WriteF("%x4  ", loc);
   IF ~fnname & (n&#xff000000)~=#xff000000
      THEN FOR i = 0 TO 3 DO
      $( LET c = [n>>(i*8)] & 255;
	 WrCh(c<32 | c>=127 -> '.', c)
      $);
   NewLine()
$)

STATIC $( buffer = 0;
	  loadAddress = 0 $)

LET Print(start, end) BE
$( LET fnname = FALSE;
   LET notInst = FALSE;

   InitialiseDisassembler(FALSE);
   FOR loc = start TO end BY 4 DO
   $( LET n = ReadWord(loc);
      LET x = n&#xffff0000;

      TEST x=0 | x=#xffff0000 | fnname
	 THEN $( PrintHexAndChars(loc, n, fnname);
		 fnname := FALSE
	      $)

      ELSE TEST (@n)%0=7 & PrintingCharacter((@n)%1) &
			   PrintingCharacter((@n)%2) &
			   PrintingCharacter((@n)%3)
	 THEN $( LET v = VEC 1;
		 v!0 := n;
		 v!1 := ReadWord(loc+4);
		 fnname := TRUE;
		 WriteF(" & &%x8    ; %s", n, v);
		 StartComment();
		 WriteF("%x4*n", loc);
		 notInst := FALSE
	      $)

      ELSE TEST notInst
	 THEN PrintHexAndChars(loc, n, FALSE)
	 ELSE PrintInstruction(loc, n)
   $);
   TerminateDisassembler()
$)

AND Grumble(a, b, c) BE
$( WriteF(a, b, c);
   FreeVec(buffer);
   Stop(1)
$)

AND Start() BE
$( LET rdargs.string = "from/A,list/K,start/K,end/K,range/K"
   LET argv = VEC 40;
   LET startloc, endloc, range = 0, 0, 0;
   LET noFile = FALSE;

   IF rdargs(rdargs.string, argv, 40)=0 THEN
   $( writes("Bad argument string*N")
      stop(15)
   $);

   $( LET rdn(s) = VALOF
      $( LET n = 0;
	 FOR i = 1 TO s%0 DO n := n*16+digit(s%i);
	 RESULTIS n
      $)
      AND Digit(c) =
	 '0'<=c<='9' -> c-'0',
	 'A'<=c<='F' -> c-'A'+10,
	 'a'<=c<='f' -> c-'a'+10,
			0;

      IF argv!2~=0 THEN startloc := rdn(argv!2);
      IF argv!3~=0 THEN endloc := rdn(argv!3);
      IF argv!4~=0 THEN range := rdn(argv!4);
      IF endloc~=0 & range~=0
	 THEN Grumble("You should use only one of END and FOR");
      IF CompString(argv!0, "store")=0 THEN noFile := TRUE
   $);
   IF argv!1~=0 THEN SelectOutput(FindOutput(argv!1));
   $( LET n = MaxVec();
      LET v = GetVec(n);
      LET size = ?;

      TEST noFile
	 THEN buffer, loadAddress, size := startloc>>2, startloc, topofstore
	 ELSE $( size := loadfile(argv!0, v);
		 buffer := v
	      $);

      IF size<=0
	 THEN Grumble("Can't load file *"%s*"*N", argv!0);

      TEST startloc=0
	 THEN startloc := loadAddress
	 ELSE IF startloc<loadAddress | (startloc-loadAddress)>=size
	    THEN Grumble("bad start address");

      IF range~=0 THEN endloc := startloc+range-4;

      TEST endloc=0
	 THEN endloc := size-4+loadAddress
	 ELSE IF endloc<startloc | (endloc-loadAddress)>=size
	    THEN Grumble("bad end address");

      Print(startloc, endloc);
      FreeVec(v)
      stop(0)
   $)
$)

AND loadfile(filename, buffer) = VALOF
$( LET size = ?
   LET params = VEC 4

   IF osfile(5, filename, params)~=1 THEN RESULTIS 0
   size := params!2;
   loadAddress := params!0;
   params!0 := buffer<<2;
   params!1 := 0;
   osfile(#xFF, filename, params);
   RESULTIS size
$)

AND ReadWord(loc) = buffer!((loc-loadAddress)>>2)

