1 REM Ins{nd av Kristoffer Eriksson SYSOP <5357>    1986-09-28 05.20.08 (DUMP)
; Fil: CDK.ASM - Kernal
; Av:  Kristoffer Eriksson, "SKE" <5357>, 1986.
;
;-Ver--/-Datum----/-Sign-/-Kommentar----------------------------------
; 1.00 / 86-08-12 / SKE  / CD
; 1.01 / 86-08-20 / SKE  / Hoppar |ver biblioteksl|senord efter "!".
;                          Bryr sig inte om enhetsangivelser inne i path.
;                          Ger inte felstopp p} blanka filnamn.
;                          Tar hand om DOS:ets specialfel OnErrDef.
; 1.20 / 86-08-24 / SKE  / FILESTAT - CDK utbruten till egen fil.
;                          Omflyttningar och andra bytebasparingar.
;                          Tolkar namnet ".." som h{nvisning till fader-UFD.
;
; Exekverar instruktionen CD, med vilken man l{tt kan byta UFD.
; LUX-NET-kompatibelt.
; Endast f|r vanligt stand-alone UFD-DOS. Ej ABC/CAT/LUX-NET.
; H|r till ett huvudprogram, och avl{ser en laddningsflagga p} stacken. Om
; den (AF) {r n}got annat {n noll l{nkas rutinen f|r byte till faderbibliotek
; in i huvudrutinen f|r CD.
; Anv{nder FINDDEV.ASM som inneh}ller rutinen FindDev.
;
; En tanke kunde vara att anv{nda vanlig USEUTLU-filhantering i st{llet f|r
; DOS-anrop, f|r att slippa dess specialbehandling av vissa fel. Men d} g}r
; det }t en av de ordinarie dosbuffertarna.

            EXTERN Exek.CD, CD.Exek.Len, DotDOt.Len

Rst.Err:    =     16
SoftNoCo:   =     18
Evalu:      =     32
Unpfd:      =     99                  ; Filnamnskontroll och formatering.
Open.:      =     24600
Close.:     =     24609
Read.:      =     24621
DR.0:       =     24678
UFDent:     =     24685               ; Pekare till UFD-pekaren.
DiscSelect: =     64769
DosFilRIB:  =     64776
DosBuffers: =     64786
DiscErr:    =     64789
OnErrDef:   =     64819
UFDptr:     =     65527               ; Normal adress till UFD-pekaren.
DevUFD:     =     30                  ; Enhetsnumret f|r UFD.

;*  Fullst{ndig exekveringsrutin f|r CD.
;*
Exek.CD:    RST   Evalu               ; $
            LD    (IPsav),DE
            POP   IX                  ; Slaskutrymme p} stacken,
            POP   DE                  ; Textpekare,
            POP   BC                  ; Textl{ngd.
            ADD   IX,SP               ; Returposition f|r stacken.
            LD    HL,-14
            ADD   HL,SP               ; Flytta upp stacken s} vi f}r en
            LD    SP,HL               ;   buffer p} 14 bytes.
            LD    (BufPtr),HL
            PUSH  IX
            LD    A,B
            OR    C
            LD    A,0                 ; A=0 Anv{nds b}de om villkoret {r
            JR    NZ,CDpath           ;   sannt eller falskt.
            LD    L,A                 ; Tom str{ng => nollst{llt UFD.
            LD    H,A                 ; (C {r redan noll, enligt testet.)
            CALL  UFDset              ; (Anv{nder HL, C och A.)

CDret:      POP   HL
            LD    SP,HL               ; ]terst{ll SP.
            LD    DE,(IPsav)          ; ]terst{ll Basic-instruktionspekaren.
            RET

; H{r utf|rs ett varv f|r varje biblioteksniv} i angiven path.
CDloop:
$$OnErr1:   LD    HL,0                ; H{r l{ggs gammalt OnErrDef-v{rde in.
            LD    (OnErrDef),HL
            LD    A,C                 ; Om kvarvarande l{ngd p} instr{ngen
            OR    B                   ;   nu {r noll, s} {r det klart.
            JR    Z,CDret
            LD    A,DevUFD            ; N{sta niv} s|ks endast i UFD:.

CDpath:     LD    (Drive),A           ; (Hit g|rs inhoppet i loopen.)
            LD    HL,UFDerr           ; (OnErrSet)
            LD    (OnErrDef),HL
            PUSH  DE              ;--,
            EX    DE,HL           ;  !  HL <- DE = Filnamnsstr{ngen.
            LD    DE,-1           ;  !  DE f}r r{kna antal passerade tecken.
CDsplitL1:  INC   DE              ;  !  S|k snedstreck eller utropstecken,
            CALL  ScanPath        ;  !    och r{kna antalet tecken f|re.
            JR    Z,CDFchk        ;  !
            CP    '!'             ;  !
            JR    NZ,CDsplitL1    ;  !
CDsplitL2:  CALL  ScanPath        ;  !  H{r efter "!" s|ker vi vidare efter
            JR    NZ,CDsplitL2   ;   !    "/", men r{knar inte tecknen.
CDFchk:     EX    (SP),HL        ;===+  HL <- Start av filnamnet, Stacka rest.
            PUSH  BC             ;--,!  L{gg kvarvarande l{ngd p} stacken.
            LD    C,E            ;  !!  BC <- Dell{ngd.
            LD    B,D            ;  !!
            LD    DE,(BufPtr)    ;  !!  DE <- M}ladr f|r filnamnet (bufferten)
            PUSH  DE            ;--,!!
$$DotDot:   CALL  Unpfd         ;  !!!  Formattera och kontrollera filnamnet
            JR    C,UFDerr21    ;  !!!  till v}r nya buffert.
            POP   HL            ;--'!!
            PUSH  HL            ;--,!!  (HL=Adr till bufferten)
            LD    A,(Drive)      ; !!!  Om vi redan ligger n}gon niv} ned i
            AND   A              ; !!!    denna path, ska filen endast s|kas
            JR    NZ,CDchkDev    ; !!!    i UFD:. Skippa enhetsangivelsen.
            LD    BC,11          ; !!!
            ADD   HL,BC          ; !!!  HL <- Adress till enhetsnamnet.
            EX    DE,HL          ; !!!
            CALL  FindDev        ; !!!  HL <- Adr i DevTba, BC <- Entry-adr.
            JR    C,UFDerr21     ; !!!
            LD    A,B            ; !!!
            CP    96             ; !!!  Acceptera inte enheter ur BASIC-
            JR    C,UFDerr21     ; !!!  prommet. Knappast diskenhet.
            LD    BC,7           ; !!!
            ADD   HL,BC          ; !!!
            LD    A,(HL)         ; !!!  F|rmodat diskenhetsnummer.
CDchkDev:   LD    C,A            ; !!!
            INC   A              ; !!!  255 {r godk{nt (s|k p} alla enheter).
            JR    Z,UFDext       ; !!!
            CP    33             ; !!!  (33 = 32 + 1 pga INC A ovan)
            JR    C,UFDext       ; !!!  Rimligt nummer, chansa och acceptera
                                 ; !!!  det. Ganska ofarligt...
; (Ett felanrop h{r, s} det kan n}s fr}n alla platser med enbart JR.)
UFDerr21:   LD    A,21
            JP    UFDerr
            RST   Rst.Err
            DEFB  21                  ; Error 21 - Hittar ej filen.
                                 ; !!!
UFDext:     POP   HL             ;-'!!
            EX    DE,HL          ;  !!  DE <- filnamnets adress, till OPEN.
            LD    HL,8           ;  !!
            ADD   HL,DE          ;  !!  HL <- Adress till filnamnsextension.
            LD    A,(HL)         ;  !!
            CP    ' '            ;  !!
            JR    NZ,UFDopen     ;  !!
            LD    A,(DE)         ;  !!  L}t helt blanka filnamn passera utan
            CP    ' '            ;  !!  effekt f|r att slippa f} okompatibla
            JR    Z,CDnext       ;  !!  errors.
            LD    (HL),'U'       ;  !!
            INC   HL             ;  !!  L{gg p} default '.Ufd', om inget annat
            LD    (HL),'f'       ;  !!  angivits.
            INC   HL             ;  !!
            LD    (HL),'d'       ;  !!
UFDopen:    LD    A,C            ;  !!
            LD    (DiscSelect),A ;  !!  V{lj drive.
            LD    B,0            ;  !!  V{lj dosbuffer 0.
            PUSH  BC             ;-,!!
            CALL  Open.          ; !!!  \ppna UFD-filen.
            JR    C,UFDerr21     ; !!!
            LD    DE,0           ; !!!
            CALL  Read.          ; !!!  L{s in f|rsta sektorn f|r koll.
            JR    C,UFDerr48     ; !!!
            LD    HL,(DosBuffers); !!!
            LD    L,0            ; !!!
            LD    E,(HL)         ; !!!
            INC   HL             ; !!!  Kontrollera filen f|rst...
            LD    A,(HL)         ; !!!
            DEC   A              ; !!!
            JR    NZ,UFDerr48    ; !!!
            INC   HL             ; !!!
            CP    (HL)           ; !!!
            JR    NZ,UFDerr48    ; !!!
            LD    L,5            ; !!!
            LD    A,E            ; !!!
            CP    (HL)           ; !!!
            JR    NZ,UFDerr48    ; !!!
            LD    DE,(DosFilRIB) ; !!!
            INC   DE             ; !!!
            INC   DE            ;  !!!  DE <- Start av sj{lva biblioteket.
            PUSH  DE            ;-,!!!
            CALL  Close.        ; !!!!
            POP   HL            ;-'!!!
            POP   BC            ;--'!!
            LD    A,(DiscSelect)  ; !!
            CP    255             ; !!
            JR    NZ,CDx1         ; !!
            LD    A,C             ; !!  A <- Drive.
CDx1:       AND   31              ; !!  ([ven inhopp fr}n DotDot-rutinen.)
            LD    C,165           ; !!  C <- Permanent-flagga.
            CALL  UFDset          ; !!  (Anv{nder HL, C, A)
CDnext      POP   BC              ;-'!  Kvarvarande l{ngd p} namnet.
            POP   DE              ;--'  Namnpekare.
            JP    CDloop

;*  St{ll/Nollst{ll UFDpekaren.
;*  HL = Biblioteks-offset, A = Drive ({ven 30=UFD), C = Permanent-flagga.
;*  Att adressera UFD-pekaren direkt tar en byte mindre {n att ladda in
;*  adressen i HL och anv{nda den, samt d} ha sektorn i DE. Observera {ven
;*  tricket att anv{nda BC, n{r det inte finns en instruktion f|r bara C.
;*
UFDset:
$$UFDptr1:  LD    (UFDptr-1),BC       ; St{ll UFD-pekaren till
$$UFDptr2:  LD    (UFDptr),HL         ;   sektor HL, drive A, flagga C.
            CP    DevUFD              ; Om Drive=UFD, f|rblir MFD-drive
            RET   Z                   ;   of|r{ndrad.
$$UFDptr3:  LD    (UFDptr+2),A
            RET

;*  Del av rutinen som delar upp biblioteks-"path" i filnamn och l|senord.
;*  BC = Antal tecken kvar av hela str{ngen. Minskas med ett.
;*  HL = Pekare till n{sta tecken. \kas med ett.
;*  Resultatet blir sann Z-flagga om str{ngen {r slut eller n{sta tkn = "/".
;*
ScanPath:   LD    A,C
            OR    B
            RET   Z
            LD    A,(HL)
            INC   HL
            DEC   BC
            CP    '/'
            RET

;*  St{llning och }terst{llning av DOS:ets felhanteringsadresser. Dessa
;*  anv{nds f|r t ex error 46 och 35. F|r att spara bytes avl{ses inte den
;*  gamla adressen av OnErrDef varje g}ng den {ndras, utan en g}ng f|r alla
;*  i INIT-rutinen.
;*  Rutinerna har placerats in direkt i CD-koden.
;*
;OnErrSet:  LD    HL,UFDerr
;           LD    (OnErrDef),HL
;           RET
;OnErrReset:LD    HL,...
;           LD   (OnErrDef),HL
;           RET

;*  Rutin f|r att leta igenom enhetslistan efter en viss enhet.
;*  In: DE = Pekare till s|kt enhetsnamn
;*  Ut: HL <- Adress till funnen l{nk i listan
;*      BC <- Enhetens drivrutinadress
;*      NC/C <- Funnen / Ej funnen
;*
FindDev:    INCLUDE FINDDEV

;*  Felkod 48. Placerad h{r, kan den n}s fr}n alla st{llen de beh|vs med JR.
;*
UFDerr48:   LD    A,48                ; Error 48 - Fel i (UFD-)biblioteket.
UFDerr:
$$OnErr2:   LD    HL,0                ; H{r l{ggs gammalt OnErrDef-v{rde in.
            LD    (OnErrDef),HL
            JP    SoftNoCo

;*  Lokala variabler.
;*
IPsav:      DEFW  0
BufPtr:     DEFW  0
Drive:      DEFB  0

CD.Exek.Len:=     * - Exek.CD

;*  Specialrutin som tar hand om och identifierar biblioteketsnamnet "..",
;*  vilket betecknar faderbiblioteket. L{nkas bara in p} beg{ran.
;*  Inl{nkningen g|rs d{r anropet till Unpfd sitter i huvudrutinen, och
;*  ers{tter det med ett anrop hit. Det ligger n}gra saker p} stacken.
;*                             ;--,!!!
DotDot?:    EXX                ;  !!!!  Om man med ".." har hamnat i MFD, {r
$$UFDptr4:  LD    DE,(UFDptr)  ;  !!!!    det inte s} bra om n{sta namn s|ks
            LD    A,E          ;  !!!!    i UFD:. D{rf|r st{lls d} Drive om.
            OR    D            ;  !!!!    N}gra olika alt finns. 0 g|r det
            JR    NZ,DD.X1     ;  !!!!    m|jl ange drive och annars defs|kn,
            LD    (Drive),A    ;  !!!!    255 ger bara defs|kn, UFDptr+2 ger
DD.X1:      EXX                ;-,!!!!    aktuell drive.
            LD    A,C          ; !!!!!
            SUB   2            ; !      (Om C verkl. {r 2 blir A noll nu.)
            JR    NZ,NoDotDot  ; !
            OR    B            ; !      H{r kollas att namnets l{ngd {r 2.
            JR    NZ,NoDotDot  ; !
            LD    A,'.'        ; !      Och h{r att det best}r av just tv}
            CP    (HL)         ; !        punkter.
            JR    NZ,NoDotDot  ; !
            INC   HL           ; !
            CP    (HL)         ; !
            JR    NZ,NoDotDotD ; !
            EXX                ;-'
            LD    A,E                 ; DE = UFD-pekaren.
            OR    D                   ; Det {r ett fel att f|rs|ka detta utan
            SCF                       ;   att vara i ett UFD (err 21).
            RET   Z
            DEC   DE
$$UFDptr5:  LD    A,(UFDptr+2)        ; UFD-drive.
            LD    (DiscSelect),A
            CALL  DR.0                ; H{r skulle det vara en JR C,UFDerr48,
            LD    HL,(DosBuffers)     ;   om vi inte litade s} p} UFD-pekaren.
            LD    L,3
            LD    E,(HL)              ; Sektor i faderbiblioteket d{r filens
            INC   HL                  ;   namn finns.
            LD    D,(HL)
            INC   HL
            LD    A,E
            OR    D                   ; Direkt klart om fadern {r MFD.
            JR    Z,DotDotSet
            LD    A,(HL)              ; Filnummer (PFN).
            AND   15                  ; Maska ut relativa sektornumret. cf<-0.
            LD    L,A
            LD    H,0
            EX    DE,HL
            SBC   HL,DE
            PUSH  HL           ;-,
            DEC   HL           ; !      Ber{kna faderns info-sektor.
            EX    DE,HL        ; !
            CALL  DR.0         ; !      L{s in sektorn och kontrollera lite.
            POP   DE           ;-'
            JR    C,UFDerr48
            LD    HL,(DosBuffers)
            LD    L,1
            LD    A,(HL)
            DEC   A
            JR    NZ,UFDerr48
            INC   HL            ; !!!!
            CP    (HL)          ; !!!!
            JR    NZ,UFDerr48   ; !!!!
DotDotSet:  POP   HL            ;-'!!!  Eliminera returadressen och adressen
            POP   HL            ;--'!!    till bufferten fr}n stacken.
            EX    DE,HL          ;  !!  HL <- Startsektor f|r UFD.
            LD    A,DevUFD       ;  !!  A=DevUFD g|r drivenr of|r{ndrat.
            JP    CDx1           ;  !!  ]terintr{de i huvudrutinen.
                            ; - - - - - - -
NoDotDotD:  DEC   HL            ; !!!!  H{r utf|rs det av inl{nkningen
NoDotDot:   JP    Unpfd         ;-'!!!    utflyttade anropet.
DotDot.Len: =     * - DotDot?

;_ Initiering                            _
CDInit:     LD    HL,(OnErrDef)       ; Tidig avl{sning av detta v{rde.
            LD    ($$OnErr1+1),HL
            LD    ($$OnErr2+1),HL
            LD    HL,(UFDent)         ; Se till att UFDent anv{nds som pekare
            DEC   HL                  ;   till UFD-datat.
            LD    ($$UFDptr1+2),HL    ; +2 eftersom LD (),BC tar 4 byte.
            INC   HL
            LD    ($$UFDptr2+1),HL
            LD    ($$UFDptr4+2),HL    ; +2 eftersom LD DE,() tar 4 byte.
            INC   HL
            INC   HL
            LD    ($$UFDptr3+1),HL
            LD    ($$UFDptr5+1),HL
            POP   HL
            POP   AF                  ; Flagga f|r DotDot-rutinen.
            PUSH  HL
            AND   A
            RET   Z
            LD    HL,DotDot?          ; Byt ut Unpfd-anropet mot ett anrop
            LD    ($$DotDot+1),HL     ;   till DotDot?.
            RET

            REL PUSH CDInit
            REL CALL
            ORG CDInit
