; This is Version 2.21 of Configure Disk for Jade DD disk images(requires Z80 Emulator 1.0.28 and up)
;	it  sets only needed disk IO configuration parameters. 
;
;***********MUST RUN ON BIOS22D*************	
;
; WARNING-- BIOS22D is modified to prevent older versions of this program from working
; The magic has changed.... (location)like-wise this program wont work on old BIOS22D
; also added JadeDD fake format entry to allow Jade Format for z80 emu to work ...
; Jade format is for JAde DISK images only...
;
; This program will configure the Z80 Emulator to access various Disk Images
; for the Jade DD FDC ... 
;
;
;For Jade Disk Images, this program simulates the Jade DD50BIOS and does it's own LOGIN
;
;for other types of disk images, this program does the same as CNFGDISK.COM 
; 
;WARNING-- this program requires a Custom BIOS(BIOS22D,asm) and works with CPM2.2 only, 
;   which reserves extra space for the XLTs, DPBs, ALL, CHK vectors
;WARNING--do not define formats that use more than the available space in 
; XLT tables, CHK vectors and allocation Vectors..
;
;
;	XLT	CHK	ALL
; A:-P:	256	512	512
;   this provides room for up to 8mb and 2048 directory entries.
; XLT is always at 0xFA00 for every drive
;  because, each drives parameters is kept in a differrent bank.
; A: in bank 0, B: in bank 1, etc, etc P: in bank 15
;
; Changing Drive A: is possible.... but dangerous, 
;   you can change it if you know enough.
;
;	XLTs can be 1 or zero based, will convert 0 to 1 base during injection
;
;(note-most BIOSes put a pointer to a shared DPB for disks that are Identical)
;
; This program can be modified to work with ANY BIOS that uses separate DPBs
;   for each disk, or if you want to change multiple disks at a time, it will work
;   with ANY BIOS whether or NOT there's individual DPBs.
; The program simply writes new DPB info into the DPB 
;   pointed to by the DPH (returned after SELDSK)
; It then writes new data to the an area for the XLT and 
;   then puts that address in the DPH
; It then reprograms the Z80 Emulator's Disk Controller for the type disk
; IT is designed to run with BIOS22D.ASM. BIOS22D.ASM has areas reserved 
;   specifically for this program
;
; This program sets sector size to 128 and then uses a modified XLT 
;        to access large sectors as 128 bytes, using the z80 emulator's auto-deblock
;
;This program requires AS8080 to assemble (symbols violate ASM/MAC rules)

	org 	100h

true	equ	-1
false	equ	not true

AS8080		equ	true

	if 	AS8080
		z80
	else
		maclib	z80
	endif

bdos	equ	05h

	jmp	start

;Storage used for testing OS version

bdos$ver 	dw	0
mpm$ver		dw	0
dir$bio		db	0	; direct bios bdos-0=no-1=yes
run$msg		db	'Running under $'
cpm$msg		db	'CP/M $'
mpm$msg		db	'MP/M $'
II$msg		db	'II $'
pri$msg		db	'Prior to 2.0$'
ukn$msg		db	'Unknown System$'
ext$msg		db	'Exiting$'
bds$msg 	db	'BDOS $'
msd$msg		db	'0.'
lsd$msg		db	'0 $'
noDB$msg 	db	'No '
DB$msg 		db	'BDOS Direct BIOS Support$'
bad$msg		db	'Can not run on this configuration$'
msg.die		db	CR,LF,LF
		db	"Requires Z80 Emulator Version 1.0.28 or higher$"
NJ$Msg		db	CR,LF,LF
		db	"Disk in drive is not a Jade DD Format$"
msg.cpu		db	CR,LF,LF
		db	"Requires Z80 CPU$"
NO$MAGIC	db	CR,LF,LF
		db	"NO MAGIC Requires Special BIOS22Dv22.ASM to run$"

BS.DSK	EQU	01BH

DSK$REG$SEL	equ	0cah
DSK$REG$LOW	equ	0c8h
DSK$REG$HI	equ	0c9h

CR		equ	13
LF		equ	10

crlf		db	CR,LF,'$'

; Storage for Program

Opening		db	cr,lf,"Jade Configure Disk Version 2.21 for Z80 Emulator 1.0.28 and up$"
Trm$Msg		db	"Finished",CR,LF,'$'
Ask$disk	db	"Select Disk to be reconfigured(letter only)...B through P - $"
Ask$Type	db	"Select Disk type (two hex characters)- $"
Notice		db	cr,lf
		DB	"This program will temporarily reconfigure a disk drive to access specific",cr,lf
		db	"  types of disks. The NEW configuration will remain in effect until the next",cr,lf
		db	"  COLD BOOT. You can read and write the disks. ",cr,lf
		db	cr,lf
		db	"  Since Jade disks do NOT need auto-deblocking, you can insert an IMD image",cr,lf
		db	"  AFTER configuring (this is reverse of normal procedure for IMD images). ",cr,lf
		db	cr,lf
		db	"NOTE- Old JadeDD formats with 48 SPT track 0, can NOT be auto detected"
		db	cr,lf,'$'

DiskNumber 	db	0
DiskType	db	0
Stack$Save	dw	0
Reset.Flag	db	0	;ff if disk reset required.

