

;**********************************************
;              XREN.ASM     2/18/84   7:45 P.M.
;
;	 File renaming with wild cards *,?
;	 allowed in both the old and new file names
;
;	USAGE:  XREN (d:)fileOld fileNew
;
;	Program: By Miguel Vasquez based on
;	         program by George M Gallen
;
;        needs 8080   and CP/M
;***********************************************
;
;--------------------EQUATES--------------------
;
BDOS	EQU	5	;Entry point to CP/M functions
PRINTS	EQU	9	;Func. # to Print String 
OPEN	EQU	15	;Func. # to Open existing File 
CLOSE	EQU	16	;Func. # to Close File 
REN	EQU	23	;Func. # to Rename File 
FCB0	EQU	5CH	;CP/M's FCB
NOFIND	EQU	0FFH	;Error code for file not found
;------------------------------------------------
;*************** MAIN PROGRAM START **************
	ORG	0100H		;Start of TPA
MAIN:	CALL	INIT		;Initialize our Stack.
	LDA	FCB0+1		;Check if source file is
	CPI	' '		;blank. If so give BAD
	JZ	BF		;FORMAT messg. and exit.
	LDA	FCB0+17		;Check second file
	CPI	' '		;also.
	JZ	BF		;
;
	LXI	H,FCB0+1	;Move original file name
	LXI	D,FCB1+1	;to its place in
	LXI	B,11		;FCB1 and FCB3.
	CALL	LDIR		;
	LXI	H,FCB0+1	;
	LXI	D,FCB3+1
	LXI	B,11		;
	CALL	LDIR		;
;
	LXI	H,FCB0+17	;Move new file name
	LXI	D,FCB5+1	;to FCB5.
	LXI	B,11		;
	CALL	LDIR		;
;
	CALL	DRIVE		;Save Drive specs
;
RNLOOP:	LXI	H,FCB3		;Try to open source file.
	CALL	FOPEN		; 
	CPI	NOFIND		;If unsuccessful, then no more
	JZ	ENDIT		;files, so end it.
;
	LXI	H,FCB0+1	;Put full file name (now without ??)
	LXI	D,FCB1+1	;(with the extensions) to
	LXI	B,11		;the appropriate spots in
	CALL	LDIR		;FCB1.
	CALL	NEWNAM		;Make new full file name in FCB2.
;
	MVI	C,CLOSE		;Close the original file
	LXI	D,FCB0		;
	CALL	BDOS		;
;
	LXI	H,FCB2+1	;Set up new full file name
	LXI	D,FCB4+1	;(with extension)
	LXI	B,11		;in FCB4.
	CALL	LDIR		;
; 
	LXI	H,FCB4		;Try to open the new file
	CALL	FOPEN		;
	CPI	NOFIND		;Could open it?  Horrors!!
	JNZ	CANNT		;Exit without renaming.
;
	MVI	C,REN		;Rename the old file
	LXI	D,FCB1		;to the new name.
	CALL	BDOS		;
;
	CALL	INFORM		;Inform of files renamed
	JMP	RNLOOP		;Process next one.
;
CANNT:	MVI	C,CLOSE		;Found a file with that name!!
	CALL	BDOS		;close it !
;
	LXI	H,FCB2+1	;Move the Bad file 
	LXI	D,MSG7		;name and extension
	LXI	B,8		;into Message #7
	CALL	LDIR		;
	INX	D		;
	LXI	B,3		;
	CALL	LDIR		;
	LXI	D,MSG8		;display message and
	JMP	STROUT		;exit.

ENDIT:	LXI	D,MSG5		;We're done, prepare message
	JMP	STROUT		;Print it and return to CP/M
;
BF:	LXI	D,MSG6		;Prepare BAD FORMAT message
	JMP	STROUT		;go printit and exit
