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
/
UTILS
/
DIRUTL
/
CHG11.LBR
/
CHG.AQM
/
CHG.ASM
Wrap
Assembly Source File
|
2000-06-30
|
11KB
|
598 lines
; CHG v1.1 04/04/86
;
; This program is a kludge of UNERA and MAKE utilities.
; It allows you to change the user area of a program without
; re-copying the entire file. It can also unerase a file.
;
; Warmboots on exit to force buffer flush/write
;
; Steve Sanders, TBKUG/DataCOM Super Systems
; (813) 791-1454/55 modem 300/1200/2400
;
;.......
;
; To use:
;
; A>CHG d:ufn.typ olduser# newuser#
;
; A>CHG C:GAME.BAS 6 0
;
; Will move GAME.BAS from user area 6 to user area 0
;
; CHG supports user#'s 0 thru 31.
;
; A>CHG C:GAME.BAS ? 4
;
; Will unerase GAME.BAS from the directory of drive C
; and restore it to C4:
;
; * * * * * * * * * * * * * * * * * *
; Conditional assembly constants
FALSE: EQU 0
TRUE: EQU NOT FALSE
; System configuration equates:
ORG 100H ;START AT BASE OF TPA
JMP BEGIN ;GET AROUND THE MESSAGES & DATA AREAS
; EQUATES
BOOT: EQU 0000H ;CP/M WARM BOOT JUMP VECTOR
BDOS: EQU 0005H ;CP/M BDOS CALL JUMP VECTOR
CR: EQU 'M'-40H ;CARRIAGE RETURN
FCB: EQU BOOT+5CH ;DEFAULT FILE CONTROL BLOCK
LF: EQU 'J'-40H ;LINE FEED
BELL: EQU 07H ;CONSOLE BELL
; CONSOLE MESSAGES
SONMSG: DB CR,LF,LF
DB 'CHG v1.1 - CP/M Change User# / Unerase Utility'
DB CR,LF,LF,'$'
BMSG: DB CR,LF,'Done -- Please <DOUBLE CHECK> file before using.'
DB bell,CR,LF,'$'
ILMSG: DB CR,LF,'ABORT -- Illegal drive requested.',bell,CR,LF,'$'
NOFMSG: DB CR,LF,'ABORT -- No file name was specified.',CR,LF,LF
DB 'Usage: chg d:ufn.typ olduser# newuser#',CR,LF,LF
DB ' chg d:ufn.typ ? user#',CR,LF,LF
DB 'Current drive is assumed if no d: parameter (optional).',CR,LF
DB 'Change unambiguous filename from olduser# to newuser#.',CR,LF
DB '"?" parameter unerases filename to specified user number.'
DB bell,CR,LF,'$'
NFMSG: DB CR,LF,'Specified filename was NOT found.',bell,CR,LF,'$'
WMSG: DB CR,LF,'Error during disk Write - ABORTING.',bell,CR,LF,'$'
BADUSR: DB CR,LF,'Bad commandline syntax - ABORTING.'
DB bell,CR,LF,'$'
; DATA AREAS
BLN: DB 0 ;'CPMCHK' STORES CP/M VERSION
DIRMAX: Dw 16 ;NUMBER OF SECTORS IN DIRECTORY =
; MAXIMUM NUMBER OF DIRECTORY ENTRIES
; DIVIDED BY 4 (ENTRIES PER SECTOR)
temp: dw 0 ;Temp storage for FCB print
maxsec: db 26 ;Maximum number of sectors/track
FIXCNT: DB 0 ;NUMBER OF ENTRIES FIXED
REWRT: DB 0 ;REWRITE FLAG 0=NO, F=YES
SECTOR: DB 0 ;CURRENT SECTOR NUMBER
TRACK: Dw 2 ;TRACK NUMBER OF DIRECTORY
OLDUSR DB 0 ;Olduser # storage
NEWUSR DB 0 ;Newuser # storage
; ADDRESS OF THE TRANSLATE TABLE
DPH: DW XLTO
DS 14
; STANDARD TRANSLATE TABLE
XLTO: DB 1,7,13,19,25,5,11,17,23,3,9,15,21
DB 2,8,14,20,26,6,12,18,24,4,10,16,22
;------------------------- main program ------------------------------
BEGIN: LXI SP,STACK ;SET STACK POINTER
CALL HELLO ;SIGN ON MESSAGE
CALL PCHECK ;CHECK PARAMETERS
CALL GETUSR ;GET USER #'S FROM CMD LINE
CALL CHANGE ;DO THE RECOVERY
CALL BYE ;SIGN OFF MESSAGE
JMP BOOT ;RETURN TO CP/M
;------------------------- subroutines -------------------------------
; SIGN OFF AND RESET SYSTEM
BYE: MVI C,13 ;SYSTEM RESET
CALL BDOS
LDA FIXCNT ;CHECK FOR ACTIVITY
ORA A
JZ NOFIND ;SAY NONE FOUND
LXI D,BMSG ;WARN FOUND
CALL PRINT
RET
; CHECKS THE CURRENT 4 DIRECTORY ENTRIES AGAINST ARGUMENT
; IF MATCH, REWRITES SECTOR WITH NEWUSER 1ST BYTES
CHKENT: XRA A ;ASSUME NO REWRITE
STA REWRT
MVI B,4 ;NUMBER OF ENTRIES PER SECTOR
LXI H,80H ;BEGINNING OF BUFFER
CKLUP: push b
MOV A,M
PUSH H
LXI H,OLDUSR ;GET USER # TO COMPARE TO
CMP M
POP H
JNZ CKINC
PUSH H ;SAVE BEGINNING ADDRESS
CALL COMPAR ;COMPARE WITH ARGUMENT
POP H
JNZ CKINC ;NO MATCH
LDA NEWUSR ;GET NEWUSER #
MOV M,A ;POKE IN TO DIRECTORY ENTRY
MVI A,0FH ;SAY NEED REWRITE
STA REWRT
LDA FIXCNT
INR A ;BUMP COUNT OF CHANGES
STA FIXCNT
CKINC: pop b
LXI D,32 ;LENGTH OF ENTRY
DAD D
DCR B
JNZ CKLUP
LDA REWRT ;SEE IF NEED REWRITE
ORA A
JZ CKDONE ;NO - DONE
; WRITE THE DIRECTORY SECTOR BACK TO THE DISK
lhld TRACK ;SET TRACK
MOV C,l
Mov B,h
CALL SETTRK
LDA SECTOR ;SET SECTOR
MOV C,A
CALL TRNSLT
MVI B,0
CALL SETSEC
CALL WRITE ;WRITE THE SECTOR BACK
ORA A
JNZ ERRWRT ;ABORT IF ERROR
CKDONE: lhld DIRMAX
dcx h ;REDUCE SECTORS LEFT
shld DIRMAX
LDA SECTOR ;POINT TO NEXT SECTOR
INR A
STA SECTOR
mov b,a
lda maxsec
dcr a
cmp b
rnc
lhld track
inx h
shld track
RET
; COMPARE 11 BYTES OF DIRECTORY ENTRY AGAINST ARGUMENT
COMPAR: shld temp ;Hold pointer in case of match
INX H
LXI D,FCB+1
XCHG
MVI C,11
CMPR1: LDAX D ;GET DIRECTORY ENTRY CHARACTER
ANI 7FH ;STRIP ANY FLAGS
CMP M
jnz cmpckam
cmpr2: INX D
INX H ;BUMP TO NEXT CHARACTER
DCR C
JNZ CMPR1 ;LOOP FOR 11 CHARACTERS
lhld temp
call printfcb
xra a
RET ;RETURNS 'ZERO' FLAG SET FOR MATCH
cmpckam:
ldax d
cpi 0e5h ;Non-allocated entry?
jz skip
mov a,m
cpi '?'
rnz
jmp cmpr2
skip: ora a
ret ;set NZ flag
; SET THINGS UP FOR CURRENT SYSTEM
; CP/M 2.X ONLY
CPMCHK: LXI D,80H ;SET DMA TO TBUFF
MVI C,26
CALL BDOS
CALL CPM22 ;IF 2.2 GO SET THINGS
CALL GTBIOS ;ESTABLISH BIOS JUMP VECTOR
; SELECT DISK AND SETUP DISK PARAMETER HEADER
LDA FCB ;GET THE DISK
mov e,a
mvi c,14
call bdos
lda fcb
MOV C,A
MVI B,0
CALL SELDSK ;MAKE SURE DRIVE IS
MOV A,H ; SELECTED
ORA L
JZ ILDISK
MOV E,M ;GET THE ADDRESS
INX H ; OF THE XLTO
MOV D,M
XCHG
SHLD DPH ;SAVE THE ADDRESS
RET
; DETERMINE NUMBER OF DIRECTORY ENTRIES ALSO
CPM22: MVI C,31 ;GET DISK PARAMETERS ADDRESS
CALL BDOS ;DPB ADDRESS IN 'HL' ON RETURN
mov a,m ;Number of sectors/track
sta maxsec
LXI D,7 ;OFFSET TO DRM
DAD D
MOV E,M ;GET NUMBER OF
INX H ; DIRECTORY ENTRIES
MOV D,M
XCHG
INX H ;ACCOUNT FOR - 1
CALL SHFHL2 ;SHIFT 'HL' RIGHT 2
shld DIRMAX ;SAVE NUMBER DIRECTORY SECTORS
LXI H,5 ;NOW POINT TO SYSTEM
DAD D ; TRACK OFFSET
MOV A,M
inx h
mov h,m
mov l,a
shld track
MVI A,48 ;SET MOVE LENGTH
STA BLN
RET
; ERROR OCCURED DURING DISK WRITE - ABORT
ERRWRT: LXI D,WMSG
CALL PRINT
JMP BOOT ;ABORT
; MAKE SURE A LEGAL FILENAME IS SPECIFIED
FCBCHK: LDA FCB ;GET DRIVE SPECIFICATION
ORA A ;SEE IF DEFAULT
JNZ FCBCK1 ;NO, GO CHECK FILENAME
MVI C,25 ;ASK FOR CURRENT DRIVE
CALL BDOS
INR A ;OFFSET FOR NEXT INSTRUCTION
FCBCK1: DCR A ;CURRENT DRIVE NUMBER
STA FCB ;SAVE IT
LDA FCB+1 ;GET 1ST BYTE OF FILENAME
CPI ' ' ;MAKE SURE IT IS NON-BLANK
RNZ ;OK - KEEP GOING
; IF NO FILE NAME IS SPECIFIED, ABORT WITH NOTICE
LXI D,NOFMSG
CALL PRINT
JMP BOOT ;ABORT
; GET BIOS JUMPS VECTORS FOR EASY REFERENCE
GTBIOS: LHLD BOOT+1 ;POINTS TO BIOS JUMP TABLE+3
LXI D,WBOOT ;WHERE WE WILL KEEP A COPY
LDA BLN ;NUMBER OF BYTES TO MOVE
MOV B,A ;MOVE LIKES IT IN REGISTER 'B'
CALL MOVE ;MOVE THE TABLE
RET
; SAY WHO WE ARE
HELLO:
LXI D,SONMSG ;POINT TO HELLO MESSAGE
CALL PRINT
RET
;SPECIFIED AN ILLEGAL DISK DRIVE - ABORT
ILDISK: LXI D,ILMSG
CALL PRINT
JMP BOOT ;ABORT
; GENERAL PURPOSE MOVE ROUTINE
; FROM 'HL' TO 'DE' FOR COUNT OF 8
MOVE: MOV A,M ;GET A BYTE
STAX D ;PUT A BYTE
INX D ;INCREMENT TO NEXT
INX H
DCR B ;COUNT DOWN
JNZ MOVE
RET
NOFIND: LXI D,NFMSG
CALL PRINT
RET
; READS NEXT SECTOR (GROUP OF FOUR DIRECTORY ENTRIES)
; RETURNS WITH ZERO FLAG SET IF NO MORE
NXTSEC: lhld DIRMAX ;SEE IF MORE SECTORS
mov a,h
ORA l
RZ ;RETURNS ZERO FLAG IF NO MORE
lhld TRACK ;SET TRACK
MOV C,l
Mov B,h
CALL SETTRK
LDA SECTOR ;SET SECTOR
MOV C,A
CALL TRNSLT
MVI B,0
CALL SETSEC
CALL READ ;READ A SECTOR
ANI 1 ;REVERSE SENSE OF ERROR FLAG
XRI 1 ;RETURNS WITH ZERO FLAG SET
RET ;IF BAD READ
; CHECK FOR VALID PARAMETERS AND SAY WHICH CP/M VERSION
PCHECK: CALL FCBCHK ;MAKE SURE FILE SPECIFIED
CALL CPMCHK ;ESTABLISH CP/M INFO
RET
; GENERAL PURPOSE PRINT ROUTINE - ENTER WITH REGS 'DE' POINTING TO MSG
; RETURNS TO CALLER FROM BDOS
PRINT: MVI C,9 ;BDOS PRINT STRING COMMAND
JMP BDOS ;GO DO THE PRINT
; FCB printing routine
printfcb:
push h
lxi d,1+8+3
dad d
mov a,m
ora a
pop h
rnz ;Print only first extent
inx h
mvi b,8
call pr1
mvi e,'.'
mvi c,2
push h
call bdos
pop h
mvi b,3
call pr1
crlf: mvi e,13 ;Send CR/LF
mvi c,2
call bdos
mvi e,10
mvi c,2
call bdos
ret
pr1: mov a,m
ani 127
cpi ' ' ;Check for blanks
jz pr2
mov e,a
push h
push b
mvi c,2
call bdos
pop b
pop h
pr2: inx h
dcr b
jnz pr1
ret
; SHIFT REGS 'HL' RIGHT 2 BITS LOGICAL
SHFHL2: CALL SHFHL ;CLEAR CARRY
SHFHL: XRA A
MOV A,H
RAR ;SHIFTED BIT IN CARRY
MOV H,A
MOV A,L
RAR
MOV L,A
RET
; TRANSLATE REG 'C' FROM LOGICAL TO PHYSICAL SECTOR NUMBER
TRNSLT: LHLD DPH ;GET ADDRESS OF XLTO
XCHG
CALL SECTRAN
MOV C,L
RET
; LOOK THROUGH DIRECTORY
CHANGE: CALL NXTSEC ;GET A DIRECTORY SECTOR
RZ ;RETURNS ZERO FLAG IF NO MORE
CALL CHKENT ;CHECK IT OUT AND MAYBE FIX
JMP CHANGE ;KEEP IT UP TILL DONE
; This routine get the user# from the command line.
getusr:
push h
lxi h,81h ;Start of tail string of cmd line
call skipsp ;Skip space(s)
loop1:
mov a,m ;Skip filename
cpi 20h ;by looking for space
inx h
jnz loop1
call skipsp ;Skip space(s) if necessary
call convert ;Get olduser# to use
sta oldusr
call skipsp
call convert ;Get newuser #
sta newusr
pop h
ret
skipsp:
mov a,m ;move past space(s) in line
cpi 20h
rnz ;Return if not a space
inx h
jmp skipsp
convert:
mov a,m ;Check for Unera operation
cpi '?' ;Check for UNERA operation
jz unera
sui 30h ;convert to binary
mov c,a ;save it
inx h
mov a,m
cpi 20h ;done with olduser #?
jz legal
cpi 00h ;done with newuser #?
jz legal
inx h ;bump pointer past second char
sui 30h ;convert second digit
mov b,a
mov a,c ;test for add value
cpi 1
jnz add20
add10: ;Is 9 < user# <20
mov a,b
adi 10
mov c,a
jmp legal
add20: ;Is 19 < user# < 30
cpi 2
jnz add30
mov a,b
adi 20
mov c,a
jmp legal
add30: ;Is 29 < user#
mov a,b
adi 30
mov c,a
legal: ;Check for user number between 0 and 31
mov a,c
cpi 32
rc
lxi d,badusr ;Bad user number try again
call print
jmp boot
; If unera operation use E5 as the user#
unera:
mvi a,0e5h
inx h
ret
; THIS IS THE WORKING COPY OF THE BIOS JUMP TABLE
WBOOT: DS 3
CONST: DS 3
CONIN: DS 3
CONOUT: DS 3
LIST: DS 3
PUNCH: DS 3
READER: DS 3
HOME: DS 3
SELDSK: DS 3
SETTRK: DS 3
SETSEC: DS 3
SETDMA: DS 3
READ: DS 3
WRITE: DS 3
LISTST: DS 3
SECTRAN: JMP STRAN
; SECTOR TRANSLATION ROUTINE FOR
; CP/M VERSIONS EARLIER THAN 2.0
; REGS 'DE' CONTAIN ADDRESS OF 'XLTO'
; REGS 'BC' CONTAIN THE LOGICAL SECTOR NUMBER
; RETURNS PHYSICAL SECTOR NUMBER IN 'HL' REGISTERS
STRAN: MVI B,0
XCHG
DAD B
MOV L,M
RET
DS 100 ;STACK DEPTH
STACK: DS 0 ;LOCATION OF STACK
END 100H