DPB		dw	0
DPH		dw	0
XLT		dw	0
SPT		dw	0

;-------------------------
start:
	sspd	Stack$Save
	lxi	sp,Stack
	lxi	d,run$msg
	call	print

;-------------------------
; check for proper CPM/MPM version

; Check for CPM prior to 2, we can not use CPM prior to 2

	mvi	c,0ch		;get CPM/bdos version
	call	bdos
	shld	bdos$ver

chk$old	xra	a
	cmp	l		;L=0 for cpm prior to 2.0
	jnz	chk$cpm
	lxi	d,cpm$msg	;CPM
	call	print
	lxi	d,pri$msg	;old CPM
	call 	print
badexit call 	printNL
	lxi	d,bad$msg	;Can not run on old CPM
	call	print
	call	printNL		;newline
exit:	lxi	d,ext$msg	;tell them about exit
	call 	print
	call	Exit$PGM
	jmp	0		;warm boot
	
chk$cpm	xra	a
	cmp	h		;H=0 for CPM
	jnz	chk$mpm
	lxi	d,cpm$msg	;CPM 
	call	print
	lda	bdos$ver	;get saved bdos version
	call	cnv$htd		;convert to ascii
	lxi	d,msd$msg
	call	print
	lda	bdos$ver	;get saved bdos version
	cpi	030h		;>=3.0 has direct bios in bdos
	jnc	no$dbios
	mvi	a,1
	sta	dir$bio		;set direct bios flag
no$dbios:
	jmp	GOT$CPM2or3

; check for MPM, but can not run on MPM

chk$mpm	mvi	a,01h		;H=1 for MPM
	cmp	h
	jnz	unknown		;something's weird
	lxi	d,mpm$msg	
	call	print
	mvi	c,0a3h		;get MPM version
	call	bdos
	shld	mpm$ver
	xra	a		;H=0 for MPM 1
	cmp	h
	jnz	chk$mII
	jmp	badexit		;MPM
chk$mII
	mvi	a,1		;H=1 for MPM 2
	cmp	h
	jnz	unknown
	lxi	d,II$msg	;MPM II
	call 	print
	lda	mpm$ver
	call	cnv$htd		;convert to ascii
	lxi	d,msd$msg	;print MPM version
	call	print

	lxi	d,bds$msg	;print bdos indicator
	call	print
	lda	bdos$ver	;get saved bdos version
	call	cnv$htd		;convert to ascii
	lxi	d,msd$msg	;print bdos version
	call	print
	jmp	badexit

unknown	lxi	d,ukn$msg	;unknown OS
	call	print
	jmp	badexit

;Got something we can use CPM 2 or 3 (both require special bios)

GOT$CPM2or3:
	call	printNL		;newline
	lda 	dir$bio		;get saved direct bios flag
	ana	a
	jz	noDB
	lxi	d,nodb$msg	;tell no direct bios
	jmp	yesDB
noDB:
	lxi	d,db$msg	;tell direct bios available
yesDB:	call	print

;-------------------------
; check for proper emulator version

; if major and minor and rev = 0 then bad
; if rev=0xff then bad
; z80 Emulators prior to 1.0.17 return unused port value of 0 or 0xff

	in 	0xc4		;read major number
	cpi 	0		;port c4 not implemented in wrong vers
	jnz	NOT_000
	in 	0xc5		;read minor number
	cpi 	0		;port c5 not implemented in wrong vers
	jnz	NOT_000
	in 	0xc6		;read revision number
	cpi 	0		;port c6 not implemented in wrong vers
	jz	Ver.Bad
NOT_000	cpi	0xff		;returns either 0 or ff if bad
	jz	Ver.Bad

; Versioning ports available so find out what version
; We can run on Version 1.0.22 or greater using NEW disk interface

	in 	0xc4		;read major number
	cpi	1
	jc	Ver.Bad
	in 	0xc5		;read minor number
	cpi	0
	jc	Ver.Bad
	in 	0xc6		;read minor number
	cpi	28
	jc	Ver.Bad
	jmp	Ver.OK
Ver.Bad	lxi	de,msg.die	;death message
	call	PrintDE		;out message
	call	Exit$PGM	;exit if bad so disks dont get trashed
	jmp	0			
Ver.OK

;-------------------------
; check CPU (we need z80)

	in 	0c2h
	cpi	0
	jz	cpu.OK
	lxi	de,msg.cpu	;death message
	call	PrintDE		;out message
	call	Exit$PGM	;exit if bad so disks dont get trashed
	jmp	0			

cpu.Ok

;-------------------------
; check for correct BIOS
;  Correct Bios contains Magic 767676 at BIOS+036h
;WARNING version 2 moves magic from BIOS+33 to BIOS+36
;V2 BIOS22D has a bios format entry as per Jade Computer products bios. 
; This allows the JadeDD format program for Z80 EMu to initialize JADE disk images
; it also prevents old version of disk configure from working on wrong bios. 

	LDA	BS.PAG
	MOV	H,A
	mvi	L,036h
	mov	a,m
	CPI	076H
	JNZ	GotNoMagic
	inx	hl
	mov	a,m
	CPI	'2'
	JNZ	GotNoMagic
	inx	hl
	mov	a,m
	CPI	'2'
	JNZ	GotNoMagic
	jmp	RunPGM

