;****************************************************************************
;
; FDUMP.M68	-	"File Dump"
;
;	Written by: Dave Heyliger - AMUS Staff
;
;	Purpose: to dump files NOT to the screen but to a VUEable, PRINTable,
;                file.
;
;	Usage: FDUMP filespec TO output-filespec
;	       Defaults on both filespecs are .TXT
;	       Output always in HEX (easy to read)
;	or
;
;       Usage: FDUMP filespec
;              Default on first filespec is .TXT
;              Output filespec is FDUMP.TXT
;              Output is always in HEX (Dave is right!)
;
;        
;****************************************************************************
; [101]  - 04/09/88
; [101]  - made output look like output from plain old DUMP
;          seperated every 2cnd display byte with 2 spaces like DUMP
;          Makes it easier to read HEX representations
; [102]  - 04/10/88
; [102]  - Fixed potential problem if user did not enter '_TO_'
;          A2 was pushed up 4 bytes. If buffer garbage was past the
;          4th byte FDUMP would pick it up as intended filespec.
;          Pushing A2 up 4 bytes without checking for possible short end
;          could cause eratic file output names.
;          Also added default of FDUMP.TXT for ease (lazyness)
; [103]  - 04/10/88
; [103]  - Added display of next block link on title output line

	SEARCH	SYS				;get the usuals
	SEARCH	SYSSYM	
	SEARCH	TRM
	SEARCH	AAA				;AAA.M68 in 100,133

	;define edit version
	VMAJOR=1				;original by Dave Heyliger
	VMINOR=0
	VEDIT=100.      ; good program Dave !
 	VEDIT=101.	; 04/09/88	;Modified by James A. Jarboe IV
 	VEDIT=102.	; 04/10/88	;Modified by James A. Jarboe IV
	VEDIT=103.	; 04/10/88	;Modified by James A. Jarboe IV
			; all in a days work !

	;define variables
	.OFINI					;define some variable space
	.OFDEF	IDDB,D.DDB			;input file DDB
	.OFDEF	ODDB,D.DDB			;output file DDB
	.OFDEF	BUFFER,20			;ascii buffer space for UNPACK
	.OFDEF	FS,4				;number of blocks in file
	.OFDEF	FT,2				;flag: 1 = seq, 0 = random
	.OFDEF	FBN,2				;block number
	.OFSIZ	IMPSIZ

	;define some macros
DEFINE	BEEP					;a "beep" macro
	MOV	#7,D1				;get a bell
	TTY					;beep!
ENDM

DEFINE	BRIGHT=PRTTAB -1,12.			;output in bright
DEFINE	DIM=PRTTAB -1,11.			;output in dim

	;START OF PROGRAM
	PHDR	-1,0,PH$REE!PH$REU		;re-entrant, reusable
	GETIMP	IMPSIZ,A3			;A3 points to variable space

	;process the input line "FDUMP filespec TO output-filespec"
	;or process "FDUMP filespec"
	BYP					;A2 points to first filespec
	LIN					;just a cr?
	BEQ	FERR				;yup, no good
	LEA	A4,IDDB(A3)			;point to input DDB w/ A4
	MOVB	#D$ERC!D$BYP,IDDB+D.FLG(A3)	;trap errors
	FSPEC	@A4,TXT				;default is .TXT
	CMPB	IDDB+D.ERR(A3),#D$ESPC		;filespec error?
	JNE	OK1				;nope, looks good Lewis!

	;filespec not a good one, give error message
