;Formatieren von Disketten in eigenen Formaten

;--------------------------------------------------------------------;
;    Murphy 1987						     ;
;--------------------------------------------------------------------;

;*** 24-2-87

  .z80

SYS      Macro    Adresse
;;dient zum Aufruf einer Routine in der Systembank
         call     0FC5Ah
	 defw     Adresse
	 endm

BDOS     Macro    Code
         ld       c,Code
	 call     5
 	 endm

PRINT    Macro    Message
;; Ausgeben einer Meldung auf den Bildschirm mit Hilfe
;; der BDOS-Funktion 9. Ab "Message" muss der auszu-
;; gebende Text durch "$" beendet stehen.

	 ld    	  de,Message    ;;Text - Adresse
	 BDOS     9		;Print String
	 endm


	 CR	  equ      13	;Carriage Return
	 LF	  equ      10	;Line Feed
	 
	 Tracks   equ	   12h	;relative Position
	 Heads    equ	   11h	;verschiedener
	 Sektor1  equ      14h	;Formparameter
	 Sekpertr equ	   13h	;im DPB
	 Sektlen  equ      0Fh
	 Gap_3	  equ      18h
	 Logflg	  equ	   1Ah
	 Fillbyte equ      0E5h


;     *** Programmstart ***

	 ld  (Stackpointer),SP 	;Eigener Stack, damit
Start:   ld	  SP,01000h	;in jeder Position ein
				;Fehlerabbruch moeglich
	 ld	  c,25		;ist
	 call	  5 		;Aktives Drive holen
	 ld	  (Old_Drive),A

	 PRINT    Hellomessage

	 ld	  a,(Drive)
	 ld	  c,a
	 ld	  e,0FFh	;;*** nicht 1. Zugriff !
	 call	  0FC1Bh	;;Select Drive

;***     SYS	  03EBBh	;DPH-Adr. f. Drive in HL

	 push	  hl
	 dec	  hl
	 dec	  hl

	 SYS	  03FE0h	;ld  l,physik. Drive

	 ld	  a,l
	 ld	  (Phys_Drive),a
	 pop	  de

	 SYS	  03F76h	;DPB in IX

	 ld 	  a,(ix+Logflg) ;Loginflag zwi-
	 ld 	  (Loginflag),a ;schenlagern,
	 ld    (ix+Logflg),0FFh ;beim Formatieren
				;Login unterdruecken,
	 call	  Forminfo	;Arbeitsformat
	 PRINT	  mal_fragen	;anzeigen

Security:
	 call	  Getchr
	 cp	  "J"		;nur wenn j,J,^J
	 jr nz,	  Security	;formatieren
	 ld 	  b,2		;Der FDC kann nur max
;   77 Tracks bei einem Recalbefehl steppen (weiss der
;   Geier warum);    daher evtl. 2 mal, damit auch von
;   Trk 80 der Trk 0 erreichbar ist.

Recal:	 push	  bc
	 SYS	  0E6Dh		;Motoren an
	 ld 	  b,77		;Max. Wartezeit
	 ld 	  a,(Phys_Drive);annehmen;
	 ld	  c,a		;C  :  Drive
	 SYS	  0D23h		;Recalibrate
	 pop	  bc
	 and	  20h		;Seek End ?
	 jr	  nz,Anfang	;Alles klar, kann
	 djnz	  Recal		;losgehn
	 ld	  de,Recalmessage;Was'n?
	 jr	  fertich	;->Fehlermeldung

Anfang:  ld	  a,(ix+Heads)	;Headmax
	 or	  a
	 ld	  a,(ix+Tracks)	;Trackmax (s. Text)
	 jr	  z,einhead
	 add	  a,a

einhead: ld	  b,a		;Tracks * Koepfe
	 ld	  d,0FFh	;Track (-1)

Format:	 push	  bc		;Zaehler
	 inc	  d
	 push	  de		;lfd. Track
	 xor	  a		;Head Adresse 0
	 bit	  0,(ix+Heads)	;1 Head --> Z
	 jr	  z,einhd2
	 srl	  b		;Bit 0 --> C-Flag
	 adc	  a,a		;Jeder zweite Track
				;auf Seite 2