GotNoMagic
	lxi	de,NO$MAGIC
	call	PrintDE
	call	Exit$PGM
	jmp 	0
;-------------------------

RunPGM:	

	call	NewLine
	lxi	d,Opening
	call 	PrintDE
	call	NewLine
	lxi	d,Notice
	call 	PrintDE

;find out what disk user wants to configure

Get.SelDisk:
	call	NewLine
	LXI 	d,Ask$disk
	CALL	PrintDE
	CALL	ReadOne
	cpi	'a'
	jc 	notLC	;LT a
	cpi	'q'
	jnc	notLC	;GTE q or GT p

	jmp	Got$diskLC
notLC
	cpi	'A'
	jc 	notUC	;LT A
	cpi	'Q'
	jnc	notUC	;GTE Q or GT Q
	
	jmp 	Got$disk
notUC
	call 	NewLine
	jmp 	Get.SelDisk

Got$diskLC
	sui	'a'-'A'
Got$disk
	sui	'A'
	sta	DiskNumber
	

;-------------------------
;Find out what the user wants to configure disk as
; supports two digit hex value-- 0-9 and a-f ..
	call	NewLine
	call 	PrintMenu

Get.Type:
	Call	NewLine
	LXI 	d,Ask$Type
	CALL	PrintDE

	CALL	ReadOne		;read first char
	call	CHK.Valid
	
	cpi	0ffh
	jz	NOT$Type

	rlc
	rlc
	rlc
	rlc
	
	mov b,a

	CALL	ReadOne		;read second char
	call	CHK.Valid
	
	cpi	0ffh
	jz	NOT$Type

	ora	b	

	cpi	NumberOfDisks
	jc	Got$Type

NOT$Type
	call 	NewLine
	jmp 	Get.Type

Got$Type

	sta	DiskType

;----------------
	
	cpi	0
	jnz	doNormal
	call	seldsk		; call exerpted Jade BIOS routines to log drive.
	ora	a
	jz	exit$here
	jmp	Get.Seldisk
	
doNormal
;-------------------------
; Get pointers to internal data in BIOS for disk config

;get DPH
	lda	DiskNumber
	mov	c,a
	call	SelDisk		; bios call returns DPH in HL
	shld	DPH
;get XLT (not needed, we use predefined locations for all, since could be 0000h)
	mov	e,m		;First entry in DPH points to XLT
	inx	hl
	mov	d,m
	sded	XLT
;get DPB
	lhld	DPH		;DPH + 10 points to DPB
	lxi	de,10
	dad	de
	mov	e,m
	inx	hl
	mov	d,m
	sded	DPB

;get SPT for XLT length 

;get SPT
	lhld	DPB		;First entry in DPB is SPT
	mov	e,m
	inx	hl
	mov	d,m
	sded	SPT

;-------------------------
; load disk config from EDP table
; this routine writes new disk config data from programs data tables
;   to the Z80 Emulator's Disk Controller config registers
	
;select drive
	lda	DiskType	
	call 	GetEDPptr	;get HL=EDPptr

	mvi	a,018h	;select
	out	DSK$REG$SEL
	lda	DiskNumber	
	out	DSK$REG$LOW

; config the disk

	call	FeedNDI

;set parameters
	mvi	a,000h	;select command Reg
	out	DSK$REG$SEL
	mvi	a,07fh	;command is NULL but causes parameters to be set
	out	DSK$REG$LOW

;-------------------------
;inject DPB from internal program area to DPB in BIOS
; assume CPM 2
; NEEDs work to run on CPM 3 (plus special BIOS)

DPBsize	equ	15	;17 for CPM3

	lda	DiskType	
	call	GetDPBptr	;hl=internal DPB
	lded	DPB		;de=DPB in bios
	lxi	b,DPBsize	;size of dpb
	ldir

; get SPT form internal DPB

	lda	DiskType	
	call	GetDPBptr	;hl=internal DPB
	mov	e,m		;SPT is first entry in DPB
	inx	hl
	mov	d,m
	sded	SPT		;SPT = new SPT

;get XLT pointer from internal table

	lda	DiskType	
	call	GetXLTptr
	mov	a,h
	ora	l
	jz	no$XLT		;zero if no XLT used

; get address of disks XLT in bios

;	call	GetXLTptrBIOS

	lxi	d,0xFA00

	lhld	DPH		;set DPH's XLT to value in DE
	mov	m,e
	inx	hl
	mov	m,d

;DE=pointer to XLT in Bios
	lda	DiskType
	call	GetXLTptr	;HL=internal XLT, a= 0 or 1 based
	lbcd	SPT		;count of sectors/bytes in XLT
	cpi	0
	jz	ZeroBase
OneBase	ldir
	jmp	Exit$Here

ZeroBase
	mov	a,m
	inr	a		; for zero based XLTs
	stax	d
	inx	h
	inx	d
	dcx	b
	mov	a,b
	ora	c
	jnz	ZeroBase

	jmp	Exit$Here

no$XLT	lhld	DPH		;set DPH's XLT to 0
	mvi	m,0
	inx	hl
	mvi	m,0

