; NOTE:
;	In order to execute this sample DUMP utility you
; 	must assemble DUMP.ASM and then link DUMP to
; 	create the DUMP.REL or DUMP.PRL file. This is shown below:
;
;	0A>RMAC dump
;	0A>LINK dump
;
	title	'File Dump Program'
	cseg
;	File dump program, reads an input file and
;	  prints in hex
;
;	Copyright (C) 1975, 1976, 1977, 1978, 1979, 1980, 1981
;	Digital Research
;	Box 579, Pacific Grove
;	California, 93950
;
;	and
;
;	Copyright (C) 1988
;	Sebastian Simon
;	Haendel-Haus Halle
;	Gr. Nikolaistr. 5-6
;	Halle
;	4020
;
;	System definitions
bdos	equ	5
fcb	equ	5ch
buff	equ	80h
;
cons	equ	1	;read console
typef	equ	2	;type function
printf	equ	9	;buffer print entry
brkf	equ	11	;break key function
openf	equ	15	;file open
readf	equ	20	;read function
;
;	non graphic characters
cr	equ	0dh	;carriage return
lf	equ	0ah	;line feed
;
;	file control block definitions
;fcbdn	equ	fcb+0	;disk name
;fcbfn	equ	fcb+1	;file name
;fcbft	equ	fcb+9	;disk file type (3 characters)
;fcbrl	equ	fcb+12	;file's current reel number
;fcbrc	equ	fcb+15	;file's record count (0 to 128)
;fcbcr	equ	fcb+32	;current (next) record number
;fcbln	equ	fcb+33	;fcb length
;
dump:
;	set up stack
	lxi	h,0
	dad	sp
;	entry stack pointer in hl from the ccp
	shld	oldsp
;	set sp to local stack area (restored at finis)
	lxi	sp,stktop
;	set up initial conditions
	xra	a
	sta	lstflg		;nicht drucken
	lxi	d,0	;start with 0000
	lxi	h,80h
	mov	a,m
	ora	a
	jz	nocond
nexwe:	inx	h
	mov	a,m
	cpi	60h
	jc	nexwe1
	ani	5fh
nexwe1:
	ora	a
	jz	nocond
	cpi	'['
	jz	auswe
	jmp	nexwe
;
auswe:
	inx	h
	mov	a,m
	cpi	60h
	jc	auswe1
	ani	5fh
auswe1:
	ora	a
	jz	nocond
	cpi	']'
	jz	nocond
	cpi	' '
	jz	auswe
;	cpi	'P'
;	jz	newlad
	cpi	'L'
	jnz	nolist
	sta	lstflg
	jmp	auswe
nolist:
	sui	'0'
	cpi	10
	jc	noabif
	sui	7
noabif:
	rept	4
	db	0cbh,23h	;	SLA	E
	db	0cbh,12h	;	RL	D		
	endm
	ani	0fh
	ora	e
	mov	e,a
	jmp	auswe
;
;	read and print successive buffers
nocond:
	xchg
	shld	startp
;	print sign on message
	lxi	d,signon
	call	prntmsg	
	call	setup	;set up input file
	cpi	255	;255 if file not present
	jnz	openok	;skip if open is ok
;
;	file not there, give error message and return
	lxi	d,opnmsg
	call	prntmsg
	jmp	finis	;to return
;
openok:	;open operation ok, set buffer index to end
	mvi	a,80h
	sta	ibp	;set buffer pointer to 80h
;	set pagecounter to 1
	mvi	a,1
	sta	pagnbr
;	initialize listing device
	lda	lstflg
	ora	a
	jz	noini
	lxi h,lstini! mvi b,8
	call	listo
;	hl contains next address to print
noini:
	mvi	a,0
	sta	lincou
	lxi	h,linbuf
	shld	libupt
	lhld	startp
	push	h	;save line position
	call	gnb
	pop	h	;recall line position
	jc	finis	;carry set by gnb if end file
	mov	b,a
	push	h
	lhld	libupt
	mov	m,a
	inx	h
	shld	libupt
	pop	h
	jmp	namout
