changeset 2390:1ac410eb636e

Level 2 SCF has been backported to Level 1 -- still needs testing but seems to work ok
author boisy
date Sun, 24 Jan 2010 03:58:59 +0000
parents b750ec9ed6cf
children f251299cd337
files level1/modules/scf.asm
diffstat 1 files changed, 1538 insertions(+), 599 deletions(-) [+]
line wrap: on
line diff
--- a/level1/modules/scf.asm	Sun Jan 24 03:51:32 2010 +0000
+++ b/level1/modules/scf.asm	Sun Jan 24 03:58:59 2010 +0000
@@ -1,134 +1,335 @@
 ********************************************************************
-* SCF - OS-9 Level One V2 SCF file manager
+* SCF - NitrOS-9 Level 2 Sequential Character File Manager
 *
 * $Id$
 *
+* This contains an added SetStat call to allow placing prearranged data
+* into the keyboard buffer of ANY SCF related device.
+*
+* Usage:
+*
+* Entry: X = Pointer to the string
+*        Y = Length of the string
+*        A = Path number
+*        B = SS.Fill ($A0) (syscall SETSTAT function call number)
+* NOTE: If high bit of Y is set, no carriage return will be appended to
+*       the read buffer (used in Shellplus V2.2 history)
+*
+* This also includes Kevin Darlings SCF Editor patches.
+*
 * Edt/Rev  YYYY/MM/DD  Modified by
 * Comment
 * ------------------------------------------------------------------
-*  10      ????/??/??
-* From Tandy OS-9 Level One VR 02.00.00
+*          1993/04/20  ???
+* V1.09:
+* - Speeded up L05CC (write char to device) routine by a few cycles
+* - Slightly optimized Insert char.
+* - Move branch table so Read & ReadLn are 1 cycle faster each; fixed
+*   SS.Fill so size is truncated @ 256 bytes.
+* - Added NO CR option to SS.Fill (for use with modified Shellplus V2.2
+*   command history).
+*
+*          1993/04/21  ???
+* Slight speedup to some of ReadLn parsing, TFM's in Open/Close.
+* - More optimization to read/write driver calls
+* - Got rid of branch table @ L05E3 for speed
+*
+*          1993/05/21  ???
+* V1.10:
+* Added Boisy Pitre's patch for non-sharable devices.
+* - Saved 4 cycles in routine @ L042B
+* - Modified Boisy's routine to not pshs/puls B (saves 2 cycles).
+* - Changed buffer prefill of CR's to save 1 byte.
+*
+*          1993/07/27  ???
+* V1.11:
+* Changed a BRA to a LBRA to a straight LBRA in L0322.
+* - Optimized path option character routine @ L032C
+*
+*          1993/08/03  ???
+* Modified vector table @ L033F to save 1 cycle on PD.PSC
+* - Sped up uppercase conversion checks for ReadLn & WritLn
+* - Changed 2 BRA's to L02F9 to do an LBRA straight to L05F8 (ReadLn loop)
+* - Moved L0565 routine so Reprint line, Insert & Delete char (on ReadLn)
+*   are 1 cycle faster / char printed
+* - Changed 2 references to L0420 to go straight to L0565
+* - Sped up ReadLn loop by 2 or 3 cycles per char read
+*
+*          1993/09/21  ???
+* V1.12:
+* Sped up L0435 by 1 or 2 cycles (depending on branch)
+* - Changed LDD ,S to TFR X,D (saves 1 cycle) @ L04F1 (Write & WritLn)
+* - Modified L04F1 to use W without TFR (+1 byte, -3 cycles) (Write)
+*
+*          1993/11/09  ???
+* Took LDX #0/LDU PD.BUF,y from L03B5 & merged in @ L028A, L02EF & L0381.
+* Also changed BEQ @ L03A5 to skip re-loading X with 0.
+*
+*          1993/11/10  ???
+* Moved L04B2 routine to allow a couple of BSR's instead of LBSR's In READ.
+* - Moved driver call right into READ loop (should save 25 cycles/char read)
+* - Moved driver call right into L0565 (should save 12 cycles/char written on echo,
+*   line editing, etc.)
+*
+*          1993/11/26  ???
+* Moved L02FE (ReadLn parsing) to end where ReadLn routine is moved L03E2
+* so Read loop would be optimized for it (read char from driver) instead of
+* L042B (write filled buffer to caller).
+* Changed LDA #C$NULL to CLRA.
+*
+*          1993/12/01  ???
+* Modified device write call (L056F) to preserve Y as well, to cut down on
+* PSHS/PULS.
+* - Changed L03E2 & L03DA to exit immediately if PD.DEV or PD.DV2 (depending
+* on which routine) is empty (eliminated redundant LEAX ,X).
+*
+*          1994/05/31  ???
+* Attempted mode to L03F1 to eliminate LDW #D$READ, changed:
+*      LDX V$DRIV,x
+*      ADDW M$Exec,x
+*      JSR w,x
+* to:
+*      LDW V$DRIV,x
+*      ADDW M$Exec,w
+*      JSR D$READ,w
+* Did same to L05C9 & L056F (should speed up each by 1 cycle)
+*
+*          1994/06/07  ???
+* Attempted to modify all M$Exec calls to use new V$DRIVEX (REQUIRES NEW IOMAN)
+* - L01FA (Get/SetStat), L03F1 (Read), L05C9 (Write), L056F (Write)
+* - Changed L046A to use LDB V.BUSY,x...CMPB ,s...TFR B,A
 *
-*  11      2010/01/20  Boisy G. Pitre
-* Added support for SHARE. bit
+*          1994/06/08  ???
+* Changed TST <PD.EKO,y in read loop (L02BC) to LDB PD.EKO,y
+* - Changed LEAX 1,X to LDB #1/ABX @ L02C4
+* - Changed LEAX >L033F,pc @ L032C to use < (8 bit) version
+* - Modified L02E5 to use D instead of X, allowing TSTA, and faster exit on 0 byte
+*   just BRAnching to L0453
+*
+*          1994/06/09  ???
+* Changed LEAX 1,X to LDB #1/ABX @ L053D, L05F8, L0312, L0351, L03B8
+* - Changed to L0573: All TST's changed to LDB's
+* - Changed Open/Create init to use LEAX,PC instead of BSR/PULS X
+* - Changed TST PD.CNT,y to LDA PD.CNT,y @ close
+* - Eliminated L010D, changed references to it to go to L0129
+* - Eliminated useless LEAX ,X @ L0182, and changed BEQ @ L0182 to go to L012A
+*   instead of L0129 (speeds CLOSE by 5 or 10 cycles)
+* - Moved L06B9 into L012B, eliminate BSR/RTS, plus
+* - Changed TST V.TYPE,x to LDB V.TYPE,x
+* - Moved L0624 to just before L05F8 to eliminate BRA L05F8 (ReadLn)
+* - Changed TST PD.EKO,y @ L0413 to LDB PD.EKO,y
+* - Moved L0413-L0423 routines to later in code to allow short branches
+* - As result of above, changed 6 LBxx to Bxx
+* - Changed TST PD.MIN,y @ L04BB to LDA PD.MIN,y
+* - Changed TST PD.RAW,y/TST PD.UPC,y @ L0523 to LDB's
+* - Changed TST PD.ALF,y @ L052A to LDB
+* - L053D: Moved TST PD.RAW,y to before LDA -1,u to speed up WRITE, changed it to LDB
+*
+*          1994/06/10  ???
+* Changed TST PD.ALF,y to LDB @ L052A
+* - Changed CLR V.WAKE,u to CLRA/STA V.WAKE,u @ L03F1 (Read)
+* - Changed CLR V.BUSY,u to CLRA/STA V.BUSY,u @ L045D
+* - Changed CLR PD.MIN,y to CLRA/STA PD.MIN,y, moved before LDA P$ID,x @ L04A7
+* - Changed CLR PD.RAW,y @ L04BB to STA PD.RAW, since A already 0 to get there
+* - Changed CLR V.PAUS,u to CLRA/STA V.PAUS,u @ L05A2
+* - Changed TST PD.RAW,y to LDA PD.RAW,y @ L05A2
+* - Changed TST PD.ALF,y to LDA PD.ALF,y @ L05A2
+* - Changed CLR V.WAKE,u to CLRB/STB V.WAKE,u @ L05C9
+* - Changed CLR V.WAKE,u to CLRB/STB V.WAKE,u @ L056F
+* - Changed TST PD.UPC,y to LDB PD.UPC,y @ L0322
+* - Changed TST PD.DLO,y/TST PD.EKO,y to LDB's @ L03A5
+*
+*          1994/06/16  ???
+* Changed TST PD.UPC,y to LDB PD.UPC,y @ L0322
+* - Changed TST PD.BSO,y to LDB PD.BSO,y @ L03BF
+* - Changed TST PD.EKO,y to LDB PD.EKO,y @ L03BF
 *
-*  11r1    2010/01/23  Boisy G. Pitre
+*          2002/10/11  Boisy G. Pitre
+* Merged NitrOS-9 and TuneUp versions for single-source maintenance.  Note that
+* the 6809 version of TuneUp never seemed to call GrfDrv directly to do fast screen
+* writes (see note around g.done label).
+*
+*  16r2    2002/05/16  Boisy G. Pitre
+* Removed pshs/puls of b from sharable code segment for non-NitrOS-9 because it was
+* not needed.
+*
+*  16r3    2002/08/16  Boisy G. Pitre
+* Now uses V$DRIVEX.
+*
+*  16r4    2004/07/12  Boisy G. Pitre
+* 6809 version now calls the FAST TEXT entry point of GrfDrv.
+*
+*  17      2010/01/15  Boisy G. Pitre
+* Fix for bug described in Artifact 2932883 on SF
+* Also added Level 1 conditionals for eventual backporting
+
+*
+*  17      2010/01/15  Boisy G. Pitre
+* Handling of device exclusivity using the SHARE. bit has been rearchitected.
+* The '93 patch looked at the mode bytes in the descriptor and driver and
+* determined that if both were set, then only one path would be allowed to
+* be opened on the device at a time.
+* I now believe this is wrong.
+* The mode bytes in the device driver and descriptor are capability bytes.
+* They advertise what the device is capable of doing (READ, WRITE, etc) so
+* the mode bytes alone do not convey action, but merely what is possible.
+* When the user calls I$Open on a device, he passes the desired mode byte
+* in RegA and IOMan checks to make sure that all bits in that register are
+* set in the mode bytes of the driver and descriptor.  So once we get into
+* the Open call of this file manager, we know that all set bits in RegA are
+* also set in the mode bytes of the driver and descriptor.
+*
+* For SHARE., what we SHOULD be doing is checking the number of open paths
+* on the device.  If the SHARE. bit is set in RegA, then we check if a path
+* is already open and if so, return the E$DevBsy error.
+* Likewise, if SHARE. is not set in RegA, we check the path at the head of
+* the open path list, and if ITS mode byte has the SHARE. bit set, we exit
+* with E$DevBsy too.  The idea is that if the SHARE. bit is set on the newly
+* opened path or an existing path, then there can "be only one."
+*
+*  17r1    2010/01/23  Boisy G. Pitre
 * SCF now returns on carry set after calling SS.Open.  Prior to this
 * change, SS.ComSt would be called right after SS.Open even if SS.Open
 * failed. This caused misery with the scdwn driver wildcard feature.
 
          nam   SCF
