Page 1 of 1

Trying to support the Xerox 820 with appmake

Posted: Wed May 18, 2022 3:23 pm
by stefano
Some time ago I submitted a patch to the MAME project fixing the disk controllers on the basic Xerox820 model (SA400->SA400l drive models).
The RAW format is not accepted yet, but IMD works fine.
Now it is possible to work on the disk images with CPMTOOLS and, with a bit of work, run CP/M programs on MAME.
The TRM has detailed technical specs, so I thought it was easy to include the disk format in appmake, but something is wrong.

Got from the TRM (SSSD, 5"1/4, 40 Tracks, 18 Sectors, 128 byte sector size):


Sectors Per Track (SPT) 18
Block Shift Factor (BSH) 3
Max. Rec. # in blk (BLM) 7
Extent Mask (EXM) 0
Total Storage capacity (DSM) 82
Total # of directory entries (DRM) 31
Allocation mask (ALO) 80H
Allocation mask (AL 1) 0
Size of dir check vector (CKS) 8
Reserved tracks (OFF) 3


Skew table: 1 ,6, 11, 16, 3, 8, 13, 18, 5, 1 0, 15, 2, 7, 12, 17, 4, 9, 14


Cpmtools (works):

# XER2 Xerox 820 - SSSD 48 tpi 5.25" - 128 x 18
diskdef xer2
seclen 128
tracks 40
sectrk 18
blocksize 1024
maxdir 32
skew 5
boottrk 3
os 2.2
end




My conclusions (close, but does not work):


static disc_spec x820_spec = {
.name = "Xerox820",
.sectors_per_track = 18,
.tracks = 40,
.sides = 1,
.sector_size = 128,
.gap3_length = 0x17,
.filler_byte = 0xe5,
.boottracks = 3,
.directory_entries = 32,
.extent_size = 1024,
.byte_size_extents = 0,
.first_sector_offset = 0,
.has_skew = 1,
.skew_track_start = 0,
.skew_tab = { 0,5,10,15,2,7,12,17,4,9,14,1,6,11,16,3,8,13 }
};


I can see a correct directory on CPMTOOLS but MAME fails. The image is accepted by MAME but CP/M says "disk error".
Suggestions ?

Re: Trying to support the Xerox 820 with appmake

Posted: Wed May 18, 2022 4:09 pm
by dom
Did you try it without the skew table? And it might need byte-sized extents as well.

Re: Trying to support the Xerox 820 with appmake

Posted: Thu May 19, 2022 6:32 am
by stefano
Yes. I'm comparing it with a working image containing only magic.com.
It looks almost identical, that's why I'm puzzled.

In the meantime I discovered a small difference in the allocation tables, now I changed from words to bytes, which you noticed as well.
Still no luck, though.

Re: Trying to support the Xerox 820 with appmake

Posted: Thu May 19, 2022 6:35 am
by stefano
I decided to create an inspection program starting from dpb.com, it will be useful.

Re: Trying to support the Xerox 820 with appmake

Posted: Thu May 19, 2022 3:13 pm
by stefano
I noticed that both my cpmtools version and MAME are not always dealing with the disk image formats as expected, e.g. a specific model could work fine with RAW and D88 formats and fail with IMD, or vice versa.

BTW, here's my current progress, tested on the emulated Bondwell 14:
BW14.png

Re: Trying to support the Xerox 820 with appmake

Posted: Fri May 20, 2022 8:11 am
by stefano
Tool is ready ;)


https://github.com/z88dk/z88dk/blob/mas ... /cpm/dpb.c


A bit of inspiration came from an ancient tool by Sydex, which is capable of listing the skew table, thus sometimes it could still be useful.
I adapted it to z80asm, so it's now easy to build with zcc or z88dk-z80asm:

Code: Select all


;  To build:   zcc +cpm -create-app /c/z88dk/examples/cpm/dpbz80.asm
;              where already available, -create-app probably helps

; ..otherwise, just add "org 100h" and build it directly with z80asm  ;)


DEFC bdos  =  0005h ; BDOS call vector
DEFC wboot  =  0000h ; Warm boot vector
DEFC cdisk  =  0004h ; current disk
DEFC cr  =  13 ; return
DEFC lf  =  10 ; line feed
DEFC bel  =  7 ; bell


GLOBAL _main

_main:
	call	Strout
	DEFM	cr,lf,"       Parameters for Drive ",0

	LD	A,(cdisk)
	AND	15
	ADD	A,'A'
	call	chout		; give a drive letter

	call	Strout
	DEFM	":",cr,lf,lf,0  ; skip a line

	LD	A,(cdisk)
	LD 	c,a
	LD	HL,(wboot+1)
	LD 	l,27		; point to seldisk
	call	Indcall		; go call (seldisk)

	LD 	a,h
	OR	l
	JP	NZ,GetDPB2		; if okay
	call	Strout
	DEFM	cr,lf,bel,"Select error",cr,lf,0
	JP	wboot		; exit...