;
gloop:
;	check for ASCII out
	mov	a,l
	ani	0fh	;check low 4 bits
	jnz	gloop1
;	output last line as ASCII
	call	ascout

gloop1:
	push	h	;save line position
	call	gnb
	pop	h	;recall line position
	jc	finis0	;carry set by gnb if end file
	mov	b,a
	push	h
	lhld	libupt
	mov	m,a
	inx	h
	shld	libupt
	pop	h
;	print hex values
;	check for line fold
	mov	a,l
	ani	0fh
	jz	linum
	ani	03h
	jnz	nonum
	jmp	absta
;	print line number
linum:
	lda	lincou
	inr	a
	sta	lincou
	cpi	64
	jnz	linum1
	xra	a
	sta	lincou
	push	b
	mvi	b,72-64-2
nexsei:
	call	crlf
	dcr	b
	jnz	nexsei
	pop	b
;
namout:
	push h! push b
	lda	lstflg
	ora	a
	jz	namou1
	lxi h,leerz! mvi b,12
	call	listo
namou1:
	mvi	c,1		;counter for position
	lxi	h,fcb+1
	mvi	b,8
	call	nexnam
	mvi	a,'.'
	call	pchar
	mvi	b,3
	call	nexnam
;
;	output of pagenr.
	mvi	a,67
	sub	c
	mov	b,a
nexle:
	mvi	a,' '
	call	pchar
	dcr	b
	jnz	nexle
	lxi	h,paget
	mvi	b,6
pagout:
	mov	a,m
	call	pchar
	dcr	b
	inx	h
	jnz	pagout
	lda	pagnbr
	inr	a
	sta	pagnbr
	dcr	a
	mvi	b,'0'-1
nexhun:
	inr	b
	sui	100
	jnc	nexhun
	adi	100
	push	psw
	mov	a,b
	call	pchar		;hunderter
	pop	psw
	mvi	b,'0'-1
nexzeh:
	inr	b
	sui	10
	jnc	nexzeh
	adi	10
	push	psw
	mov	a,b
	call	pchar		;zehner
	pop	psw
	adi	'0'
	call	pchar		;einer
	pop b! pop h
	call	crlf
	call	crlf
;
linum1:
	call	crlf
;
;	check for break key
	call	break
;	accum lsb = 1 if character ready
	rrc		;into carry
	jc	purge	;don't print any more
;
	push h! push b
	lda	lstflg
	ora	a
	jz	linum2
	lxi h,leerz! mvi b,12
	call	listo
linum2:
	pop b! pop h
	mov	a,h
	call	phex
	mov	a,l
	call	phex
	mvi	a,':'
	call	pchar

absta:
	mvi	a,' '
	call	pchar
nonum:
	inx	h	;to next line number
	mvi	a,' '
	call	pchar
	mov	a,b
	call	phex
	jmp	gloop
;
purge:
	mvi	c,cons
	call	bdos
finis0:
	lda	lstflg
	ora	a
	jz	finis
	mvi	e,0ch
	mvi	c,5
	call	bdos
finis:
;	end of dump, return to ccp
;	(note that a jmp to 0000h reboots)
	lda	lstflg
	ora	a
	jz	finis1
	mvi	e,7fh
	mvi	c,5
	call	bdos
finis1:	xra	a
	sta	lstflg
	call	crlf
	lhld	oldsp
	sphl
;	stack pointer contains ccp's stack location
	ret		;to the ccp
;
;
;	subroutines
;
break:	;check break key (actually any key will do)
	push h! push d! push b; environment saved
	mvi	c,brkf
	call	bdos
	pop b! pop d! pop h; environment restored
	ret
;
pchar:	;print a character
	push h! push d! push b! push psw; saved
	mvi	c,typef
	mov	e,a
	call	bdos
	lda	lstflg
	ora	a
	jz	pchend