-         ttl   OS-9 Level One V2 SCF file manager
+         ttl   NitrOS-9 Level 2 Sequential Character File Manager
 
-         ifp1
+         IFP1
          use   defsfile
          use   scfdefs
-         endc
+         ENDC
 
 tylg     set   FlMgr+Objct
 atrv     set   ReEnt+rev
-rev      set   $01
-edition  set   11
-
-         mod   eom,name,tylg,atrv,start,size
-
-size     equ   .
-
-name     fcs   /SCF/
-         fcb   edition
+rev      set   1
+edition  equ   17
 
-start    lbra  Create
-         lbra  Open
-         lbra  MakDir
-         lbra  ChgDir
-         lbra  Delete
-         lbra  Seek
-         lbra  Read
-         lbra  Write
-         lbra  ReadLn
-         lbra  WriteLn
-         lbra  GetStat
-         lbra  PutStat
-         lbra  Term
+         mod   eom,SCFName,tylg,atrv,SCFEnt,0
 
-L0038    puls  y
-
-
-* ChgDir/MakDir entry
-ChgDir
-MakDir   comb
-         ldb   #E$BPNam
-L003D    rts
+SCFName  fcs   /SCF/
+         fcb   edition
 
 
-* Open/Create entry
-Open
-Create   ldx   PD.DEV,y                get device table entry
-         stx   <PD.TBL,y               save copy
-         ldu   PD.RGS,y                get caller's registers in U
-         pshs  y                       save path descriptor pointer on stack
-         ldx   R$X,u                   get device name pointer
-         os9   F$PrsNam                parse it
-         bcs   L0038                   branch if error
-         lda   -1,y                    get last char
-         bmi   L0059                   branch if hi bit set
-         leax  ,y                      else point X at last char + 1
-         os9   F$PrsNam                parse... better not have another slash!
-         bcc   L0038                   another slash follows, not good!
-L0059    sty   R$X,u                   save pointer past our device name back
-         puls  y
-         lda   #READ.
-         bita  PD.MOD,y
-         beq   L00A2
-         ldd   #$0001
-         os9   F$SRqMem                allocate buffer
-         bcs   L003D                   branch if error
-         stu   PD.BUF,y                else save off
-         clrb
-         bsr   L0091
+* Default input buffer setting for SCF devices when Opened/Created
+*               123456789!123456789!1234567890
+*msg      fcc   'by B.Nobel,C.Boyle,W.Gale-1993'
+msg      fcc   'www.nitros9.org'
+msgsize  equ   *-msg        Size of default input buffer message
+         fcb   C$CR         2nd CR for buffer pad fill
+blksize  equ   256-msgsize  Size of blank space after it
+
+* Return bad pathname error
+opbpnam  puls  y
+bpnam    comb               Set carry for error
+         ldb   #E$BPNam     Get error code
+oerr     rts                Return to caller
 
-* cute message
-cute     fcb   $62,$1B,$59,$6B,$65,$65,$2A,$11,$1C,$0D,$0F
-         fcb   $42,$0C,$6C,$62,$6D,$31,$13,$0F,$0B,$49,$0C
-         fcb   $72,$7C,$6A,$2B,$08,$00,$02,$11,$00,$79
+* I$Create/I$Open entry point
+* Entry: Y= Path dsc. ptr
+open     ldx   PD.DEV,y     Get device table pointer
+         stx   PD.TBL,y     Save it
+         ldu   PD.RGS,y     Get callers register stack pointer
+         pshs  y            Save path descriptor pointer
+         ldx   R$X,u        Get pointer to device pathname
+         os9   F$PrsNam     Parse it
+         bcs   opbpnam      Error, exit
+         tsta               End of pathname?
+         bmi   open1        Yes, go on
+         leax  ,y           Point to actual device name
+         os9   F$PrsNam     Parse it again
+         bcc   opbpnam      Return to caller with bad path name if more
+open1    sty   R$X,u        Save updated name pointer to caller
+         puls  y            Restore path descriptor pointer
+         ldd   #256         Get size of input buffer in bytes
+         os9   F$SRqMem     Allocate it
+         bcs   oerr         Can't allocate it return with error
+         stu   PD.BUF,y     Save buffer address to path descriptor
+         leax  <msg,pc      Get ptr to init string
 
-* put cute message into our newly allocated PD buffer
-L0091    puls  x                       get PC into X
-         clra
-L0094    eora  ,x+
+         IFNE  H6309
+
+         ldw   #msgsize     get size of default message
+         tfm   x+,u+        Copy it into buffer (leaves X pointing to 2nd CR)
+         ldw   #blksize     Size of rest of buffer
+         tfm   x,u+         Fill rest of buffer with CR's
+
+         ELSE
+
+CopyMsg  lda   ,x+
          sta   ,u+
          decb
          cmpa  #C$CR
-         bne   L0094
-L009D    sta   ,u+
+         bne   CopyMsg
+CopyCR   sta   ,u+
          decb
-         bne   L009D
-L00A2    ldu   PD.DEV,y
-         beq   MakDir
-         ldx   V$STAT,u                X = static storage ptr
-         lda   <PD.PAG,y               get page len
-         sta   V.LINE,x                store in static
-         ldx   V$DESC,u
-         ldd   <PD.D2P,y
-         beq   L00C6
+         bne   CopyCR
+
+         ENDC
+
+         ldu   PD.DEV,y     Get device table entry address
+         beq   bpnam        Doesn't exist, exit with bad pathname error
+         ldx   V$STAT,u     Get devices' static storage address
+         lda   PD.PAG,y     Get devices page length
+         sta   V.LINE,x     Save it to devices static storage
+         ldx   V$DESC,u     Get descriptor address
+         ldd   PD.D2P,y     Get offset to device name (duplicate from dev dsc)
+         beq   L00CF        None, skip ahead
+
+         IFNE  H6309
+
+         addr  d,x          Point to device name in descriptor
+         lda   PD.MOD,y     Get device mode (Read/Write/Update)
+         lsrd               ??? (swap Read/Write bits around in A?)
+
+         ELSE
+
          leax  d,x
-         lda   PD.MOD,y
+         lda   PD.MOD,y     Get device mode (Read/Write/Update)
          lsra
          rorb
+
+         ENDC
+
          lsra
          rolb
          rola
          rorb
          rola
-         os9   I$Attach                attach to DEV2
-         bcs   L00FD
-         stu   PD.DV2,y                save dev entry
-L00C6    ldu   V$STAT,u
+         IFGT  Level-1
+         pshs  y            Save path descriptor pointer temporarily
+         ldy   <D.Proc      Get current process pointer
+         ldu   <D.SysPrc    Get system process descriptor pointer
+         stu   <D.Proc      Make system current process
+         ENDC
+         os9   I$Attach     Attempt to attach to device name in device desc.
+         IFGT  Level-1
+         sty   <D.Proc      Restore old current process pointer
+         puls  y            Restore path descriptor pointer
+         ENDC
+         bcs   OpenErr     Couldn't attach to device, detach & exit with error
+         stu   PD.DV2,y     Save new output (echo) device table pointer
+*         ldu   PD.DEV,y     Get device table pointer
+L00CF    ldu   V$STAT,u     Point to it's static storage
+
+         IFNE  H6309
+
+         clrd
+
+         ELSE
+
          clra
          clrb
-         pshs  b,a
-         ldx   <V.PDLHd,u              get path descriptor list head pointer
-         beq   YesPath                 branch if not empty (an open path already exists for this device)
+
+         ENDC
+
+         std   PD.PLP,y     Clear out path descriptor list pointer
+         sta   PD.PST,y     Clear path status: Carrier not lost
+         pshs  d            Save 0 on stack
+         ldx   V.PDLHd,u    Get path descriptor list header pointer
+* 05/25/93 mod - Boisy Pitre's non-sharable device patches
+* 01/15/10 mod - Boisy Pitre redoes his non-sharable device patch
+         beq   Yespath      No paths open, so we know we can open it
 * IOMan has already vetted the mode byte of the driver and the descriptor
 * and compared it to REGA of I$Open (now in PD.MOD of this current path).
 * here we know there is at least one path open for this device.
@@ -156,553 +357,1291 @@
 NoShare  leas  2,s          Eat extra stack (including good path count)
          comb
          ldb   #E$DevBsy    Non-sharable device busy error
-         bra   OpenErr      Go detach device & exit with error
-
-YesPath
-         sty   <V.PDLHd,u              else save this path descriptor as the head
-         bra   L00E9
+         bra   OpenErr       Go detach device & exit with error
+         
+Yespath  sty   V.PDLHd,u    Save path descriptor ptr
+         bra   L00F8        Go open the path
 
-L00D7    tfr   d,x                     change to PD.PLP path descriptor
-CkCar    ldb   <PD.PST,x               get carrier status in B
-         bne   L00E0                   carrier was lost, do not update count
-         inc   1,s                     carrier not lost, bump up count of good paths
-L00E0    ldd   <PD.PLP,x               get path descriptor list pointer
-         bne   L00D7                   there is one, go make it the current one
-         sty   <PD.PLP,x               else add this path descriptor to the tail of the list
-L00E9    lda   #SS.Open                internal open call
-         pshs  a                       save it on the stack
-         inc   2,s                     bump counter of good paths up by 1
-         lbsr  L01BD                   do the SS.Open call to the driver
-         lda   2,s                     get counter of good paths
-         leas  3,s                     clean up stack
+L00E6    tfr   d,x          Change to PD.PLP path descriptor
+CkCar    ldb   PD.PST,x     Get Carrier status
+         bne   L00EF        Carrier was lost, don't update count
+         inc   1,s          Carrier not lost, bump up count of good paths
+L00EF    ldd   PD.PLP,x     Get path descriptor list pointer
+         bne   L00E6        There is one, go make it the current one
+         sty   PD.PLP,x     Save path descriptor ptr as path dsc. list ptr
+L00F8    lda   #SS.Open     Internal open call
+         pshs  a            Save it on the stack
+         inc   2,s          Bump counter of good paths up by 1
+         lbsr  L025B        Do the SS.Open call to the driver
+         lda   2,s          Get counter of good paths
+         leas  3,s          Eat stack
 * NEW: return with error if SS.Open return error
