1 REM Ins{nd av Kristoffer Eriksson <5357>    1987-12-11 19.50.09 (KERMIT)
; Fil: HFMMAIN.ASM
; Av : Kristoffer Eriksson, "SKE" <5357>, 1987.
; F|r: ABC800-serien.
;
;-Ver--/-Datum----/-Sign-/-Kommentar----------------------------------
;      / 87-07-16 / SKE  / HFMMAIN
; 1.00 / 87-11-13 / SKE  / Klart.
;
; Huvudrutinen till HFM.ASM. Kommandotolkning, fil|ppning, huvudstruktur,
; texter, utskrifter.

SkipSp:     =  24
IO:         =  90
ErrPtr:     =  65452
Iocm.Opn:   =  0
Iocm.Prp:   =  1
Iocm.Clo:   =  2
Iocm.Del:   =  9
Err.NoExist:=  21
Lu.RndRC:   =  +17
Lu.RndO:    =  +19
Y.Int:      =  +35                    ; CTRL-C-flagga.
Int.Ctrc:   =  0

SavSP:      DEFW   0                  ; SP vid start sparas h{r.
Uppgift:    DEFB   0                  ; 1=Komprimera, 2=Dekomprimera,
Upp.Comp:   =  1                      ; 4=Frekvenstabell.
Upp.DeComp: =  2
Upp.Freq:   =  4
SvarLen:    =  80
Svar:       DEFS   SvarLen            ; Buffert f|r svar p} vissa fr}gor.

            EXTERN Start, ConsWriteS, FelSlut, ConsCR

