Čvc 042006
 

Tak bychom mohli ten program už konečně dodělat a spustit.

Programu už schází jen ta vlastní prováděcí část. Ve zdrojovém textu máme komentář, že „zde bude program pokračovat…“. Tak do tohoto místa vložíme novou část, která je obarvena červeně, celý zdrojový text zde vypisován nebude, jen jeho část:


                ld      de,16384+128+10 ;nastav pozici tisku
                ld      hl,T_HOTOVO     ;text
                call    PRINT           ;vytiskni
                ld      a,(VYSLEDEK)    ;vezmi vysledek
                ld      l,a
                ld      h,0
                call    NUM2DEC         ;a vytiskni
                ld      a,'%'
                call    ZNAK2           ;a za nim znak %

                call    READ_DISK       ;nacti 14 sektoru z diskety

                call    FIND_FILE       ;najdi soubor run.P
                jr      nz,NEXT_DISK    ;nenalezen, dalsi disk
                ld      (HEADER),hl     ;uloz si adresu hlavicky
                call    UPRAVA          ;pokus se jej modifikovat

NEXT_DISK:
                ld      ix,DISKETA
                call    BCDE_IX         ;ukazatel na disketu
                ld      ix,(AKTPAR)     ;ukazatel na udaje o partition
                ld      a,16            ;NEXTDISK
                call    SERVICE
                jr      c,RETURN        ;HOTOVO, dalsi disketa neni

Je vidět, že budeme potřebovat rutinu, která nám načte FAT a DIR diskety, rutinku, která soubor run.P najde, rutinu, která nám jej upraví a opravené sektory uloží zpět.

Takže postupně. Rutina na načtení sektorů je jednoduchá, nepotřebujeme dodržet pořadí souborů, takže 14 sektorů načteme jednoduchou smyčkou:

READ_DISK:
                ld      a,14            ;14 sektoru
                ld      hl,DIR
                ld      ix,DISKETA      ;nacti udaje do BCDE
                call    BCDE_IX
/               push    af              ;uloz pocitadlo
                ld      a,10            ;INC32
                call    SERVICE         ;BCDE+1
                push    bc              ;ulozi
                push    de
                jp      z,ERROR         ;pokud prelezlo na 0 je nekde ERROR
                ld      a,25            ;READHDD
                call    SERVICE         ;nacti
                inc     c
                dec     c               ;je-li chyba-skoncime
                jp      nz,ERROR        ;jinak hl=hl+512
                pop     de
                pop     bc              ;obnov LBA
                pop     af              ;obnov pocitadlo sektoru
                dec     a
                jr      nz,-            ;opakuj 14x
                ret

Tak. Co tam máme dál? Najití souboru. Banalitka, je to opsáno z „rutiny ROM D40“:

FIND_FILE:      ld      hl,DIR+3072     ;zacatek adresare
                ld      de,32           ;delka jedne polozky
                ld      b,128           ;pocet polozek
/               push    bc              ;vsecko schov
                push    de
                push    hl
                ld      b,11            ;jedenact znaku
                ld      de,PRUN
                call    COMPARE         ;porovnej
                pop     hl
                pop     de
                pop     bc
                ret     z               ;nalezen, pak HL=adresa polozky
                add     hl,de           ;posun adresu na dalsi polozku
                djnz    -
                ld      a,e             ;shozeni zero flagu
                or      a
                ret

PRUN:           db      "Prun"
                db      0,0,0,0,0,0,0

Následuje vlastní úprava. Jde o to, že máme soubor run.P, musíme najít ty správné sektory, najít v nich ty správné hodnoty podle verze File Manageru, patchnout a uložit zpět. Původně jsem chtěl dělat nějaký univerzální program, ale rozmyslel jsem si to. Jestli to někdo chce, nechť si jej udělá za domácí úkol.

Úprava provede načtení 6. a 7. sektoru souboru run.P, čísla těchto sektorů si uloží a při zpětném uložení na disk toho využijeme. Jednotlivé verze FM se liší takto:

1.07 a 1.08 mají na offsetu 472 hodnotu 145 a na 475 hodnotu 153

1.10 má na offsetu 548 hodnotu 145 a na 551 pak hodnotu 153.

Přepočítané ale na sektory 6 a 7. Patch to zkontroluje a patchne. Nakonec se sektory, pokud byly nějak opraveny, uloží, čísla sektorů jsou zapamatována.

UPRAVA:
                ld      ix,(HEADER)
                ld      l,(ix+17)
                ld      h,(ix+18)       ;cislo prvniho sektoru
                ld      b,6
/               call    FDBLOCK         ;zjisti nasledujici sektor
                ld      hl,3072
                sbc     hl,de           ;je prazdny?
                ret     z
                ld      a,d             ;posledni sektor
                cp      14
                ret     nc              ;ano
                ex      de,hl
                djnz    -               ;
;tedka: HL = cislo 6 sektoru souboru run.P
                push    hl
                ld      ix,SECTOR1
                call    LBA
                pop     hl
                call    FDBLOCK
                ld      a,d
                cp      14              ;jestli je precasny konec
                ret     nc              ;neni to spravny soubor
                ex      de,hl
                ld      ix,SECTOR2      ;takze uz zname LBA sektory
                call    LBA             ;nasich dvou sektoru
                call    LOAD_2LBA       ;takze je nacti

                call    PATCH           ;oprav data
                ret     nz              ;data nebyla opravena

                ld      a,2
                out     (254),a         ;cerveny bordel
                call    SAVE_2LBA       ;uloz zpet
                xor     a               ;cerny bordel
                out     (254),a
                ret