einhd2:  ld 	  e,a		;Head - Adr
	 ld	  a,(Phys_Drive)
	 add	  a,e
	 add	  a,e		;Drive + 4*Head -->
	 add	  a,e		;Unit Select (FDC)
	 add	  a,e
	 ld	  c,a		;C: Unit Select
	 push	  de		;Track & Head
	 bit 	  0,(ix+Heads)
	 jr	  z,einhd3	;Einseitiges Format
				;Zweiseitig:
	 srl	  d		;log. Track / 2 -->
				;physik. Track

einhd3:	 call	  info		;Anzeige von Track &
	 call	  Anpassen	;Head
	 pop 	  de		;Jetzt wieder log.
	 ld 	  e,Fillbyte	;Track !
	 ld	  b,1		;Bank fuer die Format-
				;maskentabelle (TPA)

;	 HL :	  Formatmaske
;	 IX :	  Disk Parameter Block
;	  C :	  Drive & Head
;	  D : 	  Zu formatierender Track (logischer !)

	 SYS	  08Fh		;Bios-Vektor fuer
	 			;Formatieren
	 pop	  de		;Lfd. Track-
	 pop	  bc		;Zaehler
	 jr	  nc,Error	;Oh ha ! Fehler
	 djnz	  Format	;Noch'n Track?
				;(wie im Goldrausch)
	 ld	  de,Readymessage;(nanu kein Fehler)
	 jr	  fertich

Error:	 ld	  de,Writeprotect;(- oder gar nix
	 jr	  z,fert2	;im Schlitz)
	 ld	  de,Errormessage;Knallharter Murks !

fertich: ld	  c,9		;BDOS "String ausgeben"
	 call	  5
	 jr	  exit

fert2:	 ld	  c,9		;Schreibgeschuetzt oder gar
	 call	  5		;keine Disk im Laufwerk
	 call	  Getchr
	 cp	  "R"
	 jr	  z,Anfang	;Nochmal versuchen

exit:	 ld	  a,(Loginflag)	;Altes Loginflag
	 ld	  (ix+Logflg),a	;wieder herstellen
	 ld	  a,(Old_Drive)
	 ld	  c,a
	 ld	  e,0FFh	;;*** nicht 1. Zugriff
	 call 	  0FC1Bh	;;*** Select Drive

	 PRINT	  weiter	;Noch weitere Disks
				;im selben Format
	 call	  Getchr
	 cp	  "J"
	 jp	  z,Start
	 ld	  SP,(Stackpointer)
	 ret

Stackpointer:
	 defw	  0
Drive:	 defb	  1		;Systemvariable fuer das aktive Drive
				;B:   (A:0  ;  B:1  ;  C:2)
Phys_Drive:
	 defb	  0		;Physikalisches Laufwerk
Old_Drive:
	 defb	  0		;Altes Laufwerk zwischenspeichern
Loginflag:			;Das Loginflag aus dem DPB wird
	 defb	  0  		;hier waehrend des Formatierens
				;abgelegt

;--------------------------------------------------------------------;
;  Unterprogramme             					     ;
;--------------------------------------------------------------------;
Anpassen:			;****  Format-Tabelle anpassen    ****

;  Fuer jeden Track muessen dem FDC Parameter uebergeben
;  werden, anhand derer er hinterher beim Schreiben
;  und Lesen erkennt, ob er zum Einen auf der richtigen
;  Spur steht, und zum Anderen, ob er auf dieser Spur
;  den richtigen Sektor gefunden hat.
	 ld	  hl,Disktab
	 push	  hl
	 push	  bc
	 push	  de
	 ld	  a,(ix+Sektor1)
	 ld	  c,(ix+Sektlen)
	 ld	  b,(ix+Sekpertr)

anp1:	 ld	  (hl),d	;Track anpassen
	 inc	  hl
	 ld	  (hl),e	;Head
	 inc	  hl
	 ld	  (hl),a	;Sektor
	 inc	  hl
	 ld	  (hl),c	;Sektorlaenge
	 inc	  hl
	 add	  a,5		;naechste Sektornr.
	 djnz	  anp2
	 jr	  Exanpass

anp2:	 ld	  (hl),d	;Track anpassen
	 inc	  hl
	 ld	  (hl),e	;Head
	 inc	  hl
	 ld	  (hl),a	;Sektor
	 inc	  hl
	 ld	  (hl),c	;Sektorlaenge
	 inc	  hl
	 add	  a,-4		;naechste Sektornr.
	 djnz	  anp1