FERR:	BEEP					;"beep"
	DIM					;dim output
	TYPE	<Usage: FDUMP >
	BRIGHT					;bright output
	TYPE	<filespec >
	DIM
	TYPE	<TO >
	BRIGHT
	TYPECR	<output-filespec>
	DIM
	TYPECR
	TYPECR	<or >
	TYPECR
        DIM	
	TYPE    <Usage: FDUMP >
	BRIGHT
	TYPECR  <filespec>
	DIM
	TYPECR
	TYPECR	<Both input filespec and output filespec defaults are .TXT>
	TYPECR	<and output will always be in HEX.>
	TYPECR  <If no output file is designated then the default output>
	TYPE    <file is >
	BRIGHT	
	TYPE	<FDUMP.TXT>
	DIM
	TYPECR  < .>	
	BRIGHT
	EXIT

	;first filespec OK, now look at second one
	; '_TO_' doesn't really have to be typed in. Just 4 positions
        ; between infile and outfile file specs, but we do need
        ; to check for carriage returns in case operator short changed
        ; us and we don't want to bypass the end of the input line
        ; and get garbage from A2 would point to if we just added 4
        ; bytes to it. Not all users are programmers they do make mistakes!

MERR:				; [102]	  ; maybe an error, maybe not
	CMPB	D2,#3		; [102]   ; first check ?
	JNE	FERR		; [102]   ; no..then it is an error
	LEA	A2,DEFFIL       ; [102]   ; load the default file
	BR	DOFIL		; [102]   ; no do it
OK1:
	MOV	#3,D2		; [102]   ;  counter = 3
5$:
	CMMB	@A2,#13.	; [102]   ;  a carriage return maybe ?
	JEQ	MERR		; [102]   ;  tell'em how
	ADD	#1,A2		; [102]   ;  move up along the input line
	CMPB	D2,#0           ; [102]   ;  past the '_TO_' yet ?
	BEQ	DOFIL		; [102]   ;  yes.. then lets see filename
	DEC	D2              ; [102]   ;  subtract 1 from counter
	BR	5$		; [102]   ;  try next place
DOFIL:
	CLR	D2		; [102]   ; clear counter someone may need it
	CMMB	@A2,#13.	; [102]   ; are you sure we aren't at end?
	JEQ	FERR		; [102]   ; well tell'em how to do it
	LEA	A5,ODDB(A3)			;point A5 to output DDB
	MOVB	#D$ERC!D$BYP,ODDB+D.FLG(A3)	;trap errors
	FSPEC	@A5,TXT				;default is .TXT
	CMPB	ODDB+D.ERR(A3),#D$ESPC		;filespec error?
	JEQ	FERR				;yup, give directions

	;setup both files for I/O
	INIT	@A4				;setup a block buffer
	LOOKUP	@A4				;find input file?
	BEQ	10$				;yup
	BEEP					;nope, error	
	TYPE	<Shoot! I can't find >
	PRNAM	IDDB+D.FIL(A3)
	TYPECR	<!>
	EXIT					;and quit

	;found first file, see if output file exists
10$:	INIT	@A5				;setup a block buffer
	LOOKUP	@A5				;there?
	BNE	IOSET				;nope, that's good
	BEEP					;yup, warn them and quit
	TYPE	<Hey! >
	PRNAM	ODDB+D.FIL(A3)
	TYPECR	< already exists!>
	EXIT

	;let the user know this thing is working..
IOSET:	TYPE	<Creating >			;portion of message
	PRNAM	ODDB+D.FIL(A3)			;print output filespec
	TYPE	<.>				;fancy dot output	

	;both files looking real good now, get em ready for I/O
	CLRW	FT(A3)				;clear file type flag
	MOV	IDDB+D.WRK(A3),FS(A3)		;save number of input blocks
	CMPW	IDDB+D.WRK+6(A3),#-1		;random input file?
	BNE	10$				;nope
	MOVW	IDDB+D.REC+2(A3),FBN(A3)	;yup, save first block
	BR	LOOP				;and bypass below
10$:	MOVW	#1,FT(A3)			;else set sequential flag

	;now for each block, READ and translate til done
LOOP:	OPENO	@A5				;open A5 for seq. output
	READ	@A4				;read first block of input

	;set HEX for easy programming (HEX is best anyway!)