;-------------------------
; this get entered by Cntrl-C check in ReadOne
; normal exit for ALL
; tests for Disk reset needed after SELDSK call
; 
Exit$here:
Exit$PGM:
	lda	Reset.Flag
	ora	a
	jz	OUT$PGM

	mvi	c,13		;reset disk system
	call	bdos

OUT$PGM:
	call	NewLine
	lxi	de,Trm$Msg
	call	PrintDE
	lspd	Stack$Save
	ret			; this should return to CPM

;-------------------
;Z80 Emualator hardware parameters (new Disk interface)

ndi.Lo	equ	0xC8
ndi.Hi	equ	0xC9
ndi.Sel	equ	0xCA

cmd.read	equ	1
cmd.write	equ	2

;macros for setting up NDI IO parmeter tables.

Set8	macro	?Register,?Value,?Label
	db	1,?Register
?Label	db	?Value
	endm

Set16	macro	?Register,?Value,?Label
	db	2,?Register
?Label	dw	?Value
	endm

; this routine feeds data to the New Disk Interface
; the data is in a parameter block as
; size(1) port(1) data (1 or 2) terminated with 0xFF
; entry -  hl points to parameter block

FeedNDI
another	mov	a,m	;got size 1=low 2=low/high and FF=finished
	cpi	0ffh
	jz	finished
	cpi	2
	jz	do2
do1	inx	hl
	mov	a,m	;got register selector in a
	out	ndi.Sel	;out to select port
	inx	hl
	mov	a,m	;got value to out to register
	out 	ndi.LO	; out to low reg
	inx	hl
	jmp 	another
do2	inx	hl
	mov	a,m	;got register selector in a
	out	ndi.Sel	;out to select port
	inx	hl
	mov	a,m	;got value to out to low register
	out 	ndi.Lo	; out to low reg
	inx	hl
	mov	a,m	;got value to out to high register
	out 	ndi.Hi	; out to high reg
	inx	hl
	jmp 	another
finished
	ret	
;-------------------------
;Entry	
;	C=disk
;Return
;	HL=ptr to DPH

SelDisk
	push	de
	push	bc
	push	a
	mvi	a,0xff
	sta	Reset.Flag
	mvi	L,bs.dsk
	call	bios
	pop	a
	pop	bc
	pop	de
	ret

;-------------------------
BS.PAG	EQU	02H

;BIOS TRANSFER ROUTINE

BIOS	LDA	BS.PAG
	MOV	H,A
	PCHL
;-------------------------

; CONSOLE LINKAGE - BDOS CALLS

CNS.RD	EQU	1
CNS.WR	EQU	2

CNTL.C	EQU	3
REBOOT	EQU	0

ReadOne:
	push	b
	push	d
	push	h
	MVI	C,CNS.RD
	CALL	BDOS
	pop	h
	pop	d
	pop	b
	ANI	07FH
	CPI	CNTL.C
	CZ	Exit$PGM
	RET
	
WriteOne:
	PUSH	H
	MOV	E,A
	MVI	C,CNS.WR
	CALL	BDOS
	POP	H
	RET
	
;-------------------------
;entry 
;	A=char
;return 
;	HEX character value or FF if bad

Valid$Chars
	db	'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
	db	'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
;   YES it checks 0-9 twice, but i dont care
CHK.valid	
	push	b
	push	h
	lxi	h,Valid$Chars+31
	mvi	b,16
..loop	
	cmp	m		;match?
	jz	Char$OK		;OK
	dcx	h		;point to next chars
	dcr	b		;dec count of characters
	jnz	..loop		;again

;	lxi	h,Valid$Chars+15
	mvi	b,16
..loop	
	cmp	m		;match?
	jz	Char$OK		;OK
	dcx	h		;point to next chars
	dcr	b		;dec count of characters
	jnz	..loop		;again
	
Char$OK	
	dcr	b
	mov	a,b
	pop	h
	pop	b
	ret

;-------------------------
;convert Binary in A to Hex 
HEX2:
HEX2H	db	030h
HEX2L	db	030h
	db	'$'
BIN2HEX:	
	push	a		
	push	a
	ani	0f0h
	rrc
	rrc	
	rrc
	rrc
	cpi	0ah
	jc	notA_FH
	adi	041h-03ah
notA_FH	adi	030h
	sta	HEX2H
	pop	a
	ani	0fh
	cpi	0ah
	jc	notA_FL
	adi	041h-03ah
notA_FL	adi	030h
	sta 	HEX2L
	pop	a
	ret

;-------------------------
PrintHEX2:
	push	de
	call	BIN2HEX
	lxi	de,HEX2
	call	PrintDE
	pop	de
	ret
;-------------------------

GetDiskEntryPtr:

;Entry
;	A=Disk Number
;Returns 
;	DE=entry size
;	HL=ptr to disk entry
;	A=0

	lxi	hl,DiskTable
	lxi	de,8
..loop	ora	a
	rz
	dad	d
	dcr	a
	jmp	..loop
;-------------------------
GetHLDEptr:

;Entry
;	DE= offset
;	HL=PTR
;Returns
;	hl=ptr at HL + DE

	dad	de
	mov	e,m
	inx	hl
	mov	d,m
	mov	h,d
	mov	l,e
	ret