-         bcs   L00FD                   +++BGP+++
-         deca                          bump down good path count
-         bne   L00FC                   if more still open, exit without error
-         lbra  L01B2                   set parity/baud & return
-L00FC    clrb
-L00FD    rts
+         bcs   L010F        +++BGP+++
+         deca               Bump down good path count
+         bne   L0129        If more still open, exit without error
+         blo   L010F        If negative, something went wrong
+         lbra  L0250        Set parity/baud & return
 
 * we come here if there was an error in Open (after I$Attach and F$SRqMem!)
-OpenErr  pshs   b,cc
-         bsr    DetDev
-         puls   b,cc,pc
-    
-* Detach device and return memory    
-DetDev   ldu   PD.DV2,y                get output device table pointer
-         beq   L010B                   branch if empty
-         os9   I$Detach                else detach it
-L010B    ldu   PD.BUF,y                get path descriptor buffer pointer
-         beq   L0EX                    branch if empty
-         ldd   #$0001
-         os9   F$SRtMem                else return to free system ram
-L0EX     rts
+L010F    bsr   L0149        Error, go clear stuff out
+OpenErr  pshs  b,cc         Preserve error status
+         bsr   L0136        Detach device
+         puls  pc,b,cc      Restore error status & return
+
+* I$Close entry point
+close    pshs  cc           Preserve interrupt status
+         orcc  #IntMasks    Disable interrupts
+         ldx   PD.DEV,y     Get device table pointer
+         bsr   L0182        Check it
+         ldx   PD.DV2,y     Get output device table pointer
+         bsr   L0182        Check it
+         puls  cc           Restore interrupts
+         lda   PD.CNT,y     Any open images?
+         beq   L012B        No, go on
+L0129    clra               Clear carry
+L012A    rts                Return
 