10$:	JOBIDX	A6				;get this JOB
	LEA	A6,JOBTYP(A6)			;A6 points to JOBTYP word
	PUSH	A6				;save JOBTYP word on stack
	HEX					;now safe to SET HEX

	;type "Block dump of filespec"
BLKDMP:	LEA	A2,FILMSG			;A2 points to file message
10$:	MOVB	(A2)+,D1			;get the message
	CMPB	D1,#'.				;at end of message?
	BEQ	20$				;yup
	FILOTB	@A5				;nope, type out message
	BR	10$				;and get next character

	;get the filespec
20$:	LEA	A2,BUFFER(A3)			;point to buffer space
	PUSH	A2				;save start location
	LEA	A1,IDDB+D.FIL(A3)		;point to RAD50 filename
	UNPACK					;get ascii filename
	UNPACK
	UNPACK					;and extension
	MOV	@SP,A2				;retrieve start location

	;now move it to the file
	MOV	#6,D2				;ascii counter	
30$:	MOVB	(A2)+,D1			;get a character
	FILOTB	@A5				;type it out
	CMPB	@A2,#40				;at a space?
	BEQ	40$				;yup, get ".ext"
	DEC	D2				;one less character
	BNE	30$				;with more to go
40$:	MOV	#'.,D1				;get the dot
	FILOTB	@A5				;type it out
	POP	A2				;get start location
	ADD	#6,A2				;point to extension
	MOV	#3,D2				;counter
45$:	MOVB	(A2)+,D1			;get a character
	FILOTB	@A5				;type it out
	CMPB	@A2,#40				;space?
	BEQ	50$				;yup
	DEC	D2				;one less character
	BNE	45$				;with more to go

	;finish header with " - block ####"
50$:	LEA	A2,BLKMSG			;A2 points to block message
55$:	MOVB	(A2)+,D1			;get the message
	CMPB	D1,#'.				;end?
	BEQ	60$				;yup
	FILOTB	@A5				;nope, type out message
	BR	55$				;and get next character
60$:	LEA	A2,ODDB(A3)			;setup A2 to point to ODDB
	MOV	IDDB+D.BUF(A3),A1		;A1 points to block read
	MOVW	IDDB+D.REC+2(A3),D1		;get block number
	OCVT	4,OT$DDB			;type out the block number

	; if sequential then print block link
	; for us simple minded ones
	CMPW	FT(A3),#1	;[103]		;sequential file?
	BNE	68$		;[103]		;nope.. then can't print it
	LEA	A2,NXTMSG	;[103]		; load next link message
65$:
	MOVB	(A2)+,D1	;[103]		; set it up
	CMPB	D1,#'.		;[103]		; until the "."
	BEQ	66$		;[103]		; then go on
	FILOTB	@A5		;[103]		; spit it out
	BR	65$		;[103]		; do it again
66$:
 	MOVW	@A1,D1		;[103]		; move block link to D1
	LEA	A2,ODDB(A3)     ;[103]		; set up output DDB
 	OCVT	4,OT$DDB	;[103]		; convert that sucker
68$:
	MOV	#15,D1				;get CR
	FILOTB	@A5				;type it out
	MOV	#12,D1				;get LF
	FILOTB	@A5				;type it out
	MOV	#15,D1				;get CR
	FILOTB	@A5				;type it out
	MOV	#12,D1				;get LF
	FILOTB	@A5				;type it out

	;save block pointer if sequential
	CMPW	FT(A3),#1			;sequential file?
	BNE	70$				;nope
	MOVW	@A1,FBN(A3)			;yup, save ptr to next block
70$:	MOV	#0,D5				;D5 contains byte count offset

	;create 32 lines of 16 bytes/line (just like DUMP)
	;on each new line, first output offset