GetDPB2:
	LD	(DPHaddr),HL		; save DPH address
	LD	DE,10
	ADD	HL,DE
	LD 	e,(HL)
	INC	HL
	LD 	d,(HL)		; get DPB address
	EX	DE,HL
	LD	(DPBaddr),HL		; save DPB address

;	Show sectors/track.

	call	Strout
	DEFM	"Sectors per Track............",0
	LD 	a,0
	call	GetField	; get a field from the DPB
	LD	(SectTrk),HL		; save it
	call	ShowDec		; show it

;	If there's a translate table, show it.

	LD	HL,(DPHaddr)
	LD 	e,(HL)
	INC	HL
	LD 	d,(HL)
	LD 	a,d
	OR	e
	JP	Z,GetDPB6		; if none..
	call	Strout
	DEFM	cr,lf,"Sectors interleaved as follows:",0

	LD	HL,(SectTrk)		; get Sectors/track
	LD 	b,h
	LD 	c,l
GetDPB4:
	call	Strout
	DEFM	cr,lf,"    ",0  ; indent
	LD	A,(DE)		; get a sector
	PUSH	HL
	LD 	l,a
	LD 	h,0
	call	ShowDec		; show it
	POP	HL
	DEC	BC
	LD 	a,b
	OR	c
	JP	NZ,GetDPB4		; loop...
	JP	GetDPB8		; do the rest...

GetDPB6:
	call	Strout
	DEFM	cr,lf,"Sectors are not interleaved",0

;	Show the rest of the fields.

GetDPB8:
	call	Strout
	DEFM	cr,lf,"Block Shift (BSH)............",0
	LD 	a,2
	call	GetField
	LD 	h,0
	call	ShowDec
	call	Strout
	DEFM	cr,lf,"Block Mask (BLM).............",0
	LD 	a,3
	call	GetField
	LD 	h,0
	call	ShowDec
	call	Strout
	DEFM	cr,lf,"Extent Mask (EXM)............",0
	LD 	a,4
	call	GetField
	LD 	h,0
	call	ShowDec
	call	Strout
	DEFM	cr,lf,"Total Blocks (DSM)...........",0
	LD 	a,5
	call	GetField
	call	ShowDec
	call	Strout
	DEFM	cr,lf,"Directory Entries (DRM)......",0
	LD 	a,7
	call	GetField
	call	ShowDec
	call	Strout
	DEFM	cr,lf,"Allocation 0 (AL0)...........",0
	LD 	a,9
	call	GetField
	LD 	h,0
	call	ShowHex
	call	Strout
	DEFM	cr,lf,"Allocation 1 (AL1)...........",0
	LD 	a,10
	call	GetField
	LD 	h,0
	call	ShowHex
	call	Strout
	DEFM	cr,lf,"Cylinder Offset (OFS)........",0
	LD 	a,13
	call	GetField
	call	ShowDec
	call	Strout
	DEFM	cr,lf,lf,0		; done...
	JP	wboot			; exit...

;*	Indirect call to (hl).
;
;	Simple, yet effective.
;

Indcall:
	JP	(HL)			; jmp to (hl)

;*	GetField - Get a DPB field into (hl)
;
;	(a) = offset on entry.
;

GetField:
	PUSH	DE
	LD	HL,(DPBaddr)
	LD 	e,a
	LD 	d,0
	ADD	HL,DE
	LD 	e,(HL)
	INC	HL
	LD 	d,(HL)
	EX	DE,HL
	POP	DE
	ret


;*	Chout - Character in (a) to console output.
;
;	Preserves all but (a)
;

chout:
	PUSH	HL
	PUSH	BC
	PUSH	DE
	LD 	e,a
	LD 	c,2
	call	bdos			; issue a console-out
	POP	DE
	POP	BC
	POP	HL
	ret

;*	Strout - Output a string following the call to this routine.
;
;	preserves all.
;
;	String is null-terminated.
;

Strout:
	EX	(SP),HL				; get return in (hl)
	PUSH	AF			; save (a)
Strout2:
	LD 	a,(HL)
	INC	HL
	OR	a
	JP	Z,Strout4			; if done...
	PUSH	DE
	PUSH	BC
	PUSH	HL
	LD 	e,a
	LD 	c,2			; console out
	call	bdos
	POP	HL
	POP	BC
	POP	DE
	JP	Strout2

Strout4:
	POP	AF
	EX	(SP),HL
	ret				; exit...all regs preserved

;*	ShowDec - Show (HL) as a decimal number.
;
;	Output to the console; blank leading zeroes.
;

ShowDec:
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	DE,DecTable	; get powers table
	EX	DE,HL
	LD 	c,0		; say blanking
