title hprom	SourceBug Monitor Prom

.z80

false	equ	0
true	equ	not false

test	equ	false		;false: org @ f000, true: moved to e000

i2716	equ	800h
i2732	equ	1000h

promsiz	equ	i2716		;eprom type


;	You must specify how many directory entries are on the disk (ndirs).
;	The number you specify must be divisible by 64 (for 2k groups).
;	The loader program must reside immediately after the directory.

;	Also specify how many sectors to load (nsecs).
;	There are 512 bytes/sector.

ndirs	equ	512		;512 directory entries
nsecs	equ	8		;load 4k



; Equates to figure loader program location -- DO NOT CHANGE.

spt	equ	17			;# sectors/track
nheds	equ	4			;# tracks/cylinder
spc	equ	spt * nheds		;# sectors/cylinder

dirsecs	equ	ndirs/16

icyl	equ	dirsecs/spc
isec	equ	dirsecs mod spc


page 60
;ascii

cr	equ	0dh
lf	equ	0ah


;ports

sioad	equ	00h
sioac	equ	01h
siobd	equ	02h
siobc	equ	03h

ctc0	equ	08h
ctc1	equ	09h
ctc2	equ	0ah
ctc3	equ	0bh

fdcmd	equ	0ch
fdtrk	equ	0d

ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее

STERS
;--------------------------------------

bsybit	equ	080h			; busy bit
errbit	equ	001h			; error bit	


;-----------------------
; Disk specific equates
;-----------------------

sectrk	equ	17			; sectors/track
seccyl	equ	68			; sectors/cyl

;---------------------
; Loader base equates
;---------------------

fbase	equ	0000h		;base adr for floppy loader
hbase	equ	0100h		;base adr for hard disk loader


page
if test
	ploc	equ	0e000h

	ld	hl,pbase	;relocate to ploc
	ld	de,ploc
	ld	bc,promsiz
	ldir
	jp	bootin

else
	ploc	equ	0f000h
endif

pbase:

.phase	ploc

stack:
bootin:	jp	booty
	jp	exec

booty:	di

	LD	A,04FH			;pon jump off, bank 00 on
	OUT	(bank0),A

	LD	SP,stack

	IN	A,(baudrd)		;set baud rate for crt
	OUT	(baudwr),A

	LD	HL,inisa
	LD	BC,800h + sioac
	OTIR

	LD	HL,inisb
	LD	BC,800h + siobc
	OTIR

	ld	a,2			;ctc reset byte
	out	(ctc0),a
	out	(ctc1),a
	out	(ctc2),a
	out	(ctc3),a

	LD	HL,signon
	CALL	strout
	JP	boot

page
;---------------------
; Top of command loop
;---------------------

exec:	LD	SP,stack

	LD	HL,prompt
	CALL	strout
	CALL	gecho

	LD	B,A
	LD	HL,cmdtbl

cloop:	LD	A,(HL)
	CP	0ffh
	JR	Z,badcmd

	CP	B
	JR	Z,gotcmd

	INC	HL
	INC	HL
	INC	HL
	JR	cloop

badcmd:	LD	HL,woops
	CALL	strout
	JR	exec

gotcmd:	INC	HL
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL
	JP	(HL)			;go to command


page
putc:	PUSH	AF

owait:	IN	A,(sioac)
	AND	4
	JR	Z,owait

	POP	AF
	OUT	(sioad),A
	RET


cetupc:	IN	A,(sioac)
	AND	1			;char ready?
	RET	Z			;no, exit -- z status

getupc:	IN	A,(sioac)
	AND	1			;char ready?
	JR	Z,getupc		;no, loop

	IN	A,(sioad)
	AND	7fh			;mask

	CP	'a'			;lt 'a'?
	RET	C			;yes, exit

	CP	'{'			;gteq '{'?
	RET	NC			;yes, exit

	AND	5fh			;upcase
	RET

gecho:	CALL	getupc
	CP	' '			;ctrl char?
	CALL	NC,putc			;no, echo
	RET
page
strout:	PUSH	AF
	PUSH	HL

stroop:	LD	A,(HL)
	OR	A			;end of string
	JR	Z,strend		;yes, jump

	CALL	putc
	INC	HL
	JR	stroop

strend:	POP	HL
	POP	AF
	RET

crlf:	push	af
	ld	a,cr
	call	putc
	ld	a,lf
	jr	hspit

space:	PUSH	AF
	LD	A,' '
	JR	hspit

