home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
RCPM
/
FASTGO11.AQM
/
FASTGO11.ASM
Wrap
Assembly Source File
|
2000-06-30
|
15KB
|
632 lines
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;$ Program name: FASTGO vers. 1.1 $
;$ Program author: James Whorton $
;$ Originally written: 04/25/84 $
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;
;FASTGO 1.1 : A PROGRAM DESIGNED TO MAKE IT EASIER
;TO MOVE TO A SPECIFIC, LABELED DRIVE/USER AREA.
;INTENDED MAINLY FOR HARD DISK SYSTEMS, BUT SHOULD
;WORK EQUALLY WELL ON ANY 2.2 SYSTEM. ALLOWS PASSWORD
;PROTECTING AND CHAINING TO ANOTHER PROGRAM AFTER
;ENTERING NEW USER-AREA. FOR USAGE, TYPE GOTO.
;
;***************************************************
;REVISIONS:
;
;05/06/84 VERS. 1.1:
; ADDED RELOCATION OF CODE TO HIGHMEM SO
; THAT A .COM FILE MAY BE LOADED AND RAN FROM
; 100H. ADDED DRIVE AND USER # DISPLAY TO
; USAGE ROUTINE. (JHW)
;***************************************************
;
;WHEN EXECUTED, THIS PROGRAM DOES THE FOLLOWING:
;
;1. RELOCATES ITSELF TO HIGH MEM (SET BY USER).
;2. CHECKS FOR INPUT, PRINTS OPTIONS AND QUITS IF NONE.
;3. EVALUATES INPUT, SEEKING A MATCH FROM THE TABLE.
;4. IF NO MATCH FOUND, TELL USER, DISPLAY OPTIONS AND QUIT.
;5. ON MATCH, CHECK FOR PASSWORD STATUS AND GET IT IF NEEDED.
;6. IF PASSWORD DOESN'T MATCH, ABORT.
;7. SELECT SPECIFIED USER-AREA.
;8. IF RUNCOM = TRUE, LOAD AND RUN A .COM FILE.
;9. EXIT TO SYSTEM.
;
;NOTE: I'VE SEEN A UTILITY OF THIS TYPE ON OTHER
;SYSTEMS, BUT HAVE NEVER BEEN ABLE TO LOCATE THE
;SOURCE CODE. SO I WROTE THIS ONE. THIS CODE IS CRUDE,
;BUT IT DOES THE JOB. I'M PLANNING ON MOVING UP TO A
;HARD DISK SYSTEM IN THE FAIRLY NEAR FUTURE SO I'M
;GATHERING UTILITIES FOR IT.
;
;RENAME THIS FILE TO GOTO.COM.
; GOTO DISPLAYS USAGE AND VALID USER-AREAS
; GOTO USER-AREA MOVES TO USER-AREA. IF PASSWORDED,
; GETS SAME FROM USER BEFORE MOVING.
;
;JAMES H. WHORTON
;402-346-4206 DATA
;402-341-0770 VOICE
;
;---------------------------------------------------
;THIS IS THE RUNNING LOCATION OF THE MAIN CODE. PUT IT
;HIGH ENOUGH SO THAT THE .COM FILE YOU LOAD, IF ANY,
;WILL NOT OVERLAY IT.
;
DEST EQU 0A000H ;RUNNING LOCATION
;.....
;EQUATES SECTION
;
WARM EQU 0 ;WARM START
BDOS EQU 5 ;BDOS CALL VECTOR
CIN EQU 1 ;CONSOLE IN
COUT EQU 2 ;CONSOLE CHAR. OUT
DIO EQU 6 ;DIRECT I/O CALL
CSTAT EQU 12 ;CONSOLE STATUS
RSTDSK EQU 13 ;RESET DISK SUBSYSTEM
STDSK EQU 14 ;SET DEFAULT DISK
OPEN EQU 15 ;OPEN FILE
READ EQU 20 ;READ SEQUENTIAL RECORD
STDMA EQU 26 ;SET DMA ADDRESS
STUSR EQU 32 ;GET/SET USER #
FCB EQU 05CH ;FIRST FCB
CR EQU 13 ;CARRAIGE RETURN
LF EQU 10 ;LINE FEED
BELL EQU 7 ;CONSOLE BELL
TRUE EQU 0FFH
FALSE EQU 0
DEFBYT EQU 4 ;CURRENT DRIVE/USER BYTE
;
;...................................................
; USER SETTABLE OPTIONS
;
WIDTH EQU 3 ;# OF COLUMNS TO PRINT ACROSS
RUNCOM EQU TRUE ;SET TO TRUE IF CHAIN DESIRED
COMDRV EQU 'A'-40H ;DRIVE COM FILE IS ON
COMUSR EQU 0 ;USER # COM FILE IS IN
DIVID EQU '|' ;DIVIDER CHARACTER FOR DISPLAY
;
;...................................................
;PROGRAM STARTS HERE
;
ORG 0100H
;
;THE FOLLOWING ROUTINE MOVES THE BODY OF THE
;PROGRAM UP TO SAFE MEMORY. THE TECHNIQUE OF THE
;$+OFFSET LABELS AND THE LOAD .COM FILE CODE ARE
;ASLO FROM BYE.
;
MOVEUP: LXI B,PEND-START+1 ;NUMBER OF BYTES TO MOVE
LXI H,DEST+PEND-START+1 ;END OF MOVED CODE
LXI D,SOURCE+PEND-START ;END OF SOURCE CODE
;
MOVLOP: LDAX D ;GET BYTE
DCX H ;BUMP POINTERS
MOV M,A ;NEW HOME
DCX D
DCX B ;BUMP BYTE COUNT
MOV A,B ;CHECK IF ZERO
ORA C
JNZ MOVLOP ;IF NOT, DO SOME MORE
;
PUSH H ;SAVE RETURN ADDRESS
RET ;RETURN TO NEW ADDRESS
;
SOURCE EQU $ ;BOUNDARY MEMORY MARKER
;
OFFSET EQU DEST-SOURCE ;RELOCATION AMOUNT
;
;THE FOLLOWING CODE IS THE MAIN BODY OF THE PROGRAM.
;IT IS FIRST MOVED TO DEST, THEN EXECUTED. FROM THIS
;POINT ON, ALL LABELS MUST BE IN THIS FORMAT:
; LABEL EQU $+OFFSET
;SO THAT THE RELOCATION WILL WORK PROPERLY.
;
START EQU $+OFFSET
;
;===================================================
;
;CHECK IF USER-AREA SPECIFIED.
;
LDA FCB+1 ;GET FIRST BYTE OF FCB
CPI 32 ;BLANK?
JZ USAGE ;YES, PRINT USAGE AND QUIT
;
;OK, A USER-AREA WAS SPECIFIED. LET'S SEE HOW LONG
;IT IS
MVI B,0 ;SET UP COUNTER
LXI H,FCB+1 ;SET UP POINTER
LENCHK EQU $+OFFSET
MOV A,M ;GET A BYTE
INX H ;INCREMENT POINTER
INR B ;INCREMENT COUNTER
CPI 32 ;IS IT A BLANK?
JNZ LENCHK ;NO, GO AGAIN
MOV A,B
STA USRLEN ;STORE COUNT FOR LATER USE
;
;NOW LET'S START CHECKING THE NAME SPECIFIED AGAINST
;THE TABLE
LXI H,TABLE+2;SET UP POINTER
SHLD CHARP ;SAVE POINTER
NAMCHK EQU $+OFFSET
LHLD CHARP ;GET TABLE POINTER
MOV A,M ;CHECK FOR END OF TABLE
CPI 0 ;ARE WE THERE?
JZ NOMATCH ;YES, ERROR MESSAGE AND USAGE
LXI D,FCB+1 ;POINT TO INPUT
LDA USRLEN ;GET LENGTH OF INPUT
MOV B,A ;MOVE IT TO B
CALL COMPAR ;DO THE COMPARISON
JZ MATCH ;IT'S A MATCH, SO DO IT
LXI D,25 ;INCREMENT THE POINTER
LHLD CHARP ;GET THE POINTER BACK
DAD D ;ADD IT
SHLD CHARP ;SAVE IT
JMP NAMCHK ;TRY NEXT ENTRY
;
;A MATCH WAS FOUND, SEE IF PWD PROTECTED
;
MATCH EQU $+OFFSET
LHLD CHARP ;GET ENTRY POINTER
DCX H ;BACK UP 1 BYTES
MOV A,M ;GET ACCESS CODE
CPI '*' ;NEED A PASSWORD?
JNZ SELECT ;NOPE, GO AHEAD AND DO IT
;GET A PASSWORD FROM USER
CALL ILPRT ;PROMPT USER
DB 'Password ? ',0
LXI H,USRPWD;POINT TO STORAGE AREA
MVI B,0 ;MAX CHARS ALLOWED = 080H
PWD1 EQU $+OFFSET
PUSH H
PUSH B
MVI E,0FFH ;SEE IF CHAR THERE
MVI C,DIO
CALL BDOS
POP B
POP H
CPI 0 ;CHAR READY?
JZ PWD1 ;NOT YET
CPI CR ;END OF INPUT?
JZ PWD2 ;YES
MOV M,A
INX H ;INCREMENT POINTER
INR B ;INCREMENT CHAR COUNTER
MOV A,B ;GET COUNTER IN A TO CHECK
CPI 080H ;BUFFER FULL?
JZ PWD2 ;NOPE, GET ANOTHER CHAR
MOV B,A
JMP PWD1
;PAD INPUT BUFFER WITH SPACES
PWD2 EQU $+OFFSET
MOV B,A ;GET COUNTER BACK
MVI A,32 ;FILL INPUT WITH NULLS
MOV M,A ;PUT IT IN STORAGE
INX H
INR B
MOV A,B ;CHECK COUNTER
CPI 080H ;FULL YET?
JNZ PWD2 ;NOPE, TRY IT AGAIN
;
;NOW DO THE CHECK
PWD3 EQU $+OFFSET
LHLD CHARP;POINT TO TABLE ENTRY
LXI D,13
DAD D
LXI D,USRPWD
MVI B,10 ;CHECK 10 CHARS (PWD LENGTH)
CALL COMPAR ;DO A COMPARISON
JZ SELECT ;CORRECT PASSWORD SUPPLIED
CALL ILPRT ;NOPE, SAY FORGET IT
DB BELL,'++ Invalid password.',CR,LF,0
JMP DONE ;DISPLAY CORRECT AREAS
;
;WE GOT THIS FAR, LET'S CHANGE THE USER # AND DRIVE
SELECT EQU $+OFFSET
LHLD CHARP ;POINT TO TABLE
DCX H ;BACK UP 2 BYTES
DCX H
MOV A,M ;GET VALUE FROM TABLE
PUSH H
STA DEFBYT ;PUT IT IN MEMORY BYTE
STA DRVUSR
ANI 0FH ;MASK OUT USER #
STA NEWDRV ;SAVE FOR LATER
MOV E,A
MVI C,STDSK ;SELECT THE DRIVE
CALL BDOS
POP H ;NOW SET THE USER #
MOV A,M ;GET THE BYTE
ANI 0F0H ;MASK OUT DRIVE
RAR ;ROTATE 4 TIMES TO GET USER #
RAR ;IN PROPER POSITION
RAR
RAR
STA NEWUSR ;SAVE IT FOR LATER
MOV E,A ;DO IT
MVI C,STUSR
CALL BDOS
MVI C,RSTDSK
CALL BDOS
;
;ROUTINE TO LOAD THE COM FILE
;
IF RUNCOM
LODCOM EQU $+OFFSET
;SELECT USER # TO LOAD FROM
MVI E,COMUSR
MVI C,STUSR
CALL BDOS
;
MVI A,COMDRV;INITIALIZE FCB
STA COMFIL
LXI H,COMFIL+12
MVI B,21
;
ZLOOP EQU $+OFFSET
MVI M,0
INX H
DCR B
JNZ ZLOOP
;
MVI C,OPEN ;NOW OPEN THE FILE
LXI D,COMFIL
CALL BDOS
INR A ;SHOULD BE NON-ZERO
JZ NOFILE ;NO FILE, ABORT
;
;NOW LOAD THE FILE
LHLD 6 ;GET TOP OF MEMORY
LXI D,-80H ;RECORD LOADS CAN'T START..
DAD D ;..ABOVE (BDOS) - 80H
PUSH H ;SAVE ON STACK
;
LXI D,80H ;TPA-80H
LXI B,0 ;KEEP A RECORD COUNTER
PUSH B ;SAVE COUNTER
PUSH D ;AND LOAD ADDRESS
;
GLOOP EQU $+OFFSET
POP D ;GET TPA ADRS
LXI H,80H ;POINT TO NXT ADRS TO READ TO
DAD D ;HL HAS THE ADDRESS
POP B ;INCREMENT THE COUNTER
;CHECK FOR LOAD PAST TOP-OF-MEMORY
POP D ;GET (TOP-OF-MEMORY)
PUSH D ;RE-SAVE FOR NEXT TIME
MOV A,E ;SUBTRACT: (TOP) - (ADRS)
SUB L
MOV A,D ;ONLY THE CARRY NEEDED
SBB H
JNC SIZEOK ;CY= BETTER MOVCPM
CALL ILPRT ;SO TELL THE STORY
DB BELL,'++ Program area too small ++ Aborting...',0
JMP DONE ;EXIT
;
SIZEOK EQU $+OFFSET
INX B
PUSH B
PUSH H ;SAVE TPA ADRS
XCHG ;ALIGN REGISTERS
MVI C,STDMA ;TELL BDOS WHERE TO PUT RECORD
CALL BDOS
LXI D,COMFIL ;NOW READ THE RECORD
MVI C,READ
CALL BDOS
ORA A
JZ GLOOP ;A=0 IF MORE TO READ
POP B ;UNJUNK STACK
POP B ;THIS IS OUR COUNTER
POP H ;MORE JUNK ON STACK
MOV A,B ;CHECK FOR ZERO
ORA C
JZ NOFILE ;WE SHOULD HAVE READ SOMETHING
LXI D,80H ;WE DID, RESET DMA TO 80H
MVI C,STDMA
CALL BDOS
;
LOADOK EQU $+OFFSET
MVI A,' ' ;MAKE THE LOADED PROGRAM THINK
STA FCB+1 ;THAT NOTHING WAS PASSED IN THE
;COMMAND LINE
LDA NEWDRV
ADI 1 ;MAKE IT RIGHT FOR FCB
STA FCB ;PUT THE PROPER DRIVE INTO THE FCB
;BEFORE JUMPING TO THE .COM FILE, RESET USER # AND DRIVE
LDA NEWUSR ;USER #
MOV E,A
MVI C,STUSR
CALL BDOS
LDA NEWDRV ;DRIVE
MOV E,A
MVI C,STDSK
CALL BDOS
MVI C,RSTDSK;RESET DISK SYSTEM
CALL BDOS
;
;BLANK THE FCB
MVI B,11
LXI H,FCB+1
QLOOP EQU $+OFFSET
MVI M,' '
INX H
DCR B
JNZ QLOOP
LXI H,FCB+1
;
;NOW JUMP TO THE CHAIN FILE
JMP 0100H ;NOW RUN IT.
;
NOFILE EQU $+OFFSET
CALL ILPRT
DB CR,LF
DB BELL,'++ Cannot find COM file ++',0
;
ENDIF
JMP DONE ;QUIT
;
NOMATCH EQU $+OFFSET
CALL ILPRT
DB CR,LF,BELL,'++ Invalid user-area specified ++',0
;
;
;NO OPTION SPECIFIED, OR BAD ONE, SO LIST USAGE AND
;TABLE OF DEFINITIONS.
;
USAGE EQU $+OFFSET
CALL ILPRT
DB CR,LF,'FASTGO 1.1 05/06/84 James Whorton'
DB CR,LF,LF,'GOTO Displays user-area info.'
DB CR,LF,'GOTO USER-AREA Moves to the specified user-area.'
DB CR,LF,LF,'Defined user-areas are --'
DB CR,LF,0
;
;THIS ROUTINE PRINTS THE DEFINITION TABLE. IT PRINTS
;<WIDTH> COLUMNS ACROSS AND DOES NOT DISPLAY ANY PASSWORDS.
LXI H,TABLE+2;POINT TO NAMES
MVI D,13 ;# OF BYTES PER ENTRY TO PRINT
MVI B,WIDTH ;# OF COLUMNS TO PRINT
CALL HEADER ;PRINT FIRST ENTRY HEADER
;NOW SEND CHAR AND CHECK FOR END OF ENTRY
INFO1 EQU $+OFFSET
CALL ENDCHK
MOV A,M ;BE SURE IT'S THERE
CALL CTYPE ;SEND IT
INX H ;INCREMENT POINTER
DCR D ;DECREMENT CHAR COUNTER
MOV A,D ;GET CHAR COUNT TO CHECK
CPI 0 ;END OF ENTRY?
JNZ INFO1 ;NO, DO ANOTHER BYTE
;
;DONE WITH ONE ENTRY, SO EVALUATE
;FIRST, SKIP PAST PASSWORD SECTION, PRINT DIVIDER
;AND NEW LINE
MVI D,13 ;RESET CHAR COUNTER
MVI A,12 ;# OF CHARS TO SKIP
SKIP EQU $+OFFSET
INX H ;INCREMENT POINTER
DCR A ;DECREMENT CHAR COUNTER
CPI 0 ;PAST IT YET?
JNZ SKIP ;NOPE, NOT YET
;
CALL ENDCHK ;SEE OF END OF TABLE REACHED
DCR B ;DECREMENT COLUMN COUNT
MOV A,B ;GET COUNT
CPI 0 ;NEED A NEW LINE?
JZ SKIP1 ;YES
;PRINT A DIVIDER SECTION
PUSH H
PUSH D
PUSH B
MVI E,DIVID
MVI C,COUT
CALL BDOS
POP B
POP D
POP H
CALL HEADER ;PRINT HEADER
JMP INFO1 ;NOW BACK TO THE GRIND
SKIP1 EQU $+OFFSET
MVI A,CR ;START A NEW LINE
CALL CTYPE
MVI A,LF
CALL CTYPE
MVI B,3 ;RESET COLUMN COUNTER
CALL ENDCHK
CALL HEADER
JMP INFO1
;
;CHECK FOR END OF ENTRY TABLE
;
ENDCHK EQU $+OFFSET
PUSH D
PUSH B
MOV A,M ;GET BYTE
CPI 0 ;END OF TABLE?
JZ DONE ;YES, QUIT
POP B
POP D
RET
;
DONE EQU $+OFFSET
JMP WARM ;QUIT
;
;SUBROUTINES
;
;DISPLAY THE DRIVE AND USER # FROM THE TABLE ENTRY
HEADER EQU $+OFFSET
PUSH D ;SAVE REGISTERS
PUSH B
DCX H ;BUMP DOWN 2
DCX H
SHLD CHARP ;SAVE POINTER FOR LATER
MOV A,M ;GET BYTE
ANI 0FH ;GET DRIVE
ADI 65 ;MAKE ASCII
MOV E,A
MVI C,COUT
CALL BDOS
LHLD CHARP ;GET POINTER BACK
MOV A,M ;GET BYTE AGAIN
ANI 0F0H ;GET USER #
RAR ;ROTATE 4
RAR
RAR
RAR
CPI 9 ;IS IT > 9?
JNC DECOUT ;YES, BRANCH TO SUBROUTINE
ADI 48 ;NO, SO MAKE ASCII AND PRINT
MOV E,A
MVI C,COUT
CALL BDOS
CALL ILPRT
DB '> ',0
HEADFIN EQU $+OFFSET
POP B ;RESTORE REGISTERS
POP D
LHLD CHARP ;GET POINTER BACK ONE MORE TIME
INX H ;BUMP BACK TO WHERE IT CAME FROM
INX H
RET ;FINISHED, RETURN
;
DECOUT EQU $+OFFSET
MOV B,A ;SAVE IT FOR A SEC
PUSH B
MVI E,'1' ;PRINT FIRST HALF OF VALUE
MVI C,COUT
CALL BDOS
POP B ;GET VALUE BACK
MOV A,B
SUI 10 ;VALUE-10=SECOND DIGIT VALUE
ADI 48 ;MAKE IT ASCII
MOV E,A
MVI C,COUT
CALL BDOS
MVI E,'>'
MVI C,COUT
CALL BDOS
JMP HEADFIN ;FINISHED
;
;CONVERT THE ASCII VALUE IN A TO A 2 DIGIT DECIMAL VALUE
;AND PRINT IT
;
OUTDEC EQU $+OFFSET
;
;DO A COMPARISON, ABORT IF MATCH FOUND
;
;COMPARE ROUTINE, # OF CHARS IN B, TEXT TO CHECK IN
;DE (INPUT) AND HL (TABLE)
;IF A MATCH, ZERO FLAG WILL BE SET ON EXIT
COMPAR EQU $+OFFSET
LDAX D ;GET A CHAR.
CALL UCASE ;MAKE SURE IT'S UPPER CASE
CMP M ;CHECK IT AGAINST TEXT
RNZ
INX H
INX D
DCR B
JNZ COMPAR
RET
;
ILPRT EQU $+OFFSET
XTHL
ILPLP EQU $+OFFSET
MOV A,M
ORA A
JZ ILPRET
CALL CTYPE
INX H
JMP ILPLP
ILPRET EQU $+OFFSET
XTHL
RET
;
CTYPE EQU $+OFFSET
PUSH B
PUSH D
PUSH H
MOV E,A
MVI C,COUT
CALL BDOS
POP H
POP D
POP B
RET
;
UCASE EQU $+OFFSET
CPI 061H ;CONVERTS LOWER CASE...
RC ;IN A TO UPPER CASE
CPI 07BH
RNC
ANI 05FH
RET
;==================================================
;END OF PROGRAM AREA
;
;STORAGE AREA
;
USRPWD EQU $+OFFSET
DS 080H ;STORAGE FOR INPUT
NEWDRV EQU $+OFFSET
DS 1 ;STORE NEW DRIVE
DRVUSR EQU $+OFFSET
DS 1
;
;*****
;THIS IS THE DEFINITION TABLE SECTION.
;
;FORMAT:
; DB 1,'233333333333334444444444'
;
;BYTE PURPOSE
;--------- -----------------------------------------
; 1 USER # AND DRIVE (EXAMPLES FOLLOW):
; 00H=A0,01H=B0,010H=A1,011H=B1, ETC.
; 2 ACCESS CODE(* FOR PASSWORDED)
; 3-15 USER-AREA NAME
; 16-25 PASSWORD (IF INDICATED IN ACCESS CODE)
;THE EXAMPLES MAY BE CHANGED, ADDED TO OR DELETED
;AS LONG AS THE PROPER FORMAT IS KEPT. ALL ENTRIES
;IN TABLE SHOULD BE IN UPPER CASE.
;
;FORMAT GUIDE... 1, '233333333333334444444444'
TABLE EQU $+OFFSET
DB 00H, ' REMOTE '
DB 01H, ' IWOJIMA '
DB 021H,' FILES '
DB 010H,'*RESERVED SORTX '
DB 011H,'*SECRET HOWDY '
DB 012H,' KEEP '
DB 0A1H,' HIGHMEM '
;NOTE: THE FOLLOWING 4 BYTES MUST BE KEPT AT THE
;END OF THIS TABLE!
DB 0,0,0,0
;
;
;IF YOU WISH TO AUTOBOOT A .COM FILE UPON ENTERING THE
;NEW USER-AREA, SET RUNCOM TO TRUE AND INSERT THE PROPER
;FILE NAME IN COMFIL.
;NOTE: THE .COM FILE YOU CHAIN TO MUST EXIT TO CP/M
;WITH A WARM BOOT OR THE USER-AREA WILL NOT BE CORRECTLY
;SELECTED.
;
COMFIL EQU $+OFFSET
DB 0,'SD COM'
; ^^^^^^^^^^^ <--MUST BE 11 CHARS.
;
CHARP EQU $+OFFSET
DS 2 ;NEXT CHAR. ADDRESS POINTER
USRLEN EQU $+OFFSET
DS 1 ;LENGTH OF USER-AREA SPECIFIED
NEWUSR EQU $+OFFSET
DS 1 ;NEW USER # TO MOVE TO
;
;** THIS MARKS THE END OF THE CODE TO BE RELOCATED.
;
PEND EQU $+OFFSET
;
END