        print "          ***  BOOTSEC .MAX  ***"

;
; *********** CP/M 2.2 Boot-Sector  ************
; *                                            *
; * modifiziert f}r 8 Bit Druckerschnittstelle *
; *       Andreas Dobbertin   23.01.1987       *
; *                                            *
; * modifiziert f}r  DOBBERTIN RAM-Erweiterung *
; *       Andreas Dobbertin   01.02.1989       *
; *                                            *
; *    Spezial-Version f}r PC International    *
; *       Andreas Dobbertin   13.02.1989       *
; *                                            *
; **********************************************
;

;
; ------ >>>  BIOS-Jumpblock ins RAM kopieren  <<< ---
;
bootsec push  bc          ;Zeiger auf original BIOS
        pop   hl          ; Sprungvector -> 'HL'
        ld    de,#2500    ;Den original BIOS-Sprung-
        ld    bc,#0033    ; Vector nach #2500-#2532
        ldir              ; kopieren

;
; ------ >>>  Track #00 & Track #01 lesen  <<< -------
;
; Die beiden Systemspuren Track #00 & #01 werden ein-
; gelesen. Der Speicher soll folgenderma~en belegt
; werden;
;
; #0100 - #02FF  Bootsector ( Loader )
; #0300 - #04FF  Configuration Sector
; #0500 - #07FF  Speicher Initialisierung
; #0800 - #0A7F  FAST-Routinen (wird -> #4800 kopiert)
; #0A80 - #0D7F  Neue BIOS-Routinen
; #0D80 - #0EFF  Initialisierungswerte f}r COMMON BANK
; #0F00 - #16F1  CCP
; #1700 - #24EE  BDOS
; #2500 - #2532  original BIOS Sprungvector
; #2533 - #3EFF  *** ungenutzt ***
; #3F00 - #3F3B  60 Byte System-Stack
; #3F3C - #3F77  60 Byte Interrupt-Stack
; #3F78 - #3F7C  *** ungenutzt ***
; #3F7D          BIOS DMA-Banknummer
; #3F7E - #3F7F  BIOS DMA-Adresse
; #3F80 - #3FFF  DMA-Puffer
; #4000 - #47FF  RAM Zeichensatz f}r FAST-Routinen
; #4800 - #4A7F  FAST-Routinen f}r Mode 0, 1 und 2
;
; Die COMMON-BANK belegt den Bereich von #FD00 - #FFFF
; in der TPA Bank und ist folgenderma~en belegt;
;
; #FD00 - #FD35  neuer (erweiterter) BIOS Sprungvector
; #FD36 - #FD8C  Bankumschaltender BIOS Sprungvector
; #FD8D - #FDFF  Banking Routinen
; #FE00 - #FE0F  DPH Drive A
; #FE10 - #FE1F  DPH Drive B
; #FE20 - #FE2F  DPH Drive C  ( reserviert )
; #FE30 - #FE3F  DPH Drive D  ( reserviert )
; #FE40 - #FE4E  DPB Drive A
; #FE4F          *** ungenutzt ***
; #FE50 - #FE5E  DPB Drive B
; #FE5F          *** ungenutzt ***
; #FE60 - #FE6E  DPB Drive C  ( reserviert )
; #FE6F          *** ungenutzt ***
; #FE70 - #FE7E  DPB Drive D  ( reserviert )
; #FE7F          *** ungenutzt ***
; #FE80 - #FE9F  ALV Drive A
; #FEA0 - #FEBF  ALV Drive B
; #FEC0 - #FEDF  ALV Drive C  ( reserviert )
; #FEE0 - #FEFF  ALV Drive D  ( reserviert )
; #FF00 - #FF1F  CSV Drive A
; #FF20 - #FF3F  CSV Drive B
; #FF40 - #FF5F  CSV Drive C  ( reserviert )
; #FF60 - #FF7F  CSV Drive D  ( reserviert )
; #FF80 - #FF9F  128 Byte Record Buffer 
;
        ld    a,15        ;Das 15. Byte des DPB's
        call  readdpb     ; ( Sectoroffset ) -> 'A'
        and   %01000000   ;#00 oder #40 -> 'A'
        or    %00000010   ;Sector #02 oder #42
        ld    c,a         ;Sector-Nr. -> 'C'