page
hexit:	PUSH	AF
	RRCA
	RRCA
	RRCA
	RRCA
	CALL	hex1

	POP	AF

hex1:	PUSH	AF
	AND	0fh
	ADD	A,90h
	DAA
	ADC	A,40h
	DAA

hspit:	CALL	putc
	POP	AF
	RET

hexhl:	PUSH	AF
	LD	A,H
	CALL	hexit

	LD	A,L
	CALL	hexit
	POP	AF
	RET


page
getnum:	CALL	gecho
	CP	','
	RET	Z			;end of #

	CP	' '
	RET	Z			;end of #

	CP	'0'
	RET	C			;woops

	CP	':'
	JP	C,isnum			;0 - 9

	CP	'A'
	RET	C			;woops

	CP	'G'
	CCF
	RET	C			;woops

	SUB	007H			;convert A - F

isnum:	SUB	030H			;decode
	RET


page
get2n:	PUSH	BC
	PUSH	DE

	LD	C,0
	LD	E,0

nloop:	CALL	getnum			;number in?
	JR	NC,nisnum		;yes, jump

	CP	cr			;cr?
	SCF
	JR	NZ,bad2n		;no, jump

	LD	A,E
	OR	A			;any input?
	JR	NZ,got2n		;yes, jump

	SCF
	LD	A,cr			;let's pretend it was a cr
	JR	bad2n

nisnum:	CP	16			;is it a number?
	JR	NC,got2n		;no, jump

	INC	E			;inc it

	LD	B,A			;save #

	LD	A,C			;get old
	ADD	A,A			;x 2
	ADD	A,A			;x 4
	ADD	A,A			;x 8
	ADD	A,A			;x 16
	ADD	A,B			;add in new #
	LD	C,A			;	-- and all to c
	JP	nloop

got2n:	LD	A,C			;return in a

bad2n:	POP	DE
	POP	BC
	RET


page
get4n:	PUSH	DE
	LD	HL,0
	SCF
	CCF
	PUSH	AF

n4loop:	CALL	getnum
	JR	NC,got4n

	CP	cr
	JR	NZ,bad4n

	CALL	space
	JR	good4n

bad4n:	POP	AF
	SCF
	POP	DE
	RET

got4n:	CP	16
	JR	NC,good4n

	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL

	LD	E,A
	LD	D,0
	ADD	HL,DE
	JR	n4loop

good4n:	POP	AF
	POP	DE
	RET


page
tstmem:	LD	(HL),A
	CP	(HL)
	RET	Z

	PUSH	HL
	LD	HL,memerr
	CALL	strout

	POP	HL
	CALL	hexhl
	JP	exec

page
;---------------------------------------
; Load function -- Display & Substitute
;---------------------------------------

load:	CALL	get4n			;get the start adr
	JP	c,badcmd

	push	hl
	pop	ix

dot:	CALL	crlf			;display the current adr
	push	ix
	pop	hl
	CALL	hexhl
	CALL	space

	LD	A,(HL)
	CALL	hexit
	CALL	space
	CALL	get2n			;get the response
	JP	C,lodcmd

	CALL	tstmem

lodinc:	inc	ix			;inc the current adr
	jr	dot

lodcmd:	CP	cr			;cr terminates
	JP	Z,exec

	CP	' '			;space means inc
	jr	Z,lodinc

	CP	'-'			;dash means dec
	JP	NZ,badcmd

dash:	dec	ix			;dec the current adr
	jr	dot


page
;-----------
; Negate DE
;-----------

negde:	PUSH	AF
	LD	A,D
	CPL
	LD	D,A
	LD	A,E
	CPL
	LD	E,A
	INC	DE
	POP	AF
	RET

page
;-----------------------
; Dump memory to screen
;-----------------------

dump:	CALL	get4de
	CALL	get4de
	CALL	negde

dloop:	CALL	crlf
	CALL	hexhl
	CALL	space

dloop1:	CALL	space

	LD	A,(HL)
	CALL	hexit
	CALL	inchlc

	CALL	abortc

	LD	A,L
	AND	0fh
	JP	Z,dloop

	JP	dloop1

page
;------------------
; Go to an address
;------------------

go:	CALL	get4de
	EX	DE,HL
	JP	(HL)


;-----------------------
; Display the help menu
;-----------------------

help:	LD	HL,helpst
	CALL	strout
	JP	exec

