 
*  ED:/LDSAV                  Feb / 25 / 93
 
*  Load, Save, Print, LdTemp, Open, Close, IO, IORec
 
*------------------
*  LOAD/SAVE Module
*------------------
 
BADNAM EQU  >F
SYNTAX EQU  >E
 
*  LOAD/SAVE PAB data and defaults
*---------------------------------
*  Note word alignment
 
PABOC  BYTE 0                 Op code
PABST  BYTE 0                 Status
PABBAD DATA PABBUF            Buffer address
PABLRL BYTE 80                Logical recode length
PABCCT BYTE 80                Character count
PABRN  DATA 0                 Record number
PABSO  BYTE 0                 Screen offset
PABNL  BYTE 0                 Name length
SLRL   DATA >5050             Default logical record length
MLRL   DATA >8080             For DF/128
PBFNOM DATA PABBUF            Usual buffer position data
THREE  EQU  $
WRITE  BYTE 3                 DSR Opcode
MASK80 EQU  MLRL              Be economical
BFC    BYTE >FC               Euro tab record
CTRLZ  BYTE >1A               MSDOS terminator
PCCENT BYTE 0                 Prt control flag for entry
PCCEXT BYTE 0                 Exit
 
*  Recognized flag chars
 
CHTAB  EQU  $
C      BYTE 'C'               |
LL     BYTE 'L'               |  Order to
F      BYTE 'F'               |
M      BYTE 'M'               |  match flags
U      BYTE 'U'               |
P      BYTE 'P'               |
Q      BYTE 'Q'               |
A      BYTE 'A'               |
CHTBL  EQU  $-CHTAB
       EVEN
 
*  Keep order of these flags
 
STARTL DATA 0                 |
STOP   DATA 0                 |
LREAD  DATA 0                 |
PFLAG  DATA 0                 | For saving line counts
 
*  User set flags
 
UFTAB  EQU  $
CFLAG  DATA 0       Clean     |
LFLAG  DATA 0       Lines     |
FFLAG  DATA 0       D/F       | Retain block order
MSFLAG DATA 0       MSDos     |
UXFLAG DATA 0       Unix      |
PCFLAG DATA 0       PrtCodes  |
QCFLAG DATA 0       Excodes   |
APFLAG DATA 0       Append DV |
UFTBN  EQU  $
 
*  SD overlay block for temp use at start
*  Current overwritten block size is >1D0
 
SDLMEM EQU  $
 
*----------------------------------------
*  LOAD entry from Command line processor
*----------------------------------------
 
LDTP01 EQU  $
       BL   @VMBWD            Save temp filename back
       DATA TFLBUV            VDP storage
       DATA CTEXT,LLL         Whole command line
       JMP  LOADT1            To common code
 
LOAD01 EQU  $
       BL   @SAVFIL           Save new file-name
LOADT1 SETO @PFLAG            No tab read unless CLR by purge
       BL   @PARSLD           CNT = line number, String -> name
       CLR  @LINENO           Merge line number.(from source)
       LI   R0,STARTL         Byte saver
       CLR  *R0+              Start line number (from destination)
       SETO *R0               Stop line number (from destination)
       DEC  *R0               @STOP
       DECT R0                Back to STARTL
 
*  Open file as Dis/Var or Fix 80
*--------------------------------
 
       BL   @OPEN             Check file pathname before purge
       DATA >0014             Open it as DV
       JMP  LOADDF            Not found
       JMP  LOAD10            Successful - proceed
 
LOADDF BL   @OPEN             Try again as D/F
       DATA >0004             Open data for DF
       JMP  ERRJM1            Bail out on error this time
 
*  Distinguish Loading modes
*--------------------------------------
*  Assume NUM1-3,NUMCHK stored in order
 
LOAD10 LI   R11,NUM1          Byte saver
       MOV  *R11,*R11         Any line numbers entered?
       JLT  LDPURG            No, purge and use defaults.
 
       INC  *R11+             NUM1
       MOV  R11,R15           Save pointer at NUM2
       INC  *R11+             NUM2
       INC  *R11+             NUM3
       MOV  *R11,*R11         NUMCHK - how many numbers entered?
       JGT  LD1NUM            One - load and insert
       JLT  LD3NUM            Three - load piece and insert
 
