[net.micro.atari8] Getting Action! to run monitor commands from a program

wa60@sdcc12.UUCP (paul van de graaf{}) (04/05/86)

This routine was originally requested by Alan J. Broder (ajb@mitre.arpa), but
Mitre's mailer seems to believe he doesn't exist, so I'm posting it here.
It runs a monitor command by filling Action!'s input buffer and making direct
hooks into command line parsing routines.  Mr. Broder seems to think that it
is necessary to have such a routine to write a decent Unix-like shell.

As far as my Unix-like shell goes, I'm not that keen on making direct hooks into
the cartridge like this.  Since there are a number of versions of the cartridge,
I can't tell how portable it'd be.  A more portable way of doing this might be
to set up a video blank interrupt which force-feeds the keyboard handler with
keystrokes.  You could also use this idea to make batch or make files.

My preliminary design of the shell calls for it to steal DOSVEC and use a built-
in command ("DOS") to get to DOS.  So to get into the shell, you'd type "D" at
the monitor, and from there you'd type "DOS" to get DOS.  I hope to hide the
shell in the memory underneath the cartridge and then copy it into memory when
it's needed-- like DOS XL.  In a future post, I'll explain how to do that.

So far, I've started writing code for parsing & expanding the arguments.  I've
also got an old routine I wrote which loads & runs binary load files.  I'll
adapt it so that it passes the arguments to the programs.  Interface to the
programs would be similar to Unix and C.  For example here's an off-the-cuff
Echo program:

PROC main(BYTE argc, CARD POINTER argv)
  CHAR ARRAY arg
  BYTE i

  FOR i = 0 TO argc DO
    arg = argv
    Print(arg)
    Put(' )
    argv ==+ 2
  OD
  PutE()
RETURN

I've thought out how to handle re-direction and pipes.  Pipes will have to be
done with temporary files, I'm afraid.  But with a ramdisk, it won't be so bad.
I'm not sure if I'll make the shell programable, or add in facilities for
variables-- there might not be room for all that.  It'll be a while before I
finish it, so if you have any suggestions I'd like to hear them.

Paul van de Graaf	U. C. San Diego

;---CUT HERE---
; Monitor Routine
; by Paul van de Graaf
;
; This routine runs a command on the
; Action! cartridge's monitor.
; It works for version 3.6 of the
; cartridge. I make no guarantee it'll
; work with other versions.
; Your mileage may vary.
; For demo purposes, I have included a
; pico-shell main routine.

; Location of monitor command
; jump table.

DEFINE MONCMDS = "$AF3D"

; mbuf:    Action! input buffer
; bank:    Current cartridge
;          memory bank
; bank0:   a write turns on bank 0
; bank3:   a write turns on bank 3
; DSPFLG:  controls whether certain
;          control chars are visable
; aux:     not certain of function,
;          but Action! parsing
;          routines play with it.

MODULE
CHAR ARRAY mbuf = $590
BYTE bank  = $04C9, bank0  = $D500,
     bank3 = $D503, DSPFLG = $02FE,
     aux   = $8C

; Routines in the Action! cartridge
; we have to hook into.  Parse 1 & 2
; do some rather gnarly parsing of
; input by calling some of the compiler
; routines.  I haven't figured out
; very much of this code.  Decode is
; a simple jump table decode routine
; which jumps to the code for the
; various monitor commands.

PROC Parse1=$B557(CHAR ARRAY cmdline,
                  BYTE aux)
PROC Parse2=$B363()
PROC Decode=$B6F4(BYTE cmd,
                  CARD jmptab)

; Monitor routine:
;
; Bank switches in bank 3,
; because the jump table is
; on that page.  Not sure if
; the 2 Pokes are necessary,
; but the regular monitor
; routine does them.  DSPFLG
; is reset because of a side-
; effect of the Parse routines.

PROC Monitor(CHAR ARRAY command)
 
  IF command(0) > 0 THEN 
    Scopy(mbuf,command)
    Poke($91,0)  Poke($98,0)
    bank = 3     bank3 = 3
    Parse1(mbuf,aux+1)
    Parse2()
    Decode(mbuf(1)%$20,MONCMDS)
    bank = 0     bank0 = 0
    DSPFLG = 0
  FI
RETURN

PROC Main()
  CHAR ARRAY line(255)

  DO
    Put('>)
    InputS(line)
    IF SCompare(line,"EXIT") = 0
      THEN EXIT
    ELSE
      Monitor(line)
    FI
  OD
  PutE()
RETURN