PATCH:
                ld      hl,DATA+471
                ld      de,OUT145
                ld      b,2
                call    COMPARE
                jr      nz,FM110
                ld      hl,DATA+474
                ld      de,OUT153
                ld      b,2
                call    COMPARE
                jr      nz,FM110        ;FM 1.07 to neni
                ld      hl,DATA+472
                ld      (hl),151
                ld      hl,DATA+475
                ld      (hl),155
                jr      PATCH_RET

FM110:          ld      hl,DATA+547
                ld      de,OUT145
                ld      b,2
                call    COMPARE
                ret     nz
                ld      hl,DATA+550
                ld      de,OUT153
                ld      b,2
                call    COMPARE
                ret     nz              ;FM 1.10 to neni
                ld      hl,DATA+548
                ld      (hl),151
                ld      hl,DATA+551
                ld      (hl),155
PATCH_RET:      xor     a
                ret

OUT145:         db      211,145
OUT153:         db      211,153

LBA:            push    ix
                ld      ix,DISKETA
                call    BCDE_IX
                inc     hl              ;musime se posunout na bootsektor
                ld      a,12            ;ADD32HL
                call    SERVICE         ;pricti HL k BCDE
                jp      c,ERROR         ;jakasi chyba, ktera by nemela nastat
                pop     ix
                jp      IX_BCDE         ;uloz LBA na sve misto

LOAD_2LBA:      ld      ix,SECTOR1
                ld      hl,DATA
                call    LOAD
                ld      ix,SECTOR2
LOAD:           call    BCDE_IX         ;nacti jej do BCDE
                ld      a,25
                call    SERVICE         ;nalouduj
                inc     c
                dec     c               ;nejaka chyba?
                jp      nz,ERROR
                ret

SAVE_2LBA:      ld      ix,SECTOR1
                ld      hl,DATA
                call    SAVE
                ld      ix,SECTOR2
SAVE:           call    BCDE_IX         ;nacti jej do BCDE
                ld      a,26
                call    SERVICE         ;sejvni
                inc     c
                dec     c               ;nejaka chyba?
                jp      nz,ERROR
                ret

Mezi proměnnými přibyly nové položky:

HEADER:         dw      0
SECTOR1:        dw      0,0
SECTOR2:        dw      0,0

a v pracovním prostoru ještě místo na další data:

DIR:            ds      14*512
DATA:           ds      2*512

Celý hotový program je ke stažení, zkoušel jsem jej na svých datech a pracoval dobře.

V celém programu jsme si vyzkoušeli hodně služeb MDOS3, jako bylo zjištění adresy AKTPAR a její význam, příkazy NEXTDISK a ADD1693 taky nejsou nezajímavé, stejně tak pracují služby PREVDISK a DEC1693. Načtení a uložení sektoru je taktéž důležité a to vše bez toho, abychom se starali, jestli disk podporuje LBA nebo ne, prostě LBA používáme. Jsou k dispozici další podpůrné službičky, využili jsme INC32 tuším.

stažení:

  3 komentáre na “Programujeme pro MDOS3 (4)”

  1. I napriek tomu, ze je to velmi dobre a pekne napisane, neodpustim si pripomienky podobneho razu ako v druhom pokracovani "serialu".

    Rovnako ako na konci v minule spomenutej rutine COMPARE je nepotrebna instrukcia ‚xor a‘, tak aj v rutine FIND_FILE su na konci zbytocne instrukcie ‚ld a,e‘ a ‚or a‘, kedze instrukcia ‚add hl,de‘ neovplyvnuje Zero flag a instrukcia ‚djnz xyz‘ neovplyvnuje ziadne flagy. Teda po neuspesnom hladani NEBUDE Zero priznak nastaveny, co sa od tejto rutiny ocakava.

    Tak isto je navestie PATCH_RET zbytocne a aj prislusna instrukcia ‚xor a‘, pretoze v tomto mieste je vdaka vysledku rutiny COMPARE a nasledujucim instrukciam, ktore flagy nemenia, priznak Zero uz nastaveny.

    Tak snad ma neukamenujete… 🙂

  2. Ahoj Romane. Děkuji ti za tvoje připomínky. A to myslím vážně, protože jsem nepředpokládal, že by snad někdo ten zdroják až takhle studoval. Velice mě to těší.

    Ještě dodatek: chyby jsem tam nechal, laskavý čtenář si je případně opraví sám a může si zkusit třeba i něco navíc. Mě osobně by třeba zajímalo, jak by se laskavý čtenář vypořádal s problémem výběru jiného oddílu.

  3. Nuž, keďže to nemám ako vyskúšať a overiť, tak môžem iba teoreticky zauvažovať 🙂

    Rutinu GET_AKTPAR a jej volanie by som nahradil rutinou napr. GET_NEXTPART, ktorá by postupne prechádzala tabuľkou PART_TABLE a pripravila adresu ďalšieho oddielu z tabuľky (preskakovala by oddiely 252 a 253). Zaroveň by na tomto mieste začínala dalšia vonkajšia slučka, ktora by vlastne prechádzala cez všetky nájdené oddiely. Samozrejme, pred tým musí byť pomocou služby 4 pripravená počiatočná adresa PART_TABLE pre rutinu GET_NEXTPART.

    V časti, kde sa pomocou služby 16 hľadá ďalší disk na aktuálnom oddieli a pri neúspechu skáče na návesie RETURN, by sa skočilo na začiatok novej slučky. Na navestie RETURN by sa skočilo, ak by rutina GET_NEXTPART prešla cez všetky oddiely.

    Teda, prešli by sa všetky "platné" oddiely bez ohľadu na práve vybraný.

    Tak to bola moja teoretická úvaha, snáď správna a zrozumiteľná …. 🙂

Je nám líto, ale formulář pro přidávání komentářů je momentálně uzavřen.