LD2NUM DECT R15               Two - load part of external file
LD3NUM MOV  *R15+,*R0+        NUM1or2 -> STARTL
       MOV  *R15,*R0          NUM2or3 -> STOPL - load all of file.
       C    @-2(R15),*R15     NUM1or2 <> NUM2or3
       JH   ERRJM1            Can't do that
 
       DECT R0                Back to STARTL
       CI   R15,NUM3          Was it 3 number entry ?
       JEQ  LD1NUM            No - do not purge buffer
 
LDPURG BL   @PURGE            Purge buffer
       JMP  LDEXTL            Go load it
 
*  Merge external file after line #
 
LD1NUM LI   R11,LINENO        Byte saver
       MOV  @NUM1,*R11        File merge
       MOV  @SAVER0,R15       Line number 0?
       JNE  LOAD05            No
       DEC  *R11              Yes - back up LINENO by 1
LOAD05 C    *R11,@EOF         Past end of file ?
       JLE  LDEXTL            No - OK
       MOV  @EOF,*R11         Replace by EoF then
 
*  Set up LOAD from external source
 
LDEXTL EQU  $
       S    *R0+,*R0          STARTL > STOPL known
       INC  *R0+              STOPL
       CLR  *R0               LREAD -> #lines read from file.
 
*  Load file records
 
LOAD20 BL   @VINIT            Clear VBuf
       BL   @IOREAD           Go read a record
       JMP  ERRJM1            Load error, code in R9
       BL   @MOVE             Move buffer to CPU
       DATA PABBUF            Standard buffer
       DATA LINBUF,80
 
*  Check MSB for -->> TAB record
 
       LI   R15,LINBUF        Point to CPU buffer
       MOV  R15,@BUFADR       Use LINBUF as source buffer
       CLR  R10               Flag for if USA tab
       CB   *R15,@MASK80      Check leading byte
       JEQ  CHKTAB            USA tab record possible
       SETO R10               Flag for if Euro tab
       CB   *R15,@BFC         Eurowriter TABs ?
       JNE  LOAD25            No
 
*  Copy to temp and check for Tab record
 
CHKTAB C    @LLL-2(R15),@DSPACE  Check last 2 bytes
       JNE  LOAD25              Not a Tab record
 
       S    R10,R15           E/W offset by 1  (SETO)
       LI   R9,SQSBUF+6       Use this as temp
       MOV  R9,R14            Copy for later use
TBRC10 MOVB *R15+,*R9         Transfer byte
       SZCB @MASK80,*R9+      Remove high bit anyway
       CI   R9,SQSBUF+6+LLL-2 Done - 78 bytes transferred
       JL   TBRC10
 
*  Search for record length and check for 22, 44, 66
 
TBRC20 C    @-2(R9),@DSPACE   Blanks ?
       JNE  TBRC30            No - stop search at INDENT
       DECT R9                Previous word
       C    R9,R14            Back at start ?
       JH   TBRC20            Line not all blanks here
       JMP  TABNOT            This should never happen !
ERRJM1 JMP  ERROR             Intermediate JMP for OofR
 
TBRC30 CLR  R8                Clear MSW of dividend
       S    R14,R9            Count as LSW
       MOV  R9,@-2(R14)       Save length
       DIV  @D22,R8           Is it a multiple of 22 ?
       MOV  R9,R9             Check remainder
       JNE  TABNOT            Yes - not legit
 
*  Check line details
 
TBRC40 DEC  R8                R8 has count
       JOC  TBRC60
 
       MOV  R14,R11           Copy starter
       AI   R11,20            Point to INDENT in this block
       LI   R12,6             Low limit
       LI   R13,85            High limit
       C    *R14,R12          LMRG low ?
       JL   TABNOT
       C    *R14+,R13         LMRG high ?
       JH   TABNOT
       C    *R14,R12          RMRG low ?
       JL   TABNOT
       C    *R14+,R13         RMRG high ?
       JH   TABNOT
       C    *R11,R12          INDENT low ?
       JL   TABNOT
       C    *R11,R13          INDENT high ?
       JH   TABNOT
 
       SWPB R12               Byte values now  6
       SWPB R13                           and  85
TBRC50 CB   *R14,R12          Tab entry byte
       JL   TABNOT            Too low
       CB   *R14+,R13
       JH   TABNOT            Too high
       C    R14,R11           16 worth
       JL   TBRC50            Not yet
 
       INCT R14               Over INDENT to next block
       JMP  TBRC40            Check if more
 
*  Assume a tab record now & write tab data 1-3
 