ShowDec2:
	LD 	a,(HL)
	OR	a		; see if last digit
	JP	Z,ShowDec8	; if so
	LD 	b,0
ShowDec4:
	INC	b
	LD 	a,e
	sub	(HL)
	LD 	e,a
	INC	HL
	LD 	a,d
	SBC	(HL)
	LD 	d,a
	DEC	HL
	JP	NC,ShowDec4	; if oversubtract

;	correct oversubtract.

	LD 	a,e
	ADD	A,(HL)
	LD 	e,a
	INC	HL
	LD 	a,d
	ADC	A,(HL)
	INC	HL
	LD 	d,a
	DEC	b
	JP	Z,ShowDec6	; if a zero
	LD 	c,1
ShowDec6:
	INC	c
	DEC	c		; check (c)
	JP	Z,ShowDec2	; loop to next digit
	LD 	a,b
	ADD	A,'0'
	call	chout		; character out
	JP	ShowDec2	; to next digit

;	Do the last digit - do not blank.

ShowDec8:
	LD 	a,e
	ADD	A,'0'
	call	chout
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	ret

DecTable:
	DEFW	10000,1000,100,10,0	; powers of 10


;*	ShowHex - Show a string of hex digits.
;
;	On entry (HL) = value.
;
;	Output is to console, leading zeroes blanked.
;

ShowHex:
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	BC,0400h			; 4 digits + blank indicator
ShowHex2:
	XOR	a
	ADD	HL,HL
	RLA
	ADD	HL,HL
	RLA
	ADD	HL,HL
	RLA
	ADD	HL,HL
	RLA				; isolate a digit in (a)
	OR	a
	JP	Z,ShowHex4		; if zero
	LD 	c,1			; say nonzero
ShowHex4:
	ADD	A,'0'                     ; bias for ASCII
	CP	'9'+1
	JP	C,ShowHex6		; if 0-9
	ADD	A,'A'-'9'-1               ; make digits
ShowHex6:
	DEC	b
	JP	Z,ShowHex8		; if last digit
	INC	c
	DEC	c
	JP	Z,ShowHex10		; skip the leading zero
ShowHex8:
	call	chout
ShowHex10:
	INC	b
	DEC	b
	JP	NZ,ShowHex2		; if not done yet
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	ret				; exit...

DPBaddr: DEFW	0		; address of DPB
DPHaddr: DEFW	0		; address of DPH
SectTrk: DEFW	0		; sectors/track


The C version should be able to identify the right block size.
When in trouble, it will warn about it and will suggest a second guess.
kaypro_a.png
kaypro_b.png
bondwell.png

Re: Trying to support the Xerox 820 with appmake

Posted: Fri May 20, 2022 3:28 pm
by stefano
MAME often allows a shortcut, after having loaded the CP/M system, to QUICKLOAD a .COM program in memory and run it directly.
So, even if you can't write in a disk image :
xerox820.png

Re: Trying to support the Xerox 820 with appmake

Posted: Fri May 20, 2022 3:50 pm
by stefano
When the QUICKLOAD is not available, run mame with the "-debug" option, boot the CP/M disk (mout the disk image and press F5), then type in the bottom row in the debugger window: "load c:\files\dpb.com,100".
alph_debugger.png
You can then move in the emulator windows and save the loaded file in the current disk image, then just run it !
alph_dpb.png

Re: Trying to support the Xerox 820 with appmake

Posted: Fri May 20, 2022 3:57 pm
by stefano
... I think the disk size is still wrong, the other results look strangely good :D

Re: Trying to support the Xerox 820 with appmake

Posted: Mon May 23, 2022 12:16 pm
by stefano
Fixed and improved.
Now it checks the CP/M version (and warns when the version is not supported) and shows the interleave table (in appmake format) when used.
I'm not yet able to create valid disk images for the Xerox820, but we now have a nice general purpose tool :D

xerox820.png

Re: Trying to support the Xerox 820 with appmake

Posted: Tue May 24, 2022 1:44 pm
by stefano
I found a side element which was increasing the confusion: when I tried to convert from IMD to RAW a disk image, MAME, ONLY ON SOME OF THE CP/M TARGETS stopped working. The odd thing was that there wasn't target specific code which could have explained such behavior.
I finally discovered that the reason is probably on the FM versus MFM disk format emulation (plus on some obscure exception for few targets) !

Code: Select all

Container FM/MFM:
  hfe                      r- - SDCard HxC Floppy Emulator HFE File format [hfe]
  mfm                      rw - HxCFloppyEmulator floppy disk image [mfm]
  td0                      r- - Teledisk disk image [td0]
  imd                      r- - IMD disk image [imd]
Container MFM:
  d88                      r- - D88 disk image [d77,d88,1dd]
  cqm                      r- - CopyQM disk image [cqm,cqi,dsk]
  dsk                      r- - CPC DSK Format [dsk]
  dmk                      r- - DMK disk image [dmk]