Exanpass:
	 pop	  de
	 pop	  bc
	 pop 	  hl
	 ret

Disktab:
;      kann durch "DEFS 40" erzeugt werden ! ! !
;      so wird aber die Struktur deutlicher.

	 defb	  Tracks	;Diese Tabelle muss fuer 
	 defb	  Heads		;jede Spur neu ini-
	 defb	  Sektor1 + 0	;tialisiert werden
	 defb	  Sektlen

         defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 5
	 defb	  Sektlen

         defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 1
	 defb	  Sektlen

         defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 6
	 defb	  Sektlen

         defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 2
	 defb	  Sektlen

	 defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 7
	 defb	  Sektlen

	 defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 3
	 defb	  Sektlen

	 defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 8
	 defb	  Sektlen

	 defb	  Tracks
	 defb	  Heads
	 defb	  Sektor1 + 4
	 defb	  Sektlen

	 defb	  Tracks	;Achtung ! 10. Sektor
	 defb	  Heads		;wird i. A. nicht
	 defb	  Sektor1 + 9	;benutzt
	 defb	  Sektlen

Getchr:	 BDOS	  1		;Tastatureingabe

	 cp	  3		;Abbruch durch ^C
	 jr	  z,CTRL_C
	 and	  01Fh		; "a";"A" --> ^A
	 or	  040h		; --> "A"
	 ret			;nur noch Grossbuchstaben!

CTRL_C:	 ld	  de,Abbruch
	 jp	  fertich

printA:  	  ;Dezimalausgabe von A --> Bildschirm
	 ld	  l,a
	 ld	  h,0

printHL: 	  ;  5 Stellen mit Nullunterdrueckung
	 ld	  d,0		;30h , wenn Nullunterdr.
	 ld	  bc,-10000	;unerwuenscht
	 call	  Decziffer	;5. Stelle
	 ld	  bc,-1000
	 call	  Decziffer	;4. Stelle...
	 ld	  bc,-100
	 call	  Decziffer	
	 ld	  bc,-10
	 call	  Decziffer
	 ld	  a,l		;Letzte Stelle wird
;	immer geprintet, auch wenn es eine Null ist.

Decprnt: or	  30h		;Ziffer --> ASCII
	 push	  hl
	 push	  de
	 push	  bc
	 ld	  e,a		;Ausgabe
	 BDOS	  2

	 pop	  bc
	 pop	  de
	 pop	  hl
	 ret

Decziffer:
	 ld	  a,-1		;Arbeitszaehler

decloop: inc	  a		;Zaehlen, wie oft BC
	 add	  hl,bc		;in HL enthalten ist
	 jr	  c,decloop
	 sbc	  hl,bc		;Rest zurueck -> HL
	 or 	  d		;Sowohl A als auch D Null?
	 ret	  z		;Fuehrende Null ignorieren
	 ld	  d,030h	;Beenden der Nullkennung
	 jr	  Decprnt       ;und Ausgabe

Hexprint:
	 push	  hl
	 push	  de
	 push	  bc
	 push	  af
	 and	  0F0h		;High Digit ausmaskieren
	 rlca			;--> low Digit rollen
	 rlca
	 rlca
	 rlca
	 call	  hexziffer	;Ausgeben
	 pop	  af
	 and	  0Fh		;Low Digit
	 call	  hexziffer
	 pop	  bc
	 pop	  de
	 pop 	  hl
	 ret

hexziffer:
	 add	  a,"0"		;0-9 --> ASCII
	 cp	  ("9"+1)
	 jr	  c,ziffer
	 add	  a,7		;A-F --> Buchstabe
	 
ziffer:	 ld	  e,a
	 BDOS	  2		;Ausgabe
	 ret

info:	 push	  bc		;Anzeige der gerade
	 push	  de		;formatierten Spur
	 push	  hl
	 push	  de		;Track & Head
	 push	  de

	 PRINT	  trktext
	 pop	  de
	 ld	  a,d		;Track anzeigen
	 call	  printA

	 PRINT	  kopftext

	 pop	  de
	 ld	  a,e		;Head anzeigen
	 call	  printA
	 ld	  c,11		;Get Console Status
	 call	  5
	 and	  a
	 jr	  z,Notbreak	;Keine Taste gedrueckt
	 call	  Getchr	;Durch ^C abbrechen
	 call	  Getchr	;oder durch zweite Taste
				;weitermachen