inchlc:	PUSH	HL			;cp hl to de -- abort if c, else inc hl
	ADD	HL,DE
	JP	C,exec

	POP	HL
	INC	HL
	RET

page
;-------------------
; Move memory block
;-------------------

move:	CALL	get4de
	PUSH	DE
	CALL	get4de
	CALL	get4de

	EX	DE,HL
	EX	(SP),HL
	CALL	negde

mloop:	LD	A,(HL)
	EX	(SP),HL
	CALL	tstmem

	INC	HL
	EX	(SP),HL

	CALL	inchlc
	CALL	abortc
	JP	mloop


page
;-------------
; Fill memory
;-------------

fill:	CALL	get4de
	CALL	get4de
	CALL	negde
	CALL	get2n
	JP	C,badcmd

floop:	CALL	tstmem
	CALL	inchlc
	JP	floop

get4de:	CALL	get4n
	JP	C,badcmd

	EX	DE,HL
	RET

abortc:	CALL	cetupc			;abort on any char
	OR	A
	JP	NZ,exec

	RET

;---------------
; In & Out port
;---------------

iport:	CALL	get2n
	JP	C,badcmd

	LD	C,A
	IN	A,(C)

	CALL	crlf
	CALL	hexit
	JP	exec

oport:	CALL	get2n
	JP	C,badcmd

	LD	C,A
	CALL	get2n
	JP	C,badcmd

	OUT	(C),A
	JP	exec

page
;----------------------------------
; Boot -- floppy or hard disk exec
;----------------------------------

boot:	CALL	abortc
	CALL	fdinit

fdlop:	CALL	abortc
	CALL	fdread
	CALL	hdread
	JR	fdlop


page
;-------------
; Floppy junk
;-------------

fdinit:	XOR	A
	OUT	(fddsd),A		;8" sd

	CALL	fdrdy?			;is the drive ready?
	ret	c			;no, return

	call	fdhome
	ret	z			;return if good home

	ld	a,8
	out	(fddsd),a		;8" dd

	call	fdhome
	ret	z			;return if good home

fderr:	LD	HL,fderms		;floppy disk err msg out
	CALL	strout

	in	a,(fdcmd)
	CALL	hexit
	ret


fdhome:	LD	A,0fh			;restore command
	OUT	(fdcmd),A

	LD	A,3

delop:	EX	(SP),HL
	EX	(SP),HL
	DEC	A
	JR	NZ,delop

	IN	A,(fddsd)		;force wait for int

	IN	A,(fdcmd)
	AND	018H			;seek or crc error?
	ret


fdrdy?:	IN	A,(fdcmd)
	RLA				;c flag if not ready
	ret

page
;------------------
; Floppy disk read
;------------------

fdread:	call	fdrdy?			;drive ready?
	ret	c			;no, return

	LD	A,1			;set sector 1
	OUT	(fdsec),A

	LD	A,08CH			;read sector
	OUT	(fdcmd),A

	LD	HL,fbase
	LD	C,fddat

fdrdlp:	IN	A,(fddsd)		;wait for data or int
	OR	A			;data?
	JP	P,fdrddn		;no, jump

	INI				;get a byte
	JP	fdrdlp

fdrddn:	IN	A,(fdcmd)
	OR	A			;errors?
	JP	Z,fbase			;no, jump to booted input

	jp	fderr

page
;---------------------
; INITALIZE HARD DISK
;---------------------

hdinit:
	ld	a,sdhreg		; drive 0 & sector size
	out	(hsdh),a		; send it to controller

	xor	a			; zero a-reg
	out	(hsec),a		; reset sector register
	out	(hcyllow),a		; reset cylinder low register
	out	(hcylhi),a		; reset cylinder high register

	inc	a			;set for 1 sector
	out	(hseccnt),a

	in	a,(hsec)		;test for hdc1001 ctrlr
	ld	b,a

	in	a,(hcyllow)
	or	b
	ld	b,a

	in	a,(hcylhi)
	or	b			; do we seem to have a controller?
	ret	nz			; no, exit

	in	a,(hstatus)
	and	0c0h
	xor	40h			; busy or not ready?
	ret	nz			; yes, exit

	ld	a,cmdrstr		; restore command
	out	(hcmd),a

	ret

page
;----------------
; READ HARD DISK
;----------------