NEWLIN:	MOV	A5,A2				;A2 points to output DDB
	MOV	D5,D1				;byte count to D1
	OCVT	6,OT$DDB			;output the offset to DDB
	MOV	#':,D1				;get a fancy colon
	FILOTB	@A5				;type it out
	MOV	#0,D4				;D4 contains line byte count

	;save start of line pointer on stack, then output 16 bytes
	PUSH	A1				;save pointer
	MOVB	#-1,D2		; [101]		;set space counter to -1
HEXLIN:
	MOV	#40,D1				;get a space
	FILOTB	@A5				;type out the space
	INC	D2		; [101]		; add 1 to counter
	CMPB	D2,#2		; [101]		; we at second space ?
	BNE	10$		; [101]		; no... then output byte
	MOV	#40,D1		; [101]		; move space into D1
	FILOTB	@A5		; [101]		; spit it out
	MOVB	#0,D2		; [101]		; clear space counter
10$:						; 
	MOVB	(A1)+,D1			;get a byte
	OCVT	2,OT$DDB			;output the byte
	INC	D4				;one less byte to do
	INC	D5				;increment total count
	CMP	D4,#16.				;at end of line?
	BNE	HEXLIN				;nope

	;now for each line, get the line again but "translate" if you can
	POP	A1				;repoint to start
	CLR	D4				;clear count again too
	MOV	#40,D1				;get a space
	FILOTB	@A5				;type it out
ASCLIN:	CMPB	@A1,#40				;space or less?
	BLT	20$				;yup
	CMPB	@A1,#176			;"~" or more?
	BGT	20$				;yup
	MOVB	(A1)+,D1			;nope, typeable!
	FILOTB	@A5				;type it out
	BR	NXTBYT				;and setup for next byte

20$:	INC	A1				;bypass character
	MOV	#'.,D1				;get "non-typable"
	FILOTB	@A5				;and type it out

NXTBYT:	INC	D4				;count the byte (NOT D5!)
	CMP	D4,#16.				;at end of line?
	BNE	ASCLIN				;no, get next character
	CMP	D5,#512.			;at the end of block
	BEQ	GNB				;yup, grab next block
	MOV	#15,D1				;get at CR
	FILOTB	@A5				;output it
	MOV	#12,D1				;get a LF
	FILOTB	@A5				;output it
	JMP	NEWLIN				;output new line

	;come here to get next block
GNB:	TYPE	<.>				;let em know it's working
	MOV	#15,D1				;get CR
	FILOTB	@A5				;type it out
	MOV	#12,D1				;get LF
	FILOTB	@A5				;type it out
	MOV	#15,D1				;get CR
	FILOTB	@A5				;type it out
	MOV	#12,D1				;get LF
	FILOTB	@A5				;type it out
	MOV	#15,D1				;get CR
	FILOTB	@A5				;type it out
	MOV	#12,D1				;get LF
	FILOTB	@A5				;type it out
	CMPW	FT(A3),#1			;sequential file?
	BNE	10$				;nope
	CMPW	FBN(A3),#0			;end of file?
	BEQ	EXIT				;yup, all done
	MOVW	FBN(A3),IDDB+D.REC+2(A3)	;yup, set next block number
	READ	@A4				;read it
	JMP	BLKDMP				;and "dump" the next block

	;here if random file
10$:	SUB	#1,FS(A3)			;one less block to do
	CMP	FS(A3),#0			;last block?
	BEQ	EXIT				;yup, quit
	INCW	IDDB+D.REC+2(A3)		;nope, point to next block
	READ	@A4				;read it
	JMP	BLKDMP				;and dump some more

EXIT:	CLOSE	@A5
	CRLF
	EXIT	

	;misc ascii messages
DEFFIL: ASCII   /FDUMP/				; [102]
	EVEN
FILMSG:	ASCII	/Block dump of ./
	EVEN
BLKMSG:	ASCII	/ - block number ./
	EVEN
NXTMSG: ASCII   /, next block link is ./	; [103]
	EVEN
	END