;-------------------------
GetLABptr:

;Entry
;	A=Disk Number
;Returns
;	hl=ptr to disk LABEL

	push	de
	push	a
	call	GetDiskEntryPtr
	lxi	de,0
	call 	GetHLDEptr	
	pop	a
	pop	de
	ret
;-------------------------
GetDPBptr:

;Entry
;	A=Disk Number
;Returns
;	hl=ptr to disk DPB

	push	de
	push	a
	call	GetDiskEntryPtr
	lxi	de,4
	call 	GetHLDEptr	
	pop	a
	pop	de
	ret
;-------------------------
GetEDPptr:

;Entry
;	A=Disk Number
;Returns
;	hl=ptr to disk Emu Disk Configuration

	push	de
	push	a
	call	GetDiskEntryPtr
	lxi	de,2
	call 	GetHLDEptr	
	pop	a
	pop	de
	ret

;-------------------------
GetXLTptr:

;Entry
;	A=Disk Number
;Returns
;	hl=ptr to disk Emu Disk Configuration
;	a=0 or 1 based

	push	de
	call	GetDiskEntryPtr
	lxi	d,6
	call 	GetHLDEptr
	dcx	h
	mov	a,m
	inx	h
	pop	de
	ret
;-------------------------
PrintHL:
	push	de
	mov	e,l
	mov	d,h
	call	PrintDE
	pop 	de
	ret
;-------------------------
PrintDE:
	push	hl
	push	bc
	push	a
	mvi	c,9
	call	bdos
	pop	a
	pop	bc
	pop	hl
	ret
;-------------------------
NL	db	13,10,'$'
NewLine:
	push	de
	lxi	de,NL
	call	PrintDE
	pop	de
	ret
;-------------------------
SP	db	' ','$'
PrintSpace:
	push	de
	lxi	de,SP
	call	PrintDE
	pop	de
	ret
;-------------------------


PrintMenu:
	call	NewLine
	mvi	a,0
..loop	call	PrintHex2
	call	PrintSpace
	call	GetLABptr
	call	PrintHL
	call	NewLine
	inr	a
	cpi	NumberOfDisks
	jnz	..loop
;	call	NewLine
	ret
	
;-------------------------
;Print NewLine and Print

printNL	lxi	d,crlf
print:	
	mvi	c,09h
	jmp	bdos

;-------------------------
;convert to bcd
cnv$htd:			
	push	psw
	ani	0f0h
	rrc
	rrc	
	rrc
	rrc
	adi	030h
	sta	msd$msg
	pop	psw
	ani	0fh
	adi	030h
	sta	lsd$msg
	ret
;-------------------------
;DPBs/DISK configuration
;-------------------------

; Label, EMU's Disk Parameters, CPM's DPB, CPM's XLT

DiskTable	
	dw	JadeLogINL,0,0,0	;dummy fields because not used
	dw 	jadeDDL,jadeDDP,jadeDDD,0
	dw 	ibm8L,ibm8P,ibm8D,ibm8X
	dw 	PC1440L,PC1440P,PC1440D,0

	dw 	jade50DSDDL,jade50DSDDP,jade50DSDDD,0
	dw 	jade50DSSDL,jade50DSSDP,jade50DSSDD,ibm8X
	dw 	jade50SSDDL,jade50SSDDP,jade50SSDDD,0
	dw 	jade50SSSDL,jade50SSSDP,jade50SSSDD,ibm8X
	dw 	jadeSSDDL,jadeSSDDP,jadeSSDDD,0
	dw 	jadeSSSDL,jadeSSSDP,jadeSSSDD,ibm8X

NumberOfDisks	equ 	($-DiskTable)/8

; Label for Jade Login 

JadeLogINL	db	"AUTO LOGIN Jade Disk Image in Drive(must already have Jade Disk Image open)$"

;-------------------------
;the parameters used to configure the z80 emulator's disk controller 
; we always use a sector size of 128...
;-------------------------

jade50DSDDL
	db	"Jade 8 - 128 26/50/50 SPT Double Sided Double Density$"

jade50DSDDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,2	;Heads

	set8	0a3h,2	;density	(data) 	Double
	set16	0a4h,50	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,50	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jade50DSDDD
	DW    50		;sectors per track
	DB    5			;block shift factor
	DB    31		;block mask
	DB    3			;extent mask
	DW    50*152/32-1	;disk size-1
	DW    127		;directory max
	DB    080h		;alloc 0
	DB    0			;alloc 1
	DW    32		;check size
	DW    2			;track offset
	DB	0,0		;physical sector size and shift
;-------------------------
jade50DSSDL
	db	"Jade 8 - 128 26/50/26 SPT Double Sided Single Density$"

jade50DSSDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,2	;Heads

	set8	0a3h,1	;density	(data) 	Single
	set16	0a4h,26	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	Single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,50	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jade50DSSDD
	DW   	26	;sectors per track
	DB   	4	;block shift factor
	DB   	15	;block mask
	DB   	1	;extent mask
	DW   	26*152/16-1	;disk size-1
	DW   	63	;directory max
	DB   	080h	;alloc 0
	DB   	0	;alloc 1
	DW   	16	;check size
	DW   	2	;track offset
	DB	0,0	;physical sector size and shift

