.Z80 ;----------------------------- ; Murphy 1987 ;----------------------------- ;******************************************************************** ;* 2 * 80 Track am CPC 6128 unter CP/M+ * ;* Austausch der DPBs von A: und C: in Loginroutine * ;******************************************************************** PATCH Macro Nr ;;ein Speicherbereich ab DE aus der TPA in die ;;Systembank an die Speicherstelle (Ziel) kopiert. Die ;;Anzahl der Bytes wird durch Laenge bestimmt. ;;DE weist auf das erste Byte danach. ld bc,ende&Nr - ptch&Nr ;;Laenge des Patch ld hl,code&Nr ;;Zieladresse call Patchexecution endm ; 4 Flagvariablen koennen den erzeugten Code veraendern: ;-------------------------------------------------------- LOGIN equ 1 ;0 : Festlegen des Formats ;1 : autom. Erkennung von 4 Formaten Drive_C equ 1 ;1 : Doppelfloppy F800k equ 0 ;0 : 512 Byte Sektoren ;1 : 1k Sektoren Step_B equ 4 ;Steprate fuer Drive B: und C: Step_C equ 8 ;in ms (geradzahlig von 2 - 30 !) ; --- durch Streichen von Sektorenpuffern ; Arbeitsplatz in der Systembank schaffen ld de,ptchS PATCH S ;neue Anzahl der Sektoren ;(nicht bei Verwendung des ;Kassettenpuffers) if F800k PATCH T ;evtl. neue Groesse endif call 0FC5Ah;Call SYS 019Ah defw 19Ah ;Sektorpuffer initialisieren ld (DIRBCB_ADR),de ld (DATBCB_ADR),hl ld de,ptchU PATCH U ld de,ptch1 PATCH 1 ;2. Kopf beim Auslesen des ;FDC nicht als Fehler werten PATCH 2 ;individuelle Steprate PATCH 3 ;Arbeitsroutinen fuer 1 & 2 ;im Sektorpuffer PATCH 4 ;fiktives Drive I: & J: ;in Drivetabelle einbinden PATCH 5 ;Flag fuer 2 Drives PATCH 6 ;logisches B: = physik. B: PATCH 7 ;entscheidet, auf welchem ;Drive weitere simuliert ;werden koennen if Drive_C PATCH 8 ;DPB - Austausch von A: & C: endif ;ins BIOS einbinden if LOGIN PATCH A ;autom. Formaterkennung else PATCH B ;oder DPB fuer B: festlegen endif if Drive_C ;zwei externe Laufwerke PATCH C ;DPH / CKS / Alloc / Hashtab PATCH D ; DPH von C: in Drivetabelle endif ld de,message ld c,9 ;BDOS "Stringausgabe" jp 5 ;Ausgabe & Ende Patchexecution: push bc ld bc,0001 ;Ziel : Bank 0 call 0FC57h ;Quelle : Bank 1 pop bc call 0FC4Bh ;Block kopieren ret if F800k ;-------------------------------------------------------------------- ptchS: ;*** 1k - Sektorpuffer !!!??? codeS equ 19Ah ld bc,400h ;4 Sektoren Dir / Bank 0 ld de,8C76h ;Adresse des 1. Puffers ld hl,8A00h ;1. Header push hl call 01D9h ;Initialisieren dec hl ld (hl),b ;letzter Eintrag dec hl ;kein Nachfolger ld (hl),b inc hl inc hl push hl Space equ 1 ;1k Bloecke (max. 4 !!!) ld b,5-Space ;max. 5 Datenpuffer call 01D9h ld bc,0B02h ;11k - Puffer in Bank 2 ld de,05080h call 01D9h dec hl ld (hl),b dec hl ld (hl),b Free_Ad equ 09C67h + 1024 * (5-Space) ; 1. freie Adresse im neuen Speicherbereich ; die letzte freie Adresse ist immer B066h endeS: ptchT: codeT equ 01F5h .phase codeT inc d ;-> neue Sektorlaenge inc d ; auf 1k setzen djnz 01DCh ret .dephase endeT: else ;-------------------------------------------------------------------- ptchS: codeS equ 1AFh ;Platz in Bank 0 schaffen Space equ 2 ;512k - Bloecke (max. 9 !!!) defb 10 - Space Free_Ad equ 09C67h + 512 * (10-Space) ; 1. freie Adresse im neuen Speicherbereich ; die letzte freie Adresse ist immer B066h endeS: endif ;-------------------------------------------------------------------- ptchU: codeU equ 0BEFBh DIRBCB_ADR: defs 2 DATBCB_ADR: defs 2 endeU: ptch1: code1 equ 0D5Ah ;Patch in der Resultphasen- ;auswertung call TwoInOne ende1: ptch2: code2 equ 0C07h ;Patch in der Seek Track ;Routine jp Steprate ende2: ptch3: code3 equ Free_Ad ;Arbeitsspeicher im freien ;Sektorpuffer .phase code3 Steprate: add iy,bc ;Funktion vor dem Patch muss ;erhalten bleiben push hl srl c ;C / 2 : Drivenr. in C ld hl,Steptab ;B ist 0 add hl,bc ;zugeh. Eintrag finden ld a,(hl) ld hl,0B0F1h ;ist die aktive Steprate cp (hl) ;gleich der gewuenschten ? jr z,stimmt ld (hl),a ;neue Steprate uebernehmen ld hl,0AD5h ;HL auf Headload; -unload call 0AF2h ;Drive Parameter an FDC stimmt: pop hl pop bc ;wurde vor Einsprung gepusht ret Steptab: ;geradzahlige Werte (2-30)! defb 12 ;12 ms fuer eingeb. Drive A: defb Step_B defb 0 ;Dummy ! defb Step_C ;das logische Drive C: ;ist physikalisch als Drive D: anzusprechen ! TwoInOne: ld a,c ;ausblenden der Headadresse res 2,a ;um Kopf 2 im Result des FDC or 020h ;wie Kopf 1 zu behandeln ret if LOGIN ;-------------------------------------------------------------------- DPBTab: ; A C H T U N G ! ; kein Highbyte-Wechsel innerhalb der Tabelle! defw 02Eh ;DE - Register f. Format_00 defw Form01 ;DPB f. Format_00 defw 02Ch ;Format_40 defw 0C0Bh defw 02Eh ;Format_80 defw Form81 defw 02Eh ;Format_C0 defw 0C25h Bereichchk: ;es sind nur 4 Formate moeglich ;Ein Overflow duerfte zwar nicht auftreten, ;aber man kann ja nie wissen. cp low DPBTab ;A war kleiner als 0 jr c,error cp low(Bereichchk-1);A war groesser als 3 ccf error: ;C = Fehler jp 03FE0h ;ld hl,(hl) ;DPB fuer Format_00 ;800k - Format ! Form01: defw 36 ;Records / Track defb 5 ;Blockshift defb 31 ;Blockmaske defb 3 ;Extent Maske defw 176 ;Bloecke - 1 defw 127 ;Directoryeintraege - 1 defw 080h ;ein Block fuer Directory defw 32 ;zu pruefende Eintraege / 4 defw 2 ;Systemsp. * Heads defb 2 ;Sektorlaenge defb 3 ;Sektormaske defb 1 ;2 Koepfe defb 80 ;Tracks defb 9 ;Sektoren / Track defb 01h ;1. Sektor defw 200h ;??? defb 2Ah ;Gap3 lesen / schreiben defb 52h ;Gap3 formatieren defb 60h ;Maske fuer MFM ;DPB fuer Format_81 Form81: defw 36 ;Records / Track defb 5 ;Blockshift defb 31 ;Blockmaske defb 3 ;Extent Maske defw 179 ;Bloecke - 1 defw 127 ;Directoryeintraege - 1 defw 080h ;ein Block fuer Directory defw 32 ;zu pruefende Eintraege / 4 defw 0 ;Systemsp. * Heads defb 2 ;Sektorlaenge defb 3 ;Sektormaske defb 1 ;2 Koepfe defb 80 ;Tracks defb 9 ;Sektoren / Track defb 081h ;1. Sektor defw 200h ;??? defb 2Ah ;Gap3 lesen / schreiben defb 52h ;Gap3 formatieren defb 60h ;Maske fuer MFM endif ;-------------------------------------------------------------------- last_3: .dephase ende3: ptch4: code4 equ 0FE2Fh + 2 * ("I"-"A") ;Drive I bzw. J sind wie der Name schon sagt eine ;imaginaere Einheit ! ; (finde ich immer wieder toll, diese Eselsbruecke) defw 3F94h ;I : DPH - Adr. fuer Drive A: defw 3FB7h ;J : DPH - Adr. fuer Drive B: ende4: ptch5: code5 equ 0BE40h defb 255 ;Flag fuer 2 Drives ende5: ptch6: code6 equ 03FB5h ;wenn beim Booten keine Diskette in B: war, steht ;hier sonst die Physikalische Adresse von Drive A: defb 1 ;Drive B: ende6: ptch7: code7 equ 03F55h ; nur ein Byte (!) entscheidet ueber die ; Simulationsmoeglichkeit von Drives dec a ;Physik. Drive B: ist auch durch J: ;anzusprechen, es erscheint beim ;Wechsel die bekannte Meldung und ;es wird eine Taste erwartet. ;**** or a ;Drive A: = I: ;**** xor a ;beide Drives mit dem Nachteil, ;jedesmal eine Taste druecken zu ;muessen, auch wenn nur zwischen A: ;und B: gewechselt wird. ende7: if Drive_C ;-------------------------------------------------------------------- ptch8: code8 equ 3E57h call Sel_Login ;DPB A: und C: tauschen ende8: ;-------------------------------------------------------------------- endif if LOGIN ;-------------------------------------------------------------------- ptchA: codeA equ 0C4Eh ; Erweiterung der Login - Routine im BIOS um zwei ; weiter Formate; dabei werden diese beiden zusaetz- ; lichen Formate abgeblockt, wenn Drive A: gemeint ; ist (kann man auch weglassen) .phase codeA ;Login bei Drive select rlca ;Bit 6,7 --> Bit 1,0 rlca jr c,cpcform ;Format auch fuer A: erlaubt inc c ;Drive A: setzt Z-Flag dec c ;Fehler jr z,0C7Fh ;A: mit 80 Track Format cpcform: nop ;alten Code loeschen nop nop nop add a,a ;Select Format (A) add a,a ;4*A -> A add a,Low DPBTab ;Lowbyte der Parametertab. ld l,a ;daher kein Highbyte - ld h,High DPBTab ;Wechsel moeglich !!! push hl call 03FE0h ;ld HL,(HL) ex (sp),hl ;1. Wort auf Stack inc hl inc hl call Bereichchk ;2. Wort in HL pop de ;Formatnr. ausserhalb von jr c,0C7Fh ;0 bis 3: Error .dephase endeA: else ;-------------------------------------------------------------------- ptchB: codeB equ 0FF7Fh ;DPB fuer Format_81 auf B: - nach eigenen Wuenschen ; anpassen defw 36 ;Records / Track defb 5 ;Blockshift defb 31 ;Blockmaske defb 3 ;Extent Maske defw 179 ;Bloecke - 1 defw 127 ;Directoryeintraege - 1 defw 080h ;ein Block fuer Directory defw 32 ;zu pruefende Eintraege / 4 defw 0 ;Systemsp. * Heads defb 2 ;Sektorlaenge defb 3 ;Sektormaske defb 1 ;2 Koepfe defb 80 ;Tracks defb 9 ;Sektoren / Track defb 081h ;1. Sektor defw 200h ;??? defb 2Ah ;Gap3 lesen / schreiben defb 52h ;Gap3 formatieren defb 60h ;Maske fuer MFM defb 0FFh ;kein Login moeglich endeB: ;-------------------------------------------------------------------- endif if Drive_C ;-------------------------------------------------------------------- ptchC: codeC equ last_3 .phase codeC ;* der folgende Code ist nur dann interessant, wenn ;* Sie als Drive C: ein drittes Laufwerk anschliessen ;* wollen. defw 03F1Ch ;Write Sektor defw 03F17h ;Read Sektor defw 03ED6h ;Select Drive C: defw 03ECBh ;Init (-> nur Return) defb 3 ;Physikalisches Drive D: defb 0 ;Userbyte; nicht benutzt DPH_C: defw 0 ;Skewing not used defb 0,0,0 ;Scratch - Bereich defb 0,0,0 defb 0,0,0 Mediaflag: defb 0 defw 0FF64h ;Diskparameter Block von A: ;mitverwenden, das ist auch ;der Grund dafuer, dass es ohne ;Login unsinnig wird: ;Es waere fuer A: und C: nur ;dasselbe Format verwendbar defw C_CHKSUM ;Pruefsummen defw C_Alloc ;Blockbelegungstabelle defw 0BEFBh ;Directory - Contr. Block defw 0BEFDh ;Datenpuffer Contr. Block defw Hash_C ;Hashtab von A: verwendet defb 0 ;Bank der Tabelle C_CHKSUM: defs 33 ;reicht fuer 128 Dir-Eintraege C_Alloc: defs 66 ;max. 256 Bloecke Sel_Login: ld (0BEF0h),a ;alte Funktion ! ld hl,aktiv_Drive;welcher DPB ab FF64 ? cp (hl) ret z ;schon richtig cp 0 ;nur bei A: jr z,Login1 cp 2 ;bzw. C: in Aktion treten ret nz Login1: push af push bc push de ld (hl),a ;neues aktives Drive ld hl,0FF64h ;DPB_A ld de,DPB_C ld b,1Bh ;Anzahl incl. Loginflag login2: ld a,(de) ;tauschen der DPBs fuer ld c,(hl) ;A: und C: ex de,hl ld (hl),c ld (de),a ex de,hl inc de inc hl djnz login2 pop de pop bc pop af ret aktiv_Drive: defb 0 ;Default erstmal A: DPB_C: defw 36 ;Records / Track defb 5 ;Blockshift defb 31 ;Blockmaske defb 3 ;Extent Maske defw 176 ;Bloecke - 1 defw 127 ;Directoryeintraege - 1 defw 080h ;ein Block fuer Directory defw 32 ;zu pruefende Eintraege / 4 defw 2 ;Systemsp. * Heads defb 2 ;Sektorlaenge defb 3 ;Sektormaske defb 1 ;2 Koepfe defb 80 ;Tracks defb 9 ;Sektoren / Track defb 01h ;1. Sektor defw 200h ;??? defb 2Ah ;Gap3 lesen / schreiben defb 52h ;Gap3 formatieren defb 60h ;Maske fuer MFM if LOGIN defb 0 ;Loginflag von A: und C: wird mit else ;ausgetauscht, so dass beide defb 0FFh ;unabhaengig voneinander sind endif Hash_C: defs 512 ;Hash - Tabelle fuer C: Hash_Ende: .dephase endeC: ptchD: codeD equ 0FE2Fh + 2 * ("C" - "A") ;C: in Drivetable eintragen defw DPH_C endeD: ;-------------------------------------------------------------------- endif message: defb 0Dh,0Ah,0Ah defb "P A T C H" defb 0Dh,0Ah,0Ah if LOGIN defb "Login von 4 Formaten auf Drive B:" if Drive_C defb " und C:" endif else defb "auf Drive B: " if Drive_C defb " und C:" endif defb "kein Login mehr moeglich" endif defb 0Dh,0Ah,0Ah defb "$" ;Stringende end  endif defb