Assembler a systemJan Hlavatý
Tentokrát se podíváme na způsob předávání parametrů, který byl do systému
zaveden s příchodem OS verze 2.0, a to tzv. TAGS. O co jde? Operační systém Amigy se neustále vyvíjí, přitom ale je nanejvýš žádoucí, aby
veškeré programové vybavení určené pro starší verze systému zůstalo i nadále
použitelné. Jedním z hlavních problémů v této oblasti jsou změny datových
struktur používaných pro předávání dat - obvykle jsou ke stávajícím strukturám
přidány další položky, nebo je dříve nevyužitým položkám přiřazován nový význam.
Starší programy pak přirozeně o nových změnách neví a vznikají problémy např.
při dynamické alokaci struktur - starší program alokuje strukturu která byla
používána v době jeho vzniku a ta může být odlišná od právě používané verze.
Tento problém se podařilo odstranit právě pomocí TAGů. Vezměme si například
takové otevření okna na Workbenchi. Starý způsob předávání parametrů systémovým
funkcím spočíval ve vyplnění určité datové struktury požadovanými hodnotami.
Tato struktura pak byla předána funkci. Význam vyplněných dat určovalo jejich
UMÍSTĚNÍ ve struktuře - v našem případě například funkce OpenWindow() ví, že v
předávané struktuře NewWindow jsou na začátku dva wordy označující X a Y
souřadnice umístění otevíraného okna a za nimi (kromě jiného) další dva wordy
udávající jeho rozměry. Kdybychom chtěli strukturu NewWindow rozšířit, narazíme
na problém, protože starší programy vyplní jen tu "starou" část a nové položky
budou nevyplněny, t.j. budou obsahovat náhodná data. Jak tento problém obejít?
Je prostě třeba ke každé předávané hodnotě také napsat, která že to je hodnota.
Je to jako bychom místo "0, 10, 320, 100" napsali "x=0, y=10, šířka=320,
výška=100". V praxi se tento způsob předávání parametrů řeší pomocí dvojic
longů, nazývaných TAGs. Hodnota prvního longu určuje význam druhého longu. Takto
je struktura TAGu definována v systémovém include souboru "utility/tagitem.i":
STRUCTURE Tagitem,0 ULONG ti_Tag typ hodnoty ULONG ti_Data ; hodnota LABEL ti
SIZEOF
Tagy se používají ve skupinách za sebou (taglistech), poslední je ukončovací tag
se speciální hodnotou ti_Tag. Je možné i propojit víc oddělených skupinek do
jednoho velkého taglistu. Funkce zpracovávající data z taglistu se řídí dvěma
pravidly:
1. Najde-li funkce tag který nezná, ignoruje ho. Tak je možné funkci použít i
když program zná a používá novější tagy než Funkce (i když nemusí dělat úplně
totéž co by udělala novější funkce, která tag zná).
2. Nenajde-li funkce v dodaném taglistu některý méně důležitý tag (tj. ne
nezbytně nutný pro funkci), vhodným způsobem si tento parametr "domyslí" (tj.
přiřadí mu implicitní hodnotu). Takto je možné danou funkci rozšiřovat aniž by o
tom starší programy musely vědět - funkce pro ně zůstane použitelná a nemusí se
vytvářet funkce nová.
Na nejnižší úrovni si systém rezervuje některé hodnoty tagů pro "administrativu"
taglistů:
TAG_DONE, TAG_END (hodnota 0) ukončují celý taglist. V tomto případě je jedno,
jakou hodnotu bude mít
ti_Data tohoto tagu.
TAG_IGNORE (hodnota 1) - obsah ti_Data je ignorován, prohledávání pokračuje
následujícím tagem.
TAG_MORE (hodnota 2) - pomocí tohoto tagu můžete propojit více samostatných
bloků tagů dohromady. ti_Data obsahuje adresu začátku dalšího taglistu, kde má
prohledávání taglistu pokračovat (podobně jako instrukce JMP).
TAG_SKIP (hodnota 3) - přeskočit tolik následujících tagů, kolik je hodnota
ti_Data.
Ostatní hodnoty jsou pak používány různými částmi systému, případně i
uživatelskými programy. Obecně všechna nesystémová ID tagů by měla být větší než
TAG_USER ($80000000) a neměla by využívat bity 16-30 (nechat nulové).
Použití tagů bychom si mohli demonstrovat na funkci intuition.library
OpenScreenTagList().
OpenScreenTag List(A0: NewScreen,A1 :TagItems)->D0:Screen
Tato funkce vyžaduje v A0 pointer na strukturu NewScreen, která může být použita
jako základ popisu otevíraného screenu, a v registru A1 ukazatel na taglist s
údaji. Pokud chceme použít jen taglist může být A0 NULL. Taktéž pokud nechceme
použít taglist, může být v A1 NULL.
Tzv. BODL tagy jsou tagy, jejichž hodnota může nabývat jen dvou hodnot - TRUE
(nerovno nule) a FALSE (nula). Tady je seznam tagů použitelných pro tuto funkci
který je definovaný v include souboru "intuition/screens.i":
SA_Left, SA_Top, SA_Width, SA_Height - X, Y, šířka a výška screenu. Pokud
neuvedete žádný z těchto tagů, bude screen velký přesně jako celá viditelná
oblast obrazovky (nejlépe použijete-li i SA_Overscan).
SA_Depth - počet bitplánů screenu (hloubka). Počet barev screenu je 2 na n, kde
n je hloubka. (implicitně 1) SA_DetailPen, SA_BlockPen implicitní barvy použité
pro kreslení textu a pozadí lišty screenu
SA_Title - ukazatel na titul screenu (implicitně NULL)
SA_Font - font pro screen (ukazatel na TextAttr).
SA_BitMap - ukazatel na BitMap pro CUSTOMBITMAP.
SA_ShowTitle - (BOOL) - zapíná zobrazování lišty screenu (implicitně TRUS -
zobrazuje)
SA_Behind - (BOOL) - má-li se screen otevřít pod všemi ostatními screeny - t.j.
nebude vidět, dokud ho nepřesunete dopředu. To je možno využít pokud chcete
například na screen něco nakreslit než ho uživatel uvidí. (implicitně FALSE)
SA_Quiet - (BOOL) - zakáže kreslení titulu a gadgetů screenu. (implicitně FALSE)
SA_Type - typ otevíraného screenu PUBLICSCREEN nebo CUSTOMSCREEN.
SA_DispIayID - mole ID zobrazovacího módu který má být použit. Definovány v
"graphics/modeid.i" pro OS 3.0+, nebo v "graphics/displayinfo.i" pro OS 2.0.
Pomocí tohoto tagu si můžete otevřít screen třeba v NTSC.
SA_Overscan - ti_Data obsahuje identifikátor módu overscanu který má být použit
- jeden z OSCAN_TEXT, OSCAN_STANDARD, OSCAN_MAX, OSCAN_VIDEO.
SA_DClip - ti_Data je pointer na strukturu Rectangle přesně specifikující
overscan screenu. Normálně je jednodušší použít SA_Overscan.
SA_AutoScroll - (BOOL) - automatický scrolling screenu většího než je
zobrazitelná část
SA_PubName - jméno public screenu. Zároveň indikuje že screen má být public
screen. Ke zpřístupnění public screenu je třeba použít ještě PubScreenStatus().
SA_Pens - ukazatel na pole s čísly barev pro DrawInfo screenu. Zároveň zapíná
"new look" vzhled screenu (3D).
SA_PubTask - pro public screen - task kterému bude nastaven signál až ze screenu
zmizí poslední cizí okno (implicitně task který volá OpenScreenTagList())
SA_PubSig - pro public screen - číslo signálu pro SA_PubTask
SA_Colors - ti_Data ukazuje na pole struktur ColorSpec s definicí palety screenu
SA_FullPalette - (BOOL) - nastavit všech 32 barev podle preferencí (implicitně
FALSE)
SA_ErrorCode - ti_Data je pointer na ulong kam se uloží případný důvod selhání
otevření screenu nebo 0 (viz OSERR_... z intuition/screens.i)
SA_SysFont - použít některý implicitní font: 0 pro topaz.8, 1 pro Font
WorkbenchScreen.
OS 3.0 umožňuje připojit ke screenu (parent) jiný (child) screen tak, že jsou
navzájem spojeny při přesouvání dopředu nebo dozadu, případně při stažení dolů.
Tyto 3 tagy umožňují spojení screenů:
SA_Parent - (OS 3.0) ti Data obsahuje pointer na už otevřený screen, ke kterému
má být nový screen připojen.
SA_FrontChild - (OS 3.0) ti_Data obsahuje pointer na už otevřený screen, který
má být připojen k novému screenu (před něj)
SA_BackChild - (OS 3.0) ti Data obsahuje pointer na už otevřený screen, který má
být připojen k novému screenu (za něj)
SA_BackFill - (OS 3.0) ti Data obsahuje pointer na hook pro vyplňování pozadí
screenu (speciální funkce, pomocí které je například realizován pattern na
pozadí workbenche)
SA_Draggable - (OS 3.0) (BOOL) smí-li uživatel screen stáhnout dolů. Jeli false,
screen stáhnout nejde. U child screenů (připojených k parent screenům) se tímto
zakáže hýbání s child screenem vůči parent screenu. Oba screeny se pak jeví jako
jeden screen.
SA_Exclusive (OS 3.0) (BOOL) - screen nebude nikdy sdílet displej s jiným
screenem
SA_SharePens (OS 3.0) (BOOL) nastavit na TRUE budete-li používat sdílení barev
SA_Colors32 - (OS 3.0) - Paleta barev ve formátu jako pro LoadRGB32() z
graphics.library
SA_Interleaved - (OS 3.0) (BOOL) pokusit se vytvořit bitplány screenu v
interleaved formátu (zmenšuje blikání např. při scrollování velkých ploch)
SA_VideoControl - (OS 3.0) - taglist který bude po otevření screenu předán
funkci VideoControl() - např. pro zapnutí sprajtů v okrajích...
SA_ColorMapEntries - (OS 3.0) - počet položek ColorMap screenu (je-li potřeba
víc)
SA_LikeWorkbench - (OS 3.0) (BOOL) - pokusit se otevřít screen stejný jako je
Workbench. Nemusí se povést. Ostatní tagy přebíjí takto získané hodnoty.
SA_MinimizeISG - (OS 3.1) minimalizovat mezeru mezi screeny
Abyste si s tím mohli pohrát, připravil jsem vám malinký prográmek, který otevře
screen pomocí OpenScreenTagList(), počká 5 sekund a pak screen zavře. Na začátku
je konstanta MODEID - je jí přiřazena hodnota $00019020, což je ModeID pro NTSC,
super-hires. Tento mód vám nebude fungovat, pokud nemáte instalován driver pro
monitor NTSC! Zkuste si dosadit i jiné hodnoty, např. $00000000 pro LoRes v
implicitním módu (pravděpodobně PAL), $00008000 pro HiRes... viz příslušné
include (graphics/modeid.i pro OS 3.0). Všimněte si, že v tomto případě jsou
automaticky nastaveny rozměry screenu - to lze např. využít aby váš program měl
k dispozici co největší ale přitom viditelné místo na monitoru - v závislosti na
nastavení preferencí overscanu. Jaké rozměry váš screen ve skutečnosti má
zjistíte snadno po otevření screenu ze struktury Screen - sc_Width je šířka a
sc_Height je výška. Tamtéž lze zjistit i jiné užitečné údaje.
Tagy jsou v novém OS velice rozšířené a jsou mj. základem pro objektově
orientovaný přístup k intuitionu, jako jsou BOOPSI gadgety nebo datatypy, právě
pro svou flexibilitu a snadnost rozšíření. HOOKS
U SA_Backfill jsem se zmínil o hooku. Co to je? V některých případech
potřebují systémové rutiny od uživatele nějakou funkci. Například file requester
z asl.library umožňuje při načítání výpisu directory volajícímu programu
rozhodnout, zdali se má právě načtená položka directory v requesteru zobrazit či
nikoliv. Program poskytne tuto funkci prostřednictvím tzv. callback hooku. V
podstatě váš program předává systému adresu vaší funkce, která bude systémem
volána ve vhodném okamžiku. Je to jakýsi "opačný" způsob, obvykle voláte vy
rutiny systému a ne systém vaše. Hook je struktura, která vypadá takto
(utility/hooks.i):
STRUCTURE HOOK,MLN_SIZE APTR h_Entry ; assembler entry point APTR h_SubEntry ;
optional HLL entry point APTR h Data ; owner specific LABEL h SIZEOF
Program uloží adresu své rutiny do h_Entry. Když je funkce zavolána, A0 obsahuje
ukazatel na hook, A1 pointer na nějaká data a A2 pointer na objekt kterého se
volání týká. incdir incl:
include dos/dos lib.i
include exec/exec lib.i
include intuition/intuition lib.i
include intuition/screens.i
MODEID = $00019020 ;ntsc, superhires
section prg,code
START move.l 4.w,a6
lea intname(pc),a1
moveq #37,d0
jsr _LVOOpenLibrary(a6)
move.l d0,intbase
beq .fail1
lea dosname(pc),a1
moveq #37,d0
jsr _LVOOpenLibrary(a6)
move.l d0,dosbase
beq .fail2
move.l intbase(pc),a6
sub.l a0,a0
lea testtags(pc),a1
jsr _LVOOpenScreenTagList(a6)
move.l d0,screen
beq .fail3
move.l dosbase(pc),a6
move.l #5*50,d1
jsr _LVODelay(a6)
move.l intbase(pc),a6
move.l screen(pc),a0
jsr _LVOCloseScreen(a6)
.fail3 move.l 4.w a6
move.l dosbase(pc),a1
jsr _LVOCloseLibrary(a6)
.fail2 move.l intbase(pc),a1
jsr _LVOCloseLibrary(a6)
.fail1 moveq #0,d0
rts
cnop 0,4
testtags dc.l SA_Overscan,OSCAN_TEXT
dc.l SA_Depth,2
dc.l SA_Title,title
dc.l SA_Pens,pens
dc.l SA_DispIayID,MODEID
dc.l TAG_END
intbase dc.l 0
dosbase dc.l 0
screen dc.l 0
pens dc.w -1
intname dc.b "intuition.library,0
dosname dc.b "dos.library",0
title dc.b "pokusny screen",0 Vytlačiť článok
Pozn.: články boli naskenované ako text a preto obsahujú aj zopár chýb. Taktiež neručíme za zdrojové kódy (Asm, C, Arexx, AmigaGuide, Html) a odkazy na web. Dúfame, že napriek tomu vám táto databáza dobre poslúži.
Žiadna časť nesmie byť reprodukovaná alebo inak šírená bez písomného povolenia vydavatela © ATLANTIDA Publishing
none
|