Notbreak:
	 pop	  hl
	 pop	  de
	 pop	  bc
	 ret

	 org	  0200h

Forminfo:
	 PRINT	  Formtracks	;Formatparameter des
	 ld	  a,(ix+Tracks) ;verwendeten Formats
				;anzeigen
	 call	  printA	;Anzahl der Spuren

	 PRINT	  Form1sektor	;Basissektor
	 ld	  a,(ix+Sektor1)
	 call	  Hexprint

	 PRINT	  Formheads	;Ein- oder zweiseitig
	 ld	  a,(ix+Heads)
	 inc	  A		;( weil 0 = einseitig
	 call	  printA

	 PRINT	  Formsekpertr	;Sektoren / Spur
	 ld	  a,(ix+Sekpertr)
	 call	  printA

	 PRINT	  Formlen	;Laenge eines Sektors
	 ld	  b,(ix+Sektlen)
	 inc	  b		;ist im DPB als
	 ld	  hl,64		;log2 (Laenge/128 Bytes)
				;abgelegt
lencalc: add	  hl,hl		
	 djnz	  lencalc
	 call	  printHL
	 ret


;--------------------------------------------------------------------;
;        Meldungen						     ;
;--------------------------------------------------------------------;
	 org	  0280h

Hellomessage:
	 defb	  CR,LF,LF
	 defb	  "Diskettenformatierprogramm"
	 defb	  "     Murphy 1986"
	 defb	  CR,LF,LF
	 defb	  "Format:"
	 defb	  "$"

;*** Meldungen fuer "info" / Anzeige der laufenden Spur

	 org	  0300h

trktext: defb	  CR
	 defb	  "Track  :  "
	 defb	  "$"

	 org	  0380h

kopftext:
	 defb	  "     Kopf  :  "
	 defb	  "$"

;*** Fehlermeldungen bzw. Erfolgsmeldung

	 org	  0400h

Readymessage:
	 defb	  CR,LF,LF
	 defb	  "Nun gut, das Formatieren hat "
	 defb	  "geklappt"
	 defb	  CR,LF,LF
	 defb	  "$"

	 org	  0480h

Errormessage:
	 defb	  CR,LF,LF
	 defb	  "Scheisse, geht nicht !"
	 defb	  CR,LF,LF
	 defb 	  "$"

	 org	  0500h

Writeprotect:
	 defb	  CR,LF,LF
	 defb	  "Versuch's mal mit einer nicht "
	 defb	  "schreibgeschuetzten Diskette"
	 defb	  CR,LF,LF
	 defb	  "R-etry ? / .$"

	 org	  0580h

Recalmessage:
	 defb	  CR,LF,LF
	 defb	  "Fehler beim Suchen von Spur  Null !"
	 defb	  CR,LF,LF
	 defb	  "$"

	 org	  0600h

Abbruch: defb	  CR,LF,LF
	 defb	  "Abbruch der Formatierung"
	 defb	  CR,LF,LF
	 defb 	  "$"

	 org	  0680h

weiter:  defb	  CR,LF,LF
	 defb	  "Nochmal, oder ist jetzt endlich "
	 defb	  "Schluss ?!"
	 defb	  CR,LF,LF
	 defb	  "( J / N )"
	 defb	  "$"

;*** Meldungen fuer die Anzeige des verwendeten Formats

	 org	  0700h

mal_fragen:
	 defb	  CR,LF,LF
	 defb	  "Format korrekt ?  ( J / CTRL-C )"
	 defb	  CR,LF,LF
	 defb	  "."
	 defb	  8,"$"

	 org	  0780h

Formtracks:
	 defb	  CR,LF,LF
	 defb	  "Spuren auf einer Seite  :  $"

	 org	  0800h

Form1sektor:
	 defb	  "      Basissektor  :  $"

	 org	  0880h

Formheads:
	 defb	  CR,LF
	 defb	  "Kopfanzahl  :  $"

	 org	  0900h

Formsekpertr:
	 defb	  CR,LF,LF
	 defb	  "Sektoren / Track  :  $"

	 org	  0980h

Formlen: defb	  "              Sektorgroesse  :  $"

end
	  