TBRC60 ABS  @PFLAG            Has it been purged ?
TABINC JNE  LOAD20            Ignore tab record  (no purge)
 
       BL   @VSTRU            Write as string to VDP
       DATA SQSBUF+5          Length in LSB (22,44, or 66)
       DATA TABBUV            Buffer for tab data
       BL   @MOVE             Write to format table
       DATA TABBUV            VDP storage
       DATA FORMO,22          Work with first block
LOAD21 JMP  LOAD20            Tabs taken care of now
 
TABNOT EQU  $                 Direct exit - tabs taken care of
LOAD25 LI   R11,LREAD         Byte saver
       INC  *R11              Count one read
       C    *R11,@STARTL      Time to insert line yet ?
       JLT  LOAD20            No, just forget it
 
       BLWP @INSTLN           Insert line
       DEC  @STOP             All read in ?
       JNE  LOAD30            Not yet
 
*  All read in now
 
LOADCL BL   @CLOSE            Close the file
         Even addresses
       JGT  DISP10
 
*  Error handling code
 
ERRHAN EQU  $
       MOV  @ERFLAG,R9        Check if error message
       JEQ  ERH40             No
 
       MOV  R9,R10            Copy error #
       CLR  @ERFLAG           We have seen it now
       MOV  R11,R13           Temporary save
       LI   R8,ERMBUF         Line buffer for error line
       MOV  R8,@ERRLIN        Line table pointer
EHN10  MOV  @DSPACE,*R8+      Clear buffer
       CI   R8,ERMBUF+86      End of buffer ?
       JL   EHN10             Not yet
 
       LI   R8,ERMBUF+6       Start at text line
       BL   @MVISTR           Fetch error message from VDP
       CI   R10,IOERP         Was it IO error ?
       JNE  ERH40             No
 
       MOV  @IORNM,*R8+       Fetch #
ERH40  MOV  @MESGAD,R9        The normal exit
       LI   R8,CPUSCN         Top line of screen
       BL   @MVISTR           Drop through to MVISTR
       B    *R13
 
 
*  Modify MOVEM to move indexed strings
*--------------------------------------
*  R8  -->>  CPU target
*  R9  -->>  Pointer into VDP pointer table
*  Version to allow separate language files
 
MVISTR EQU  $                 Preserve return
       AI   R9,TEXTV          VDP table start
       BLWP @SETVDR           Set read address
       LI   R6,VDPRD          Byte saver
       MOVB *R6,R9            First byte of string pointer
       SWPB R9                To LSByte
       MOVB *R6,R9            Second byte of string pointer
       SWPB R9                To regular address
       AI   R9,TEXTV          Offset from table start
       BLWP @SETVDR           Set to read string length
       MOVB *R6,R6            Fetch string length byte
       SRL  R6,8              Make count
       JMP  MOVE40            Do the move
 
*  Data VMBR from here
 
MOVE   MOV  *R11+,R9          VDP pointer
MOVF   MOV  *R11+,R8          CPU target
MOVG   MOV  *R11+,R6          Count
 
MOVE05 BLWP @SETVDR           Set VDP read address
MOVE40 MOVB @VDPRD,*R8+       Fetch byte
       DEC  R6                Count off
       JGT  MOVE40            More
       B    *R11
 
*  Color switches
*----------------
 
COLORC EQU  $
       LI   R6,COLCH          Main screen color index
COLX10 INC  *R6               Next one
       C    *R6,@TENS         Ten ?
       JNE  NXCOLX            No
 
       CLR  *R6               Reset cycle
NXCOLX MOV  *R6+,R9           VReg #
       MOVB @TWCOLS(R9),*R6   Color list
       MOV  *R6,R9
       JMP  SETRDB            VWTR - bypass SWPB
 
 
*  Set VDP Read/Write/Register
*-----------------------------
 
SETWDA EQU  $
VADW   EQU  $
       ORI  R9,>4000          Write vdp address for write
SETRDA SWPB R9                Write vdp address for read
SETRDB MOVB R9,@VDPWA         Use as entry for SETVRG
       SWPB R9
       MOVB R9,@VDPWA
       RT
 
*  No register use version
 
SETVR1 EQU  $
       MOVB *R11,@>83D4       Load for next console keyscan
SETVRG MOVB *R11+,@VDPWA
       MOVB *R11+,@VDPWA
       RT
 
 
*  BLWP Versions
*------------------
*  BLWP vector data
 
