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
/
SIMTEL
/
CPMUG
/
CPMUG078.ARK
/
MAKE.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-02-10
|
12KB
|
382 lines
********************************************
* MAKE USER NUMBER CHANGE *
* *
* SYNTAX: A>MAKE FILENAME.TYP 5 *
* OR A>MAKE *.ASM 3 *
* *
* (ALLOWS ALL AMBIGOUS FILES FOR MULTI- *
* PROCESSING OF FILES) *
* *
* PROGRAM DESIGNED TO ALLOW PROGRAMS TO *
* BE CHANGED FROM ONE USER AREA TO ANOTHER*
* THE USER NUMBER FOR A FILE IS STORED IN *
* DIRECTORY ENTRY FOR THAT FILE IN THE DR *
* (FIRST) BYTE IN ITS FCB. THIS PROGRAM *
* ASSUMES THAT THE TRACK AND SECTOR ARE *
* SET BY THE SEARCH FUNCTIONS AND USES A *
* SIMPLE BIOS WRITE TO UPDATE THE DIREC- *
* TORY. THIS PROGRAM DOES NOT COPY THE *
* FILE INTO THE NEW USER NUMBER, ONLY *
* CHANGE THE NUMBER FOR AN EXISTING FILE. *
* IF YOUR BIOS DOES SOMETHING OTHER *
* THAN THE STANDARD BIOS WRITE ROUTINE *
* AS INDICATED IN THE CP/M DOCUMENTATION *
* THEN THIS PROBABLY WON'T WORK. IT HAS *
* BEEN CHECKED ONLY ON A THINKER TOYS 2D *
* SO BEFORE YOU USE THIS PROGRAM, TEST *
* IT ON A GARBAGE DISK THAT YOU DON'T *
* MIND LOSING. *
* *
* VERSION 1.0 - 07/05/81 R.E.D. *
* 1.1 - 07/15/81 R.E.D. *
* *
********************************************
ENTRY EQU 0005H ;BDOS ENTRY ADDRESS
BUFFER EQU 80H ;DEFAULT CP/M BUFFER
FCB EQU 5CH ;DEFAULT CP/M FCB
TFCB EQU 6CH ;TEMPORY FCB
ORG 0100H
MAKE: LHLD ENTRY + 1 ;GET BDOS ADRESS
MVI L,0 ;MAKE PAGE START
SPHL ;SET UP STACK HERE
LXI D,MAKMSG ;SIGN ON
CALL PRNTLIN ; PRINT IT
CALL VERSNO ; CHECK FOR 2.0 OR UP
CPI ' ' ;AT LEAST 20
JNC GOODVER ;JUMP IF VERSION OK
LXI D,BADVER ; AND RETURN
PRNRET: CALL PRNTLIN ;PRINT CONSOLE MESSAGE
CPMRET: CALL CRLF ; CR/LF FOR END
JMP 0000 ;SILENT RET REMOVED BECAUSE
;- DIRECTORY SUM CHECK
;- GETS MESSED UP DURING THIS
;- ROUTINE; SO YOU NEED WBOOT
;- TO UPDATE BDOS AFTERWARDS.
;
;CHOOSE NOT TO USE CR/LF ROUTINE BUT INCORPORATED
;CR/LF IN MESSAGE STRING
;
********************
* CONSOLE MESSAGES *
********************
MAKMSG: DB 0DH,0AH,'MAKE USER CHANGE - Ver. 1.1',0DH,0AH,'$$$'
BADVER: DB 0DH,0AH,'Requires CP/M version 2.0 or higher.',0DH,0AH
DRVERR: DB 0DH,0AH,'Drive select error',0DH,0AH,'$$$'
BADSEC: DB 0DH,0AH,'Bad Sector Write Error',0DH,0AH,'$$$'
ROMSG: DB 0DH,0AH,'Drive is set to R/O',0DH,0AH,'$$$'
USRMSG: DB 0DH,0AH,'User must be 0-15',0DH,0AH,'$$$'
FROMSG: DB ' is R/O',0DH,0AH,'$$$'
SYSMSG: DB ' is SYS',0DH,0AH,'$$$'
EQUMSG: DB ' = $$$'
WRITE: JMP 0000 ;VECTOR TO BIOS WRITE ROUTINE
;FILLED IN LATER
WRTOK: DB 0 ;FLAG FOR CHANGE REQUIRING WRITE
;SET IF CHANGE TO DIRECTORY MADE
AMBFIL: ;FCB FOR MATCH ANYTHING FILE
DB '????????????????',0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0
USERNO: DB 0 ;STORAGE FOR NEW USER NUMBER
;OBTAINED FROM TFCB
DIRCODE:DB 0 ;STORAGE FOR DIRECTORY CODE
;PROVIDED BY BDOS IN ACCUM
DBOFF: DW 00 ;ADDRESS FOR CURRENT FCB
;IN THE BUFFER STARTING AT 80H
;CREATED BY (32 * DIRCODE + BUFFER
;ADDRESS) 32 BYTES PER DIR ENTRY
DRVNO: DB 00 ;STORAGE FOR SELECTED DRIVE NUMBER
;PROVIDED BY FCB DR BYTE(1ST BYTE)
;AND CONFIRMED BY BDOS IF NEEDED
GOODVER:LXI H,0 ;CLEAR STORAGE LOCATIONS IN MEMORY
MOV A,H ;JUST TO ENSURE THEIR CONTENTS
STA USERNO ;NOT REALLY NEEDED BUT WHY NOT
STA WRTOK
STA DRVNO
STA DIRCODE
SHLD DBOFF
LHLD 0001 ;GET WBOOT ADDR (BASE OF BIOS + 3)
;ADDRESS WRITTEN THERE BY CP/M
LXI D,27H ;OFFSET FOR JUMP TO BIOS WRITE
;SECTOR ROUTINE (BASE OF BIOS + 2AH)
DAD D ;COMPUTE ADDRESS FOR WRITE ROUTINE
SHLD WRITE + 1 ; LOAD OUR VECTOR WITH THIS ADDRESS
;NOW A JUMP TO WRITE SHOULD WRITE
;A SECTOR BACK TO THE DISK
LXI H,TFCB + 1 ;GET THE NEW USER NUMBER
***************************
* GET THE NEW USER NUMBER *
* FROM THE TEMP FCB AT 6CH*
* AND CONVERT IT FROM *
* ASCII TO BINARY *
***************************
GETURS: LXI B,0BH ;COUNTER TO LOOK AT ALL OF TFCB
; SOMEONE MIGHT TYPE SEVERAL SPACES
MVI E,0 ;E WILL RECORD THE NUMBER OF
; CHARACTERS OTHER THEN BLANKS
; SO THAT WE CAN CHECK IF TFCB
; HAS ALL BLANKS (ERROR)
NUM1: MOV A,M ;GET BYTE FROM TFCB
CPI 20H ;IGNORE BLANKS
JZ NUM2 ; IF ' ' THAN JUMP AND DCR COUNT
INX H ;ELSE UPDATE POINTERS
INR E ;NOT A BLANK SO INCR COUNTER
SUI 30H ;MAKE BINARY FROM ASCII
CPI 0AH ;MUST BE NUMERIC
JNC USRERR ; REPORT ERROR AND RETURN
MOV D,A ;SAVE NUMBER FOR LATER
MOV A,B ;GET TOTAL THUS FAR
RLC ;MULT BY 10 / ROTATE IT
RLC ; TO THE NEXT DECIMAL DIGIT
RLC ;ROTATES DOUBLE;
ADD B ;2,4,8; NOW ADD 9TH & 10TH
ADD B
ADD D ;AND ADD CURRENT DIGIT
MOV B,A ;SAVE THE TOTAL FOR NEXT LOOP
NUM2: DCR C ;DCR TFCB COUNTER
JNZ NUM1 ; AND LOOP UNTIL COUNTER = 0
CPI 0 ;MUST BE AT LEAST 1
JZ USRERR ; ELSE REPORT ERROR IF ALL BLANKS
MOV A,B ;GET TOTAL BINARY USER NUMBER
CPI 10H ;IS IT GREATER THAN 15?
JNC USRERR ;REPORT ERROR IF > 15
CPI 0 ;BUT MUST BE 0 OR GREATER
JC USRERR ;SO JUMP IF LESS THAN ZERO
STA USERNO ;SAVE USER NUMBER FOR LATER
LDA FCB ;GET FCB DRIVE NUMBER (1ST BYTE)
CPI 0 ;CHECK FOR DEFAULT DRIVE (0)
JZ DEFAULT ;JUMP IF DEFAULT ELSE SUBTRACT 1
SBI 01 ; TO CONVERT INTO BDOS USABLE
; DRIVE NUMBER A=0,B=1,C=2
STA DRVNO ;SAVE DRIVE NUMBER FOR LATER
JMP RDONLY
DEFAULT:MVI C,19H ;BDOS GET DRIVE NUMBER FUNCTION
CALL ENTRY ;GET DRIVE NUMBER
STA DRVNO ;SAVE THE ACTUAL DRIVE NUMBER
;
; CHECK DRIVE FOR READ ONLY STATUS - DO THIS BEFORE SELECTING
; DRIVE BECAUSE SELECTION WILL VOID R/O STATUS
;
RDONLY: MVI C,1DH ;BDOS R/O VECTOR FUNCTION
CALL ENTRY ;DO IT
LDA DRVNO ;GET THE DRIVE NUMBER BACK
ADI 02 ;INCREMENT COUNT TO
; ROTATE VECTOR BIT TO CARRY
MOV C,A ;SET UP ROTATE
SHIFT: DCR C ;CHECK FOR END
JZ CHECK ;CHECK CARRY IF FINISHED
MOV H,A ;ELSE GET FIRST BYTE
ORA A ;CLEAR CARRY
RAR ;SHIFT IT
MOV H,A ;AND PUT IT BACK
MOV A,L ;GET NEXT BYTE
RAR ;SHIFT IT
MOV L,A ;PUT IT BACK
JMP SHIFT ;LOOP FOR MORE
CHECK: JC ROERR ;JUMP IF CARRY SET
LDA DRVNO ;GET DRIVE NUMBER
MOV E,A ;SET UP FOR BDOS CALL; MOVE
;DRIVE NUMBER TO E
MVI C,0EH ;BDOS SELECT DISK FUNCTION
CALL ENTRY ;DO IT LOGIC IS MESSED UP HERE
;CAUSE DEFAULT DRIVE IS RESELECTED.
;IT IS NEEDED IF OTHER THAN DEFAULT
;TO SELECT THE DRIVE BUT I CHOOSE
;NOT TO MAKE THE CHECK AND SELECT
;THE DRIVE EVEN IF IT IS THE DEFAULT.
LXI D,AMBFIL ;POINT TO MATCH ANY FILENAME.TYP
MVI C,11H ;BDOS SEARCH FIRST FUNCTION
CALL ENTRY ;DO IT
STA DIRCODE ;SAVE DIRECTORY CODE
CPI 0FFH ;SEE IF END OF ENTRIES
JZ CPMRET ;RETURN IF END
;
; MAIN PROGRAM FUNCTION LOOP
;
LOOP: LDA DIRCODE ;GET THE DIRECTORY CODE
ADD A ;OFFSET BY 32 BYTES PER ENTRY
ADD A
ADD A
ADD A
ADD A
MOV E,A ;PREPARE FOR OFFSET COMPUTATION
MVI D,00 ;CLEAR HIGH BYTE
LXI H,BUFFER ;GET BUFFER ADDRESS
DAD D ;COMPUTE OFFSET INTO BUFFER
SHLD DBOFF ;SAVE THE ADDRESS INTO THE BUFFER
XCHG ;SWAP
LDAX D ;GET THE DR BYTE FOR THIS ENTRY
CPI 0E5H ;SEE IF ERASED
JZ INDIRCD ;JUMP TO DO NEXT ENTRY IF ERASED
LXI H,USERNO ;POINT TO USER NUMBER
CMP M ;SEE IF OLD AND NEW USER NUMBER
; ARE THE SAME
JZ INDIRCD ;JUMP TO DO NEXT ENTRY
;
COMPARE:LXI H,FCB+1 ;POINT TO FIRST CHARACTER
; OF FCB AT 5DH
MVI C,0AH ;LOAD COUNT FOR COMPARE
XCHG ;SWAP
INX H ;INCR PAST DIRECTORY USER NUMBER
CP1: LDAX D ;GET FCB FILE CHARACTER
CPI '?' ;SEE IF ANYTHING MATCHES
JZ MATCH ;JUMP PAST COMPARE IF '?'
SUB M ;COMPARE THRU SUBTRACTION
ANI 7FH ;CLEAR HIGH (FLAG) BIT
;WE'LL CHECK FLAGS LATER
JNZ INDIRCD ;QUIT IF NO MATCH
MATCH: INX D ;POINT TO NEXT CHARACTERS
INX H
DCR C ;DECREASE COUNT OF CHARACTERS
JNZ CP1 ;LOOP UNTIL ZERO
LHLD DBOFF ;GET OFFSET BUFFER ADDRESS
XCHG ;SWAP
LXI H,09 ;OFFSET TO t1 BYTE IN DIRECTORY
DAD D ;COMPUTE ADDRESS
MOV A,M ;GET THE CHARACTER
RAL ;CHECK R/O FLAG IN CARRY
JC FROERR ;PRINT FILE NAME, ERROR AND CONTINUE
INX H ;OFFSET TO t2 BYTE IN DIRECTORY
MOV A,M ;GET THIS CHARACTER
RAL ;CHECK SYS FLAG IN CARRY
JC SYSERR ;PRINT FILE NAME, ERROR AND CONTINUE
LHLD DBOFF ;GET OFFSET ADDRESS
LDA USERNO ;GET THE NEW USER NUMBER
MOV M,A ;PUT NEW USER NUMBER IN DIRECTORY
;BUFFER ENTRY FCB BYTE 0
LDA WRTOK ;GET WRITE FLAG
INR A ;INCREASE FLAG
STA WRTOK ;SAVE UPDATED FLAG
CALL FILPRN ;PRINT THE FILE NAME
LXI D,EQUMSG ;PRINT '='
CAL╠ PRNTLI╬ ;DO IT
LDA USERNO ;GET USER NUMBER
CPI 09 ;SEE ONE OR TWO DIGIT USER NUMBER
JNC DOUBLE ;JUMP IF TWO DIGITS
SINGLE: ADI 30H ;ELSE CONVERT TO ASCII
MOV E,A ;SET UP FOR OUTPUT
CALL CHAROUT ;AND PRINT IT
JMP INDIRCD ;JUMP FOR NEXT ENTRY
DOUBLE: ADI 26H ;SUBTRACT 9 TO GET FIRST DIGIT
; AND ADD 30H TO MAKE ASCII.
; OR JUST ADD 26H TO DO BOTH...
PUSH PSW ;SAVE THIS DIGIT AND PRINT '1'
MVI E,'1' ;LOAD THE CHARACTER
CALL CHAROUT ; AND PRINT IT
POP PSW ;GET THE REMAINDER DIGIT
MOV E,A ;SET UP FOT PRINT
CALL CHAROUT ; AND DO IT
INDIRCD:LDA DIRCODE ;GET THE DIRECTORY CODE
INR A ;INCREASE IT ONE
STA DIRCODE ;SAVE NEW KEY INTO BUFFER
CPI 04 ;ONLY FOUR ENTRIES IN BUFFER
JZ WRTBUF ;UPDATE BUFFER IF LAST ENTRY
JMP LOOP ;ELSE LOOK AT REMAINDER OF BUFFER
WRTBUF:LDA WRTOK ;GET WRITE FLAG - ANYTHING GREATER
; THAN ZERO MEANS A CHANGE WAS MADE
CPI 0 ;CHECK FOR CHANGE MADE
JZ SRNXT ;JUMP IF NO CHANGES MADE
CALL WRTDE ;ELSE WRITE THE BUFFER BACK TO
; THE DIRECTORY
XRA A ;ZERO ACCUM TO CLEAR WRITR FLAG
STA WRTOK ;SAVE CLEARED FLAG
SRNXT: LXI D,AMBFIL ;POINT TO ANY MATCH FCB
MVI C,12H ;BDOS SEARCH NEXT FUNCTION
CALL ENTRY ;DO IT
CPI 0FFH ;SEE IF END OF ENTRIES
JZ CPMRET ;AND RETURN IF NO MORE FILES
CPI 0 ;LOOP UNTIL BUFFER IS UPDATED
;BY BDOS
JNZ SRNXT ;JUMP UNTIL DIRCODE IS ZERO
STA DIRCODE ;SAVE THE 0 IN DIRCODE
JMP LOOP ; AND LOOP AGAIN
RET ;END OF MAIN PROGRAM
******************
* ERROR MESSAGES *
******************
FROERR: CALL FILPRN ;PRINT THE FILE NAME
LXI D,FROMSG ; AND R/O MESSAGE
CALL PRNTLIN
JMP INDIRCD ;AND CONTINUE
SYSERR:CALL FILPRN ;PRINT THE FILE NAME
LXI D,SYSMSG ; AND SYS MESSAGE
CALL PRNTLIN
JMP INDIRCD ;AND CONTINUE
ROERR: LXI D,ROMSG ;PRINT DISK R/O
JMP PRNRET ; AND END
SECERR: LXI D,BADSEC ;PRINT BIOS SECTOR ERROR
JMP PRNRET ; AND END
USRERR: LXI D,USRMSG ;PRINT USER NUMBER ERROR
JMP PRNRET ; AND END
VERSNO: MVI C,0CH ;BDOS VERSION NUMBER FUNCTION
JMP ENTRY
PRNTLIN:MVI C,09H ;BDOS PRINT STRING FUNCTION
JMP ENTRY
CHAROUT:MVI C,06 ;BDOS DIRECT CONSOLE I/O
JMP ENTRY
CRLF: MVI E,0DH ;PRINT CR/LF
CALL CHAROUT
MVI E,0AH
JMP CHAROUT
FILPRN: CALL CRLF ;PRINT CR/LF
LHLD DBOFF ;ADDRESS OF FILE FCB
MVI C,0CH ;FILENAME.TYP CHAR COUNT
INX H ;BYPASS DR BYTE
FP1: PUSH B ;SAVE COUNT
MVI A,4 ;CHECK FOR PERIOD POSITION
CMP C
JZ PERIOD ;PRINT PERIOD IF TIME
MOV A,M ;IGNORE BLANKS
CPI 20H
JZ FP2 ;JUMP IF BLANK
PUSH H
MOV E,A
CALL CHAROUT ;ELSE PRINT CHARACTER
POP H
FP2: POP B ;GET COUNT
DCR C ;DCR COUNT
INX H ;POINT TO NEXT CHAR
JNZ FP1 ; LOOP UNTIL ZERO
RET
PERIOD: PUSH H ;SAVE THE ADDRESS
MVI E,'.' ;PRINT THE PERIOD
CALL CHAROUT
POP H ;GET ADDRESS BACK
POP B ;GET COUNT
DCR C ;DCR COUNT
JMP FP1
WRTDE: LXI D,BUFFER ;SET DMA TO BUFFER
MVI C,1AH ;BDOS SETDMA FUNCTION
CALL ENTRY
MVI C,1H ;SET BIOS WRITE TO DIRECTORY
;WRITE VICE 0=WRITE TO ALLOCATED
; 2=WRITE TO UNALLOCATED
CALL WRITE ;BIOS WRITE
ORA A ;CHECK FOR ERROR
JNZ SECERR
LXI D,BUFFER ;RESET BUFFER ADDRESS TO BUFFER
MVI C,1AH ;BDOS SETDMA FUNCTION
JMP ENTRY
END