-* term routine
-Term     tst   PD.CNT,y
-         beq   L0115                   branch if count is zero
+* Detach device & return buffer memory
+L012B    bsr   L0149
+         lda   #SS.Close    Get setstat code for close
+         ldx   PD.DEV,y     get pointer to device table
+         ldx   V$STAT,x     get static mem ptr
+         ldb   V.TYPE,x     Get device type    \ WON'T THIS SCREW UP WITH
+         bmi   L0136        Window, skip ahead / MARK OR SPACE PARITY???
+         pshs  x,a          Save close code & X for SS.Close calling routine
+         lbsr  L025B        Not window, go call driver's SS.Close routine
+         leas  3,s          Purge stack
+L0136    ldu   PD.DV2,y     Get output device pointer
+         beq   L013D        Nothing there, go on
+         os9   I$Detach     Detach it
+L013D    ldu   PD.BUF,y     Get buffer pointer
+         beq   L0147        None defined go on
+         ldd   #256         Get buffer size
+         os9   F$SRtMem     Return buffer memory to system
+L0147    clra               Clear carry
+         rts                Return
+
+L0149    ldx   #1
+         pshs  cc,d,x,y,u
+         ldu   PD.DEV,y     Get device table pointer
+         beq   L017B        None, skip ahead
+         ldu   V$STAT,u     Get static storage pointer
+         beq   L017B        None, skip ahead
+         ldx   V.PDLHd,u    Get path descriptor list header
+         beq   L017B        None, skip ahead
+         ldd   PD.PLP,y     Get path descriptor list pointer
+         cmpy  V.PDLHd,u
+         bne   L0172
+         std   V.PDLHd,u
+         bne   L017B
+         clr   4,s          Clear LSB of X on stack
+         bra   L017B        Return
+
+L016D    ldx   PD.PLP,x
+         beq   L0180
+L0172    cmpy  PD.PLP,x
+         bne   L016D
+         std   PD.PLP,x
+
+         IFNE  H6309
+
+L017B    clrd
+
+         ELSE
+
+L017B    clra
+         clrb
+
+         ENDC
+
+         std   PD.PLP,y
+L0180    puls  cc,d,x,y,u,pc
 
 
-* seek/delete routine
-Seek
-Delete   clra
-         rts
+* Check path number?
+* Entry: X=Ptr to device table (just LDX'd)
+*        Y=Path dsc. ptr
+L0182    beq   L012A        No device table, return to caller
+         ldx   V$STAT,x     Get static storage pointer
+         ldb   PD.PD,y      Get system path number from path dsc.
+         lda   PD.CPR,y     Get ID # of process currently using path
+         pshs  d,x,y        Save everything
+         cmpa  V.LPRC,x     Current process same as last process using path?
+         bne   L01CA        No, return
+         IFGT  Level-1
+         ldx   <D.Proc      Get current process pointer
+         ELSE
+         ldx   >D.Proc      Get current process pointer
+         ENDC
+         leax  P$Path,x     Point to local path table
+         clra               Start path # = 0 (Std In)
+L0198    cmpb  a,x          Same path as one is process' local path list?
+         beq   L01CA        Yes, return
+         inca               Move to next path
+         cmpa  #NumPaths    Done all paths?
+         blo   L0198        No, keep going
+         pshs  y            Preserve path descriptor pointer
+
+         IFNE  H6309
+
+         lda   #SS.Relea    Release signals SetStat
+         ldf   #D$PSTA      Get Setstat offset
+
+         ELSE
+
+         ldd   #SS.Relea*256+D$PSTA
+
+         ENDC
+
+         bsr   L01FA        Execute driver setstat routine
+         puls  y            Restore path pointer
+         IFGT  Level-1
+         ldx   <D.Proc      Get current process pointer
+         ELSE
+         ldx   >D.Proc      Get current process pointer
+         ENDC
+         lda   P$PID,x      Get parent process ID
+         sta   ,s           Save it
+         IFGT  Level-1
+         os9   F$GProcP     Get pointer to parent process descriptor
+         ELSE
+         ldx   <D.PrcDBT
+         os9   F$Find64
+         ENDC
+         leax  P$Path,y     Point to local path table
+         ldb   1,s          Get path number
+         clra               Get starting path number
+L01B9    cmpb  a,x          Same path?
+         beq   L01C4        Yes, go on
+         inca               Move to next path
+         cmpa  #NumPaths    Done all paths?
+         blo   L01B9        No, keep checking
+         clr   ,s           Clear process ID
+L01C4    lda   ,s           Get process ID
+         ldx   2,s          Get static storage pointer
+         sta   V.LPRC,x     Store it as last process
+L01CA    puls  d,x,y,pc     Restore & return
 
-L0115    bsr   DetDev
-         ldx   #$0001
-         lda   #SS.Close
-         pshs  x,a
-         ldu   PD.DEV,y
-         ldu   V$STAT,u
-         ldx   <V.PDLHd,u
-         ldd   <PD.PLP,y
-         cmpy  <V.PDLHd,u
-         bne   L013A
-         std   <V.PDLHd,u
-         bne   L0143
-         clr   2,s
-         bra   L0143
-L0135    ldx   <PD.PLP,x
-         beq   L0147
-L013A    cmpy  <PD.PLP,x
-         bne   L0135
-         std   <PD.PLP,x
-L0143    sty   <PD.PLP,y
-L0147    lbsr  L01BD
-         leas  3,s                     fix stack
-         rts
+* I$GetStt entry point
+getstt   lda   PD.PST,y     Path status ok?
+         lbne  L04C6        No, terminate process
+         ldx   PD.RGS,y     Get register stack pointer
+         lda   R$B,x        Get function code
+         bne   L01F8        If not SS.Opt, go on
+* SS.Opt Getstat
+         pshs  a,x,y        Preserve registers
+         lda   #SS.ComSt    Get code for Comstat
+         sta   R$B,x        Save it in callers B
+         ldu   R$Y,x        Preserve callers Y
+         pshs  u
+         bsr   L01F8        Send it to driver
+         puls  u            Restore callers Y
+         puls  a,x,y        Restore registers
+         sta   R$B,x        Do SS.OPT
+         ldd   R$Y,x        Get com stat
+         stu   R$Y,x        Put original callers Y back
+         bcs   L01F6        Return if error
+         std   PD.PAR,y     Update path descriptor
+L01F6    clrb               Clear carry
+L01F7    rts                Return
+
+* Execute device driver Get/Set Status routine
+* Entry: A=GetStat/SetStat code
+
+         IFNE  H6309
+
+L01F8    ldf   #D$GSTA      Get Getstat driver entry offset
+L01FA    ldx   PD.DEV,y     Get device table pointer
+         ldu   V$STAT,x     Get static storage pointer
+         IFGT  Level-1
+         ldx   V$DRIVEX,x   get execution pointer of driver
+         ELSE
+         pshs  d
+         ldx   V$DRIV,x     get driver module
+         ldd   M$EXEC,x
+         leax  d,x
+         puls  d
+         ENDC
+         pshs  y,u          Preserve registers
+         jsr   f,x          Execute driver
+         puls  y,u,pc       Restore & return
+
+         ELSE
+
+L01F8    ldb   #D$GSTA
+L01FA    ldx   PD.DEV,y
+         ldu   V$STAT,x
+         IFGT  Level-1
+         ldx   V$DRIVEX,x
+         ELSE
+         pshs  d
+         ldx   V$DRIV,x     get driver module
+         ldd   M$EXEC,x
+         leax  d,x
+         puls  d
+         ENDC
+         pshs  u,y
+LC486    jsr   b,x
+         puls  y,u,pc
+
+         ENDC
 
 
-* getstat routine
-GetStat  lda   <PD.PST,y
-         lbne  L0404
-         ldx   PD.RGS,y
-         lda   R$B,x                   get status code
-         cmpa  #SS.Opt
-         bne   L0179                   branch if not
-         pshs  y,x,a
-         lda   #SS.ComSt               call driver's SS.ComSt
-         sta   R$B,x
-         ldu   R$Y,x
-         pshs  u
-         bsr   L0179
-         puls  u
-         puls  y,x,a
-         sta   R$B,x
-         ldd   R$Y,x
-         stu   R$Y,x
-         bcs   L0177
-         std   <PD.PAR,y
-L0177    clrb
-         rts
-L0179    ldb   #$09                    getstat offset
-JsrDrvr  pshs  a
+* I$SetStt entry point
+setstt   lbsr  L04A2
+L0212    bsr   L021B        Check codes
+         pshs  cc,b         Preserve registers
+         lbsr  L0453        Wait for device
+         puls  cc,b,pc      Restore & return
+
+putkey   cmpa  #SS.Fill     Buffer preload?
+         bne   L01FA        No, go execute driver setstat
+         IFEQ  H6309
+         pshs  u,y,x
+         ENDC
+         IFGT  Level-1
+         ldx   <D.Proc      Get current process pointer
+         ELSE
+         ldx   >D.Proc      Get current process pointer
+         ENDC
+         lda   R$Y,u        Get flag byte for CR/NO CR
+         pshs  a            Save it
+         IFGT  Level-1
+         lda   P$Task,x     Get task number
+         ldb   <D.SysTsk    Get system task
+         IFNE  H6309
+         ldx   R$X,u        Get pointer to data to move
+         ldf   R$Y+1,u      Get number of bytes (max size of 256 bytes)
+         ldu   PD.BUF,y     Get input buffer pointer
+         clre               High byte of Y
+         tfr   w,y          Move size into proper register for F$Move
+         ELSE
+         pshs  d
          clra
-         ldx   PD.DEV,y
-         ldu   V$STAT,x
-         ldx   V$DRIV,x
-         addd  M$Exec,x
-         leax  d,x
-         puls  a
-         jmp   ,x                      jump into driver
-
-
-* putstat routine
-PutStat  lbsr  L03E0
-PutStat2 bsr   L0198
-         pshs  b,cc
-         lbsr  L0391
-         puls  pc,b,cc
-L0198    lda   R$B,u
-         ldb   #$0C                    setstat offset
-         cmpa  #SS.Opt                 SS.Opt?
-         bne   JsrDrvr                 jsr into driver
-* copy passed options to path desc
-         pshs  y
+         ldb   R$Y+1,u
          ldx   R$X,u
-         leay  <PD.OPT,y
+         ldu   PD.BUF,y
+         tfr   d,y
+         puls  d
+         ENDC
+* X=Source ptr from caller, Y=# bytes to move, U=Input buffer ptr
+         os9   F$Move       Move it
+         bcs   putkey1      Exit if error
+         tfr   y,d          Move number of bytes to D
+         ELSE
+loop
+         lda   ,x+
+         sta   ,u+
+         leay  -1,y
+         bne   loop
+         ENDC
+         lda   ,s           Get CR flag
+         bmi   putkey1      Don't want CR appended, exit
+         lda   #C$CR        Get code for carriage return
+         sta   b,u          Put it in buffer to terminate string
+         IFNE  H6309
+putkey1  puls  a,pc         Eat stack & return
+L021B    ldf   #D$PSTA      Get driver entry offset for setstat
+         ELSE
+putkey1  puls  a,x,y,u,pc   Eat stack & return
+L021B    ldb   #D$PSTA      Get driver entry offset for setstat
+         ENDC
+         lda   R$B,u        Get function code from caller
+         bne   putkey       Not SS.OPT, go check buffer load
+* SS.OPT SETSTAT
+         ldx   PD.PAU,y     Get current pause & page
+         IFGT  Level-1
+         pshs  y,x          Preserve Path pointer & pause/page
+         ldx   <D.Proc      Get current process pointer
+         lda   P$Task,x     Get task number
+         ldb   <D.SysTsk    Get system task number
+         ldx   R$X,u        Get callers destination pointer
+         leau  PD.OPT,y     Point to path options
+         ldy   #OPTCNT      Get option length
+         os9   F$Move       Move it to caller
+         puls  y,x          Restore Path pointer & page/pause status
+         bcs   L01F7        Return if error from move
+         ELSE
+         pshs  x,y
+         ldx   R$X,u
+         leay  PD.OPT,y
          ldb   #OPTCNT
-L01A9    lda   ,x+
+optloop
+         lda   ,x+
          sta   ,y+
          decb
-         bne   L01A9
-         puls  y
+         bne   optloop
+         puls  x,y
+         ENDC
+         IFEQ  H6309
+         pshs  x
+         ENDC
+         ldd   PD.PAU,y     Get new page/pause status
+         IFNE  H6309
+         cmpr  d,x          Same as old?
+         ELSE
+         cmpd  ,s++
+         ENDC
+         beq   L0250        Yes, go on
+         ldu   PD.DEV,y     Get device table pointer
+         ldu   V$STAT,u     Get static storage pointer
+         beq   L0250        Go on if none
+         stb   V.LINE,u     Update new line count
+L0250    ldx   PD.PAR,y     Get parity/baud
+         lda   #SS.ComSt    Get code for ComSt
+         pshs  a,x          Preserve them 
+         bsr   L025B        Update parity & baud
+         puls  a,x,pc       Restore & return
 
-L01B2    ldx   <PD.PAR,y
-         lda   #SS.ComSt
-         pshs  x,a
-         bsr   L01BD
-         puls  pc,x,a
-         
-L01BD    pshs  u,y,x
-         ldx   PD.RGS,y
-         ldu   R$Y,x
-         lda   R$B,x
-         pshs  u,y,x,a
-         ldd   <$10,s
-         std   R$Y,x
-         lda   $0F,s
-         sta   R$B,x
+* Update path Parity & baud
+L025B    pshs  x,y,u        Preserve everything
+         ldx   PD.RGS,y     Get callers register pointer
+         ldu   R$Y,x        Get his Y
+         lda   R$B,x        Get his B
+         pshs  a,x,y,u      Preserve it all
+         ldd   $10,s        Get current parity/baud
+         std   R$Y,x        Put it in callers Y
+         lda   $0F,s        Get function code
+         sta   R$B,x        Put it in callers B
+         IFEQ  H6309
          ldb   #$0C
-         lbsr  L03E5
-         bsr   PutStat2
-         puls  u,y,x,a
-         stu   R$Y,x
-         sta   R$B,x
-         bcc   L01E6
-         cmpb  #E$UnkSvc
-         orcc  #Carry
-         bne   L01E6
-         clrb
-L01E6    puls  u,y,x
-L01E8    rts
+         ENDC
+         lbsr  L04A7        Wait for device to be ready
+         lbsr  L0212        Send it to driver
+         puls  a,x,y,u      Restore callers registers
+         stu   R$Y,x        Put back his Y
+         sta   R$B,x        Put back his B
+         bcc   L0282        Return if no error
+         cmpb  #E$UnkSvc    Unknown service request?
+         beq   L0282        Yes, return
+         coma               Set carry
+L0282    puls  x,y,u,pc     Restore & return
+
+* I$Read entry point
+read     lbsr  L04A2        Go wait for device to be ready for us
+         bcc   L028A        No error, go on
+L0289    rts                Return with error
+L028A    inc   PD.RAW,y     Make sure we do Raw read
+         ldx   R$Y,u        Get number of characters to read
+         beq   L02DC        Return if zero
+         pshs  x            Save character count
+         ldx   #0
+         ldu   PD.BUF,y     Get buffer address
+         bsr   L03E2        Read 1 character from device
+         bcs   L02A4        Return if error
+         tsta               Character read zero?
+         beq   L02C4        Yes, go try again
+         cmpa  PD.EOF,y     End of file character?
+         bne   L02BC        No, keep checking
+L02A2    ldb   #E$EOF       Get EOF error code
+L02A4    leas  2,s          Purge stack
+         pshs  b            Save error code
+         bsr   L02D5        Return
+         comb               Set carry
+         puls  b,pc         Restore & return
+
+******************************
+*
+* SCF file manager entry point
+*
+* Entry: Y = Path descriptor pointer
+*        U = Callers register stack pointer
+*
+
+SCFEnt   lbra  open         Create path
+         lbra  open         Open path
+         lbra  bpnam        Makdir
+         lbra  bpnam        Chgdir
+         lbra  L0129        Delete (return no error)
+         lbra  L0129        Seek (return no error)
+         bra   read         Read character
+         nop
+         lbra  write        Write character
+         lbra  readln       ReadLn
+         lbra  writln       WriteLn
+         lbra  getstt       Get Status
+         lbra  setstt       Set Status
+         lbra  close        Close path
+
+* MAIN READ LOOP (no editing)
+L02AD    tfr   x,d          move character count to D
+         tstb               past buffer end?
+         bne   L02B7        no, go get character from device
+* Not often used: only when buffer is full
+         bsr   L042B        move buffer to caller's buffer
+         ldu   PD.BUF,y     reset buffer pointer back to start
+* Main char by char read loop
+L02B7    bsr   L03E2        get a character from device
+         bcs   L02A4        exit if error
+L02BC    ldb   PD.EKO,y     echo turned on?
+         beq   L02C4        no, don't write it to device
+         lbsr  L0565        send it to device write
+L02C4    ldb   #1           Bump up char count
+         abx
+         sta   ,u+          save character in local buffer
+         beq   L02CF        go try again if it was a null
+         cmpa  PD.EOR,y     end of record charcter?
+         beq   L02D3        yes, return
+L02CF    cmpx  ,s           done read?
+         blo   L02AD        no, keep going till we are
 
+L02D3    leas  2,s          purge stack
+L02D5    bsr   L042B        move local buffer to caller
+         ldu   PD.RGS,y     get register stack pointer
+         stx   R$Y,u        save number of characters read
+L02DC    bra   L0453        update path descriptor and return
+
+* Read character from device
+L03E2    pshs  u,y,x        Preserve regs
+         ldx   PD.DEV,y     Get device table pointer for input
+         beq   L0401        None, exit
+         ldu   PD.DV2,y     Get device table pointer for echoed output
+         beq   L03F1        No echoed output device, skip ahead
+L03EA    ldu   V$STAT,u     Get device static storage ptr for echo device
+         ldb   PD.PAG,y     Get lines per page
+         stb   V.Line,u     Store it in device static
+L03F1    tfr   u,d          Yes, move echo device' static storage to D
+         ldu   V$STAT,x     Get static storage ptr for input
+         std   V.DEV2,u     Save echo device's static storage into input device
+         clra
+         sta   V.WAKE,u     Flag input device to be awake
+         IFGT  Level-1
+         ldx   V$DRIVEX,x   Get driver execution pointer
+         ELSE
+         pshs  d
+         ldx   V$DRIV,x     get driver module
+         ldd   M$EXEC,x
+         leax  d,x
+         puls  d
+         ENDC
+         jsr   D$READ,x     Execute READ routine in driver
+L0401    puls  pc,u,y,x     Restore regs & return
+
+* Move buffer to caller
+* Entry: Y=Path dsc. ptr
+*        X=# chars to move
+L042B    pshs  y,x            Preserve path dsc. ptr & char. count
+         ldd   ,s             Get # bytes to move
+         beq   L0451          Exit if none
+         tstb                 Uneven # bytes (not even page of 256)?
+         bne   L0435          Yes, go on
+         deca                 >256, so bump MSB down
+L0435    clrb                 Force to even page
+         ldu   PD.RGS,y       Get callers register stack pointer
+         ldu   R$X,u          Get ptr to caller's buffer
+         IFNE  H6309
+         addr  d,u            Offset to even page into buffer
+         clre                 Clear MSB of count
+         ldf   1,s            LSB of count on even page?
+         bne   L0442          No, go on
+         ince                 Make it even 256 
+L0442
+         IFGT  Level-1
+         lda   <D.SysTsk      Get source task number
+         ENDC
+         ELSE
+         leau  d,u
+         clra
+         ldb   1,s
+         bne   L0442          No, go on
+         inca
+L0442    pshs  d
+         IFGT  Level-1
+         lda   <D.SysTsk      Get source task number
+         ENDC
+         ENDC
+         IFGT  Level-1
+         ldx   <D.Proc        Get destination task number
+         ldb   P$Task,x
+         ldx   PD.BUF,y       Get buffer pointer
+         IFNE  H6309
+         tfr   w,y            Put count into proper register
+         ELSE
+         puls  y
+         ENDC
+         os9   F$Move         Move it to caller
+         ELSE
+         ldx   PD.BUF,y       Get buffer pointer
+         puls  y
+         pshs  u
+L0443
+         lda   ,x+
+         sta   ,u+
+         leay  -1,y
+         bne   L0443
+         puls  u
+         ENDC
+L0451    puls  pc,y,x         Restore & return
 
-* read routine
-Read     lbsr  L03E0
-         bcs   L01E8
-         inc   PD.RAW,y
-         ldx   R$Y,u
-         beq   L0235
-         pshs  x
-         ldx   #$0000
-         ldu   R$X,u
-         lbsr  L0348
-         bcs   L020A
-         tsta
-         beq   L0220
-         cmpa  <PD.EOF,y
-         bne   L0218
-L0208    ldb   #E$EOF
-L020A    leas  2,s
-         pshs  b
-         bsr   L0231
-         comb
-         puls  pc,b
+* I$ReadLn entry point
+readln   bsr   L04A2        Go wait for device to be ready for us
+         bcc   L02E5        No error, continue
+         rts                Error, exit with it
+L02E5    ldd   R$Y,u        Get character count
+         beq   L0453        If none, mark device as un-busy
+         tsta               Past 256 bytes?
+         beq   L02EF        No, go on
+         ldd   #$0100       Get new character count
+L02EF    pshs  d            Save character count
+         ldd   #$FFFF       Get maximum character count
+         std   PD.MAX,y     Store it in path descriptor
+         ldx   #0           Set character count so far to 0
+         ldu   PD.BUF,y     Get buffer ptr
+         lbra  L05F8        Go process readln
+
+* Wait for device - Clears out V.BUSY if either Default or output devices are
+* no longer busy
+* Modifies X and A
+L0453 
+         IFGT  Level-1
+         ldx   <D.Proc        Get current process
+         ELSE
+         ldx   >D.Proc        Get current process
+         ENDC
+         lda   P$ID,x         Get it's process ID
+         ldx   PD.DEV,y       Get device table pointer from our path dsc.
+         bsr   L045D          Check if it's busy
+         ldx   PD.DV2,y       Get output device table pointer
+L045D    beq   L0467          Doesn't exist, exit
+         ldx   V$STAT,x       Get static storage pointer for our device
+         cmpa  V.BUSY,x       Same process as current process?
+         bne   L0467          No, device busy return
+         clra
+         sta   V.BUSY,x       Yes, mark device as free for use
+L0467    rts                  Return
+
+L0468    pshs  x,a            Preserve device table entry pointer & process ID
+L046A    ldx   V$STAT,x       Get device static storage address
+         ldb   V.BUSY,x       Get active process ID
+         beq   L048A          No active process, device not busy go reserve it
+         cmpb  ,s             Is it our own process?
+         beq   L049F          Yes, return without error
+         bsr   L0453          Go wait for device to no longer be busy
+         tfr   b,a            Get process # busy using device
+         os9   F$IOQu         Put our process into the IO Queue
+         inc   PD.MIN,y       Mark device as not mine
+         IFGT  Level-1
+         ldx   <D.Proc        Get current process
+         ELSE
+         ldx   >D.Proc        Get current process
+         ENDC
+         ldb   P$Signal,x     Get signal code
+         lda   ,s             Get our process id # again for L046A
+         beq   L046A          No signal go try again
+         coma                 Set carry
+         puls  x,a,pc         Restore device table ptr (eat a) & return
+
+* Mark device as busy;copy pause/interrupt/quit/xon/xoff chars into static mem
+L048A    sta   V.BUSY,x       Make it as process # busy on this device
+         sta   V.LPRC,x       Save it as the last process to use device
+         lda   PD.PSC,y       Get pause character from path dsc.
+         sta   V.PCHR,x       Save copy in static storage (faster later)
+         ldd   PD.INT,y       Get keyboard interrupt & quit chars
+         std   V.INTR,x       Save copies in static mem
+         ldd   PD.XON,y       Get XON/XOFF chars
+         std   V.XON,x        Save them in static mem too
+L049F    clra                 No error & return
+         puls  pc,x,a         Restore A=Process #,X=Dev table entry ptr
 
-L0213    lbsr  L0348
-         bcs   L020A
-L0218    tst   <PD.EKO,y
-         beq   L0220
-         lbsr  L046C
-L0220    leax  1,x
+* Wait for device?
+L04A2    lda   PD.PST,y       Get path status (carrier)
+         bne   L04C4          If carrier was lost, hang up process
+L04A7
+         IFGT  Level-1
+         ldx   <D.Proc        Get current process ID
+         ELSE
+         ldx   >D.Proc        Get current process ID
+         ENDC
+         clra
+         sta   PD.MIN,y       Flag device is mine
+         lda   P$ID,x         Get process ID #
+         ldx   PD.DEV,y       Get device table pointer
+         bsr   L0468          Busy?
+         bcs   L04C1          No, return
+         ldx   PD.DV2,y       Get output device table pointer
+         beq   L04BB          Go on if it doesn't exist
+         bsr   L0468          Busy?
+         bcs   L04C1          No, return
+L04BB    lda   PD.MIN,y       Device mine?
+         bne   L04A2          No, go wait for it
+         sta   PD.RAW,y       Mark device with editing
+L04C1    ldu   PD.RGS,y       Get register stack pointer
+         rts                  Return
+
+* Hangup process
+L04C4    leas  2,s            Purge return address
+L04C6    ldb   #E$HangUp      Get hangup error code
+         cmpa  #S$Abort       Termination signal (or carrier lost)?
+         blo   L04D3          Yes, increment status flag & return
+         lda   PD.CPR,y       Get current process ID # using path
+         ldb   #S$Kill        Get kill signal
+         os9   F$Send         Send it to process
+L04D3    inc   PD.PST,y       Set path status
+         orcc  #Carry         Set carry
+         rts                  Return
+
+* I$WritLn entry point
+writln   bsr   L04A2          Go wait for device to be ready for us
+         bra   L04E1          Go write
+
+* I$Write entry point
+write    bsr   L04A2          Go wait for device to be ready for us
+         inc   PD.RAW,y       Mark device for raw write
+L04E1    ldx   R$Y,u          Get number of characters to write
+         lbeq  L055A          Zero so return
+         pshs  x              Save character count
+         ldx   #$0000         Get write data offset
+         bra   L04F1          Go write data
+
+L04EC    tfr   u,d            Move current position in PD.BUF to D
+         tstb                 At 256 (end of PD.BUF)?
+         bne   L0523          No, keep writing from current PD.BUF
+
+* Get new block of data to write into [PD.BUF]
+* Only allows up to 32 bytes at a time, and puts them in the last 32 bytes of
+* the 256 byte [PD.BUF] buffer. This way, can use TFR U,D/TSTB to see if fin-
+* inshed
+L04F1    pshs  y,x            Save write offset & path descriptor pointer
+         tfr   x,d            Move data offset to D
+         ldu   PD.RGS,y       Get register stack pointer
+         ldx   R$X,u          Get pointer to users's WRITE string
+         IFNE  H6309
+         addr  d,x            Point to where we are in it now
+         ldw   R$Y,u          Get # chars of original write
+         subr  d,w            Calculate # chars we have left to write
+         cmpw  #64            More than 64?
+         bls   L0508          No, go on
+         ldw   #64            Max size per chunk=64
+L0508    ldd   PD.BUF,y       Get buffer ptr
+         inca                 Point to PD.BUF+256 (1 byte past end
+         subr  w,d            Subtract data size
+         ELSE
+         leax  d,x
+         ldd   R$Y,u
+         subd  ,s
+         cmpd  #$0020
+         bls   L0508
+         ldd   #$0020
+L0508    pshs  d
+         ldd   PD.BUF,y
+         inca
+         subd  ,s
+         ENDC
+         tfr   d,u            Move it to U
+         lda   #C$CR          Put a carriage return 1 byte before start
+         sta   -1,u           of write portion of buffer
+         IFGT  Level-1
+         ldy   <D.Proc        Get current process pointer
+         lda   P$Task,y       Get the task number
+         ldb   <D.SysTsk      Get system task number
+         IFNE  H6309
+         tfr   w,y            Get number of bytes to move
+         ELSE
+         puls  y
+         ENDC
+         os9   F$Move         Move data to buffer
+         ELSE
+         puls  y
+         pshs  u
+L0509    lda   ,x+
          sta   ,u+
-         beq   L022B
-         cmpa  <PD.EOR,y
-         beq   L022F
-L022B    cmpx  ,s
-         bcs   L0213
-L022F    leas  $02,s
-L0231    ldu   PD.RGS,y
-         stx   R$Y,u
-L0235    lbra  L0391
+         leay  -1,y
+         bne   L0509
+         puls  u
+         ENDC
+         puls  y,x            Restore path descriptor pointer and data offset
+
+* at this point, we have
+* 0,s = end address of characters to write
+* X = number of characters written
+* Y = PD pointer
+* U = pointer to data buffer to write
+* Use callcode $06 to call grfdrv (old DWProtSW from previous versions,
+*   now unused by GrfDrv
+L0523    ldb   PD.PAR,y     get device parity: bit 7 set = window
+         cmpb  #$80         is it even potentially a CoWin window?
+         bne   L0524        no, skip the rest of the crap
+
+         clrb               set to no uppercase conversion
+         lda   PD.RAW,y     get raw output flag
+         bne   g.raw        if non-zero, we do raw writes: no conversion
+         ldb   PD.UPC,y     get uppercase conversion flag: 1 = do uppercase
+
+g.raw    pshs  b,x,y,u      save length, PD, data buffer pointers
+
+         IFGT  Level-1
+         lbsr  get.wptr     get window table ptr into Y
+         bcs   no.wptr      do old method on error
+
+* now we find out the number of non-control characters to write...
+g.fast   lda   5,s          grab page number
+         inca               go to the next page
+         clrb               at the top of it
+         subd  5,s          take out number of bytes left to write
+         pshs  b            max. number of characters
+
+         clrb               always <256 characters to write
+g.loop   lda   ,u+          get a character
+         cmpa  #$20         is it a control character?
+         blo   g.done       yes, we're done this stint
+         tst   1,s          get uppercase conversion flag
+         beq   g.loop1      don't convert
+         lbsr  L0403        do a lower-uppercase conversion, if necessary
+         sta   -1,u         save again
+
+g.loop1  incb               done one more character
+         cmpb  ,s           done as many as we can?
+         bne   g.loop
+
+g.done   leas  1,s          kill max. count of characters to use
+         cmpb  #1           one or fewer characters?
+         bls   no.wptr      yes, go use old method
+
+*         IFEQ  H6309
+* Note: this was present in the TuneUp version of SCF, and seems to
+* never allow grfdrv to be called directly, so did fast text screens
+* ever work in TuneUp??? - BGP
+*         bra   no.wptr      
+*         ENDC
+
+* now we call grfdrv...
+         ldu   5,s          get start pointer again
+         abx                done B more characters...
+         stx   1,s          save on-stack
+         lbsr  call.grf     go call grfdrv: no error possible on return
+         leau  b,u          go up B characters in U, too
+         stu   5,s          save old U, too
+         puls  b,x,y,u      restore registers
+         bra   L0544        do end-buffer checks and continue
+         ENDC
+
+no.wptr  puls  b,x,y,u      restore all registers
+
+L0524    lda   ,u+            Get character to write
+         ldb   PD.RAW,y       Raw mode?
+         bne   L053D          Yes, go write it
+         ldb   PD.UPC,y       Force uppercase?
+         beq   L052A          No, continue
+         bsr   L0403          Make it uppercase
+L052A    cmpa  #C$LF          Is it a Line feed?
+         bne   L053D          No, go print it
+         lda   #C$CR          Get code for carriage return
+         ldb   PD.ALF,y       Auto Line feed?
+         bne   L053D          Yes, go print carriage return first
+         bsr   L0573          Print carriage return
+         bcs   L055D          If error, go wait for device
+         lda   #C$LF          Now, print the line feed
 
+* Write character to device (call driver)
+L053D    bsr   L0573          Go write it to device
+         bcs   L055D          If error, go wait for device
+         ldb   #1             Bump up # chars we have written
+         abx
+L0544    cmpx  ,s             Done whole WRITE call?
+         bhs   L0554          Yes, go save # chars written & exit
+         ldb   PD.RAW,y       Raw mode?
+         lbne  L04EC          Yes, keep writing
+         lda   -1,u           Get the char we wrote
+         lbeq  L04EC          NUL, keep writing
+         cmpa  PD.EOR,y       End of record?
+         lbne  L04EC          No, keep writing
+L0554    leas  2,s            Eof record, stop & Eat end of buffer ptr???
+L0556    ldu   PD.RGS,y       Get callers register pointer
+         stx   R$Y,u          Save character count to callers Y
+L055A    lbra  L0453          Mark device write clear and return
+
+* Check for forced uppercase
+L0403    cmpa  #'a            Less then 'a'?
+         blo   L0412          Yes, leave it
+         cmpa  #'z            Higher than 'z'?
+         bhi   L0412          Yes, leave it
+         suba  #$20           Make it uppercase
+L0412    rts                  Return
+
+L055D    leas  2,s            Purge stack
+         pshs  b,cc           Preserve registers
+         bsr   L0556          Wait for device
+         puls  pc,b,cc        Restore & return
+
+* Check for end of page (part of send char to driver)
+L0573    pshs  u,y,x,a        Preserve registers
+         ldx   PD.DEV,y       Get device table pointer
+         cmpa  #C$CR          Carriage return?
+         bne   L056F          No, go print it
+         ldu   V$STAT,x       Get pointer to device stactic storage
+         ldb   V.PAUS,u       Pause request?
+         bne   L0590          Yes, go pause device
+         ldb   PD.RAW,y       Raw output mode?
+         bne   L05A2          Yes, go on
+         ldb   PD.PAU,y       End of page pause enabled?
+         beq   L05A2          No, go on
+         dec   V.LINE,u       Subtract a line
+         bne   L05A2          Not done, go on
+         ldb   #$ff           do a immediate pause request
+         stb   V.PAUS,u
+         bra   L059A          Go read next character
+
+L03DA    pshs  u,y,x        Preserve registers
+         ldx   PD.DV2,y     Get output device table pointer
+         beq   NoOut        None, exit
+         ldu   PD.DEV,y     Get device table pointer
+         lbra  L03EA        Process & return
+
+NoOut    puls  pc,u,y,x     No output device so exit
+
+* Wait for pause release
+L0590    bsr   L03DA          Read next character
+         bcs   L059A          Error, try again
+         cmpa  PD.PSC,y       Pause char?
+         bne   L0590          No, try again
+
+L059A    bsr   L03DA          Reset line count and read a character
+         cmpa  PD.PSC,y       Pause character?
+         beq   L059A          Yes, go read again
+
+* Process Carriage return - do auto linefeed & Null's if necessary
+* Entry: A=CHR$($0D)
+L05A2    ldu   V$STAT,x       Get static storage pointer
+         clra
+         sta   V.PAUS,u       Clear pause request
+         lda   #C$CR          Carriage return (in cases from pause)
+         bsr   L05C9          Send it to driver
+         lda   PD.RAW,y       Raw mode?
+         bne   L05C7          Yes, return
+         ldb   PD.NUL,y       Get end of line null count
+         pshs  b              Save it
+         lda   PD.ALF,y       Auto line feed enabled?
+         beq   L05BE          No, go on
+         lda   #C$LF          Get line feed code
+L05BA    bsr   L05C9          Execute driver write routine
+         bcs   L05C5          Error, purge stack and return
+L05BE    clra                 Get null character
+         dec   ,s             Done null count?
+         bpl   L05BA          No, go send it to driver
+         clra                 Clear carry
+L05C5    leas  1,s            Purge stack
+L05C7    puls  pc,u,y,x,a     Restore & return
+
+* Execute device driver write routine
+* Entry: A=Character to write
+* Execute device driver
+* Entry: W=Entry offset (for type of function, ex. Write, Read)
+*        A=Code to send to driver
+L05C9    ldu   V$STAT,x       Get device static storage pointer
+         pshs  y,x            Preserve registers
+         clrb
+         stb   V.WAKE,u       Wake it up
+         IFGT  Level-1
+         ldx   V$DRIVEX,x     Get driver execution pointer
+         ELSE
+         pshs  d
+         ldx   V$DRIV,x     get driver module
+         ldd   M$EXEC,x
+         leax  d,x
+         puls  d
+         ENDC
+         jsr   D$WRIT,x       Execute driver
+         puls  pc,y,x         Restore & return
 
-* readln routine
-ReadLn   lbsr  L03E0
-         bcs   L01E8
-         ldx   R$Y,u
-         beq   L0231
-         tst   R$Y,u
-         beq   L0248
-         ldx   #256
-L0248    pshs  x
-         ldd   #$FFFF
-         std   PD.MAX,y
-         lbsr  L030D
-L0252    lbsr  L0348
-         bcs   L02C8
-         tsta
-         beq   L0265
-         ldb   #$29
-L025C    cmpa  b,y
-         beq   L0285
-         incb
-         cmpb  #$31
-         bls   L025C
-L0265    cmpx  PD.MAX,y
-         bls   L026B
-         stx   PD.MAX,y
-L026B    leax  1,x
-         cmpx  ,s
-         bcs   L027B
-         lda   <PD.OVF,y
-         lbsr  L046C
-         leax  -1,x
-         bra   L0252
-L027B    lbsr  L0369
-         sta   ,u+
-         lbsr  L0379
-         bra   L0252
-L0285    pshs  pc,x
-         leax  >L0298,pcr
-         subb  #$29
-         lslb
-         leax  b,x
-         stx   2,s
-         puls  x
-         jsr   [,s++]
-         bra   L0252
-L0298    bra   L0313
-         bra   L02FD
-         bra   L02AA
-         bra   L02BE
-         bra   L02D9
-         bra   L02E3
-         puls  pc
-         bra   L02FD
-         bra   L02FD
-L02AA    leas  2,s
+* Send character to driver
+L0565    pshs  u,y,x,a        Preserve registers
+         ldx   PD.DV2,y       Get output device table pointer
+         beq   L0571          Return if none
+         cmpa  #C$CR          Carriage return?
+         beq   L05A2          Yes, go process it
+L056F    ldu   V$STAT,x       Get device static storage pointer
+         clrb
+         stb   V.WAKE,u       Wake it up
+         IFGT  Level-1
+         ldx   V$DRIVEX,x     Get driver execution pointer
+         ELSE
+         pshs  d
+         ldx   V$DRIV,x     get driver module
+         ldd   M$EXEC,x
+         leax  d,x
+         puls  d
+         ENDC
+         jsr   D$WRIT,x       Execute driver
+L0571    puls  pc,u,y,x,a     Restore & return
+
+* Check for printable character
+L0413    ldb   PD.EKO,y       Echo turned on?
+         beq   NoEcho         No, return
+L0418    cmpa  #C$SPAC        CHR$(32) or higher?
+         bhs   L0565          Yes, go send to driver
+         cmpa  #C$CR          Carriage return?
+         bne   L0423          No, change it to a period
+         bra   L0565          Anything else output to driver
+
+NoEcho   rts
+
+L0423    pshs  a              Save code
+         lda   #'.            Get code for period
+         bsr   L0565          Output it to device
+         puls  pc,a           Restore & return
+
+L0624    bsr   L0418        check if it's printable and send it to driver
+* Process ReadLn
+L05F8    lbsr  L03E2        get a character from device
+         lbcs  L0370        return if error
+         tsta               usable character?
+         lbeq  L02FE        no, check path descriptor special characters
+         ldb   PD.RPR,y     get reprint line code
+         cmpb  #C$RPRT      cntrl D?
+         lbeq  L02FE        yes, check path descriptor special characters
+         cmpa  PD.RPR,y     reprint line?
+         bne   L0629        no, Check line editor keys
+         cmpx  PD.MAX,y     character count at maximum?
+         beq   L05F8        yes, go read next character
+         ldb   #1           Bump char count up by 1
+         abx
+         cmpx  ,s           done?
+         bhs   L0620        yes, exit
+         lda   ,u+          get character read
+         beq   L0624        null, go send it to driver
+         cmpa  PD.EOR,y     end of record character?
+         bne   L0624        no, go send it to driver
+         leau  -1,u         bump buffer pointer back 1
+L0620    leax  -1,x         bump character count back 1
+         bra   L05F8        go read next character
+
+* Process print rest of line
+L0629    cmpa  #C$PLINE       Print rest of line code?
+         bne   L0647          No, check insert
+L062D    pshs  u              Save buffer pointer
+         lbsr  L038B          Go print rest of line
+         lda   PD.BSE,y       Get backspace echo character
+L0634    cmpu  ,s             Beginning of buffer?
+         beq   L0642          Yes, exit
+         leau  -1,u           Bump buffer pointer back 1
+         leax  -1,x           Bump character count back 1
+         IFNE  H6309
+         bsr   L0565          Print it
+         ELSE
+         lbsr  L0565          Print it
+         ENDC
+         bra   L0634          Keep going
+L0642    leas  2,s            Purge buffer pointer
+         bra   L05F8          Return
+
+* Process Insert character (NOTE:Currently destroys W)
+L0647    cmpa  #C$INSERT      Insert character code?
+         bne   L0664          No, check delete
+         IFNE  H6309
+         pshs  x,y            Preserve x&y a moment
+         tfr   u,w            Dupe buffer pointer into w
+         ldf   #$fe           End of buffer -1
+         tfr   w,x            Source copy address
+         incw                 Include char we are on & dest address is+1
+         tfr   w,y            Destination copy address
+         subr  u,w            w=w-u (Size of copy)
+         tfm   x-,y-          Move buffer up one
+         puls  y,x            Get back original y & x
+         lda   #C$SPAC        Get code for space
+         sta   ,u             Save it there
+         ELSE
+         pshs  u
+         tfr   u,d
+         ldb   #$FF
+         tfr   d,u
+L06DE    lda   ,-u
+         sta   1,u
+         cmpu  ,s
+         bne   L06DE
+         lda   #C$SPAC
          sta   ,u
-         lbsr  L0379
-         ldu   R$Y,y
-         leax  1,x
-         stx   R$Y,u
-         bsr   L0332
          leas  2,s
-         lbra  L0391
-L02BE    leas  2,s
-         leax  ,x
-         lbeq  L0208
-         bra   L0265
+         ENDC
+         bra   L062D          Go print rest of line
+
+* Process delete line
+L0664    cmpa  #C$DELETE      Delete character code?
+         bne   L068B          No, check end of line
+         pshs  u              Save buffer pointer
+         lda   ,u             Get character there
+         cmpa  PD.EOR,y       End of record?
+         beq   L0687          Yes, don't bother to delete it
+L0671    lda   1,u            Get character beside it
+         cmpa  PD.EOR,y       This an end of record?
+         beq   L067C          Yes, delete it
+         sta   ,u+            Bump character back
+         bra   L0671          Go do next character
+L067C    lda   #C$SPAC        Get code for space
+         cmpa  ,u             Already there?
+         bne   L0685          No, put it in
+         lda   PD.EOR,y       Get end of record code
+L0685    sta   ,u             Put it there
+L0687    puls  u              Restore buffer pointer
+         bra   L062D          Go print rest of line
+
+* Delete rest of buffer
+L068B    cmpa  PD.EOR,y       End of record code?
+         bne   L02FE          No, check for special path dsc. chars
+         pshs  u              Save buffer pointer
+         bra   L069F          Go erase rest of buffer
+
+L0696    pshs  a              Save code
+         lda   #C$SPAC        Get code for space
+         lbsr  L0565          Print it
+         puls  a              Restore code
+L069F    cmpa  ,u+            End of record?
+         bne   L0696          No, go print a space
+         puls  u              Restore buffer pointer
 
-L02C8    pshs  b
+* Check character read against path descriptor
+L02FE    tsta               Usable character?
+         beq   L030C        No, go on
+         ldb   #PD.BSP      Get start point in path descriptor
+L0303    cmpa  b,y          Match code in descriptor?
+         beq   L032C        Yes, go process it
+         incb               Move to next one
+         cmpb  #PD.QUT      Done check?
+         bls   L0303        No, keep going
+L030C    cmpx  PD.MAX,y     Past maximum character count?
+         bls   L0312        No, go on
+         stx   PD.MAX,y     Update maximum character count
+L0312    ldb   #1           Add 1 char
+         abx
+         cmpx  ,s           Past requested amount?
+         blo   L0322        No, go on
+         lda   PD.OVF,y     Get overflow character
+         lbsr  L0565        Send it to driver
+         leax  -1,x         Subtract a character
+         lbra  L05F8        Go try again
+
+L0322    ldb   PD.UPC,y     Force uppercase?
+         beq   L0328        No, put char in buffer
+         lbsr  L0403        Make character uppercase
+L0328    sta   ,u+          Put character in buffer
+         lbsr  L0413        Check for printable
+         lbra  L05F8        Go try again
+
+* Process path option characters
+L032C    pshs  x,pc         Preserve character count & PC
+         leax  <L033F,pc    Point to branch table
+         subb  #PD.BSP      Subtract off first code
+         lslb               Account for 2 bytes a entry
+         abx                Point to entry point
+         stx   2,s          Save it in PC on stack
+         puls  x            Restore X
+C8E3         jsr   [,s++]       Execute routine
+         lbra  L05F8        Continue on
+
+* Vector points for PD.BSP-PD.QUT
+L033F    bra   L03BB        Process PD.BSP
+         bra   L03A5        Process PD.DEL
+         bra   L0351        Process PD.EOR
+         bra   L0366        Process PD.EOF
+         bra   L0381        Process PD.RPR
+         bra   L038B        Process PD.DUP
+         rts                PD.PSC we don't worry about
+         nop
+         bra   L03A5        Process PD.INT
+         bra   L03A5        Process PD.QUT
+
+* Process PD.EOR character
+L0351    leas  2,s          Purge return address
+
+         sta   ,u           Save character in buffer
+         lbsr  L0413
+         ldu   PD.RGS,y     Get callers register stack pointer
+         ldb   #1           Bump up char count by 1
+         abx
+         stx   R$Y,u        Store it in callers Y
+         lbsr  L042B
+         leas  2,s
+         lbra  L0453
+
+* Process PD.EOF
+L0366    leas  2,s          Purge return address
+         leax  ,x           read anything?
+         lbeq  L02A2
+         bra   L030C
+
+L0370    pshs  b
          lda   #C$CR
          sta   ,u
-         bsr   L02D5
+         lbsr  L0565        Send it to the driver
          puls  b
-         lbra  L020A
-L02D5    lda   #C$CR
-         bra   L032F
-L02D9    lda   <PD.EOR,y
-         sta   ,u
-         bsr   L030D
-L02E0    lbsr  L037E
-L02E3    cmpx  PD.MAX,y
-         beq   L02FA
-         leax  1,x
-         cmpx  2,s
-         bcc   L02F8
-         lda   ,u+
-         beq   L02E0
-         cmpa  <PD.EOR,y
-         bne   L02E0
-         leau  -1,u
-L02F8    leax  -1,x
-L02FA    rts   
-L02FB    bsr   L0317
-L02FD    leax  ,x
-         beq   L030D
-         tst   <PD.DLO,y
-         beq   L02FB
-         tst   <PD.EKO,y
-         beq   L030D
-         bsr   L02D5
-L030D    ldx   #$0000
-         ldu   PD.BUF,y
-L0312    rts
-L0313    leax  ,x
-         beq   L02FA
-L0317    leau  -1,u
-         leax  -1,x
-         tst   <PD.EKO,y
-         beq   L0312
-         tst   <PD.BSO,y
-         beq   L032C
-         bsr   L032C
-         lda   #C$SPAC
-         lbsr  L046C
-L032C    lda   <PD.BSE,y
-L032F    lbra  L046C
-L0332    ldx   R$X,u
-         ldu   PD.BUF,y
-L0336    lda   ,u+
-         sta   ,x+
-         cmpa  <PD.EOR,y
-         bne   L0336
-         rts
+         lbra  L02A4
+
+* Process PD.RPR
+L0381    lda   PD.EOR,y     Get end of record character
+         sta   ,u           Put it in buffer
+         ldx   #0
+         ldu   PD.BUF,y     Get buffer ptr
+L0388    lbsr  L0418        Send it to driver
+L038B    cmpx  PD.MAX,y     Character maximum?
+         beq   L03A2        Yes, return
+         ldb   #1           Bump char count up by 1
+         abx
+         cmpx  2,s          Done count?
+         bhs   L03A0        Yes, exit
+         lda   ,u+          Get character from buffer
+         beq   L0388        Null, go send it
+         cmpa  PD.EOR,y     Done line?
+         bne   L0388        No go send it
+         leau  -1,u         Move back a character
+L03A0    leax  -1,x         Move character count back
+L03A2    rts                Return
+
+L03A3    bsr   L03BF
+* PD.DEL/PD.QUT/PD.INT processing
+L03A5    leax  ,x           Any characters?
+         beq   L03B8        No, reset buffer ptr
+         ldb   PD.DLO,y     Backspace over line?
+         beq   L03A3        Yes, go do it
+         ldb   PD.EKO,y     Echo character?
+         beq   L03B5        No, zero out buffer pointers & return
+         lda   #C$CR        Send CR to the driver
+         lbsr  L0565        send it to driver
+L03B5    ldx   #0           zero out count
+L03B8    ldu   PD.BUF,y     reset buffer pointer
+L03BA    rts                return
 
-L0340    pshs  u,y,x
-         ldx   PD.DV2,y
-         ldu   PD.DEV,y
-         bra   L0350
-
-L0348    pshs  u,y,x
-         ldx   PD.DEV,y
-         ldu   PD.DV2,y		U now points to dev table entry of device 2
-         beq   L0357
-L0350    ldu   V$STAT,u		U now points to static storage of device 2
-         ldb   <PD.PAG,y
-         stb   V.LINE,u
-L0357    leax  ,x
-         beq   L0367
-         tfr   u,d		D now holds pointer to static storage of device 2
-         ldu   V$STAT,x		U now holds ???
-         std   V.DEV2,u
-         ldu   #$0003           call READ routine in driver
-         lbsr  L04D3
-L0367    puls  pc,u,y,x
+* Process PD.BSP
+L03BB    leax  ,x           Any characters?
+         beq   L03A2        No, return
+L03BF    leau  -1,u         Mover buffer pointer back 1 character
+         leax  -1,x         Move character count back 1
+         ldb   PD.EKO,y     Echoing characters?
+         beq   L03BA        No, return
+         ldb   PD.BSO,y     Which backspace method?
+         beq   L03D4        Use BSE
+         bsr   L03D4        Do a BSE
+         lda   #C$SPAC      Get code for space
+         lbsr  L0565        Send it to driver
+L03D4    lda   PD.BSE,y     Get BSE
+         lbra  L0565        Send it to driver
 
-L0369    tst   <PD.UPC,y
-         beq   L0378
-         cmpa  #'a
-         bcs   L0378
-         cmpa  #'z
-         bhi   L0378
-         suba  #32
-L0378    rts
-L0379    tst   <PD.EKO,y
-         beq   L0378
-L037E    cmpa  #C$SPAC
-         bcc   L0386
-         cmpa  #C$CR
-         bne   L0389
-L0386    lbra  L046C
-L0389    pshs  a
-         lda   #C$PERD
-         bsr   L0386
-         puls  pc,a
+         IFGT  Level-1
+* check PD.DTP,y and update PD.WPTR,y if it's device type $10 (grfdrv)
+get.wptr pshs  x,u
+         ldu   PD.DEV,y     get device table entry
+         ldx   V$DRIV,u     get device driver module
+         ldd   M$Name,x     offset to name
+         ldd   d,x
+         cmpd  #"VT         is it VTIO?
+         bne   no.fast      no, don't do the fast stuff
+         ldd   >WGlobal+G.GrfEnt     does GrfDrv have an entry address?
+         beq   no.fast      nope, don't bother calling it.
+
+         ldu   V$STAT,u     and device static storage
+         tst   V.ParmCnt,u  are we busy getting more parameters?
+         bne   no.fast      yes, don't do buffered writes
 
-L0391    ldx   <D.Proc
-         lda   P$ID,x
-         ldx   PD.DEV,y
-         bsr   L039B
-         ldx   PD.DV2,y
-L039B    beq   L03A5
-         ldx   V$STAT,x
-         cmpa  V.BUSY,x
-         bne   L03A5
-         clr   V.BUSY,x
-L03A5    rts
+* Get window table pointer & verify it: copied from CoWin and modified
+         ldb   V.WinNum,u   Get window # from device mem
+         lda   #Wt.Siz      Size of each entry
+         mul                Calculate window table offset
+         addd  #WinBase     Point to specific window table entry
+         tfr   d,y          Move to y, the register we want
+         lda   Wt.STbl,y    Get MSB of scrn tbl ptr
+         bgt   VerExit      If $01-$7f, should be ok
+
+* Return illegal window definition error
+no.fast  comb               set carry: no error code, it's an internal routine
+         puls  x,u,pc
+
+VerExit  clra               No error
+         puls  x,u,pc
 
-* A = PID
-* X = dev entry
-* Y = path desc
-L03A6    pshs  x,a
-         ldx   V$STAT,x
-         lda   V.BUSY,x
-         beq   L03C8
-         cmpa  ,s                      compare to A on stack
-         beq   L03DD                   branch if same
-         pshs  a
-         bsr   L0391
-         puls  a
-         os9   F$IOQu
-         inc   PD.MIN,y
-         ldx   <D.Proc
-         ldb   <P$Signal,x
-         puls  x,a
-         beq   L03A6
-         coma
-         rts
-L03C8    lda   ,s                      get passed PID on stack
-         sta   V.BUSY,x
-         sta   V.LPRC,x
-         lda   <PD.PSC,y
-         sta   V.PCHR,x
-         ldd   <PD.INT,y               get int/qut
-         std   V.INTR,x                save in static
-         ldd   <PD.XON,y               get xon/xoff
-         std   V.XON,x                 save in static
-L03DD    clra
-         puls  pc,x,a
+call.grf pshs  d,x,y,u      save registers
+         ldx   #$0180       where to put the text
+         IFNE  H6309
+         pshs  cc           save old CC
+         ELSE
+         tfr   cc,a
+         sta   -2,x
+         ENDC
+         orcc  #IntMasks+Entire  shut everything else off
 
-L03E0    lda   <PD.PST,y
-         bne   L0402
-L03E5    ldx   <D.Proc
-         lda   P$ID,x
-         clr   PD.MIN,y
-         ldx   PD.DEV,y
-         bsr   L03A6
-         bcs   L03FF
-         ldx   PD.DV2,y
-         beq   L03F9
-         bsr   L03A6
-         bcs   L03FF
-L03F9    tst   PD.MIN,y
-         bne   L03E0
-         clr   PD.RAW,y
-L03FF    ldu   PD.RGS,y
-         rts
-L0402    leas  2,s
-L0404    ldb   #E$HangUp
-         cmpa  #$02
-         bcs   L0411
-         lda   PD.CPR,y
-         ldb   #S$Kill
-         os9   F$Send
-L0411    inc   <PD.PST,y
-         orcc  #Carry
-         rts
+         IFNE  H6309
+         clra               make sure high byte=0
+         tfr   d,w
+         tfm   u+,x+        move the data into low memory
+         ELSE
+l@       lda   ,u+
+         sta   ,x+
+         decb
+         bne   l@
+         ENDC
 
-
-* writeln routine
-WriteLn  bsr   L03E0
-         bra   L041F
-
+         ldb   #6           alpha put
+         stb   >WGlobal+G.GfBusy  flag grfdrv busy
+         IFNE  H6309
+         lde   ,s+          grab old CC off of the stack
+         lda   1,s          get the number of characters to write
+         ELSE
+*         ldb   ,s+          grab old CC off of the stack
+         lda   1,s          get the number of characters to write
+         ENDC
+* A = number of bytes at $0180 to write out...
+         bsr   do.grf       do the call
+* ignore errors : none possible from this particular call
+call.out puls  d,x,y,u,pc   and return
 
-* write routine
-Write    bsr   L03E0
-         inc   PD.RAW,y
-L041F    ldx   R$Y,u
-         beq   L0461
-         pshs  x
-         ldx   #$0000
-         ldu   R$X,u
-L042A    lda   ,u+
-         tst   PD.RAW,y
-         bne   L0444
-         lbsr  L0369
-         cmpa  #C$LF
-         bne   L0444
-         lda   #C$CR
-         tst   <PD.ALF,y
-         bne   L0444
-         bsr   L047A
-         bcs   L0464
-         lda   #C$LF
-L0444    bsr   L047A
-         bcs   L0464
-         leax  1,x
-         cmpx  ,s
-         bcc   L045B
-         lda   -1,u
-         beq   L042A
-         cmpa  <PD.EOR,y
-         bne   L042A
-         tst   PD.RAW,y
-         bne   L042A
-L045B    leas  2,s
-L045D    ldu   PD.RGS,y
-         stx   R$Y,u
-L0461    lbra  L0391
-L0464    leas  2,s
-         pshs  b,cc
-         bsr   L045D
-         puls  pc,b,cc
+* this routine should always be called by a BSR, and grfdrv will use the
+* PC saved on-stack to return to the calling routine.
+* ALL REGISTERS WILL BE TRASHED
+do.grf   sts   >WGlobal+G.GrfStk    stack pointer for GrfDrv
+         lds   <D.CCStk     get new stack pointer
+         IFNE  H6309
+         pshs  dp,x,y,u,pc
+         pshsw
+         pshs  cc,d         save all registers
+         ELSE
+         pshs  dp,cc,d,x,y,u,pc
+         ENDC
+
+         ldx   >WGlobal+G.GrfEnt     get GrfDrv entry address
 
-L046C    pshs  u,x,a
-         ldx   PD.DV2,y
-         beq   L0478
-         cmpa  #C$CR
-         beq   L04A9
-L0476    bsr   L04D0
-L0478    puls  pc,u,x,a
+         stx   R$PC,s       save grfdrv entry address as PC on the stack
+         IFNE  H6309
+         ste   R$CC,s       save CC onto CC on the stack
+         ELSE
+         stb   R$B,s
+         ldb   $017E
+         stb   R$CC,s
+         ENDC
+         jmp   [>D.Flip1]   flip to grfdrv and execute it
+         ENDC
+
+* GrfDrv will execute function, and then call [D.Flip0] to return here. It 
+* will use an RTS to return to the code that called here in the first place
+* Only SP, PC & CC are set up - ALL OTHER REGISTERS MAY BE MODIFIED
 
-L047A    pshs  u,x,a
-         ldx   PD.DEV,y
-         cmpa  #C$CR
-         bne   L0476
-         ldu   V$STAT,x
-         tst   V.PAUS,u
-         bne   L0497
-         tst   PD.RAW,y
-         bne   L04A9
-         tst   <PD.PAU,y
-         beq   L04A9
-         dec   V.LINE,u
-         bne   L04A9
-         bra   L04A1
-L0497    lbsr  L0340
-         bcs   L04A1
-         cmpa  <PD.PSC,y
-         bne   L0497
-L04A1    lbsr  L0340
-         cmpa  <PD.PSC,y
-         beq   L04A1
-L04A9    ldu   V$STAT,x
-         clr   V$USRS,u
-         lda   #C$CR
-         bsr   L04D0
-         tst   PD.RAW,y
-         bne   L04CE
-         ldb   <PD.NUL,y
-         pshs  b
-         tst   <PD.ALF,y
-         beq   L04C5
-         lda   #C$LF
-L04C1    bsr   L04D0
-         bcs   L04CC
-L04C5    lda   #C$NULL
-         dec   ,s
-         bpl   L04C1
-         clra
-L04CC    leas  1,s
-L04CE    puls  pc,u,x,a
-
-* Call Driver
-L04D0    ldu   #$0006        call write routine in driver
-L04D3    pshs  u,y,x,a
-         ldu   V$STAT,x      get pointer to device static storage entry
-         clr   V.WAKE,u      clear V.WAKE (driver will populate this)
-         ldx   V$DRIV,x      get pointer to device driver for this path
-         ldd   M$Exec,x      get entry point into device driver
-         addd  $05,s         add in offset
-         leax  d,x           
-         lda   ,s+           
-         jsr   ,x
-         puls  pc,u,y,x
+*         ELSE
+*
+*call.grf pshs  u,y,x,d
+*         tfr   cc,a
+*         orcc  #IntMasks+Entire
+*         ldx   #$0180
+*         sta   -2,x
+*call.lp  lda   ,u+
+*         sta   ,x+
+*         decb
+*         bne   call.lp
+*         stb   ,x
+*         lda   1,s
+*         bsr   do.grf
+*         puls  u,y,x,d,pc
+*
+*do.grf   sts   >$1007
+*         lds   <D.CCStk
+*         ldu   #$1100
+*         ldb   #$3A
+*         stb   >$1002
+*         stb   >$017F
+*         pshs  pc,u,y,x,dp,b,a,cc
+*         ldx   >$106E
+*         stx   R$PC,s
+*         ldb   >$107E
+*         stb   ,s
+*         jmp   [>D.Flip1]
+*         ENDC
 
          emod
 eom      equ   *
          end
+