Start:      EXX
            PUSH   HL
            PUSH   DE
            PUSH   BC
            LD     (SavSP),SP
            LD     (TopMem),HL        ; N{sta adress i relokeringskoden enligt
                                      ; RELOCATE.ASM.
            CALL   ConsInit
            JP C   Exit               ; Hittar inte fil 0.
            LD     HL,TStart
            CALL   ConsWriteS         ; H{lsa anv{ndaren.
            CALL   GIOInit
            LD     (GIO+1),HL
            LD     (GIOClose+1),DE
            LD     HL,TGIOFel
            JP C   FelSlut            ; Hittar inte GIO-rutinen.

CommandLine:CALL   Chain.Clr          ; F|rbered Chain-data.
            CALL   Clinepar           ; Hitta kommandoraden.
            JP C   IaktCommand        ; Inga parametrar - fr}ga.
            CP     ";"
            JP Z   IaktCommandC
            LD     B,0                ; BC <- C.
            CALL   Caps               ; Omvandla hela raden till versaler.
            LD     E,0                ; Samla optioner i E.
            LD     A,(HL)
CL.OLoop:   CP     13
            JP Z   SyntaxFel          ; Bara optioner {r ocks} fel.
            CALL   Option
            JP C   SyntaxFel
            INC    HL
            LD     A,(HL)             ; N{sta tecken.
            CP     " "
            JP NZ  CL.OLoop
            CALL   OptCheck           ; Lagra och kolla optioner.
            JR NC  CL.Pars
            LD     HL,TOptComb
            JP     FelSlut
CL.Pars:    CALL   SkipSp             ; Forts{tt in i filnamnsparametrarna.
            CP     13                 ; ([ven IaktCommand g}r in h{r.)
            JP Z   SyntaxFel
CL.Files:   CP     ";"
            JP Z   SyntaxFel
CL.NextFile:
            LD     BC,0
            LD     (FNamA.Ut),BC      ; Inget utfilnamn angivet f.n.
            CALL   WordSplit          ; Avgr{nsa filnamn p} kommandoraden.
            LD     A,C                ; Tomt ord?
            OR     B
            JP Z   SyntaxFel
            LD     (FNamA.In),HL      ; Spara filnamnsparametern.
            LD     (FNamL.In),BC      ; FNamL.In f}r max vara 255, men det {r
            PUSH   DE                 ; ingen risk att den blir mer.
            LD     A,(DE)             ; F|rsta tkn i n{sta ord.
            CP     "="                ; Efter "=" kan utfilens namn spec'as.
            JR NZ  CL.DoFile
            POP    HL                 ; HL <- Aktuell pos.
            CALL   SkipSP
            CP     13
            JP Z   SyntaxFel
            CALL   WordSplit
            LD     A,C                ; Utnamnet tomt ord?
            OR     B
            JP Z   SyntaxFel
            LD     (FNamA.Ut),HL      ; Spara utfilens namn.
            LD     (FNamL.Ut),BC
            PUSH   DE
CL.DoFile:  CALL   ProcessFile
            POP    HL                 ; N{sta position i kommandoraden.
            LD     A,(HL)
            CP     13
            JR Z   Exit
            CP     ";"
            JR NZ  CL.NextFile
            CALL   Chain.Load         ; Chain-fil sist p} raden.
            JP C   SyntaxFel

Exit:       LD     SP,(SavSP)
            CALL   CloseFiles         ; Ifall felstopp l{mnat filer |ppna.
            RES    Int.Ctrc,(IY+Y.Int); Nolla CTRL-C-flagga.
            POP    BC                 ; ]terst{ll relokeringsregistren.
            POP    DE
            POP    HL
            EXX
            RET


; IaktCommand - Interaktiv inmatning av uppgift och filnamn om inget angivet.

IaktCommandC:CALL  Chain.Load
            JP C   SyntaxFel
IaktCommand:LD     HL,TUppgift        ; Fr}ga vad som ska g|ras. K/D/F.
            CALL   ConsWriteS
            LD     HL,Svar
            LD     BC,3               ; Max svar {r "KF" + CR.
            CALL   ConsRead
            CALL   ConsCR
            LD     E,0                ; Samla optioner i E.
            LD     HL,Svar-1
IC.OptL:    CALL   SkipSP
            CP     13
            JR Z   IC.OChk
            CALL   Option
            JR C   IaktCommand        ; Felaktigt svar - fr}ga igen.
            JR     IC.OptL

IC.OChk:    CALL   OptCheck           ; Lagra och kolla optioner.
            JR C   IC.OFel
            LD     A,E
            AND    A
            JP Z   Exit               ; Tomt svar - sluta.
            LD     HL,TInfil          ; Fr}ga efter infil(er).
            CALL   ConsWriteS
            LD     HL,Svar
            LD     BC,SvarLen
            CALL   ConsRead
            CALL   ConsCR
            LD     HL,Svar
            LD     BC,SvarLen
            CALL   Caps               ; Omvandla svaret till versaler.
            DEC    HL
            CALL   SkipSP
            CP     13
            JP Z   Exit               ; Tomt svar - sluta.
            JP     CL.Files           ; Forts{tt med behandling av filnamnen.

IC.OFel:    LD     HL,TOptComb
            CALL   ConsWrites
            JR     IaktCommand

; In: A=Tecken, E=Tidigare optionsbittar, Ut: E=E OR optionsbitt f|r A.
; Carry vid otill}tet optionstecken. D och A p}verkas.

Option:     CP     "-"                ; Dummyoption.
            RET Z
            AND    223                ; G|r till versal.
            LD     D,Upp.Comp
            CP     "K"
            JR Z   OptKlar
            CP     "C"
            JR Z   OptKlar
            INC    D                  ; Upp.DeComp
            CP     "D"
            JR Z   OptKlar
            LD     D,Upp.Freq
            CP     "F"
            SCF
            RET NZ
OptKlar:    LD     A,D
            OR     E                  ; L{gg ihop optioner.
            LD     E,A
            RET


; Lagra optionsbittarna i Uppgift, samt kolla att de inte strider mot
; varandra. In: E=Optionsbittar. Ut: Sann Carry vid otill}tna kombinationer.
; Endats A p}verkas.

OptCheck:   LD     A,E
            LD     (Uppgift),A        ; Lagra optioner.
            AND    Upp.Freq+Upp.DeComp
            CP     Upp.Freq+Upp.DeComp
            SCF
            RET Z                     ; Optionerna F och D kan ej kombineras.
            LD     A,E
            AND    Upp.Comp+Upp.DeComp
            CP     Upp.Comp+Upp.DeComp
            SCF
            RET Z                     ; Inte D och K heller.
            AND    A
            RET


; Genomf|r de optionsbest{mda behandlingen av en fil.
; In: (FNamA.In) och (FNamL.In) = Infilens namns adress och l{ngd.
;     (FNamA.Ut) och (FNamL.Ut) = Utfilens namn om n}got angivet, annars 0.
; Denna rutin mixtrar med filnamnen, men garanterar inte att in-variablerna
; efter}t pekar p} de {ndrade filnamnen, eller p} n}got alls. Och de nya
; filnamnsstr{ngarna {r utsatta f|r |verskrivning i DefExt:s lokala buffert.

ProcessFile:LD     HL,(FNamA.In)
            LD     BC,(FNamL.In)
            LD     DE,HFMExt
            LD     A,(Uppgift)
            CP     Upp.DeComp         ; L{gg till default extension p} infil
            CALL Z DefExt             ; vid dekomprimering.
            PUSH   HL
            PUSH   BC
            CALL   ConsWrite          ; Visa filnamnet som ska behandlas,
            POP    BC                 ; OBS: inget radbyte, utskriften fort-
            POP    HL                 ; s{tter senare.

            LD      IX,LU.In
            LD      A,Iocm.Opn        ; OPEN.
            CALL    OpenUnForm        ; \ppna filen.
            JP   C  FilFelCR
            LD      A,(Uppgift)
            AND     Upp.DeComp
            JP   NZ PF.DeComp

            ; Komprimera och/eller frekvensr{kna filen.
            LD      A,(Uppgift)
            AND     Upp.Comp
            PUSH    AF
            CALL Z  ConsCR
            POP     AF
            JR   Z  PFC.Freq
            LD      HL,TLika
            CALL    ConsWriteS        ; Skriv " = ".
            LD      DE,HFMExt         ; Om utfilens namn har angivits, s}
            LD      HL,(FNamA.Ut)     ; l{gg bara till ev saknad enhet och,
            LD      A,L               ; extension. Skapa annars ett default
            OR      H                 ; utfilnamn utifr}n infilens namn.
            JR   Z  PFC.DefNam
            CALL    CpDev             ; OBS b}de DefExt o DefDev ger samma
            LD      DE,HFMExt         ; buffert, s} DefExt m}ste anropas sist.
            CALL    DefExt            ; .HFM default extension.
            JR      PFC.Prep
PFC.DefNam: LD      HL,(FNamA.In)
            LD      BC,(FNamL.In)
            CALL    NewExt            ; L{gg till extension f|r att f} utfil.
PFC.Prep:   PUSH    HL
            PUSH    BC
            CALL    ConsWrite         ; Visa utfilnamnet.
            CALL    ConsCR
            POP     BC
            POP     HL
            LD      IX,LU.Ut
            CALL    IaktPrep          ; Skapa utfilen.
            JP   C  IPFel
PFC.Freq:   LD      HL,BinFileSize
            CALL    ZeroTriB          ; Nollst{ll filstorleken.
            LD      IX,LU.In
            CALL    Freq.Byte         ; Frekvensr{kning.
            CALL NC RewindFile
            JP   C  AvbrytsFel
            LD      A,(Uppgift)
            AND     Upp.Freq
            CALL NZ DispFreq
            CALL    DispBinSize
            LD      A,(Uppgift)
            AND     Upp.Comp
            JR   Z  PF.End
            CALL    RemoveUnused
            CALL    ConstructTree     ; Konstruera kodningstr{det.
            CALL    StartBitOut
            LD      IX,LU.Ut
            CALL    PutHead           ; Lagra filhuvudet.
            CALL NC PutTree           ; Lagra kodningstr{det i filen.
            CALL NC Cmprs.Byte        ; Genomf|r komprimeringen av infilen.
            LD      IX,LU.Ut
            CALL NC BitFlush          ; Skriv ut sista bit-bufferten.
            JR   C  AvbrytsFel
            CALL    DispCmpSize
            JR      PF.End

            ; Dekomprimera fil.
PF.DeComp:  LD      IX,LU.In
            CALL    GetHead           ; L{s in filhuvud och utfilens namn.
            JR   C  GHFel
            LD      IX,LU.In
            CALL    StartBitIn
            CALL    GetTree
            JP   C  FilFelCR
            LD      HL,TLika
            CALL    ConsWriteS        ; Skriv " = ".
            CALL    CpDev             ; Kopiera enhetsnamn fr}n infil t utfil.
            LD      (FNamA.Ut),HL
            LD      (FNamL.Ut),BC
            PUSH    HL
            PUSH    BC
            CALL    ConsWrite         ; Visa utfilnamn.
            CALL    ConsCR
            CALL    DispBinSize
            POP     BC
            POP     HL
            LD      IX,LU.Ut
            CALL    IaktPrep          ; Skapa utfilen.
            JR   C  IPFel
            CALL    DeCom.Byte        ; Genomf|r dekomprimeringen.
            JR   C  AvbrytsFel
            CALL    DispCmpSize

PF.End:     CALL    CloseFiles
            RET

IPFel:      AND    A                  ; Filen ej skapad.
            JP NZ  FilFelSlut         ; [kta fel - rapportera och avsluta.
            LD     HL,TAvbryt         ; Avbrutet av anv{ndaren.
            CALL   ConsWriteS
            JR     PF.End             ; Forts{tt med ev n{sta fil.

AvbrytsFel: AND    A                  ; Avbrutet.
            JP NZ  FilFelSlut         ; [kta fel - rapportera och avsluta.
            LD     HL,TAvbryt         ; Avbrutet av anv{ndaren.
            CALL   ConsWriteS
            JP     Exit               ; Avsluta programmet.

GHFel:      AND    A                  ; D}ligt filhuvud.
            JP NZ  FilFelCR           ; IO-fel - rapportera.
            PUSH   HL
            CALL   ConsCR
            POP    HL
            CALL   ConsWriteS         ; D}ligt inneh}ll.
            JR     PF.End

; St{ng in- och utfiler om de {r |ppna. Kan anropas {ven om filerna inte {r
; |ppna. (Hanteras av GIOClose) Det {r inte risk f|r loopning av att
; CloseFiles kan anropa FilFel som anropar Exit som anropar CloseFiles igen,
; eftersom Close p} fil med fel inte ger fel p}nytt.

CloseFiles: LD      IX,LU.In           ; St{ng filerna.
            CALL    GIOClose
            LD      IX,LU.Ut
            CALL NC GIOClose
            JP   C  FilFelSlut
            RET

; Visa filstorlekar.

DispBinSize:LD     HL,TBSDig
            LD     DE,BinFileSize
            LD     BC,8 << 8 + 10     ; F{ltvidd 8 tkn, Bas 10.
            XOR    A                  ; Undertryck nollor.
            CALL   TriBAsc
            LD     HL,TBinSize
            CALL   ConsWriteS
            RET

DispCmpSize:LD     HL,TCSDig
            LD     DE,CmpFileSize
            LD     BC,8 << 8 + 10     ; F{ltvidd 8 tkn, Bas 10.
            XOR    A                  ; Undertryck nollor.
            CALL   TriBAsc
            LD     HL,TCmpSize
            JP     ConsWriteS

TBinSize:   DEFM   "Ej komprimerad storlek = "
TBSDig:     DEFM   "        "
            DEFM   " tokens."
            DEFB   13,10,0
TCmpSize:   DEFM   "Komprimerad storlek    = "
TCSDig:     DEFM   "        "
            DEFM   " bytes."
            DEFB   13,10,0

;*  Fel-stopp.

SyntaxFel:  LD     HL,TSyntax
FelSlut:    CALL   ConsWriteS         ; Skriv felmeddelandet.
            JP     Exit

FilFelCR:   PUSH   AF
            CALL   ConsCR
            POP    AF
FilFelSlut: CALL   FilFel
            JP     Exit

FilFel:     LD     HL,TFilFel
            CP     Err.NoExist
            JR NZ  BasicFel
            LD     HL,TFinnsEj
            JP     ConsWriteS

BasicFel:   PUSH   AF
            CALL   ConsWriteS
            POP    AF
            LD     HL,-80
            ADD    HL,SP
            LD     SP,HL
            EX     DE,HL
            PUSH   DE
            LD     HL,(ErrPtr)
            DEC    H
            INC    H
            SCF
            CALL NZ JPHL
            EX     DE,HL
            JR NC  BFX1
            PUSH   HL
            PUSH   AF
            LD     HL,TFelkod
            CALL   ConsWriteS
            POP    AF
            POP    HL
            LD     E,A
            LD     D,0
            XOR    A
            CALL   I2ASC
BFX1:       POP    DE
            AND    A
            SBC    HL,DE
            LD     C,L
            LD     B,H
            EX     DE,HL
            CALL   ConsWrite
            CALL   ConsCR
            LD     HL,80
            ADD    HL,SP
            LD     SP,HL
            RET

BasicFelSlut:CALL  BasicFel
            JP     Exit

JPHL:       JP     (HL)

;*  Ta reda p} l{ngden av en str{ng, vars slut markeras av ett NUL-tecken.
;*  In: HL = Str{ngens start, Ut: BC = Str{ngens l{ngd exkl NUL.
;*  Inga register utom BC {ndras.
;*
StrLen:     PUSH   AF
            PUSH   HL
            LD     BC,65535
            XOR    A
            CPIR
            LD     HL,65534
            SBC    HL,BC
            LD     C,L
            LD     B,H
            POP    HL
            POP    AF
            RET

;*  Skriv ut str{ng avslutad med NUL-tecken. HL=Str{ngens start.
;*
ConsWriteS: CALL   StrLen
            JP     ConsWrite

;*  Skriv ut radskifte.
;*
ConsCR:     LD     HL,CR
            LD     BC,2
            JP     ConsWrite

;*  Interaktiv prepare. Skapa fil. Om filen redan finns, fr}ga f|rst om
;*  den f}r skrivas |ver. HL=Filnamn, BC=Namnets l{ngd, IX=LU-block.
;*  Fel fr}n OPEN ger carry och A=felkod, avbrutet arbete ger carry och A=0.

IaktPrep:   PUSH   HL
            PUSH   BC
            LD     A,Iocm.Opn
            CALL   OpenUnForm
            POP    BC
            POP    HL
            JR NC  IP.Exist
            CP     Err.NoExist
            JR Z   IP.Prep
            SCF
            RET                       ; Annat fel - avbryt.

IP.Fr}ga:   POP    BC
            POP    HL

IP.Exist:   PUSH   HL
            PUSH   BC
            PUSH   IX
            CALL   ConsWrite          ; Filnamnet.
            LD     HL,TFinns
            CALL   ConsWriteS         ; " finns redan. Skriva |ver?"
            LD     HL,IP.Svar
            LD     BC,2
            CALL   ConsRead
            CALL   ConsCR
            POP    IX
            LD     A,(IP.Svar)
            AND    95
            CP     "J"                ; Ja - skapa filen.
            JR Z   IP.Del
            CP     "N"
            JR NZ  IP.Fr}ga           ; Fel - fr}ga igen.
            CALL   GIOClose
            POP    BC
            POP    HL
            XOR    A
            SCF                       ; Nej - retur med A=0, Carry.
            RET

IP.Del:     LD     A,Iocm.Del         ; Ta bort filen. Beh|ver den st{ngas
            CALL   IO                 ; ocks} sen?
            POP    BC
            POP    HL

IP.Prep:    LD     A,Iocm.Prp         ; Prepare.
            CALL   OpenUnForm         ; \ppna filen.
            RET

IP.Svar:    DEFS   2,0

;*  G|r POSIT till filens (IX) b|rjan. Uppenbarligen fungerar detta bara p}
;*  blockorienterade filenheter. Markerar inte textfilslut f|r PRINT:ade
;*  filer. GIO ser till att r{tt block blir inl{st vid n{sta l{sning, och
;*  ev uppdaterad buffert blir utskriven.

RewindFile: LD     (IX+Lu.RndO),3     ; Offset i buffert.
            XOR    A
            LD     (IX+Lu.RndRC),A    ; Logisk sektor.
            LD     (IX+Lu.RndRC+1),A
            RET

;*  Om infilen har enhetsnamn angivet, och utfilen inte har det, s} kopiera
;*  enhetsnamnet fr}n infilen till utfilen. Adress och l{ngd till det nya
;*  filnamnet returneras i HL och BC. Filnamnet hamnar i DefDev:s lokala
;*  buffert. DE {ndras.

CpDev:      LD     HL,(FNamA.In)
            LD     BC,(FNamL.In)
            LD     A,":"
            CPIR                      ; Kolla om det finns kolon i infilen.
            LD     DE,(FNamA.In)
            LD     HL,(FNamA.Ut)
            LD     BC,(FNamL.Ut)      ; Ta d} infilens enhet som default enhet
            JP  Z  DefDev             ; f|r utfilens namn.
            RET

;*  Omvandla till enbart versaler i str{ng. HL=Adress, BC=L{ngd.
;*  HL och BC {ndras ej.

Caps:       PUSH   HL
            PUSH   BC
            DEC    HL
C.L:        INC    HL
            LD     A,C                ; Slut?
            OR     B
            JR NZ  C.X
            POP    BC
            POP    HL
            RET
C.X:        DEC    BC
            LD     A,(HL)
            CP     "`"
            JR C   C.L
            CP     127
            JR NC  C.L                ; Omvandla bara tecken fr}n "`" - "~".
            SUB    "a"-"A"
            LD     (HL),A
            JR     C.L

;*  Texter.

TStart:     DEFM   "HFM Ver 1.00, Av Kristoffer Eriksson 1987."
            DEFB   13,10,10,0
TGIOFel:    DEFM   "Hittar inte GIO. Ok{nd Basic-version. Rapportera!"
            DEFB   13,10,0
TSyntax:    DEFM   "Syntax: RUN HFM,(-)Optioner Filnamn (= Utfilnamn) ..."
            DEFM   " (;CHAIN-fil)"
            DEFB   13,10
            DEFM   "Optioner: K=Komprimera, D=Dekomprimera, F=Frekvenstabell."
            DEFB   13,10
            DEFM   "HFM huffmannkodar filer s} de blir mindre."
CR:         DEFB   13,10,0
TOptComb:   DEFM   "Otill}ten kombination av optioner."
            DEFB   13,10,0
TUppgift:   DEFM   "Komprimering, Dekomprimering eller Frekvenstabell"
            DEFM   " (K/D/F) ? "
            DEFB   0
TInfil:     DEFM   "Infil: "
            DEFB   0
TFinns:     DEFM   " finns redan. Skriva |ver (J/N) ? "
            DEFB   0
TAvbryt:    DEFM   "Behandlingen avbruten."
            DEFB   13,10,0
TLika:      DEFM   " = "
            DEFB   0
TFilFel:    DEFM   "Fel i filhantering: "
            DEFB   0
TFinnsEj:   DEFM   "Kan inte hitta filen."
            DEFB   13,10,0
TFelkod:    DEFM   "Basic-felkod "
            DEFB   0
HFMExt:     DEFB   4                  ; L{ngd av ".HFM"
            DEFM   ".HFM"