;
        ld    de,#0000    ;Track 0, Drive A
        ld    hl,#0300    ;Puffer-Adr. = #0300
;
        ld    b,17        ;17 Sectoren einlesen
nextsec call  #be89       ;Sector einlesen
        jr    nc,readerr  ;Springe bei Readerror
        ld    a,c         ;Sector-Nr. -> 'A'
        and   %00111111   ;Absolute Sectornr. -> 'A'
        cp    #09         ;Trackende erreicht ?
        jr    c,sametrk   ;Nein, dann springe
        ld    a,c         ;Sectornr. -> 'A'
        and   %01000000   ;#00 oder #40 -> 'A'
        ld    c,a         ;#00 oder #40 -> 'C'
        inc   d           ;Tracknr. erh|hen
sametrk inc   c           ;Sectornr. erh|hen
        inc   h           ;Pufferadresse um
        inc   h           ; 512 erh|hen
        djnz  nextsec
;
        call  raminit     ;RAM initialisieren
        call  fast_on     ;Fast-Routine aktivieren
        call  patchpr     ;8. Drucker-Bit aktivieren
newboot call  config      ;Configuration auswerten
        jp    newwarm     ;Warmstart ausf}hren

;
; ------ >>>  Fehlermeldung ausgeben  <<< ------------
;
readerr call  prtext      ;Fehlermeldung ausgeben
;
        defb  #0a,#0d
        defm  "Failed to lo"
        defm  "ad CP/M$"
;
        jr    $           ;Jump forever

;
; ------ >>>  Patchroutine nach #BE22 - #BE3F  <<< ---
;
patchpr ld    hl,prpatch
        ld    de,#be22
        ld    bc,30
        ldir