SETVDW DATA >FFDC,STVW10
SETVDR DATA >FFDC,STVR10
 
 
STVW10 MOV @18(R13),R9        SETVDW
       BL  @SETWDA
       RTWP
 
STVR10 MOV  @18(R13),R9       SETVDR
       BL   @SETRDA
       RTWP
 
 
*  Data VMBWD as BL routine
*--------------------------
 
VMBWD  MOV  *R11+,R9          For VDP address
VMBWE  MOV  *R11+,R8          For CPU address
VMBWL  BLWP @SETVDW           Set for write
       MOV  *R11+,R9          Now for count
       JMP  VMBW10
 
*  String writing variation
 
VSTRM  LI   R8,MARKR
       JMP  VSTRW
 
VSTRU  MOV  *R11+,R8          Get CPU string pointer
VSTRV  MOV  *R11+,R9          VDP target
VSTRW  BLWP @SETVDW           R9 = vdp address
       MOVB *R8+,R9           First byte of date = length
       SRL  R9,8              Make word count
       JEQ  VMBW20
VMBW10 MOVB *R8+,@VDPWD       Write date using length byte
       DEC  R9                Tick off
       JGT  VMBW10            All done ?
VMBW20 B    *R11              Return
 
 
*  VFILL   VDP fill from MSB of R8
*          Count in R6, VDPA in R9, uses R14
*  -----------------------------------------
 
VFILH  LI   R8,>2000          For VINIT
       LI   R6,80             Saves bytes in L/S
       JMP  VFILL
VFILI  LI   R8,>2083
VFILJ  MOV  *R11+,R6
VFILK  MOV  *R11+,R9
VFILL  BLWP @SETVDW
VF1    MOVB R8,@VDPWD
       DEC  R6
       JNE  VF1
       B    *R11
 
 
*--------------------------
*  CMD line number scanner
*  Uses R0,R6,R8,R8,R10,R12
*--------------------------
 
NUM    EQU  $                56w  ----
       LI   R8,CTEXT         Start of entry area
NUMBER MOV  R8,R9            Save copy
       SETO R6               Initialize digit counter
       MOV  @EOF,R12         Just in case EoF
       CB   *R8+,@EOFLIN     Is it "E" ?
       JEQ  NUM50            Yes - EoF already set
 
       DEC  R8                Back up to first char again
NUM10  INC  R6                Count one
       CI   R6,4              Max # digits allowed
       JGT  PARERR             Error in entry
       CB   *R8,@DSPACE       Space terminator ?
       JEQ  NUM20             Yes
       CB   *R8,@SLASH        Slash separator ?
       JEQ  NUM20             Yes
       CB   *R8+,@COMMA       Comma separator ?
       JNE  NUM10             No
 
NUM20  MOV  R6,R6             Any digits at all ?
       JEQ  PARERR            No
       SLA  R6,1              Word adjust for calcs
       CLR  R12               Initialize
       MOV  R9,R8             Restore pointer to start
NUM40  MOVB *R8+,R9           Fetch digit
       SRL  R9,8              Word adjust
       AI   R9,->30           Remove ASCII bias
       JLT  PARERR            Not legit
       CI   R9,9              Above "9"
       JGT  PARERR            Not legit
 
       MPY  @TEN-2(R6),R9     Factor in power of 10
       A    R10,R12           Accumulate result
       DECT R6                Count off
       JGT  NUM40             Back for more
 
       C    R12,@EOF          Was it <= EoF ?
       JLE  NUM50             Acceptable in any event
       ABS  @COLNUM           Was it a line # entry ?
       JNE  NUM50             No - worry about it elsewhere
 
       MOV  @EOF,R12          Too big so use EoF anyway
NUM50  CLR  R0                Initialize line #0 offset flag
       MOV  R12,R12           Was "0" entered
       JEQ  NUM60             Yes
 
       INC  R0                Set offset
       DEC  R12               Internally uses zero base
NUM60  INC  R8                For start of next field
       RT                     NORMAL return
 
 
*  Number parse routine for PARSE versions
*-----------------------------------------
*  Called from RS/FS, L/S PARSLD
 
PRNUMS EQU  $
       MOV  R11,R14           Save return
       SETO @COLNUM           Turn off EoF check
       SETO @NUM1             Initialize first number for CNT
       MOV  @WTWO,@NUMCHK     Initialize counter
PRNU10 BL   @CMLH10           Check command line to end
       JMP  PRNUEX            Only separators
       JMP  PRNU30            Non-number
 