;-------------------------
jade50SSDDL
	db	"Jade 8 - 128 26/50/50 SPT Single Sided Double Density$"

jade50SSDDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,2	;density	(data) 	Double
	set16	0a4h,50	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,50	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jade50SSDDD
	DW    50		;sectors per track
	DB    4			;block shift factor
	DB    15		;block mask
	DB    1			;extent mask
	DW    50*75/16-1	;disk size-1
	DW    63		;directory max
	DB    080h		;alloc 0
	DB    0			;alloc 1
	DW    16		;check size
	DW    2			;track offset
	DB	0,0		;physical sector size and shift

;-------------------------
jade50SSSDL
	db	"Jade 8 - 128 26/50/26 SPT Single Sided Single Density$"

jade50SSSDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,1	;density	(data) 	Single
	set16	0a4h,26	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	Single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,50	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jade50SSSDD
	DW   	26	;sectors per track
	DB   	3	;block shift factor
	DB   	7	;block mask
	DB   	0	;extent mask
	DW   	26*75/8-1	;disk size-1
	DW   	63	;directory max
	DB   	0c0h	;alloc 0
	DB   	0	;alloc 1
	DW   	16	;check size
	DW   	2	;track offset
	DB	0,0	;physical sector size and shift

;-------------------------
jadeSSSDL
	db	"Jade 8 - 128 26/48/26 SPT Single Sided Single Density$"

jadeSSSDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,1	;density	(data) 	Single
	set16	0a4h,26	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	Single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,48	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jadeSSSDD
	DW   	26	;sectors per track
	DB   	3	;block shift factor
	DB   	7	;block mask
	DB   	0	;extent mask
	DW   	242	;disk size-1
	DW   	63	;directory max
	DB   	0c0h	;alloc 0
	DB   	0	;alloc 1
	DW   	16	;check size
	DW   	2	;track offset
	DB	0,0	;physical sector size and shift

;-------------------------
jadeSSDDL
	db	"Jade 8 - 128 26/48/48 SPT Single Sided Double Density$"

jadeSSDDP:
	set8	080h,0	;order
	set8	081h,1	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,2	;density	(data) 	Double
	set16	0a4h,48	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	set16	0b2h,1	;#t0
	set8	0b3h,1	;density	(T0) 	single
	set16	0b4h,26	;SPT		(T0) 
	set8	0b5h,0	;Sector Size	(T0) 	128
	set8	0b6h,2	;clock		(T0)	8inch

	set16	0c2h,1	;#sys
	set8	0c3h,2	;density	(SYS) 	Double
	set16	0c4h,48	;SPT		(SYS) 
	set8	0c5h,0	;Sector Size	(SYS) 	128
	set8	0c6h,2	;clock		(SYS) 	8inch

	db	0ffh

jadeSSDDD
	DW    48	;sectors per track
	DB    4		;block shift factor
	DB    15	;block mask
	DB    1		;extent mask
	DW    224	;disk size-1
	DW    63	;directory max
	DB    080h	;alloc 0
	DB    0		;alloc 1
	DW    16		;check size
	DW    2		;track offset
	DB	0,0	;physical sector size and shift

;-------------------------
; This format is wrong.. it uses 48 sectors for track 0 when it should be 26
; but this was the only way to do Jade disks prior to Z80 emulator version 1.0.17
jadeDDL
	db	"Jade Z80 Emulator- 48/48/48 old Double Density format(can NOT be Auto detected)$"

jadeDDP:
	set8	080h,0	;order
	set8	081h,0	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,2	;density	(data) 	Double
	set16	0a4h,48	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch

	db	0ffh

jadeDDD
	DW    48	;sectors per track
	DB    4		;block shift factor
	DB    15	;block mask
	DB    1		;extent mask
	DW    224	;disk size-1
	DW    63	;directory max
	DB    080h	;alloc 0
	DB    0		;alloc 1
	DW    16		;check size
	DW    2		;track offset
	DB	0,0	;physical sector size and shift


;default drive parametr block for IBM 3740

ibm8L	db	"Standard 8 IBM 3740 Single Sided Single Density$"

ibm8P:
	set8	080h,0	;order
	set8	081h,0	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,77	;Cylinders
	set8	0a1h,1	;Heads

	set8	0a3h,1	;density	(data) 	Single=1
	set16	0a4h,26	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128
	set8	0a6h,2	;clock		(data) 	8inch=2

	db	0ffh

ibm8D	dw	26		;spt
	db	3		;bsh
	db	7		;blm
	db	0		;exm
	dw	242		;dsm
	dw	63		;drm
	db	0c0h		;al0
	db	0		;al1
	dw	16		;cks
	dw	2		;off
	DB	0,0		;physical sector size and shift

;default drive parametr block for 3$5" pc1440

;-------------------------
PC1440L	db	"Z80 Emulator 3.5 PC1440$"

PC1440P:
	set8	080h,0	;order
	set8	081h,0	;formatType
	set8 	082h,0	;DONT use prepost

	set16	09ah,0	;IDM flag	0

	set16	0a0h,80	;Cylinders
	set8	0a1h,2	;Heads

	set8	0a3h,2	;density	(data) 	Double=2
	set16	0a4h,72	;SPT		(data) 
	set8	0a5h,0	;Sector Size	(data) 	128=0
	set8	0a6h,4	;clock		(data) 	3inch=4

	db	0ffh