;
; ------ >>>  Rechnerabh{ngige Adressen {ndern  <<< --
;
        ld    a,(#bd32)   ;CPC 464  'JP   #0808'
        inc   a           ;CPC 664  'JP   #0835'
        ld    (#be3e),a   ;CPC 6128 'JP   #0845'
;
        ld    a,(#bd2f)   ;CPC 464  'CALL #081B'
        ld    (#be26),a   ;CPC 664  'CALL #0848'
;                            CPC 6128 'CALL #0858'

;
; ------ >>>  Vektor und Indirection patchen  <<< ----
;
        ld    hl,#be22
        ld    (#bdf2),hl
        ld    hl,#be31
        ld    (#bd32),hl
        ld    a,#ef       ;= RST 5
        ld    (#bd31),a
        ret

;
; ------ >>>  Druckerpatch f}r 8. Bit  <<< -----------
;
prpatch ld    bc,#0032
pr_wait call  #081b       ;Adr. wird evtl. gepatched
        jr    nc,sendchr
        djnz  pr_wait
        dec   c
        jr    nz,pr_wait
        or    a           ;Carry-Flag l|schen
        ret
;
sendchr push  bc
        ld    bc,#f600    ;PIO Port-C
        bit   7,a         ;8. Bit gesetzt ?
        jr    z,resbit8   ;Nein, dann springe
        ld    c,%00100000
resbit8 out   (c),c       ;8. Bit setzen/r}cksetzen
        jp    #0808       ;Adr. wird evtl. gepatched

;
; ------ >>>  Parametersector auswerten  <<< ---------
;
config  call  prtext      ;Mode 2 einschalten
;
        defb  #04,#02,"$"

;
; ------ >>>  Configuration Sector }berpr}fen  <<< ---
;
        ld    a,(#0301)   ;Ist das zweite Byte des
        cp    #12         ; Config.-Sectors #12 ?
        jr    z,goodsec

;
; ------ >>>  Falscher Configuration Sector  <<< -----
;
        call  prtext
;
        defb  #0d,#0a
        defm  "Illegal conf"
        defm  "iguration se"
        defm  "ctor"
        defb  #0d,#0a,#0a,"$"
;
        ret

;
; ------ >>>  Zeichensatz ausw{hlen  <<< -------------
;
goodsec ld    a,(#0317)   ;Zeichensatz-Flag holen
        ld    c,a         ;Zeichensatz-Flag -> 'C'
        call  setchar     ;Zeichensatz ausw{hlen

;
; ------ >>>  Drive-Parameter setzen  <<< ------------
;
        ld    hl,(#0302)  ;'MOTOR_ON'-Delay holen
        ld    (drvetab),hl
        ld    hl,(#0304)  ;'MOTOR_OFF'-Delay
        ld    (drvetab+2),hl
        ld    a,(#0306)   ;'STEP_RATE'
        ld    (drvetab+6),a
        ld    hl,drvetab  ;'HL' zeigt auf Tabelle
        call  #be83       ;= DOS-Befehl '82'

;
; ------ >>>  CP/M IO-Byte setzen  <<< ---------------
;
        ld    a,(#0307)   ;IO-Byte holen und in
        ld    (#0003),a   ; #0003 ablegen

;
; ------ >>>  Error-Message ON/OFF setzen  <<< -------
;
        ld    a,(#0308)   ;ON/OFF (#00/#FF) holen
        call  #be80       ;= DOS-Befehl '81'

;
; ------ >>>  Ser. Interface initialisieren  <<< -----
;
        ld    hl,#030a    ;'HL' zeigt auf SIO-Table
        call  #bea1       ;Z80-SIO initialisieren

;
; ------ >>>  Einschaltstring ausgeben  <<< ----------
;
        ld    hl,#0364    ;'HL' zeigt auf Text
        call  prtext2     ;Einschalttext ausgeben
        call  prtext
;
        defm  #0a,#0d
        defm  "v 1.2, "
        defm  "63K TPA"
        defm  #0a,#0d,"$"

;
; ------ >>>  Drucker String senden  <<< -------------
;
        ld    a,(hl)      ;L{nge des Printerstrings
        inc   hl          ; holen. Ist ein Printer-
        or    a           ; string vorhanden ?
        jr    z,noprter   ;Nein, dann }berspringen
;
        ld    b,a         ;'B' ist Schleifenz{hler
sendprt ld    c,(hl)      ;Ein Zeichen holen
        inc   hl          ;Zeiger erh|hen
        push  hl
        push  bc
        call  #250f       ;Zeichen zum Drucker
        pop   bc
        pop   hl
        djnz  sendprt     ;Weiter bis alle Zeichen
;                             gesendet sind

;
; ------ >>>  Tastatur umdefinieren  <<< -------------
;
noprter ex    de,hl       ;Zeiger -> 'DE'
        ld    hl,#bb27    ;Adresse 'KM_SET_NORMAL'
        call  defkeys     ;Eventuell neu definieren
        ld    hl,#bb2d    ;Adresse 'KM_SET_SHIFT'
        call  defkeys     ;Eventuell neu definieren
        ld    hl,#bb33    ;Adresse 'KM_SET_CONTROL'
        call  defkeys     ;Eventuell neu definieren
        ex    de,hl       ;Zeiger -> 'HL'

;
; ------ >>>  Expansionsstrings setzen  <<< ----------
;
        ld    a,(hl)      ;Anzahl holen
        inc   hl          ;Zeiger erh|hen
        or    a           ;Anzahl = 0 ?
        jr    z,no_exp    ;Ja, dann springe
;
        ld    d,a
set_exp ld    b,(hl)      ;Expansions Token -> 'B'
        inc   hl          ;Zeiger erh|hen.
        ld    c,(hl)      ;L{nge des Strings -> 'C'
        inc   hl          ;Zeiger erh|hen
        push  hl
        push  de
        push  bc
        call  #bb0f       ;KM_SET_EXPANSION string
        pop   bc
        pop   de
        pop   hl
        jr    c,noexper   ;Springe wenn fehlerfrei

;
; ------ >>>  Fehlermeldung ausgeben  <<< ------------
;
        call  prtext
;
        defb  #0d,#0a
        defm  "Expansion bu"
        defm  "ffer full or"
        defm  " illegal tok"
        defm  "en specified"
        defb  #0d,#0a,#0a,"$"
;
        ret

;
; ------ >>>  SET_EXPANSION Fortsetzung  <<< ---------
;
noexper ld    b,#00       ;Zeiger um die L{nge des
        add   hl,bc       ; letzten Strings erh|hen
        dec   d           ;War's der letzte String ?
        jr    nz,set_exp  ;Nein, dann noch einen

;
; ------ >>>  Initial Command ausf}hren  <<< ---------
;
no_exp  ld    a,(#0316)
        jp    #bea4

;
; ------ >>>  Tabelle der Laufwerksparameter  <<< ----
;
drvetab defw  #0000       ;F}r 'MOTOR_ON' -Delay
        defw  #0000       ;F}r 'MOTOR_OFF'-Delay
        defb  #af         ;Wartezeit bei Format
        defw  #001e       ;F}r 'STEP_RATE'
        defb  #01         ;'HEAD_LOAD'  -Time
        defb  #03         ;'HEAD_UNLOAD'-Time

;
; ------ >>>  Tastatur definieren Unterprgr.  <<< ----
;
defkeys ld    a,(de)      ;Anzahl der neu zu defi-
        ld    c,a         ; nierenden Tasten nach
        inc   de          ; 'C' bringen
        or    a           ;Anzahl = 0 ?
        ret   z           ;Ja, dann zur}ck
;
set_key ld    a,(de)      ;Neuen Tastenwert holen
        ld    b,a         ; und nach 'B' bringen
        inc   de          ;Zeiger erh|hen
        ld    a,(de)      ;Tastennummer nach 'A'
        inc   de          ;Zeiger erh|hen
        push  hl          ;Sprungadresse merken
        call  jp_tohl     ;Taste neu definieren
        pop   hl          ;Sprungadresse holen
        dec   c           ;War's die letzte Taste ?
        jr    nz,set_key  ;Nein, dann noch eine
        ret

;
; ------ >>>  Text ( ab RET-Adr. ) ausgeben  <<< -----
;
prtext  ex    (sp),hl     ;RET-Adresse -> 'HL'
        call  prtext2     ;Text ausgeben
        ex    (sp),hl
        ret

;
; ------ >>>  Text ( ab 'HL' ) ausgeben  <<< ---------
;
prtext2 ld    a,(hl)      ;Ein Zeichen holen
        inc   hl          ;Zeiger erh|hen
        cp    "$"         ;End of Text ?
        ret   z           ;Ja, dann zur}ck
        ld    c,a         ;Sonst Zeichen -> 'C'
        push  hl
        call  #250c       ;Zeichen ausgeben
        pop   hl
        jr    prtext2

;
; ------ >>>  Springe zu 'HL'  <<< -------------------
;
jp_tohl jp    (hl)

;
; ------ >>>  Lade 'HL' aus 'HL' und 'HL'+1  <<< -----
;
ld_hlhl ld    a,(hl)      ;LD HL,(HL)
        inc   hl
        ld    h,(hl)
        ld    l,a
        ret

;
; ------ >>>  'A'-ter Eintrag des DPB -> 'A'  <<< ----
;
readdpb ld    hl,(#be40)  ;Adr. DPH Drive A -> 'HL'
        ld    de,#000a    ;Offset f}r Drive A
        add   hl,de       ;Offset addieren
        ld    e,a         ;DPB-Offset -> 'DE'
        call  ld_hlhl     ;Start DPB -> 'HL'
        add   hl,de       ;DPB-Offset addieren
        ld    a,(hl)      ;Gew}nschtes Byte -> 'A'
        ret
