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)”
Je nám líto, ale formulář pro přidávání komentářů je momentálně uzavřen.
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… 🙂
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.
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á …. 🙂