PC1440D	dw	72		;spt
	db	4		;bsh
	db	15		;blm
	db	0		;exm
	dw	710		;dsm
	dw	255		;drm
	db	0f0h		;al0
	db	0		;al1
	dw	64		;cks
	dw	2		;off
	DB	0,0		;physical sector size and shift

;---------
; XLT tables
;----------
	db	1	; 1 based
ibm8X	db	01h,07h,0dh,13h,19h,05h
	db	0bh,11h,17h,03h,09h,0fh
	db	15h,02h,08h,0eh,14h,1ah
	db	06h,0ch,12h,18h,04h,0ah
	db	10h,16h

;---------------
; load this to select drv (done separate to allow 1.0.18 - 1.0 22 to work) 
; for 1.0.23 up cnfg parms accumulate until NDI IO command
; 18-22 required you set drive first.

Select
	set8	0x18,0,bt.drv	;drive number
	db	0xff

; load  this to do IO

DIO
	set16	0x10,0,bt.dma	;system tranfer address
	set16	0x22,0,bt.trk	;track number
	set16	0x24,0,bt.sec	;sector number
	set8	0x00,0,bt.cmd	;NDI command
	db	0xff

; load this to read ID sector 

LIO
	set16	010h,log.buf	;DMA address of Log buffer
	set16	022h,0		;Track 0
	set16	024h,1		;Sector 1
	set8	0x00,cmd.read	;NDI command
	db	0xff

;---------

; CfgData is for variable config Data set after reading ID sector
CfgData
	set8	0a1h,2,bt.hds		;Heads

	set8	0a3h,2,bt.Ddat		;density	(data) 	Double
	set16	0a4h,50,bt.SPTdat	;SPT		(data) 

	set8	0c3h,2,bt.Dsys		;density	(SYS) 	Double
	set16	0c4h,50,bt.SPTsys	;SPT		(SYS) 

	set8	0,127			;issue null command to set all parameters.

	db	0xFF

; Log Data is set before read ID sector and configures Non-variable config parameters.
;writing to disk conf interface does not set parameters until a disk IO command is issued
; for 1.0.18-1.0.22 Drive MUST be selected first or failure occurs. 
; For 1.0.23 up parameters accumulate and are set by IO (no need to select first)
; the parameters are set by disk IO command in LIO

LogData	
	set8	080h,0			;order
	set8	081h,1			;formatType
;	set8 	082h,0			;DONT use prepost

	set16	09ah,0			;IDM flag	0

	set16	0a0h,77			;Cylinders
;	set8	0a1h,2,bt.hds		;Heads		

;	set8	0a3h,2,bt.Ddat		;density	(data) 	Double
;	set16	0a4h,50,bt.SPTdat	;SPT		(data) 
	set8	0a5h,0			;Sector Size	(data) 	128
	set8	0a6h,2			;clock		(data) 	8inch

	set16	0b2h,1			;#t0
	set8	0b3h,1			;density	(T0) 	Single
	set16	0b4h,26			;SPT		(T0) 
	set8	0b5h,0			;Sector Size	(T0) 	128
	set8	0b6h,2			;clock		(T0)	8inch

	set16	0c2h,1			;#sys
;	set8	0c3h,2,Dsys		;density	(SYS) 	Double
;	set16	0c4h,50,SPTsys		;SPT		(SYS) 
	set8	0c5h,0			;Sector Size	(SYS) 	128
	set8	0c6h,2			;clock		(SYS) 	8inch

	db	0ffh			;end it


;disk read write format exits 

dsk.ok:	
	xra	a		;clear a to indicate OK
	ret

dsk.er:	
	mvi	a,0FFh		;set a to indicate ERROR
	ret


; disk status

dsk.sts
	mvi	a,8	;select for status register
	out 	ndi.Sel
	in	ndi.Lo
	ana	a	;set status
	ret

;disk login

dsk.log
	lxi	hl,Select	;select is done first only to support 1.0.18-1.0.22
	call	feedNDI

	lxi	hl,LogData	;set defaults needed to read ID sector
	call	FeedNDI

	lxi	hl,LIO		; finalize set of parms and read ID sector
	call	FeedNDI

	call	dsk.sts		; we did a read so get status
	
	ret

;Disk Configure after Log in (Select Drive NDI parameter is already set)

dsk.cfg

;these parameter values are found in the DPB

	call	dpb.ad		;de points to dpb
	xchg			;hl ->dpb SPT data
	lxi	b,DPBsize
	dad	b		;hl -> to CPM3 physicals
	xra	a
	mov	m,a		;set CPM3 PHS and PHM to 0
	inx 	hl
	mov	m,a


	call	dpb.ad		;de points to dpb
	xchg			;hl ->dpb SPT data
	mov	a,m
	sta	bt.SPTdat
	inx	h
	mov	a,m
	sta	bt.SPTdat+1

	lxi	hl,CfgData
	call	feedNDI
	
	ret

;disk executive