;
;=============== SUBROUTINES ======================
;
;********************************************************
;                INFORM
;
;      to print message with files being renamed
;********************************************************
INFORM:	LXI	H,FCB1+1	;Move old file name
	LXI	D,MSG3		;and extension into
	LXI	B,8		;MSG3.
	CALL	LDIR		;
	INX	D		;
	LXI	B,3		;
	CALL	LDIR		;
	LXI	H,FCB2+1	;Move new file name
	LXI	D,MSG4		;and extension into
	LXI	B,8		;MSG4.
	CALL	LDIR		;
	INX	D		;Then display message
	LXI	B,3		;with the two names
	CALL	LDIR		;to let us know what's
	LXI	D,MSG1		;going on. (Drop down
;	JMP	STROUT		;into STROUT to do it)
;********************************************************
;                STROUT  to send a string to the console
;
;   Arguments : DE has the addr. of the string to be sent
;*******************************************************
STROUT:	MVI	C,PRINTS	;Set function code
	JMP	BDOS		;go doit
;		
;*******************************************************
;                 DRIVE   to save drives
;
;    Arguments:  The first byte of FCB0 contains
;                the source drive:
;                0  for the logged drive
;		 1  for drive A
;                2  for drive B, etc.
;*******************************************************
DRIVE:	LDA	FCB0		;Get the drive # and store
	STA	FCB1		;it in its place in FCB1,
	STA	FCB3		;FCB3, and FCB4.
	STA	FCB4		;
	ORA	A		;Is it the Logged drive?
	RZ			;Yes, leave drive blank.
	ADI	64		;No, convert to letter,
	STA	DRV1		;Save it and 
	STA	DRV2		;add a colon.
	MVI	A,':'		;
	STA	DRV1+1		;
	STA	DRV2+1		;
	RET
;
;********************************************************
;                NEWNAM  to make new name
;
; 	Arguments:    FCB0 has a regular full filename 
;		      FCB5 hs a file name with wild cards (?)
;		      On exit FCB2 will have FCB5 but
;                     with ?'s replaced with the corresponding
;                     character from FCB0.
;********************************************************
NEWNAM:	MVI	B,11		;Counter (bytes in file name).
	LXI	D,FCB2+1	;Destination addr. in DE.
	LXI	H,FCB0+1	;Use Stack as an extra
	PUSH	H		;index register for FBC0.(Source)
	LXI	H,FCB5+1	;Mask addr. in HL
LBA:	MOV	A,M		;Move mask byte to A.
	CPI	'?'		;MasK='?' ?
	JNZ	LBB		;no, output A.
	XTHL			;yes, Get FCB0 index into HL.
	MOV	A,M		;Get source byte. 
	XTHL			;Put FCB0 index back in stack.
	CPI	' '		;Is source a blank?
	JNZ	LBB		;No, then output it.
	MVI	C,1		;Yes, set C to number of
	MOV	A,B		;bytes neccessary to
	CPI	4		;fill the rest of
	JM	LBC		;the name or extension
	MVI	C,4		;with blanks. That is:
LBC:	MOV	A,B		;if B<4 then C=1 else C=4
	SUB	C		;C=B-C
	MOV	C,A		;
LBD:	MOV	A,C		;If C=0 then we are
	ORA	A		;at the last blank byte,
	MVI	A,' '		;Go and output it.
	JZ	LBB		;
	STAX	D		;Put blank in FCB5.
	INX	H		;Increment the three
	INX	D		;indexes.
	XTHL			;
	INX	H		;
	XTHL			;
	DCR	B		;Decrement the two
	DCR	C		;counters.
	JMP	LBD		;
LBB:	STAX	D		;Put char. in FCB5.
	INX	H		;Increment the three
	INX	D		;indexes.
	XTHL			;
	INX	H		;
	XTHL			;
	DCR	B		;Process next byte if
	JNZ	LBA		;not thru yet.
	POP	H		;If thru, restore stack
	RET			;and return