*  Try it as a number then
 
       BL   @NUMBER           Yes - retrieve number
       DEC  R8                Back up to delimiter
       DEC  @NUMCHK           Count it off
       JLT  PARS12            Must be 3rd #
       JEQ  PARS11            Must be 2nd #
 
*  Enter the numbers
 
       MOV  R0,@SAVER0        For zero correction
       MOV  R12,@NUM1         Save as 1st #
       JMP  PRNU10            Resume search
 
PARS11 MOV  R12,@NUM2         Save as 2nd #
       JMP  PRNU10            Resume search
 
PARS12 MOV  R12,@NUM3         Save as 3rd #
       JMP  PRNU10            Resume
 
*  Set up delimiter etc
 
PRNU30 INCT R14               Step over error return
PRNUEX LI   R9,NUM1           Byte saver
       CLR  @COLNUM           Make sure EoF check re-enabled
       B    *R14
 
PARERR B    @PRSERR
 
 
*  Parse command line for L/S
*----------------------------
 
PARSLD LI   R8,CTEXT          Point to start of command line
PARSLE MOV  R11,R13           Save return
       BL   @PRNUMS           Parse 1 to 3 numbers
       JMP  PARERR            Error
       MOVB @DSPACE,@DELIM    Use space as filename delimiter
       MOV  R8,@STRING        Start pointer
       BL   @GSLASH           Chase delimiter after name
       JMP  PARERR            None found
       MOV  R6,@STRL          Save length byte
       MOV  @NUMCHK,R6        Check count of #s
       JEQ  PRLDEX            Must be 2 #s
       DEC  R6                Test again   - necessary ????
       JGT  PRLDEX            No #s entered
       C    *R9,@EOF          1 or 3 - limit first by EoF
       JLT  PRLDEX            No problem
       MOV  @EOF,*R9          Make it EoF then
PRLDEX B    *R13              Return
 
 
*  Check for delimiter
*---------------------
 
GSLASH SETO R6                Initialize counter
GSLA10 CI   R8,CTXTND         At end ?
       JHE  GSLA20            Yes
 
       INC  R6
       CB   *R8+,@DELIM       Well, is it ?
       JNE  GSLA10            No
       INCT R11
GSLA20 RT
 
 
*  Check to end of command line
*------------------------------
*  Called from COMSTA, PRNUMS
 
CMLCHK EQU  $
       LI   R8,CTEXT          Start of command line
CMLH10 CI   R8,CTXTND         End of command line ?
       JHE  CMLH40            No more
 
       CB   *R8+,@COMMA       Commas as separator
       JEQ  CMLH10
       DEC  R8
       CB   *R8+,@DSPACE      Ignore leading blanks
       JEQ  CMLH10
       DEC  R8
       CB   *R8,@AZERO        Check if number digit
       JL   CMLH30            No
       CB   *R8,@H39
       JH   CMLH30            No
       INCT R11               Double step over for number
CMLH30 INCT R11               Return for not a number
CMLH40 RT                     END of line error
 
 
*  Restore Line Address
*----------------------------------
*  Called from START, RS/FS, COMSTA
 
RESTLA EQU  $
       LI   R9,LINBF0         For find and replace string.
RESTLB MOV  R9,@LINADR        Start of current line data
       AI   R9,85             Point to last char on line
D85    EQU  $-2
       MOV  R9,@LINEND        Save as data
       RT
 
*  Clear flags for CMD mode
*------------------------------------
*  Called from COMAND, ERRMSG, CMDXIT
 
CLRCMD EQU  $
       LI   R8,SCLR           Start (>2000)
CLRBUF CLR  *R8+              Loop on it
       CI   R8,SCLR+CMDCL
       JL   CLRBUF
       RT
 
*  TAB forward
*-------------
 
TABF   EQU  $
       LI   R8,TABTP          Point to Tab table start
TAB10  CB   @SCNWS+5,*R8      R2LB for cursor offset
       JL   TABSET            Go move to this tab
 
       INC  R8                Next Tab entry
       CI   R8,TABTND         Past end yet ?
       JLE  TAB10             No
 
TAB15  MOV  @LMRG,R2          Force back to LMrg
       RT
 
*  Back Tabs
*-----------
 
BTAB   EQU  $
       LI   R8,TABTND         Tab table end
BTAB10 CB   @SCNWS+5DATA VDPPAB+10         Where name goes in VDP PAB
       JMP  IO05              Let IO do the work.
 
*--------------------------------------------------------
 