dsk.ex
	lxi	h,Select	;select is done first only to support 1.0.18-1.0.22
	call 	FeedNDI

	lxi	h,DIO
	call	FeedNDI	

	call	dsk.sts
	
	ret

;block move (z80 LDIR register usage)

block	mov	a,m		;
	stax	d		;
	inx	h		;
	inx	d		;
	dcx	b		;
	mov	a,b		;
	ora	c		;
	jnz	block		;
	ret			;

;log on set dpb

log.on	lda	log.rq		;check log on req
	ani	&H01		;log on bit test
	jnz	dsk.ok		;already logged on

;read id sector

	call	dsk.log

	jz	log.ck		;id sector got read
	lxi	h,0		;bad log on hl=0(no Drive table)
	jmp	dsk.er		;exit error

;check if a JADE disk
;original Jade software had bug where Jade ID was sometimes ALL CAPS
;we check for both here

log.ck	
	lxi	h,log.buf	;get address of dd
	lxi	d,jadeid	;de points to "JADE ID" value
	mvi	b,id.sze	;label size
log.id	ldax	d		;get label character
	cmp	m		;match?
	jnz	log.ck2		;check for other "Jade ID"
	inx	h		;point to next chars
	inx	d		;
	dcr	b		;dec count of characters
	jnz	log.id		;again
	jmp	found.id
log.ck2	
	lxi	h,log.buf	;get address of dd
	lxi	d,jadeid2	;de points to id value
	mvi	b,id.sze	;label size
log.id2	ldax	d		;get label character
	cmp	m		;match?
	jnz	not.jade	;tell not jade
	inx	h		;point to next chars
	inx	d		;
	dcr	b		;dec count of characters
	jnz	log.id2		;again

;diskette contains JADE id

found.id
	call	trnone		;no sector translation

	call	dpb.ad		;get dpb address in de
	lxi	h,log.buf+log.dpb	;get address of dpb in log.buf

	lxi	b,DPBsize	;size of dpb
	call	block		;move dpb on dd to bios dpb


; by happenstance, 48 spt z80 emulator disks UNUSED field (log.ddf-1) contain 6 and 50 spt contain 0

;get value of log.ddf-1
	lda	log.buf+log.ddf-1	;a is either 6 or 0
	ani	2		;a now is either 2 or 0
	cma			;a now is partially negated(need add 1)
	adi	51		;a now is either 48 or 50 (plus 51)
	sta	bt.SPTsys	;store in config block

;	assume SYS tracks are double density

	mvi	a,2		; density is double=2
	sta	bt.Dsys		; store in config block

	lda	log.buf+log.ddf		;get density flags from sector(id) buffer
	mov	b,a		;save for later
	rar
	rar
	rar
	ani	1		;0 for single sided 1 for double sided
	inr	a		;now 1 for single sided 2 for double sided
	sta	bt.hds

	mov	a,b

	ani	&H04		;test data trk-2 density
	cz	tr3740		;if single density use 3740

	rar
	rar
	ani	1		;0 for single 1 for double
	INR	A		;now 1 for single 2 for double
	sta	bt.Ddat

	call	dsk.cfg

	lhld	dt.ptr		;reload ptr to dph table
	jmp	dsk.ok		;return with drv ptr in hl

;assume 3740

not.jade
	lxi	de,NJ$Msg
	Call	PrintDE
	jmp	dsk.er		;exit if not a jade disk


;set 3740 sector translation

tr3740
;	call	GetXLTptrBIOS	;DE=address of XLT in bios
	lxi	d,0xFA00
	lhld	dt.ptr		;ptr to dph table
	mov	m,e		;put xlat table pointer into dph at 0
	inx	h		;
	mov	m,d		;

	lxi	h,IBM8X		;HL=single density translation table
	lxi	b,26		; 26 SPT for all single density disks.
	ldir
	ret

;set no xlation

trnone	xra	a		;zero
	lhld	dt.ptr		;ptr to dph table
	mov	m,a		;put null xlat table pointer into dph at 0
	inx	h		;
	mov	m,a		;
	ret

;get drv par block address

dpb.ad	lhld	dt.ptr		;ptr to dph table
	lxi	d,10		;
	dad	d		;d points to dpb in dph
	mov	e,m		;get dpb from dph at offset 10
	inx	h		;
	mov	d,m		;
	ret

; this seldsk routine calls the real seldsk routine just to get DPH pointer
; but then does everything else as though it is the real seldsk with login

seldsk
	lda	DiskNumber
	sta	bt.drv
	mov	c,a
	call	SelDisk
	shld	dt.ptr		;store drive table pointer

	xra	a		;force log on
	sta	log.rq		;save log on req in log.rq

	jmp	log.on
;-------------
;id label
;original Jade software had bug where Jade ID was sometimes ALL CAPS

jadeid	text	"JADE DD " ;"JADE ID" ?????
id.sze	equ	$-jadeid
jadeid2	text	"Jade DD " ;"Jade ID" ?????

;bios variable storage

dt.ptr	dw	0	;drive table pointer
log.rq	db	0	;log on request

;log buffer takes the place of DD log buffer

log.dpb	equ	20h		;offset to dpb in buffer
log.ddf	equ	31h		;id sec - flags	


log.buf ds	80

;---------------

	ds	256
Stack	equ	$
	end	0100h
	