;	
;********************************************************
;             FOPEN  to try to open an existing file
;
;      Arguments:  HL has addr. of FCB with file to be opened
;********************************************************
FOPEN:	LXI	D,FCB0		;Move FCB to CP/M's
	LXI	B,35		;FCB.
	CALL	LDIR		;
	MVI	C,OPEN		;Try to open the file.
	LXI	D,FCB0		;
	CALL	BDOS		;
        RET
;
;********************************************************
;              LDIR     to simulate Z-80's LDIR
;
;  used to move a string from a location to another
;  
;  Arguments:   HL  addr. of source
;               DE  addr. of destination
;               BC  Number of bytes to be moved
;
; All the registers are modified
;
; Any Z-80 based computer (such as Osborne 1's)
; can replace all the CALL LDIR's
; with:	 DB	0EDH,0B0H 
; or replace this subroutine with
; LDIR:	DB	0EDH,0B0H
; 	RET
;*************************************************** 
LDIR:	MOV	A,M		;Move next byte
	STAX	D		;to its destination.
	INX	H		;Increment the pointers
	INX	D		;to source and destination.
	DCX	B		;Decrement byte count.
	MOV	A,B		;Test if BC
	ORA	C		;is zero.
	RZ     			; Yes, then return.
	JMP	LDIR		; No, process another byte
;
;********************************************************
;		INIT to initialize the stack
;		and save CP/M's stack
;********************************************************
INIT:	POP	B		;get return addr.
	LXI	H,0		;load HL with
	DAD	SP		;the stack pointer.
	SHLD	CPMSTK		;save it in CPMSTK.
	LXI	H,MYSTAK	;Change to my stack.
	SPHL			;
	LXI	D,FINISH	;Put finish routine
	PUSH	D		;in stack.
	PUSH	B		;put return addr.in stack.
	RET			;return 
FINISH	LHLD	CPMSTK		;reinstall CP/M's stack
	SPHL			;
	RET			;and return to CP/M.
;
;========================= DATA AREAS ==================
FCB1:	DB	0		;Drive for the Original FCB, 
	DB	'????????'	;Name
	DB	'???'		;Extension
	DB	0,0,0,0		;Filler
;
FCB2:	DB	0		;New FCB, (drive)
	DB	'????????'	;Name
	DB	'???'		;Extension
	DB	0,0,0,0		;Filler
;
FCB3:	DB	0		;Full original FCB 
	DB	'????????'
	DB	'???'
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0
;
FCB4:	DB	0		;Full new FCB
	DB	'????????'
	DB	'???'
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0,0,0
	DB	0,0,0
;
FCB5:	DB	0		;Mask for New FCB
	DB	'????????'	;Name
	DB	'???'		;Extension
;
; misc messages to let you know what's going on
;
MSG1:	DB	'RENAMING '
DRV1:	DB	'  '		;2 spaces
MSG3:	DB	'        ' 	;8 spaces
	DB	'.'
	DB	'   '		;3 spaces
	DB	' TO '
MSG4:	DB	'        ' 	;8 spaces
	DB	'.'
	DB	'   '		;3 spaces
	DB	13,10,'$'
MSG5:	DB	10,'No more matches',13,10
	DB	'I AM DONE......',13,10,'$'
MSG6:	DB	'* INVALID FORMAT *',13,10,10
	DB	'It should be :  '
	DB	'XREN [d:]fileOld fileNew',13,10,10,7,'$'
MSG8:	DB	10,'THE FILE '
DRV2:	DB	'  '		;2 spaces
MSG7:	DB	'        ' 	;8 spaces
	DB	'.'
	DB	'   '		;3 spaces
	DB	' ALREADY EXISTS. ',13,10
        DB	'PROCESSING HALTED. CANNOT RENAME ALL FILES'
        DB	13,10,10,7,'$'
;
CPMSTK	DS	2		;CP/M's stack pointer
	DS	40		;
MYSTAK	EQU	$		;My stack.
	END