hdread:
	call	hdinit			; does everything look good on init?
	ret	nz			; no, exit

	call 	polbsy			; wait until not busy
	ret	nz			; exit if bad

	in	a,(hstatus)
	and	50h
	cp	50h			;ready & seek (restore) complete?
	ret	nz			;no, exit

	ld	hl,hbase		;start adr of load
	ld	de,icyl			;initial cyl #
	ld	bc,isec+(nsecs*100h)	;b = nsecs, c = isec

hread1:	call	hsettsk
	call	hrdsec
	call 	polbsy			; any errors?
	jp	nz,hdbadx		; yes, jump

	inc	c
	ld	a,c
	sub	seccyl			;new cylinder?
	jr	c,hread2		;no, jump

	ld	c,a			;set sector # to 0
	inc	ix			;inc cyl #

hread2:	djnz	hread1

	jp	hbase			;all loaded -- go to it

hdbadx:	ld	hl,hdrms
	call	strout

	in	a,(herror)
	call	hexit
	jp	exec



page	
;--------------------
; SET TASK HARD DISK
;--------------------

;Enter with de = track # and c = sector #

hsettsk:
	push	hl
	push	de

	ld	a,e			; set cyl #
	out	(hcyllow),a
	ld	a,d
	out	(hcylhi),a

	ld	a,sdhreg		; sdh proto byte
	ld	de,sectrk		; # sectors/track
	ld	l,c			; set hl to sector #
	ld	h,0

hsloop:	or	a			; divide modulo sectors/track
	sbc	hl,de
	jp	m,hsend

	inc	a			; add a head bit to sdh
	jr	hsloop

hsend:	add	hl,de			; l = sector #, a = sdh w/head bits
	out	(hsdh),a		; load siz drv hd register

	ld	a,l
	out	(hsec),a		; send to sector register

	pop	de
	pop	hl
	ret

page
;----------------------------
; READ SECTOR FROM HARD DISK 
;----------------------------

;Enter with hl set to dest adr -- exits with hl = hl + 512

hrdsec:
	ld	a,cmdrd
	out	(hcmd),a
	call	polbsy

	push	bc
	ld	bc,hdata		; 0 to b, data port to c
	inir
	inir
	pop	bc

	ret


;---------------------
; POLL BUSY HARD DISK
;---------------------

polbsy:
	in	a,(hstatus)		; read status port
	and	a			; set flags
	jp	m,polbsy		; loop if busy bit set

	and	errbit			; mask for error bit
	ret


page
signon:	db	cr,lf,lf
	db	lf,lf,'     SourceBug  V1.0',cr
	db	lf,lf,'Hit any key to enter Sourcebug.'
	db	cr,lf,'  Hit "?" for function list.',0

prompt:	db	cr,lf,'!',0

woops:	db	cr,lf,lf,'?',0

memerr:	db	cr,cr,lf,'MEMORY WRITE ERROR AT ',0

fderms:	db	cr,lf,'FDC COLD BOOT ERROR CODE ',0

hdrms:	db	cr,lf,'HDC1001 COLD BOOT ERROR CODE ',0

helpst:	db	cr,lf,'SourceBug Function List:',cr
	db	lf,lf,'B               = Load disk boot loader'
	db	cr,lf,'DSSSS,QQQQ      = Dump memory in hex from S to Q'
	db	cr,lf,'FSSSS,QQQQ,BB   = Fill memory from S to Q with B'
	db	cr,lf,'GAAAA           = Go to address A'
	db	cr,lf,'IPP             = Input from port P'
	db	cr,lf,'LAAAA           = Load memory starting at A'
	db	cr,lf,'MSSSS,QQQQ,DDDD = Move starting at S to Q to Addr. D'
	db	cr,lf,'OPP,DD          = Output data D to port P'
	db	cr,lf,'Any key will terminate a command',0


page
;---------------
; SIO init data
;---------------

inisa:	db	018h,004h,044h,003h,0c1h,005h,0eah,0

inisb:	db	018h,004h,044h,003h,0c1h,005h,0eah,0

;--------------------------
; Function code jump table
;--------------------------

cmdtbl:	db	'L'
	dw	load
	db	cr
	dw	exec
	db	'.'
	dw	dot
	db	'-'
	dw	dash
	db	'D'
	dw	dump
	db	'I'
	dw	iport
	db	'O'
	dw	oport
	db	'F'
	dw	fill
	db	'G'
	dw	go
	db	'M'
	dw	move
	db	'?'
	dw	help
	db	'B'
	dw	boot

	db	0ffh


.dephase

	ds	promsiz-($-pbase),0ffh

	end