Files
RomWBW/Source/Images/d_fortran/u0/FCHAIN.MAC
2023-06-14 12:45:41 -04:00

460 lines
9.1 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
SUBTTL Global Equates,Temps,Defs
TITLE FCHAIN - Fortran CALL FCHAIN Statement
ENTRY FCHAIN
EXTRN $CLSFL,$INIT,$IOERR
CPM SET 0 ; True for CP/M
CPM42 SET 1 ; True for CP/M's at X'4200'
ISIS SET 0 ; True for ISIS-II
MOD1 SET 0 ; True for TRS-80 Mod-1
MOD2 SET 0 ; True for TRS-80 Mod-2
TEK SET 0 ; True for Tektronics
CR SET 13
LF SET 10
NAMLEN SET 11 ; Default Filename Length **3.36
IF MOD1
NAMLEN SET 23
ENDIF
IF MOD2
NAMLEN SET 30
ENDIF
IF CPM42
CPM SET 1
ENDIF
IF CPM
CPMWRM SET 0 ; CP/M Base ( & Warm Boot Addr)
ENDIF
IF CPM42
CPMWRM SET 4200H
ENDIF
; ----
IF CPM
C.EMSG SET 9
C.OPEN SET 15
C.READ SET 20
C.BUFF SET 26
CPMENT SET CPMWRM+5 ; CP/M Entry (BDOS Funct call addr)
TFCB SET CPMWRM+5CH
TBUFF SET CPMWRM+80H
TPA SET CPMWRM+100H
;**3.36 DFTEXT: DB 'COM'
ENDIF
; ================
IF ISIS
CISIS SET 40H ;ISIS Entry Point
I.LOAD SET 6 ;Load Pgrm Function
ENDIF
; ================
IF MOD1
M.ABRT SET 4430H ;Error return to system
M.GET SET 13H ;Input a byte from an I/O device
M.OPEN SET 4424H ;Open an existing file
M.EXIT SET 402DH ;Normal return to system
ENDIF
; ================
IF TEK
SRB SET 3
T.CHAN SET SRB+1 ; Channel No.
T.LEN SET SRB+5 ; Filename Len
T.BPTR SET SRB+6 ; Address of Buffer
T.FNAM SET SRB+8 ; Filename Buffer
ENDIF
; ================
IF2
.PRINTX/Fortran CHAIN/
IF CPM
.PRINTX/ For CPM/
ENDIF
IF CPM42
.PRINTX/ ..at 4200H/
ENDIF
IF ISIS
.PRINTX/ For ISIS-II/
ENDIF
IF MOD1
.PRINTX/ For TRS80 Mod-1/
ENDIF
IF MOD2
.PRINTX/ For TRS80 Mod-2/
ENDIF
IF TEK
.PRINTX/ For Tektronics/
ENDIF
ENDIF
PAGE
SUBTTL FCHAIN - Process a CALL FCHAIN statement
; FCHAIN processes a CALL FCHAIN statement by the following steps:
;
; 1. Parse filename to see if valid
;
; 2. Open file in default OS File Control Block
;
; 3. Move a short program loader to top of memory
; and load new program
;
; SYNTAX: CALL FCHAIN ('<OS dependent filename> ')
; ENTRY [HL] = FWA SDESC for Filename
; EXIT Start executing new program
; USES ALL
FCHAIN:
IF CPM
LDAX D ;Get Drive no.
STA TFCB ;Put in TFCB
ENDIF
SHLD .NFWA ; Save FWA of Name
LXI H,CHN01
PUSH H
LHLD $CLSFL
PCHL ; Close all Files
CHN01:
LXI B,CHN02 ; Addr to RET to..
JMP $INIT ; Reset SP to top of ram
CHN02:
IF CPM
CALL .SNAM ; Go scan filename
LXI D,TBUFF ;Set DMA buffer
MVI C,C.BUFF
CALL CPMENT
LXI D,TFCB ;Open file
MVI C,C.OPEN
CALL CPMENT
INR A
JZ $IOERR ; **IO** Error - File not found
LXI H,0
DAD SP
DCR H
MVI L,0 ;Get 1 page below user stack
LXI D,LOADER ;Move program loader to high memory
MVI B,ENDIPL-IPL
CALL $$MOV
MOV L,B ;[HL] = addr of loader
PUSH H ;For 'RET' to loader
LXI D,LOCTAB ;[DE] = addr of ADDRESS MODIFY TABLE
CHN03: LDAX D ;Get low byte address
ORA A ;Are we done?
JZ CHN04 ; Yes
MOV L,A ;[HL] = address to modify
MOV M,H ;Modify it with [H]
INX D
JMP CHN03 ;Keep looping
CHN04: LXI H,TPA ;[HL] = TPA address
RET ;'RET' to loader
ENDIF
; ================
IF ISIS
LHLD .NFWA
XCHG ;[DE] = Strt of Name
LXI H,I.FNAM
MVI B,15
CALL $$MOV ;Move Filename to FCB
MVI C,I.LOAD ;Load Function
LXI D,I.FCB
CALL CISIS ;Load next Pgm & Go
JMP $IOERR ; (Just in case)
ENDIF
; ================
IF MOD1
LXI H,0 ;Get stack address
DAD SP
MVI L,0 ;Get below user stack
DCR H
DCR H ;Blocking buffer address
DCR H ;Loader start address
PUSH H ;Save loader start address
MVI B,32 ;Blank fill 32 byte DCB
SPLOOP: DCX H
MVI M,' '
DCR B
JNZ SPLOOP
POP B ;Loader start address
PUSH H ;Save DCB addr
LHLD .NFWA
XCHG ;[DE] = Strt of Filename
POP H
PUSH H ;[HL] = DCB addr
PUSH B ;Save loader start address
CALL .SNAM ;Scan Filename into DCB
MVI B,0 ;LRL = 256
POP H ;Loader start address
POP D ;DCB (Filespec) address
PUSH D ;Save DCB address
PUSH H ;Save loader start address
INR H ;Blocking buffer address
CALL M.OPEN ;Open an existing file
JNZ $IOERR ;**IO** Err - Fnf.
DCR H ;Top loader start address
LXI D,LOADER ;Loader start address
MVI B,ENDIPL-IPL ;Size of loader program
CALL $$MOV ;Move to top of memory
POP H ;Loader start address
POP D ;DCB address
PCHL ;Run loader
ENDIF
; ================
IF MOD2
LHLD .NFWA ;[HL] points to name
PUSH H ;Save SOS
LXI B,NAMLEN ;[B]=0, [C]=Max Name Len
CHN03:
MOV A,M
CPI ' '+1
JC CHN04 ;Brif EOS
INX H
INR B ;String Len+1
DCR C ;Max len-1
JNZ CHN03
JMP $IOERR ;**IO** Error, Name too long
CHN04:
MVI M,CR ;Proper TRSDOS Terminator
POP H ;Get SOS
MVI A,37 ;Exeq TRSDOS cmnd, no ret
RST 1 ;Do it, [HL]=string, [B]=string len
JMP $IOERR ; (Who trusts Trash-DOS)
ENDIF
; ================
IF TEK
LHLD .NFWA
XCHG ; [DE]=Filename STR
LXI H,T.FNAM ; [HL]=Filename Buffer
LXI B,NAMLEN ; [B]=0, [C]=Max Name Len
CHN03:
LDAX D
CPI ' '+1
JC CHN04 ; Brif End-of-Name
MOV M,A
INX D
INX H
INR B ; Len+1
DCR C ; Max-1
JZ $IOERR ; **IO** Error if name too long..
JMP CHN03
CHN04:
MVI M,CR ; Store Terminator
MOV A,B
INR A ; Include CR in Len Cnt
STA T.LEN ; Store Filename Len in SRB
MVI A,18H ; Load Overlay & Execute
STA SRB
MVI A,4
STA T.CHAN ; Store Chan 4 (Doc is unclear)
LXI D,T.FNAM
LXI H,T.BPTR
MOV M,D
INX H ; Store Fname Pntr in SRB
MOV M,E
MVI A,0FFH
OUT 0F7H ; Load Overlay & Execute
JMP $IOERR ; Should never happen
ENDIF
; ================
PAGE
SUBTTL Scan for valid Filename
.SNAM:
IF CPM
LHLD .NFWA ; FWA of Filename
XCHG ; [DE] = name FWA
LXI H,TFCB+1 ; [HL] = FILE CTRL BLOCK
MVI B,NAMLEN
.COMMENT & **3.36
.SNAM1:
LDAX D ; GET NAME CHAR
INX D
STA .NFWA ; Set '.' if user supplied Ext.
CPI '.'
JZ .SNAM3 ; Brif saw Ext
CPI ' '+1
JC .SNAM3 ; Brif End-of-Name
MOV M,A ; PUT IN FCB
INX H
DCR B ; UNTIL STRING EXHAUSTED
JNZ .SNAM1
.SNAM2:
LDAX D
INX D
STA .NFWA
CPI '.' ; Looking for Ext..
JZ .SNAM4
CPI ' '+1 ; or end of name
JNC .SNAM2
JMP .SNAM4 ; Go copy user or default ext
.SNAM3:
MVI M,' '
INX H
DCR B
JNZ .SNAM3
.SNAM4:
MVI B,3 ; Scan Extention
LDA .NFWA
CPI '.'
JZ .SNAM5 ; Brif user supplied ext
LXI D,DFTEXT ; ..Else use default
**3.36 &
.SNAM5:
LDAX D
INX D
MOV M,A
INX H
DCR B
JNZ .SNAM5
; ----------------
MOV M,B ; Clear File EX
MOV A,B
STA TFCB+32 ; NR = 0
RET
ENDIF
; ================
IF MOD1
MVI B,NAMLEN
.SNAM0:
LDAX D
CPI ' '+1
JC .SNAM1 ;Brif EOS
MOV M,A
INX D
INX H
DCR B
JNZ .SNAM0
JMP $IOERR ;**IO** Error if name too long
.SNAM1:
MVI M,CR ;Terminate with CR
RET
ENDIF
PAGE
SUBTTL Relocated loader for CP/M & MOD1
IF CPM
LOCTAB:
DB (X0+2) AND 0FFH
DB (X1+1) AND 0FFH
DB (X2+2) AND 0FFH
DB (X3+2) AND 0FFH
DB 0
; ================
LOADER:
.PHASE 0
IPL: LXI D,TPA ;Program start address
PUSH D ;Save as return address
IPL1: XCHG ;[DE] = Next load address
PUSH D ;Save load address
MVI C,C.BUFF ;Set DMA address
CALL CPMENT
LXI D,TFCB ;Read record
MVI C,C.READ
CALL CPMENT
POP D ;Restore base address of record
ORA A
X0: JNZ IPLDON ;EOF
LXI H,128 ;[HL] = Record size
DAD D ;[HL] = Start of next record
X1: MVI A,IPL/256 ;Get hi byte of IPL address
CMP H ;Are we there?
X2: JNZ IPL1 ;No - continue loading program
X3: LXI D,OVFMSG ;Print '* OUT OF MEMORY*'
MVI C,C.EMSG
CALL CPMENT
JMP CPMWRM ;Reset and die
IPLDON:
XRA A
STA TBUFF ; 0 = No cmnd line passed
MVI A,' '
STA TFCB+1 ; Clear TFCB for Utilities
LXI B,CPMWRM ; Push Warm Boot addr for
PUSH B ; Utilities that just return...
JMP TPA ;CLOSE FILE AND START PROG
OVFMSG:
DB CR,LF,'* Out of Memory *',CR,LF,'$'
ENDIPL:
.DEPHASE
ENDIF
; ================
IF MOD1
LOADER:
IPL: CALL M.GET ;Read character
JNZ M.ABRT ;In case of error
CPI 2 ;Is it EOF ?
.Z80
JR Z,(IPL1) ;Get start address
.8080
CPI 1 ;Is it data ?
JNZ M.ABRT ;Not data then error
CALL M.GET ;Length + 2
DCR A
DCR A
MOV B,A ;Length
CALL M.GET ;Load address
JNZ M.ABRT ;In case of error
MOV L,A
CALL M.GET
JNZ M.ABRT ;In case of error
MOV H,A
IPL0: CALL M.GET ;Get data
MOV M,A ;Put data in load address
INX H ;Increment load address
DCR B ;# of bytes left to load
.Z80
JR NZ,(IPL0)
JR Z,(IPL)
.8080
IPL1: CALL M.GET ;Get second 2 (EOF)
CPI 2
JNZ M.ABRT ;In case of error
CALL M.GET ;Get start address
JNZ M.ABRT ;In case of error
MOV L,A
CALL M.GET
JNZ M.ABRT ;In case of error
MOV H,A
PCHL ;Run program
ENDIPL:
ENDIF
; ================
IF CPM OR ISIS OR MOD1
$$MOV:
LDAX D
MOV M,A
INX D
INX H
DCR B
JNZ $$MOV
RET
ENDIF
DSEG
.NFWA: DS 2 ; Temp for FWA of Filename
IF ISIS
I.FCB: DW I.FNAM ;Pntr to Filename
DW 0 ;Bias field
DW 1 ;RETSW, Xfer control to new pgm
DW I.NTRY ;Pntr to Entry addr store
DW I.STAT ;Status
; --
I.FNAM: DS 15 ;Filename
I.NTRY: DS 2 ;Entry Point Address
I.STAT: DS 2 ;Ret Status
ENDIF
END