;	output to listing-device
	pop	psw
	push	psw
	mov	e,a
	mvi	c,5		;bdos list function
	call	bdos
pchend:
	pop psw! pop b! pop d! pop h; restored
	ret
;
crlf:
	mvi	a,cr
	call	pchar
	mvi	a,lf
	call	pchar
	ret
;
;
pnib:	;print nibble in reg a
	ani	0fh	;low 4 bits
	cpi	10
	jnc	p10
;	less than or equal to 9
	adi	'0'
	jmp	prn
;
;	greater or equal to 10
p10:	adi	'A' - 10
prn:	call	pchar
	ret
;
phex:	;print hex char in reg a
	push	psw
	rrc
	rrc
	rrc
	rrc
	call	pnib	;print nibble
	pop	psw
	call	pnib
	ret
;
prntmsg:	;print message
;	d,e addresses message ending with "$"
	mvi	c,printf	;print buffer function
	jmp	bdos
;	ret
;
;
gnb:	;get next byte
	lda	ibp
	cpi	80h
	jnz	g0
;	read another buffer
;
;
	call	diskr
	ora	a	;zero value if read ok
	jz	g0	;for another byte
;	end of data, return with carry set for eof
	stc
	ret
;
g0:	;read the byte at buff+reg a
	mov	e,a	;ls byte of buffer index
	mvi	d,0	;double precision index to de
	inr	a	;index=index+1
	sta	ibp	;back to memory
;	pointer is incremented
;	save the current file address
	lxi	h,buff
	dad	d
;	absolute character address is in hl
	mov	a,m
;	byte is in the accumulator
	ora	a	;reset carry bit
	ret
;
setup:	;set up file 
;	open the file for input
	xra	a	;zero to accum
	sta	fcb+32	;clear current record
;
;	open the file in R/O mode
	lxi	h,fcb+6
	mov	a,m
	ori	80h
	mov	m,a	;set f6' on
	lxi	d,fcb
	mvi	c,openf
	call	bdos
;	255 in accum if open error
	ret
;
diskr:	;read disk file record
	push h! push d! push b
	lxi	d,fcb
	mvi	c,readf
	call	bdos
	pop b! pop d! pop h
	ret
;
ascout:	;output ascii code of line
	mvi a,' '! call pchar
	mvi a,' '! call pchar
	mvi a,' '! call pchar
	push h! push b
	mvi	b,10h
	lxi	h,linbuf
	shld	libupt
nexasc:
	mov	a,m
	cpi	20h
	jc	nonasc
	cpi	7fh
	jc	ascou
nonasc:
	mvi	a,'.'
ascou:
	call	pchar
	inx	h
	dcr	b
	jnz	nexasc
	pop b! pop h
	ret
;
nexnam:	;output filename
	mov	a,m
	inx	h
	ani	7fh
	cpi	' '
	jz	nexna1
	inr	c
	call	pchar
nexna1:	dcr	b
	rz
	jmp	nexnam
;
;	listout
listo:
	push h! push b
	mov e,m! mvi c,5
	call	bdos
	pop b! pop h! inx h! dcr b
	jnz	listo
	ret
;
;	fixed message area
signon:
	db	'CP/M DUMP V2.1'
	db	cr,lf,'$'
opnmsg:
	db	cr,lf,'No input file present on disk$'
paget:
	db	'Page: '
lstini:
	db	1bh,5bh,32h,20h,4bh,1bh,52h,0
leerz:
	db	'            '
;
;	variable area
ibp:	ds	2	;input buffer pointer
startp:	ds	2
oldsp:	ds	2	;entry sp value from ccp
lstflg:	ds	1
pagnbr:	ds	1
lincou:	ds	1
libupt:	ds	2
linbuf:	ds	10h
;
;	stack area
	ds	128	;reserve 64 level stack
stktop:
;
	end	dump
