;****************************************************************************
;
; 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