[{"c":" Verzia dokumentácie Action26 1.3.0.361\nČo je Atari Atari 800XL a 130XE sú domáce počítače z osemdesiatych rokov. Majú procesor 6502, 64 alebo 128 kilobajtov pamäte a pripájali sa k televízoru. Po zapnutí na nich nebeží žiadny Windows – počítač čaká, kým mu dáš program z kazety, z diskety alebo zo zásuvného modulu (cartridge).\nDnes tie počítače stále fungujú a kto ich nemá, používa emulátor: program, ktorý sa na dnešnom počítači správa ako Atari.\nČo je Action! Action! je programovací jazyk, ktorý pre Atari v roku 1983 vydala firma Optimized Systems Software. Predával sa ako cartridge. Stal sa obľúbeným, lebo programy v ňom sú skoro také rýchle ako programy písané priamo v strojovom kóde, a pritom sa čítajú ako obyčajný text:\nAction! PROC Main() PrintE(\"Hello, Atari!\") RETURN Ak poznáš Pascal alebo C, veľa vecí ti bude povedomých. Ak nepoznáš nič, nevadí – táto kniha začína od nuly.\nČo je action26 Pôvodný Action! bežal priamo na Atari: písalo sa na jeho klávesnici a prekladalo sa na ňom. action26 je prekladač toho istého jazyka, ktorý beží na počítači s Windows.\nProgram píšeš v ľubovoľnom textovom editore (Poznámkový blok, Visual Studio Code, Sublime Text …). action26 ho preloží za zlomok sekundy. Výsledok je súbor, ktorý sa dá spustiť na Atari alebo v emulátore. Jazyk je ten istý. Program z tejto knihy preloží aj pôvodný Action! (okrem kapitol 35 až 42, ktoré ukazujú, čo vie action26 navyše).\nNiekoľko slov, ktoré budeš stretávať Slovo Čo znamená program zoznam príkazov, ktoré počítač vykoná jeden po druhom zdroják (zdrojový text) program tak, ako ho píše človek – obyčajný textový súbor s príponou .act prekladač program, ktorý zdroják premení na príkazy pre procesor; tu je to action26 XEX súbor s preloženým programom pre Atari (prípona .xex) simulátor časť action26, ktorá preložený program hneď spustí a jeho výpis ukáže v okne príkazového riadka emulátor samostatný program (atari800), ktorý ukáže celé Atari aj s obrazovkou, farbami a zvukom knižnica hotové rutiny, ktoré môžeš volať – napríklad výpis textu alebo kreslenie čiary Ďalšie slová vysvetlí kniha vtedy, keď ich bude treba. Všetky sú v slovníčku.\nČo potrebuješ Počítač s Windows 10 alebo 11. Súbor action26.exe. Je to jeden súbor, nič sa neinštaluje. Skopíruj si ho do priečinka, kde budeš mať svoje programy, alebo do priečinka, ktorý máš v systémovej ceste (PATH) – potom ho môžeš volať odkiaľkoľvek. Textový editor. Stačí Poznámkový blok. Pohodlnejší je editor, ktorý čísluje riadky, lebo prekladač hlási chyby číslom riadka. Príkazový riadok – okno, do ktorého sa píšu príkazy. Vo Windows je to Terminál alebo PowerShell (nájdeš ho v ponuke Štart). Na kapitoly o grafike, zvuku a joysticku navyše:\nEmulátor atari800 v priečinku atari800 vedľa action26.exe. Do kapitoly 26 ho nepotrebuješ. Emulátor potrebuje operačný systém Atari ako súbor ROM (ATARIXL.ROM vedľa atari800.exe). Namiesto neho poslúži aj voľná náhrada AltirraOS od Averyho Leeho – knižnica action26 volá operačný systém len cez jeho oficiálne vstupné body, takže s ňou funguje rovnako. Keď vedľa emulátora ATARIXL.ROM nie je a action26 nájde súbor external\\Altirra\\altirraos-xl.rom, použije pri --run sám AltirraOS. Skúška, či všetko funguje Otvor príkazový riadok a napíš:\naction26 --version Mal by odpovedať svojou verziou, napríklad:\naction26 1.3.0.301 Copyright (C) 2026 Pedro. MIT License. Author web: https://action26.pohroma.de Na prvom riadku je číslo verzie; posledné číslo (revízia) sa s každou novou verziou zväčšuje.\nAk namiesto toho príde hlásenie, že príkaz action26 nie je známy, príkazový riadok nevie, kde action26.exe leží. Najjednoduchšia náprava: prejdi v príkazovom riadku do priečinka, kde ten súbor máš, a píš .\\action26 namiesto action26.\ncd C:\\Atari .\\action26 --version Ako je kniha usporiadaná Každá kapitola má tie isté časti:\nNa čo to je – o čom príkaz je, jednou vetou. Ako sa to píše – tvar príkazu. Celý program – nie úryvok; dá sa preložiť tak, ako je. Preklad a spustenie – príkaz, ktorý stačí skopírovať. Čo uvidíš – skutočný výpis programu. Ako to funguje – program riadok po riadku. Časté chyby – čo sa pokazí najčastejšie a čo na to povie prekladač. Vyskúšaj si – malé úlohy. Zhrnutie. Všetky programy sú hotové v priečinku examples/. Texty, ktoré programy vypisujú, sú po anglicky: Atari nemá slovenské písmená s dĺžňami a mäkčeňmi.\nĎalej: 2. Prvý program\n","t":"1. Úvod","u":"01-uvod/"},{"c":"Na čo to je Prejdeš celú cestu od prázdneho súboru po bežiaci program: napísať, uložiť, preložiť, spustiť. Všetky ďalšie kapitoly robia to isté, len s inými príkazmi.\nCelý program Otvor textový editor a napíš (alebo si otvor hotový súbor examples/hello.act):\nAction! ; My first program in Action! PROC Main() PrintE(\"Hello, Atari!\") RETURN Ulož ho ako hello.act. Prípona .act hovorí, že je to zdroják v jazyku Action!.\nPozor pri ukladaní z Poznámkového bloku: v okne Uložiť ako zvoľ typ Všetky súbory, inak sa súbor uloží ako hello.act.txt.\nPreklad a spustenie V príkazovom riadku prejdi do priečinka, kde súbor leží, a napíš:\naction26 hello.act --sim Prekladač program preloží a voľba --sim ho hneď spustí vo vstavanom simulátore.\nČo uvidíš Hello, Atari! To je všetko, čo program robí: vypíše jeden riadok a skončí.\nAko to funguje Action! ; My first program in Action! Riadok, ktorý začína bodkočiarkou, je komentár. Prekladač ho preskočí. Je to poznámka pre človeka.\nAction! PROC Main() PROC začína procedúru – pomenovaný kus programu. Táto sa volá Main. Prázdne zátvorky hovoria, že procedúra nedostáva žiadne údaje. Meno si môžeš zvoliť sám; Main (anglicky „hlavná“) je zvyk.\nAction! PrintE(\"Hello, Atari!\") PrintE je hotová rutina z knižnice: vypíše text v zátvorkách a prejde na nový riadok. Text sa píše do úvodzoviek.\nAction! RETURN RETURN končí procedúru. Keďže Main je jediná procedúra, končí tým aj celý program.\nMedzery na začiatku riadka nie sú povinné. Píšu sa preto, aby bolo vidieť, čo patrí dovnútra procedúry.\nČo vzniklo na disku Po preklade pribudol vedľa zdrojáka súbor hello.xex. To je hotový program pre Atari – má 277 bajtov. Dá sa skopírovať na disketu alebo spustiť v emulátore.\nKeď chceš program len preložiť a nespúšťať, voľbu --sim vynechaj:\naction26 hello.act Keď sa preklad podarí, prekladač nevypíše nič. Ticho znamená „v poriadku“.\nSpustenie v emulátore Simulátor ukáže len to, čo program vypíše. Emulátor ukáže celé Atari. Ak ho máš (priečinok atari800 vedľa action26.exe), spustíš program takto:\naction26 hello.act --run Tento program však skončí hneď po výpise a Atari po skončení programu ukáže svoju vlastnú obrazovku, takže text nestihneš prečítať. Preto sa do programov pre emulátor na koniec pridáva čakanie na kláves (examples/hello-key.act):\nAction! ; Hello for the emulator: it waits for a key before it ends PROC Main() PrintE(\"Hello, Atari!\") PutE() Print(\"Press any key\") GetD(7) RETURN action26 hello-key.act --run GetD(7) čaká, kým na klávesnici Atari stlačíš kláves. Čo presne znamená sedmička, vysvetlí kapitola 30; zatiaľ ber GetD(7) ako „počkaj na kláves“.\nKeď prekladač nájde chybu Chyby sú pri programovaní bežné. Skús úmyselne jednu spraviť: zmaž druhú úvodzovku.\nAction! PROC Main() PrintE(\"Hello, Atari!) RETURN Prekladač odpovie:\nhello.act(2,10): error ACT001: missing double quote in string hello.act(4,1): error ACT018: unmatched parentheses: expected ')', got 'end of file' Každé hlásenie má štyri časti:\nČasť V príklade Čo znamená súbor hello.act v ktorom súbore je chyba miesto (2,10) riadok 2, stĺpec 10 druh a číslo error ACT001 error je chyba, warning len upozornenie; číslo sa dá nájsť v prílohe C popis missing double quote in string čo prekladaču vadí (po anglicky) Dve rady:\nOpravuj vždy prvú chybu. Ďalšie sú často len jej následkom – tu druhé hlásenie zmizne, keď doplníš úvodzovku. Chyba je na označenom mieste alebo tesne pred ním. Prekladač si ju všimne, až keď mu prestane dávať zmysel to, čo číta. Kým má program chybu, súbor .xex nevznikne a nič sa nespustí.\nČasté chyby Čo sa stalo Čo povie prekladač preklep v mene rutiny (Prit namiesto Print) error ACT008: undeclared name 'Prit' chýba úvodzovka na konci textu error ACT001: missing double quote in string chýba zátvorka error ACT018: unmatched parentheses súbor sa volá inak, ako píšeš v príkaze fatal error ACT201: file not found: hello.act Veľké a malé písmená prekladač nerozlišuje: PrintE, printe aj PRINTE je to isté. V knihe sú slová jazyka veľkými písmenami (PROC, RETURN) a mená rutín s veľkým začiatočným písmenom, aby sa program dobre čítal.\nVyskúšaj si Zmeň text v úvodzovkách na svoje meno a program znova prelož a spusti. Pridaj druhý riadok PrintE(\"…\") s iným textom pod prvý. Zmaž slovo RETURN a pozri, čo sa stane. (Nič – posledná procedúra programu sa skončí aj tak. Píš ho však vždy; v kapitole 3 uvidíš, prečo.) Zhrnutie Program je textový súbor s príponou .act. action26 meno.act ho preloží do meno.xex; --sim ho hneď spustí v simulátore, --run v emulátore. Program je zložený z procedúr: PROC Meno() … RETURN. PrintE(\"text\") vypíše riadok textu. Riadok za ; je komentár. Chybové hlásenie hovorí súbor, riadok, stĺpec a dôvod. Opravuj od prvého. Späť: 1. Úvod · Ďalej: 3. Rutiny\n","t":"2. Prvý program","u":"02-prvy-program/"},{"c":"Na čo to je Program sa delí na menšie pomenované kusy – procedúry. Kus, ktorý sa opakuje, napíšeš raz a potom ho len voláš menom.\nAko sa to píše Action! PROC Meno() príkazy RETURN Časť Význam PROC začiatok procedúry Meno meno, ktoré si zvolíš: začína písmenom, potom písmená, číslice a _ () zátvorky sú povinné, aj keď sú prázdne RETURN koniec procedúry: program sa vráti tam, odkiaľ ju zavolal Procedúra sa volá tak, že napíšeš jej meno so zátvorkami: Meno().\nKomentár začína bodkočiarkou a siaha do konca riadka. Môže stáť na vlastnom riadku aj za príkazom.\nCelý program Súbor examples/proc.act:\nAction! ; Three routines. The program starts in the last one. PROC Line() PrintE(\"--------------------\") RETURN PROC Greet() PrintE(\"Good morning!\") ; a comment may follow a statement RETURN PROC Main() Line() Greet() Greet() Line() RETURN Preklad a spustenie action26 proc.act --sim Čo uvidíš -------------------- Good morning! Good morning! -------------------- Ako to funguje Program má tri procedúry: Line, Greet a Main.\nProgram začína v poslednej procedúre. To je pravidlo Action! – nezáleží na mene, ale na poradí. Tu je posledná Main, takže program začne v nej.\nMain postupne zavolá Line(), dvakrát Greet() a znova Line(). Pri každom volaní program odskočí do volanej procedúry, vykoná jej príkazy a po RETURN pokračuje za volaním.\nKeď RETURN vykoná posledná procedúra (tá, v ktorej program začal), program končí.\nProcedúra musí byť napísaná skôr, než ju niekto zavolá. Prekladač číta súbor zhora nadol a meno, ktoré ešte nevidel, nepozná. Preto sú pomocné procedúry hore a Main dole.\nČasté chyby Čo sa stalo Čo povie prekladač procedúra je napísaná až pod miestom, kde sa volá error ACT008: undeclared name 'Greet' chýbajú zátvorky pri PROC Main error ACT007: invalid argument list: expected '(' after the routine name chýbajú zátvorky pri volaní (Greet namiesto Greet()) error ACT010: illegal assignment: expected '=', '==' or '(' after 'Greet' dve procedúry majú rovnaké meno error ACT006: 'Greet' is already declared Chýbajúci RETURN prekladač nehlási. Procedúra bez RETURN neskončí a program pokračuje príkazmi nasledujúcej procedúry, čo skoro nikdy nechceš. Keby v tomto programe chýbal RETURN za Greet, program by z Greet „prepadol“ do Main, tá by znova zavolala Greet – a Good morning! by sa vypisovalo donekonečna. Na konci každej procedúry preto píš RETURN.\nVyskúšaj si Pridaj procedúru Bye, ktorá vypíše Good night!, a zavolaj ju z Main pred poslednou čiarou. Presuň procedúru Main na začiatok súboru. Čo povie prekladač a prečo? Zavolaj Line() aj z procedúry Greet. Koľko čiar program vypíše? Zhrnutie PROC Meno() … RETURN je procedúra; volá sa Meno(). Program začína v poslednej procedúre súboru. Procedúra musí byť v súbore nad miestom, kde sa volá. RETURN na konci procedúry nevynechávaj. ; začína komentár do konca riadka. Späť: 2. Prvý program · Ďalej: 4. Výpis\n","t":"3. Rutiny: PROC a RETURN","u":"03-proc/"},{"c":"Na čo to je Program, ktorý nič nevypíše, nevieš skontrolovať. Rutiny na výpis preto potrebuješ v každej kapitole. Sú súčasťou knižnice – netreba ich deklarovať, stačí ich zavolať.\nAko sa to píše Rutina Čo vypíše Príklad Print(\"text\") text; kurzor ostane za ním Print(\"Name: \") PrintE(\"text\") text a koniec riadka PrintE(\"Hello\") Put('A) jeden znak Put('*) PutE() len koniec riadka PutE() PrintB(číslo) číslo 0 až 255 PrintB(200) PrintC(číslo) číslo 0 až 65535 PrintC(50000) PrintI(číslo) číslo so znamienkom, −32768 až 32767 PrintI(-150) Písmeno E na konci mena (z anglického End of line) znamená „a potom prejdi na nový riadok“. Majú ho aj rutiny na čísla: PrintBE, PrintCE, PrintIE.\nPrečo sú na čísla tri rutiny, vysvetlí kapitola 6: písmená B, C a I sú tri druhy čísel – BYTE, CARD a INT.\nCelý program Súbor examples/print.act:\nAction! ; Writing texts, characters and numbers PROC Main() Print(\"One \") ; a text, the cursor stays on the line Print(\"line.\") PutE() ; the end of the line PrintE(\"A line of its own.\") Put('A) ; one character Put('B) Put('C) PutE() Print(\"A small number: \") PrintBE(200) ; BYTE: 0 to 255 Print(\"A big number: \") PrintCE(50000) ; CARD: 0 to 65535 Print(\"A number below zero: \") PrintIE(-150) ; INT: -32768 to 32767 PrintB(1) Put(' ) PrintB(2) Put(' ) PrintB(3) PutE() RETURN Preklad a spustenie action26 print.act --sim Čo uvidíš One line. A line of its own. ABC A small number: 200 A big number: 50000 A number below zero: -150 1 2 3 Ako to funguje Dva Print za sebou píšu na ten istý riadok. Až PutE() riadok ukončí. PrintE robí oboje naraz: text aj koniec riadka. Put('A) vypíše jeden znak. Znak sa píše s jedným apostrofom pred ním a žiadnym za ním – viac v kapitole 5. Put(' ) je apostrof a medzera: vypíše medzeru. Posledný riadok ukazuje, že na jednom riadku môže byť viac príkazov. Stačí ich oddeliť medzerou; žiadna bodkočiarka ani čiarka medzi ne nepatrí. Časté chyby Čo sa stalo Čo povie prekladač alebo program číslo sa do PrintB nezmestí (PrintB(300)) warning ACT215: value 300 does not fit into a BYTE a vypíše sa 44 znak s apostrofom aj za ním (Put('A')) error ACT018: unmatched parentheses – druhý apostrof začal nový znak ) text v Put (Put(\"A\")) prekladač mlčí, program vypíše nezmysel číslo v PrintE (PrintE(5)) prekladač mlčí, program vypíše nezmysel Posledné dva riadky stoja za zapamätanie: Action! nekontroluje, či rutine dávaš to, čo čaká. Text patrí do Print, znak do Put, číslo do PrintB, PrintC alebo PrintI. Keď program vypíše niečo čudné, pozri najprv, či si nepomiešal tieto rutiny.\nOdkiaľ sa vzalo 44? Do BYTE sa zmestí 256 hodnôt (0 až 255). 300 je o 44 viac ako 256, a práve ten zvyšok ostane.\nVyskúšaj si Vypíš svoje meno a vek na jeden riadok: Name: … Age: …. Vypíš pomocou Put a PutE trojuholník z hviezdičiek na tri riadky. Zmeň PrintIE(-150) na PrintCE(-150). Čo sa vypíše? (65386 – PrintC nepozná záporné čísla a to isté číslo číta inak.) Zhrnutie Print píše text, Put jeden znak. PrintB, PrintC, PrintI píšu čísla – podľa toho, aké veľké číslo to je a či môže byť záporné. E na konci mena pridá koniec riadka; samotný koniec riadka je PutE(). Na riadku môže byť viac príkazov oddelených medzerou. Prekladač nekontroluje, či rutine dávaš správny druh údaja. Späť: 3. Rutiny · Ďalej: 5. Čísla, znaky a texty\n","t":"4. Výpis: Print, Put a výpis čísel","u":"04-vypis/"},{"c":"Na čo to je Hodnotu môžeš do programu napísať štyrmi spôsobmi. Všetky štyri stretneš v každom programe pre Atari.\nAko sa to píše Zápis Príklad Čo to je desiatkové číslo 65, 1000 číslo, ako ho poznáš šestnástkové číslo $41, $D40E to isté číslo zapísané v šestnástkovej sústave; začína znakom $ znak 'A, '*, ' jeden znak; apostrof je len pred ním reťazec (text) \"Hello\" text v úvodzovkách, najviac 255 znakov Šestnástková sústava v skratke V desiatkovej sústave máš desať číslic (0–9) a ďalšie miesto znamená desaťnásobok. V šestnástkovej je číslic šestnásť: 0 1 2 3 4 5 6 7 8 9 A B C D E F, kde A je desať a F pätnásť. Ďalšie miesto znamená šestnásťnásobok.\nŠestnástkovo Výpočet Desiatkovo $0A 10 10 $10 1 × 16 + 0 16 $41 4 × 16 + 1 65 $FF 15 × 16 + 15 255 $FFFF 65535 Prečo sa to používa: dve šestnástkové číslice sú presne jeden bajt (0 až 255) a adresy v pamäti Atari sa v knihách a časopisoch píšu takmer vždy takto. Počítať v nej nemusíš – stačí vedieť, že $41 a 65 je to isté číslo.\nZnak je tiež číslo Počítač si znaky pamätá ako čísla – každý znak má svoj kód. Písmeno A má kód 65, B 66, medzera 32, číslica 0 48. Zápis 'A je teda len pohodlnejší spôsob, ako napísať 65.\nAtari používa vlastnú tabuľku kódov, ATASCII. Pre písmená, číslice a bežné znamienka je rovnaká ako ASCII na dnešných počítačoch. Tabuľka je v prílohe D.\nCelý program Súbor examples/numbers.act:\nAction! ; The four ways to write a value PROC Main() Print(\"Decimal 65: \") PrintBE(65) Print(\"Hexadecimal $41: \") PrintBE($41) ; the same number, written in base 16 Print(\"Character 'A: \") PrintBE('A) ; a character is a number too - its code Print(\"Put(65): \") Put(65) ; and a number can be written as a character PutE() Print(\"$FFFF: \") PrintCE($FFFF) ; the biggest CARD PrintE(\"A text with \"\"quotes\"\" inside.\") RETURN Preklad a spustenie action26 numbers.act --sim Čo uvidíš Decimal 65: 65 Hexadecimal $41: 65 Character 'A: 65 Put(65): A $FFFF: 65535 A text with \"quotes\" inside. Ako to funguje Prvé tri výpisy dajú zakaždým 65: 65, $41 a 'A sú tri zápisy toho istého čísla. Put(65) vypíše A. Rutina Put berie číslo ako kód znaku; PrintB ho berie ako číslo. Hodnota je tá istá, líši sa len to, čo s ňou rutina spraví. $FFFF je najväčšie číslo, ktoré sa zmestí do dvoch bajtov. Úvodzovku vnútri textu napíšeš zdvojenú: \"\". Časté chyby Čo sa stalo Čo povie prekladač znak ukončený druhým apostrofom ('A') chyba na nasledujúcom znaku – druhý apostrof začne ďalší znak číslo s desatinnou čiarkou alebo bodkou (1.5) error ACT211 – Action! desatinné čísla nepozná medzera v čísle (10 000) error ACT018 – sú to dve čísla za sebou, 10 a 000 text dlhší ako 255 znakov error ACT001 – rozdeľ ho na viac Print Šestnástkové číslice píš veľkými písmenami ($FF, nie $ff). action26 prijme aj malé, pôvodný Action! nie.\nVyskúšaj si Vypíš kódy znakov 'a, 'z, '0 a '9 pomocou PrintBE. Vypíš Put(72) Put(105) – aké slovo to je? Koľko je $100? Tipni si a over to cez PrintCE($100). Zhrnutie Číslo sa píše desiatkovo (65) alebo šestnástkovo ($41). Znak sa píše s jedným apostrofom pred ním ('A) a je to číslo – kód znaku. Text sa píše do úvodzoviek; úvodzovka v texte sa zdvojí. Desatinné čísla Action! nemá. Späť: 4. Výpis · Ďalej: 6. Premenné\n","t":"5. Čísla, znaky a texty","u":"05-cisla/"},{"c":"Na čo to je Premenná je pomenované miesto v pamäti, do ktorého si program odloží hodnotu, aby ju mohol neskôr použiť alebo zmeniť. Bez premenných by program vedel len vypisovať to, čo máš napísané v zdrojáku.\nAko sa to píše Premennú treba najprv deklarovať – povedať, ako sa volá a aký druh hodnoty v nej bude:\nAction! BYTE age CARD year, score ; viac premenných toho istého typu, oddelené čiarkou INT temperature CHAR grade BYTE lives=[3] ; premenná, ktorá má hodnotu hneď od začiatku Druh hodnoty sa volá typ. Action! má štyri základné:\nTyp Veľkosť v pamäti Aké hodnoty Na čo sa hodí BYTE 1 bajt 0 až 255 malé čísla: vek, počet životov, súradnica na obrazovke CHAR 1 bajt 0 až 255 jeden znak; je to to isté ako BYTE, len meno hovorí, že ide o znak CARD 2 bajty 0 až 65535 väčšie čísla bez znamienka: rok, skóre, adresa INT 2 bajty −32768 až 32767 čísla, ktoré môžu byť záporné CARD je skratka z cardinal (číslo bez znamienka), INT z integer (celé číslo).\nHodnotu do premennej vloží priradenie: meno=hodnota.\nDeklarácie patria na začiatok procedúry, pred prvý príkaz.\nCelý program Súbor examples/variables.act:\nAction! ; Variables of the four basic types PROC Main() BYTE age ; 0 to 255 CARD year ; 0 to 65535 INT temperature ; -32768 to 32767 CHAR grade ; one character BYTE lives=[3] ; a variable with a value from the start age=12 year=1983 temperature=-5 grade='A Print(\"Age: \") PrintBE(age) Print(\"Year: \") PrintCE(year) Print(\"Temperature: \") PrintIE(temperature) Print(\"Grade: \") Put(grade) PutE() Print(\"Lives: \") PrintBE(lives) age=13 ; a variable can change Print(\"Next year: \") PrintBE(age) RETURN Preklad a spustenie action26 variables.act --sim Čo uvidíš Age: 12 Year: 1983 Temperature: -5 Grade: A Lives: 3 Next year: 13 Ako to funguje Prvých päť riadkov procedúry sú deklarácie. Až po nich idú príkazy. age=12 uloží do premennej age číslo 12. Odvtedy sa dá age napísať všade, kde by mohlo stáť číslo – napríklad v PrintBE(age). Typ premennej určuje, ktorou rutinou ju vypíšeš: BYTE cez PrintB, CARD cez PrintC, INT cez PrintI, CHAR cez Put. lives=[3] v deklarácii dá premennej hodnotu už pri nahraní programu. Hranaté zátvorky sú tu povinné. age=13 starú hodnotu prepíše. Premenná si pamätá vždy len poslednú. Ako vybrať typ Zmestí sa hodnota vždy do 0 až 255? Použi BYTE. Je najrýchlejší a zaberie najmenej miesta – procesor Atari počíta po jednom bajte. Môže byť hodnota záporná? Použi INT. Inak CARD. Časté chyby Čo sa stalo Čo povie prekladač alebo program premenná nie je deklarovaná, alebo je v mene preklep error ACT008: undeclared name 'ag' deklarácia až za príkazom error ACT006: declaration error: declarations must come before the statements chýba čiarka medzi menami (BYTE a b) chyba na prvom príkaze, ktorý premennú použije hodnota sa do typu nezmestí (age=300) warning ACT215: value 300 does not fit into a BYTE; v premennej bude 44 INT t a t=40000 prekladač mlčí; v premennej bude −25536 BYTE lives=3 bez hranatých zátvoriek prekladač mlčí – a je to niečo celkom iné Posledný riadok je najzákernejší. BYTE lives=3 nedá premennej hodnotu 3. Znamená „premenná lives leží v pamäti na adrese 3“. Na to sa hodí pri práci s pamäťou počítača (kapitola 24), ale začiatočník tým prepíše niečo, čo patrí systému. Počiatočná hodnota sa píše vždy do hranatých zátvoriek: BYTE lives=[3].\nPremenná, ktorej si nič nepriradil, má po nahraní programu hodnotu 0. Nespoliehaj sa na to – keď program spustíš druhýkrát bez nového nahrania, ostane v nej to, čo tam bolo naposledy.\nVyskúšaj si Pridaj premennú CARD score s počiatočnou hodnotou 1000 a vypíš ju. Zmeň temperature na typ BYTE a pozri, čo sa vypíše pri temperature=-5. (Použi PrintBE. Vyjde 251 – BYTE záporné čísla nemá.) Priraď do grade znak 'B a potom číslo 66. Líši sa výpis? Zhrnutie Premenná sa deklaruje typom a menom na začiatku procedúry. BYTE a CHAR 0–255, CARD 0–65535, INT −32768 až 32767. meno=hodnota do premennej uloží hodnotu; stará sa stratí. Počiatočná hodnota je v hranatých zátvorkách: BYTE lives=[3]. Bez nich je to adresa. Hodnota, ktorá sa do typu nezmestí, sa skráti – prekladač to pri číslach v zdrojáku ohlási varovaním. Späť: 5. Čísla, znaky a texty · Ďalej: 7. Počítanie\n","t":"6. Premenné: BYTE, CARD, INT, CHAR","u":"06-premenne/"},{"c":"Na čo to je Program počíta: sčíta skóre, zistí, koľko ostáva životov, prepočíta súradnice. Zápis výpočtu sa volá výraz a jeho výsledok sa zvyčajne uloží do premennej.\nAko sa to píše Action! premenná = výraz Znak = tu neznamená „rovná sa“ ako v matematike. Znamená „vypočítaj to, čo je vpravo, a ulož to do premennej vľavo“. Preto dáva zmysel aj x=x+1: zober x, pripočítaj 1 a ulož späť do x.\nOperátor Význam Príklad Výsledok + sčítanie 17+5 22 - odčítanie 17-5 12 * násobenie 17*5 85 / delenie bez zvyšku 17/5 3 MOD zvyšok po delení 17 MOD 5 2 ( ) zátvorky – počíta sa najprv to, čo je v nich (2+3)*4 20 Poradie: najprv zátvorky, potom *, / a MOD, nakoniec + a -. Operátory rovnakej sily sa počítajú zľava doprava.\nSkrátené priradenie Zmeniť premennú o nejakú hodnotu je také časté, že má vlastný zápis:\nSkrátene Znamená x==+5 x=x+5 x==-1 x=x-1 x==*2 x=x*2 x==/2 x=x/2 Celý program Súbor examples/expr.act:\nAction! ; Counting with numbers PROC Main() BYTE a, b, small CARD result INT x, y, diff a=17 b=5 result=a+b Print(\"17 + 5 = \") PrintCE(result) result=a-b Print(\"17 - 5 = \") PrintCE(result) result=a*b Print(\"17 * 5 = \") PrintCE(result) result=a/b Print(\"17 / 5 = \") PrintCE(result) result=a MOD b Print(\"17 MOD 5 = \") PrintCE(result) result=2+3*4 Print(\"2 + 3 * 4 = \") PrintCE(result) result=(2+3)*4 Print(\"(2 + 3) * 4 = \") PrintCE(result) diff=b-a Print(\"5 - 17 with BYTE = \") PrintIE(diff) x=5 y=17 diff=x-y Print(\"5 - 17 with INT = \") PrintIE(diff) small=250 small=small+10 Print(\"250 + 10 in a BYTE = \") PrintBE(small) result=100 result==+5 Print(\"100, then ==+5: \") PrintCE(result) result==*2 Print(\"then ==*2: \") PrintCE(result) RETURN Preklad a spustenie action26 expr.act --sim Čo uvidíš 17 + 5 = 22 17 - 5 = 12 17 * 5 = 85 17 / 5 = 3 17 MOD 5 = 2 2 + 3 * 4 = 14 (2 + 3) * 4 = 20 5 - 17 with BYTE = 244 5 - 17 with INT = -12 250 + 10 in a BYTE = 4 100, then ==+5: 105 then ==*2: 210 Ako to funguje Delenie je celočíselné. 17 delené 5 je 3 a zvyšok 2. Výsledok delenia je 3, zvyšok dá MOD. Desatinné čísla Action! nemá.\nNásobenie má prednosť pred sčítaním. 2+3*4 je 2 + 12 = 14. Ak chceš najprv sčítať, daj sčítanie do zátvoriek.\nDve pasce, ktoré treba poznať 1. Typ výsledku určujú typy vo výraze, nie premenná, do ktorej ukladáš.\ndiff=b-a počíta 5 − 17. Obe premenné sú BYTE, preto sa aj výsledok počíta ako BYTE – a ten záporný byť nemôže. Vyjde 244 a až táto hodnota sa uloží do diff. To, že diff je INT, už nepomôže.\nV druhom výpočte sú x a y typu INT, výsledok je INT a vyjde správnych −12.\nPravidlo:\nVo výraze je Výsledok je len BYTE BYTE BYTE a INT, alebo len INT INT aspoň jeden CARD CARD Keď výsledok môže vyjsť mimo 0 až 255, musí byť aspoň jedna premenná vo výraze väčšieho typu.\n2. Pretečenie sa nehlási.\nsmall=250 a small=small+10 dá 4, nie 260. BYTE má len 256 hodnôt a po 255 nasleduje znova 0 – ako počítadlo kilometrov, ktoré sa pretočí. Program nezastane ani nič nevypíše. Rovnako pretečie CARD za 65535 a INT za 32767.\nČasté chyby Čo sa stalo Čo povie prekladač alebo program delenie nulou v zdrojáku (a=10/0) warning ACT217: division by zero in a constant expression delenie premennou, v ktorej je nula program beží ďalej s nezmyselným výsledkom výsledok sa nezmestí do typu nič – hodnota sa pretočí x=+5 namiesto x==+5 error ACT017: bad expression: unexpected '+' Vyskúšaj si Koľko je 7/2*2? A 7*2/2? Vypočítaj si to najprv na papieri (pozor na celočíselné delenie) a over programom. Vypíš počet hodín a minút v 200 minútach pomocou / a MOD. Zmeň typ a a b na CARD a pozri, čo sa stane s výpisom 5 - 17 with BYTE. Zhrnutie premenná=výraz vypočíta výraz a uloží výsledok. / delí bez zvyšku, zvyšok dá MOD. Najprv zátvorky, potom * / MOD, potom + -. Výraz zo samých BYTE sa počíta v BYTE. Ak má vyjsť viac ako 255 alebo menej ako 0, použi vo výraze CARD alebo INT. Pretečenie program nehlási. x==+1 je skratka za x=x+1. Späť: 6. Premenné · Ďalej: 8. Vstup\n","t":"7. Počítanie: výrazy a priradenie","u":"07-vyrazy/"},{"c":"Na čo to je Doteraz program vedel len to, čo si mu napísal do zdrojáka. Rutiny vstupu počkajú, kým používateľ niečo napíše na klávesnici a stlačí RETURN (Enter), a napísanú hodnotu odovzdajú programu.\nAko sa to píše Rutina Čo načíta Ako sa použije InputB() číslo 0 až 255 age=InputB() InputC() číslo 0 až 65535 year=InputC() InputI() číslo so znamienkom temperature=InputI() InputS(text) riadok textu InputS(name) Prvé tri sú funkcie: vrátia hodnotu a tú priradíš do premennej. Písmená B, C, I znamenajú zase BYTE, CARD, INT.\nInputS je procedúra: text uloží do premennej, ktorú jej dáš v zátvorkách. Na text nestačí BYTE ani CARD – treba miesto pre viac znakov:\nAction! CHAR ARRAY name(40) To je pole znakov s miestom pre 40 bajtov: jeden si Action! vezme na dĺžku textu, ostane 39 znakov. Poliam a reťazcom sa venujú kapitoly 18 a 19; tu stačí vedieť, že takto sa deklaruje premenná na text a že sa dá vypísať cez Print(name).\nCelý program Súbor examples/input.act:\nAction! ; A program that asks PROC Main() CHAR ARRAY name(40) ; room for a text of up to 39 characters BYTE age CARD year Print(\"What is your name? \") InputS(name) Print(\"How old are you? \") age=InputB() Print(\"What year is it? \") year=InputC() PutE() Print(\"Hello, \") Print(name) PrintE(\"!\") Print(\"You were born in \") PrintC(year-age) PrintE(\" or the year before.\") RETURN Preklad a spustenie action26 input.act --sim V simulátore píšeš odpovede na klávesnici svojho počítača. V emulátore (--run) na klávesnici Atari.\nČo uvidíš Program sa trikrát opýta. To, čo píšeš ty, je v ukážke za otáznikom:\nWhat is your name? Pedro How old are you? 12 What year is it? 2026 Hello, Pedro! You were born in 2014 or the year before. Ako to funguje Print(\"What is your name? \") vypíše otázku a nechá kurzor na riadku, aby sa odpoveď písala hneď za ňu. Preto tu nie je PrintE. InputS(name) počká na riadok textu a uloží ho do name. age=InputB() počká na riadok, prevedie ho na číslo a uloží do age. Prázdne zátvorky za InputB sú povinné – je to volanie funkcie. PrintC(year-age) ukazuje, že do zátvoriek rutiny nemusí ísť len premenná: môže tam byť celý výraz. year je CARD, takže výsledok je CARD a patrí do PrintC. Časté chyby Čo sa stalo Čo sa stane používateľ napíše písmená tam, kde program čaká číslo funkcia vráti 0 číslo sa nezmestí (300 do InputB) vráti zvyšok, 44 – ako pri priradení chýbajú zátvorky (age=InputB) prekladač mlčí; do age sa uloží kus adresy rutiny, nie odpoveď text je dlhší ako miesto v poli program si prepíše vlastnú pamäť a zvyčajne spadne Rutiny vstupu nekontrolujú, čo používateľ napísal. Číselný vstup číta číslice, kým nenarazí na iný znak: 12abc dá 12, abc dá 0.\nPole na text rob radšej väčšie. Riadok na obrazovke Atari má 40 znakov, ale používateľ môže písať ďalej – jeden vstup môže mať až 120 znakov. Kto chce mať istotu, použije CHAR ARRAY name(121).\nVyskúšaj si Pridaj otázku na obľúbené číslo a vypíš jeho dvojnásobok. Načítaj dve čísla a vypíš ich súčet, rozdiel, súčin a podiel. Zmeň age=InputB() na age=InputI() a zadaj záporný vek. Čo vypíše program a prečo? (Premenná age je BYTE.) Zhrnutie InputB(), InputC(), InputI() vrátia číslo napísané na klávesnici. InputS(pole) uloží napísaný text do poľa znakov. Otázku píš cez Print, nie PrintE, aby odpoveď stála za ňou. Vstup sa nekontroluje: zlé číslo je 0, pridlhý text prepíše pamäť. Späť: 7. Počítanie · Ďalej: 9. Podmienka\n","t":"8. Vstup: InputB, InputC, InputI, InputS","u":"08-vstup/"},{"c":"Na čo to je Program sa rozhoduje: niektoré príkazy vykoná, len keď niečo platí. „Ak je skóre viac ako rekord, vypíš gratuláciu.“\nAko sa to píše Najkratší tvar:\nAction! IF podmienka THEN príkazy ; vykonajú sa, len keď podmienka platí FI Plný tvar:\nAction! IF podmienka THEN príkazy ; keď platí prvá podmienka ELSEIF iná podmienka THEN príkazy ; keď prvá neplatí a druhá áno ELSE príkazy ; keď neplatí žiadna FI Slovo Význam IF „ak“ – začína podmienku THEN „tak“ – za ním sú príkazy, ktoré sa vykonajú ELSEIF „inak ak“ – ďalšia podmienka; môže ich byť koľkokoľvek ELSE „inak“ – čo spraviť, keď neplatilo nič FI koniec celého príkazu (IF odzadu) ELSEIF a ELSE sú nepovinné. FI je povinné vždy.\nPorovnania Zápis Platí, keď a=b sa rovnajú a#b alebo a\u003c\u003eb sa nerovnajú a\u003cb a je menšie a\u003eb a je väčšie a\u003c=b a je menšie alebo rovné a\u003e=b a je väčšie alebo rovné Znak = má v Action! dve úlohy. V príkaze x=5 je to priradenie, za IF je to porovnanie. Prekladač to spozná podľa miesta.\nSpájanie podmienok Zápis Platí, keď podm1 AND podm2 platia obe podm1 OR podm2 platí aspoň jedna Celý program Súbor examples/if.act:\nAction! ; Decisions PROC Main() BYTE age Print(\"How old are you? \") age=InputB() PutE() IF age\u003c6 THEN PrintE(\"You do not go to school yet.\") ELSEIF age\u003c15 THEN PrintE(\"You go to primary school.\") ELSEIF age\u003c19 THEN PrintE(\"You go to secondary school.\") ELSE PrintE(\"You are grown up.\") FI IF age\u003e=13 AND age\u003c=19 THEN PrintE(\"You are a teenager.\") FI IF age=0 OR age\u003e120 THEN PrintE(\"Is that really your age?\") FI IF age#18 THEN PrintE(\"You are not 18.\") FI RETURN Preklad a spustenie action26 if.act --sim Čo uvidíš Po zadaní čísla 14:\nHow old are you? 14 You go to primary school. You are a teenager. You are not 18. Spusti program viackrát s rôznym vekom (3, 14, 17, 18, 40, 200) a sleduj, ktoré riadky sa vypíšu.\nAko to funguje Prvý IF je reťaz. Podmienky sa skúšajú zhora nadol a vykoná sa len prvá vetva, ktorá platí. Pri veku 14 neplatí age\u003c6, platí age\u003c15 – vypíše sa „primary school“ a ostatné vetvy sa preskočia, hoci aj age\u003c19 by platilo. Preto v druhej vetve netreba písať age\u003e=6 AND age\u003c15: keby bol vek menší ako 6, program by sa sem nedostal.\nĎalšie tri IF sú samostatné. Každý sa vyhodnotí zvlášť, takže sa môžu vypísať aj všetky.\nage\u003e=13 AND age\u003c=19 je spôsob, ako zapísať „medzi 13 a 19“. Matematický zápis 13\u003c=age\u003c=19 Action! nepozná.\nČasté chyby Čo sa stalo Čo povie prekladač chýba THEN error ACT012: missing THEN chýba FI error ACT013: missing FI – často až na konci súboru == namiesto = (zvyk z jazyka C) error ACT012: missing THEN: expected THEN, got '==' reťaz porovnaní (1\u003ca\u003c3) error ACT023: illegal conditional expression Dve veci, ktoré prekladač nehlási:\nAND má prednosť pred OR. a=5 OR a=6 AND b=7 znamená a=5 OR (a=6 AND b=7). Keď miešaš AND a OR, daj zátvorky – aj tam, kde nie sú nutné, pomôžu čitateľovi. Podmienka bez porovnania. IF lives THEN platí, keď lives nie je nula. Je to dovolené a používa sa to, ale začiatočníkovi sa odporúča písať porovnanie celé: IF lives\u003e0 THEN. Vyskúšaj si Pridaj vetvu pre vek presne 18: „You have just come of age.“ Načítaj dve čísla a vypíš väčšie z nich. Čo vypíšeš, keď sú rovnaké? Načítaj číslo a vypíš, či je párne alebo nepárne. (Pomôže MOD z kapitoly 7.) Zhrnutie IF podmienka THEN … FI vykoná príkazy, len keď podmienka platí. ELSEIF pridá ďalšiu podmienku, ELSE vetvu „inak“. Z reťaze IF … ELSEIF … ELSE sa vykoná vždy najviac jedna vetva. Porovnania: =, # (alebo \u003c\u003e), \u003c, \u003e, \u003c=, \u003e=. AND – obe, OR – aspoň jedna. AND má prednosť. Späť: 8. Vstup · Ďalej: 10. Slučka\n","t":"9. Podmienka: IF, THEN, ELSEIF, ELSE, FI","u":"09-if/"},{"c":"Na čo to je Počítač vie robiť tú istú vec znova a znova bez únavy. Slučka (cyklus) je kus programu, ktorý sa opakuje.\nAko sa to píše Action! DO príkazy OD Slovo Význam DO začiatok slučky OD koniec slučky (DO odzadu); program skočí späť na DO EXIT vyskoč zo slučky hneď teraz; program pokračuje za OD Samotné DO … OD sa opakuje donekonečna. Aby slučka niekedy skončila, treba v nej EXIT – zvyčajne v podmienke.\nDO a OD sú základ všetkých slučiek v Action!. Slučky WHILE, UNTIL a FOR z ďalších kapitol sú to isté DO … OD s pridaným pravidlom, kedy skončiť.\nCelý program Súbor examples/do.act:\nAction! ; A loop: add numbers until the user enters 0 PROC Main() CARD sum, number sum=0 PrintE(\"Enter numbers, 0 ends.\") DO Print(\"? \") number=InputC() IF number=0 THEN EXIT FI sum==+number OD PutE() Print(\"The sum is \") PrintCE(sum) RETURN Preklad a spustenie action26 do.act --sim Čo uvidíš Po zadaní čísel 12, 30, 8 a 0:\nEnter numbers, 0 ends. ? 12 ? 30 ? 8 ? 0 The sum is 50 Ako to funguje sum=0 – súčet začína na nule. Bez tohto riadka by v premennej mohlo byť čokoľvek. Slučka vypíše otáznik a načíta číslo. Ak je číslo 0, EXIT slučku ukončí a program pokračuje za OD. Inak sa číslo pripočíta k súčtu (sum==+number) a OD vráti program na DO. Príkazy medzi DO a OD sa volajú telo slučky. Odsadzujú sa, aby bolo vidieť, čo sa opakuje.\nSlučka v slučke Keď je slučka vnútri inej slučky, EXIT ukončí len tú najbližšiu – tú, v ktorej priamo stojí. Vonkajšia beží ďalej.\nČasté chyby Čo sa stalo Čo povie prekladač alebo program chýba OD error ACT019: missing OD EXIT mimo slučky error ACT025: illegal EXIT (not inside DO-OD loop) v slučke nie je EXIT, alebo jeho podmienka nikdy nenastane program beží donekonečna Nekonečná slučka nie je chyba prekladu – niekedy ju chceš (hra beží, kým ju niekto nevypne). Keď sa ti to stane omylom:\nv simulátore sa program po chvíli zastaví sám a vypíše simulation stopped: instruction limit reached. Simulátor má poistku – po desiatich miliónoch inštrukcií skončí. Kým čaká na vstup z klávesnice, zastavíš ho klávesmi Ctrl+C; v emulátore zatvor okno alebo stlač kláves, ktorým emulátor resetuje Atari. Vyskúšaj si Uprav program, aby popri súčte počítal, koľko čísel si zadal, a vypíš aj počet. Uprav ho, aby skončil pri čísle 999 namiesto 0. Vypíš na konci aj priemer (súčet delený počtom). Čo treba ošetriť, keď používateľ zadá hneď nulu? Zhrnutie DO … OD opakuje príkazy medzi nimi. EXIT slučku ukončí; bez neho beží donekonečna. EXIT ukončí len najbližšiu slučku. Pred slučkou nastav premenné, ktoré v nej počítaš (súčet, počítadlo), na začiatočnú hodnotu. Späť: 9. Podmienka · Ďalej: 11. Slučka s podmienkou na začiatku\n","t":"10. Slučka: DO, OD, EXIT","u":"10-do/"},{"c":"Na čo to je Väčšina slučiek má jasné pravidlo, dokedy bežať: „kým je hodnota menšia ako tisíc“. WHILE ho zapíše priamo, bez IF a EXIT.\nAko sa to píše Action! WHILE podmienka DO príkazy OD WHILE znamená „kým“. Pred každým prechodom slučkou sa podmienka vyhodnotí:\nplatí → vykoná sa telo slučky a program sa vráti na WHILE, neplatí → slučka končí a program pokračuje za OD. Podmienka je taká istá ako pri IF (kapitola 9).\nJe to skratka za:\nAction! DO IF podmienka neplatí THEN EXIT FI príkazy OD Celý program Súbor examples/while.act:\nAction! ; WHILE: the condition is tested before each turn PROC Main() CARD value BYTE count value=1 count=0 WHILE value\u003c1000 DO PrintC(value) Put(' ) value==*2 count==+1 OD PutE() Print(\"Doubled \") PrintB(count) PrintE(\" times.\") count=10 WHILE count\u003e20 DO PrintE(\"This line is never written.\") OD PrintE(\"Done.\") RETURN Preklad a spustenie action26 while.act --sim Čo uvidíš 1 2 4 8 16 32 64 128 256 512 Doubled 10 times. Done. Ako to funguje Prvá slučka zdvojnásobuje value, kým je menšie ako 1000. Vypíše 1, 2, 4 … 512. Po poslednom zdvojnásobení je value 1024, podmienka value\u003c1000 prestane platiť a slučka skončí. Číslo 1024 sa už nevypíše – test je pred výpisom.\nDruhá slučka sa nevykoná ani raz. count je 10, podmienka count\u003e20 neplatí hneď na začiatku, a tak program telo preskočí. To je hlavná vlastnosť WHILE: telo sa nemusí vykonať vôbec.\nV tele slučky sa musí meniť niečo, od čoho podmienka závisí. Keby v prvej slučke chýbalo value==*2, podmienka by platila navždy.\nEXIT funguje aj vo WHILE – slučku ukončí predčasne.\nČasté chyby Čo sa stalo Čo sa stane v tele sa nemení premenná z podmienky nekonečná slučka chýba DO za podmienkou error ACT015: missing DO na prvom príkaze tela podmienka je opačne (\u003e namiesto \u003c) slučka sa nevykoná ani raz, alebo nikdy neskončí Pozor na pretečenie (kapitola 7): keby value bolo BYTE, po 128 by nasledovalo 0 (256 sa do bajtu nezmestí), 0*2 je stále 0 a value\u003c1000 platí vždy. Slučka by sa nikdy neskončila.\nVyskúšaj si Zmeň hranicu z 1000 na 50000. Koľkokrát sa hodnota zdvojnásobí? Napíš odpočítavanie: vypíš čísla od 10 po 1 a potom Start!. (Premenná začína na 10 a v tele sa zmenšuje o 1.) Načítaj číslo a vypíš, koľkokrát sa dá deliť dvoma, kým neklesne na 0. Zhrnutie WHILE podmienka DO … OD opakuje telo, kým podmienka platí. Podmienka sa skúša pred každým prechodom – telo sa nemusí vykonať ani raz. V tele musí byť niečo, čo podmienku časom zmení. Späť: 10. Slučka · Ďalej: 12. Slučka s podmienkou na konci\n","t":"11. Slučka s podmienkou na začiatku: WHILE","u":"11-while/"},{"c":"Na čo to je Niekedy treba telo slučky vykonať najprv a až potom zistiť, či ho opakovať. Typický prípad: opýtať sa, a ak odpoveď nevyhovuje, opýtať sa znova.\nAko sa to píše Action! DO príkazy UNTIL podmienka OD UNTIL znamená „až kým“. Stojí tesne pred OD. Po každom prechode telom sa podmienka vyhodnotí:\nplatí → slučka končí, neplatí → program sa vráti na DO. Dva rozdiely oproti WHILE:\nWHILE UNTIL kedy sa skúša podmienka pred telom za telom koľkokrát sa vykoná telo 0-krát alebo viac 1-krát alebo viac slučka beží, kým podmienka platí kým podmienka neplatí Je to skratka za:\nAction! DO príkazy IF podmienka THEN EXIT FI OD Celý program Súbor examples/until.act:\nAction! ; UNTIL: the condition is tested after each turn PROC Main() BYTE number DO Print(\"Enter a number from 1 to 10: \") number=InputB() UNTIL number\u003e=1 AND number\u003c=10 OD PutE() Print(\"Thank you, you entered \") PrintBE(number) RETURN Preklad a spustenie action26 until.act --sim Čo uvidíš Po zadaní 0, potom 25 a nakoniec 7:\nEnter a number from 1 to 10: 0 Enter a number from 1 to 10: 25 Enter a number from 1 to 10: 7 Thank you, you entered 7 Ako to funguje Program sa opýta, načíta číslo a až potom skúša, či je medzi 1 a 10. Ak nie, opýta sa znova. Za slučkou má program istotu, že number je v poriadku – inak by sa cez UNTIL nedostal.\nTu je UNTIL prirodzenejšie ako WHILE: pred prvou otázkou ešte žiadne číslo nie je, takže podmienku na začiatku nie je s čím vyhodnotiť.\nVšimni si podmienku: hovorí, kedy slučka skončí („až kým je číslo medzi 1 a 10“), nie kedy pokračuje.\nČasté chyby Čo sa stalo Čo sa stane UNTIL nie je posledný príkaz pred OD error ACT019: missing OD: expected OD, got … podmienka napísaná ako pri WHILE („kým pokračovať“) slučka skončí po prvom prechode, alebo nikdy chýba OD za UNTIL error ACT019: missing OD Na druhý riadok tabuľky pozor zvlášť. Ak prepisuješ WHILE na UNTIL, podmienku treba obrátiť: z \u003c sa stane \u003e=, z AND sa stane OR a naopak.\nVyskúšaj si Zmeň rozsah na 50 až 100. Pridaj za InputB() výpis Wrong, try again., ktorý sa objaví, len keď číslo nevyhovuje. (Treba IF v tele slučky.) Prepíš slučku pomocou WHILE. Čo musíš spraviť pred slučkou, aby fungovala? Zhrnutie DO … UNTIL podmienka OD opakuje telo, až kým podmienka začne platiť. Telo sa vykoná vždy aspoň raz. UNTIL stojí tesne pred OD. Podmienka hovorí, kedy skončiť – opačne ako pri WHILE. Späť: 11. Slučka s podmienkou na začiatku · Ďalej: 13. Slučka s počítadlom\n","t":"12. Slučka s podmienkou na konci: UNTIL","u":"12-until/"},{"c":"Na čo to je Najčastejšia slučka zo všetkých: „sprav toto desaťkrát“ alebo „prejdi čísla od 1 do 100“. FOR sa o počítanie postará sám.\nAko sa to píše Action! FOR premenná=začiatok TO koniec DO príkazy OD alebo s krokom:\nAction! FOR premenná=začiatok TO koniec STEP krok DO príkazy OD Slovo Význam FOR začína slučku s počítadlom premenná počítadlo – obyčajná premenná, ktorú si deklaroval začiatok hodnota, ktorú počítadlo dostane pred prvým prechodom TO koniec posledná hodnota, pri ktorej sa telo ešte vykoná STEP krok o koľko sa počítadlo po každom prechode zväčší; bez STEP o 1 Je to skratka za:\nAction! premenná=začiatok WHILE premenná\u003c=koniec DO príkazy premenná==+krok OD Celý program Súbor examples/for.act:\nAction! ; FOR: a loop with a counter PROC Main() BYTE i, row, col FOR i=1 TO 10 DO PrintB(i) Put(' ) OD PutE() FOR i=0 TO 20 STEP 5 DO PrintB(i) Put(' ) OD PutE() PutE() PrintE(\"The 7 times table:\") FOR row=1 TO 10 DO PrintB(row) Print(\" x 7 = \") PrintBE(row*7) OD PutE() FOR row=1 TO 4 DO FOR col=1 TO row DO Put('*) OD PutE() OD RETURN Preklad a spustenie action26 for.act --sim Čo uvidíš 1 2 3 4 5 6 7 8 9 10 0 5 10 15 20 The 7 times table: 1 x 7 = 7 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35 6 x 7 = 42 7 x 7 = 49 8 x 7 = 56 9 x 7 = 63 10 x 7 = 70 * ** *** **** Ako to funguje Prvá slučka: i ide od 1 do 10 vrátane. Počítadlo sa dá v tele normálne používať – tu sa vypisuje. Druhá slučka: STEP 5 zväčšuje i po piatich: 0, 5, 10, 15, 20. Násobilka: počítadlo row vstupuje do výpočtu row*7. Trojuholník: slučka v slučke. Vonkajšia ide po riadkoch, vnútorná vypíše toľko hviezdičiek, aké je číslo riadka. Vnútorná slučka má ako koniec premennú row – koniec nemusí byť číslo. Začiatočníci často volajú počítadlá i, j, k. Je to zvyk z matematiky; meno ako row alebo col však hovorí viac.\nTri vlastnosti, ktoré treba poznať 1. Koniec a krok sa vyhodnotia raz, pri vstupe do slučky. Keď v tele zmeníš premennú, ktorá bola koncom, počet prechodov sa už nezmení.\n2. FOR nepočíta nadol. FOR i=10 TO 1 sa nevykoná ani raz, lebo 10 je už na začiatku väčšie ako koniec. Nepomôže ani STEP -1. Na odpočítavanie použi WHILE:\nAction! i=10 WHILE i\u003e0 DO PrintBE(i) i==-1 OD 3. BYTE počítadlo a koniec 255 je nekonečná slučka.\nAction! BYTE i FOR i=0 TO 255 ; never ends DO OD Slučka končí, keď je počítadlo väčšie ako koniec. BYTE však väčší ako 255 byť nemôže – po 255 sa pretočí na 0 a ide sa odznova. Ak potrebuješ prejsť všetkých 256 hodnôt, použi počítadlo typu CARD.\nČasté chyby Čo sa stalo Čo sa stane počítadlo nie je deklarované error ACT008: undeclared name chýba DO error ACT015: missing DO na prvom príkaze tela začiatok je väčší ako koniec telo sa nevykoná ani raz BYTE počítadlo, koniec 255 nekonečná slučka v tele meníš počítadlo slučka preskakuje hodnoty – radšej to nerob Po skončení slučky má počítadlo hodnotu o krok väčšiu ako koniec: po FOR i=1 TO 3 je v i číslo 4.\nVyskúšaj si Vypíš párne čísla od 2 do 20. Vypíš malú násobilku celú: desať riadkov a v každom desať čísel. (Slučka v slučke; výsledok môže byť až 100, to sa do BYTE zmestí.) Sčítaj čísla od 1 do 100 a vypíš súčet. Akého typu musí byť premenná na súčet? Zhrnutie FOR i=a TO b DO … OD vykoná telo pre i od a po b vrátane. STEP n mení krok; bez neho je 1. Koniec a krok sa vyhodnotia raz na začiatku. FOR počíta len nahor. BYTE počítadlo nikdy neprekročí 255 – slučka TO 255 neskončí. Späť: 12. Slučka s podmienkou na konci · Ďalej: 14. Parametre\n","t":"13. Slučka s počítadlom: FOR, TO, STEP","u":"13-for/"},{"c":"Na čo to je Procedúra Line z kapitoly 3 vedela nakresliť čiaru len jednej dĺžky. S parametrom jej pri každom volaní povieš, akú dlhú. Jedna procedúra tak zvládne veľa podobných úloh.\nAko sa to píše Deklarácia:\nAction! PROC Meno(TYP parameter, parameter, TYP parameter) Volanie:\nAction! Meno(hodnota, hodnota, hodnota) Parametre sa deklarujú v zátvorkách rovnako ako premenné: typ a meno. Viac parametrov toho istého typu stačí oddeliť čiarkou – BYTE width, height. Pri volaní dáš do zátvoriek argumenty: čísla, premenné alebo celé výrazy. Prvý argument ide do prvého parametra, druhý do druhého a tak ďalej. Vnútri procedúry sa parameter používa ako obyčajná premenná. Procedúra môže mať najviac 8 parametrov. Celý program Súbor examples/params.act:\nAction! ; Procedures with parameters PROC Stars(BYTE count) BYTE i FOR i=1 TO count DO Put('*) OD PutE() RETURN PROC Box(BYTE width, height, CHAR c) BYTE x, y FOR y=1 TO height DO FOR x=1 TO width DO Put(c) OD PutE() OD RETURN PROC Change(BYTE value) value=99 ; changes only the copy RETURN PROC Main() BYTE n Stars(5) Stars(12) n=3 Stars(n*2) PutE() Box(8, 3, '#) PutE() Change(n) Print(\"n is still \") PrintBE(n) RETURN Preklad a spustenie action26 params.act --sim Čo uvidíš ***** ************ ****** ######## ######## ######## n is still 3 Ako to funguje Stars(5) zavolá procedúru a do parametra count uloží 5. Slučka potom vypíše päť hviezdičiek. Stars(n*2) ukazuje, že argument môže byť výraz. Najprv sa vypočíta (3 × 2 = 6) a výsledok sa odovzdá. Box(8, 3, '#) má tri argumenty pre tri parametre: šírku, výšku a znak. Premenná i v Stars a x, y v Box sú deklarované vnútri procedúry. Patria len jej – viac v kapitole 16. Procedúra dostane kópiu Change(n) odovzdá procedúre hodnotu premennej n, nie premennú samotnú. Parameter value je vlastná premenná procedúry, do ktorej sa trojka skopíruje. Keď ju procedúra prepíše na 99, n v Main sa nezmení.\nAk má procedúra zmeniť premennú volajúceho, treba jej odovzdať adresu premennej – to je téma kapitoly 20. Častejšie stačí, aby rutina výsledok vrátila; to vie funkcia z nasledujúcej kapitoly.\nČasté chyby Čo sa stalo Čo povie prekladač alebo program viac argumentov ako parametrov error ACT007: invalid argument list: 'Stars' takes 1 argument(s), got 2 menej argumentov ako parametrov prekladač mlčí; chýbajúce parametre dostanú 0 argument sa do typu parametra nezmestí (Stars(300)) warning ACT215; odovzdá sa 44 argumenty v zlom poradí prekladač mlčí – všetky sú čísla Menej argumentov Action! dovoľuje a niektoré staršie programy to využívajú. Ak chceš, aby ťa prekladač na to upozornil, pridaj voľbu --wextra:\naction26 params.act --wextra Potom pri Stars() vypíše warning ACT213: 'Stars' takes 1 argument(s), got 0.\nVyskúšaj si Pridaj procedúre Stars druhý parameter – znak, ktorý sa má vypisovať. Napíš procedúru Triangle(BYTE size), ktorá vypíše trojuholník z hviezdičiek s daným počtom riadkov. Môže volať Stars. Zavolaj Box(3, 8, 'O) a potom Box('O, 3, 8). Prečo druhé volanie vypíše niečo celkom iné? Zhrnutie Parametre sa deklarujú v zátvorkách za menom procedúry, s typom. Pri volaní sa argumenty priraďujú parametrom podľa poradia. Argument môže byť číslo, premenná aj výraz. Procedúra pracuje s kópiou – premennú volajúceho nezmení. Počet argumentov prekladač kontroluje len nahor; --wextra upozorní aj na chýbajúce. Späť: 13. Slučka s počítadlom · Ďalej: 15. Funkcie\n","t":"14. Parametre: procedúra, ktorá dostane údaje","u":"14-parametre/"},{"c":"Na čo to je Procedúra niečo spraví. Funkcia niečo vypočíta a vráti – jej volanie sa dá napísať všade, kde môže stáť číslo. Poznáš ich už z knižnice: InputB() je funkcia.\nAko sa to píše Action! TYP FUNC Meno(parametre) príkazy RETURN(výsledok) Časť Význam TYP typ hodnoty, ktorú funkcia vracia: BYTE, CHAR, CARD alebo INT FUNC namiesto PROC RETURN(výsledok) skončí funkciu a vráti hodnotu v zátvorkách Zátvorky za RETURN sú vo funkcii povinné. RETURN môže byť vo funkcii aj viackrát – vykoná sa ten, ku ktorému program dôjde prvý.\nVolanie funkcie sa píše do výrazu:\nAction! x=Max(a, b) PrintBE(Max(7, 12)) IF IsEven(n)=1 THEN … FI Celý program Súbor examples/func.act:\nAction! ; Functions: routines that give back a value BYTE FUNC Max(BYTE a, b) IF a\u003eb THEN RETURN(a) FI RETURN(b) CARD FUNC Square(CARD n) RETURN(n*n) BYTE FUNC IsEven(CARD n) IF n MOD 2=0 THEN RETURN(1) FI RETURN(0) PROC Main() CARD i, sum Print(\"The bigger of 7 and 12: \") PrintBE(Max(7, 12)) Print(\"12 squared: \") PrintCE(Square(12)) sum=0 FOR i=1 TO 10 DO sum==+Square(i) OD Print(\"Squares of 1 to 10 added: \") PrintCE(sum) FOR i=1 TO 4 DO PrintC(i) IF IsEven(i)=1 THEN PrintE(\" is even\") ELSE PrintE(\" is odd\") FI OD RETURN Preklad a spustenie action26 func.act --sim Čo uvidíš The bigger of 7 and 12: 12 12 squared: 144 Squares of 1 to 10 added: 385 1 is odd 2 is even 3 is odd 4 is even Ako to funguje Max má dva RETURN. Ak je a väčšie, funkcia skončí hneď prvým a vráti a. Inak program dôjde až na koniec a vráti b. Square je celá na jednom riadku: vypočíta n*n a vráti to. IsEven vracia 1 alebo 0 ako „áno“ a „nie“. Action! nemá zvláštny typ pre pravdu a nepravdu, používa sa číslo: 0 je nie, čokoľvek iné áno. PrintBE(Max(7, 12)) – najprv sa zavolá Max, jej výsledok (12) sa stane argumentom PrintBE. sum==+Square(i) – volanie funkcie vo výraze, v slučke desaťkrát. Funkcia má tú výhodu, že volajúci nemusí vedieť, ako výsledok vznikol. Keď raz Max funguje, používaš ju ako hotovú súčiastku.\nProcedúra alebo funkcia? Ak rutina Použi niečo vypíše, nakreslí, zahrá PROC vypočíta jednu hodnotu FUNC má vrátiť viac hodnôt PROC s ukazovateľmi (kapitola 20) alebo globálne premenné (kapitola 16) Spoločné slovo pre procedúry a funkcie je rutina.\nČasté chyby Čo sa stalo Čo povie prekladač RETURN a bez zátvoriek error ACT028: illegal RETURN: expected '(' with the function result funkcia končí holým RETURN to isté hlásenie RETURN(5) v procedúre error ACT028: illegal RETURN: a PROC cannot return a value chýba typ pred FUNC error ACT006: FUNC needs a result type (BYTE, CHAR, CARD or INT) Funkciu možno zavolať aj ako procedúru (Max(1, 2) na vlastnom riadku). Výsledok sa vtedy zahodí. Pri Max to nemá zmysel; pri funkcii, ktorá okrem výsledku aj niečo robí, niekedy áno.\nTyp funkcie rozhoduje o tom, čo sa vráti. BYTE FUNC, ktorá vráti 300, vráti 44.\nVyskúšaj si Napíš BYTE FUNC Min(BYTE a, b) a vypíš menšie z dvoch čísel. Napíš CARD FUNC Power(CARD base, BYTE exponent), ktorá vypočíta mocninu opakovaným násobením v slučke. Použi Max na nájdenie najväčšieho z troch čísel: Max(Max(a, b), c). Zhrnutie TYP FUNC Meno(…) je rutina, ktorá vracia hodnotu. RETURN(hodnota) – so zátvorkami – funkciu ukončí a hodnotu vráti. Volanie funkcie môže stáť vo výraze, v podmienke aj ako argument inej rutiny. „Áno“ a „nie“ sa vracia ako 1 a 0. Späť: 14. Parametre · Ďalej: 16. Kde premenná platí\n","t":"15. Funkcie: FUNC a RETURN(hodnota)","u":"15-func/"},{"c":"Na čo to je Doteraz si premenné deklaroval vnútri procedúry. Taká premenná patrí len tej procedúre. Keď má hodnotu vidieť viac rutín – skóre, počet životov – deklaruje sa mimo rutín.\nAko sa to píše Action! BYTE score ; globálna: pred prvou rutinou PROC Something() BYTE helper ; lokálna: na začiatku rutiny … RETURN MODULE ; dovolí ďalšie globálne deklarácie za rutinou BYTE lives PROC Main() … RETURN Druh Kde sa deklaruje Kto ju vidí globálna na začiatku súboru pred prvou rutinou, alebo za slovom MODULE všetky rutiny, ktoré sú v súbore pod ňou lokálna na začiatku rutiny (aj parametre sú lokálne) len tá rutina MODULE je potrebné, keď chceš deklarovať globálne premenné až za nejakou rutinou. Bez neho by prekladač ohlásil, že deklarácie musia byť pred príkazmi.\nCelý program Súbor examples/scope.act:\nAction! ; Where a variable lives BYTE score=[0] ; global: every routine below sees it PROC AddPoints(BYTE points) BYTE bonus ; local: only AddPoints sees it bonus=points/10 score==+points+bonus RETURN PROC Counter() BYTE calls=[0] ; a local keeps its value between calls calls==+1 Print(\"Counter was called \") PrintB(calls) PrintE(\" times\") RETURN PROC Hide() BYTE score ; a local with the name of a global hides it score=200 Print(\"Inside Hide: \") PrintBE(score) RETURN MODULE ; global declarations after a routine need MODULE BYTE lives=[3] PROC Main() AddPoints(20) AddPoints(50) Print(\"Score: \") PrintBE(score) Counter() Counter() Counter() Hide() Print(\"Score after Hide: \") PrintBE(score) Print(\"Lives: \") PrintBE(lives) RETURN Preklad a spustenie action26 scope.act --sim Čo uvidíš Score: 77 Counter was called 1 times Counter was called 2 times Counter was called 3 times Inside Hide: 200 Score after Hide: 77 Lives: 3 Ako to funguje score je globálna. AddPoints ju mení, Main ju vypisuje – obe pracujú s tou istou premennou. Po dvoch volaniach je v nej 20 + 2 + 50 + 5 = 77. bonus je lokálna. Mimo AddPoints neexistuje; keby si ju použil v Main, prekladač ohlási neznáme meno. calls v Counter si pamätá hodnotu medzi volaniami. To je zvláštnosť Action!, o ktorej je ďalšia časť. score v Hide je iná premenná. Lokálna premenná s rovnakým menom globálnu zakryje: vnútri Hide znamená score tú lokálnu. Globálna ostane nedotknutá – po návrate je v nej stále 77. lives je deklarovaná za MODULE a vidí ju len Main, lebo len tá je pod ňou. Lokálne premenné nezanikajú V mnohých jazykoch lokálna premenná vznikne pri volaní rutiny a po návrate zmizne. V Action! má každá lokálna premenná svoje pevné miesto v pamäti po celý čas behu programu. Z toho plynú tri veci:\nHodnota prežije medzi volaniami. Counter to využíva: calls sa pri každom volaní zväčší a pamätá si to. Počiatočná hodnota =[0] sa nastaví len raz – pri nahraní programu, nie pri každom volaní. Ak má premenná začínať pri každom volaní od nuly, priraď jej nulu príkazom (calls=0). Rutina nesmie volať samu seba. Volanie rutiny zo seba samej (rekurzia) v Action! prepíše jej vlastné parametre a lokálne premenné, lebo existujú len raz. Program sa preloží, ale počíta zle. Namiesto rekurzie použi slučku. Globálna alebo lokálna? Lokálna, kedykoľvek sa dá. Počítadlo slučky, medzivýsledok – nikto iný ich nepotrebuje a nik iný ich omylom neprepíše. Globálna pre stav celého programu: skóre, životy, poloha hráča. Časté chyby Čo sa stalo Čo povie prekladač lokálna premenná použitá v inej rutine error ACT008: undeclared name globálna deklarácia za rutinou bez MODULE error ACT006: declaration error: declarations must come before the statements dve premenné s rovnakým menom v tej istej rutine error ACT006: 'x' is already declared lokálna premenná, ktorú nikde nepoužiješ warning ACT212: local variable 'x' is never used Zakrytie globálnej premennej lokálnou prekladač nehlási – je to dovolené. Keď sa ti „nemení“ globálna premenná, pozri, či si v rutine omylom nedeklaroval lokálnu s rovnakým menom.\nVyskúšaj si Použi bonus v Main a prečítaj si hlásenie prekladača. Zmaž riadok MODULE a prelož. Čo sa stane? Presuň deklaráciu lives na začiatok súboru k score. Potrebuješ ešte MODULE? Zhrnutie Globálna premenná je deklarovaná mimo rutín a vidia ju všetky rutiny pod ňou. Lokálna premenná a parameter patria jednej rutine. MODULE dovolí globálne deklarácie medzi rutinami. Lokálna premenná zakryje globálnu s rovnakým menom. Lokálne premenné v Action! nezanikajú: pamätajú si hodnotu a rekurzia nefunguje. Späť: 15. Funkcie · Ďalej: 17. Mená pre čísla\n","t":"16. Kde premenná platí: lokálne, globálne, MODULE","u":"16-rozsah/"},{"c":"Na čo to je Číslo 20 v programe nič nehovorí. WIDTH hovorí, že ide o šírku. DEFINE dá menu text, ktorým ho prekladač pri preklade nahradí. Keď sa šírka zmení, opravíš ju na jednom mieste.\nAko sa to píše Action! DEFINE MENO=\"text\" DEFINE MENO1=\"text\", MENO2=\"text\" Text je vždy v úvodzovkách, aj keď je to číslo: DEFINE WIDTH=\"20\". Viac mien naraz sa oddeľuje čiarkou. Deklarácia môže pokračovať na ďalšom riadku. Všade, kde prekladač v programe nájde MENO, dosadí namiesto neho text – ako keby si ho tam napísal sám. Mená z DEFINE sa zvyčajne píšu veľkými písmenami, aby sa odlíšili od premenných. DEFINE nie je premenná. Nezaberá pamäť, nedá sa do neho nič priradiť a za behu programu neexistuje. Je to pokyn pre prekladač: „toto slovo čítaj ako tento text“.\nCelý program Súbor examples/define.act:\nAction! ; DEFINE: names for numbers and pieces of the program DEFINE WIDTH=\"20\", HEIGHT=\"4\", FRAME=\"'#\", STRING=\"CHAR ARRAY\" PROC Main() BYTE x, y STRING title=\"A box of WIDTH by HEIGHT\" PrintE(title) FOR y=1 TO HEIGHT DO FOR x=1 TO WIDTH DO IF y=1 OR y=HEIGHT OR x=1 OR x=WIDTH THEN Put(FRAME) ELSE Put(' ) FI OD PutE() OD Print(\"Characters in the box: \") PrintBE(WIDTH*HEIGHT) RETURN Preklad a spustenie action26 define.act --sim Čo uvidíš A box of WIDTH by HEIGHT #################### # # # # #################### Characters in the box: 80 Ako to funguje WIDTH a HEIGHT sú čísla. FOR x=1 TO WIDTH prekladač číta ako FOR x=1 TO 20. FRAME je znak: Put(FRAME) je Put('#). STRING nahrádza dve slová naraz. STRING title=… je CHAR ARRAY title=…. Tento DEFINE je medzi programátormi v Action! bežný zvyk – nájdeš ho v mnohých starých programoch. V reťazcoch sa nenahrádza. Text \"A box of WIDTH by HEIGHT\" sa vypíše tak, ako je. Úvodzovky chránia svoj obsah. Podmienka y=1 OR y=HEIGHT OR x=1 OR x=WIDTH platí pre prvý a posledný riadok a prvý a posledný stĺpec – teda pre okraj. Skús zmeniť WIDTH na 30 a HEIGHT na 6: rám, slučky aj výpočet počtu znakov sa prispôsobia samy.\nPasca: DEFINE je text, nie hodnota Action! DEFINE SIZE=\"5+5\" … PrintBE(SIZE*2) Vyzerá to ako 10 × 2 = 20, ale vypíše sa 15. Prekladač dosadí text a číta 5+5*2 – a násobenie má prednosť. Keď je v DEFINE výpočet, daj ho do zátvoriek: DEFINE SIZE=\"(5+5)\".\nČasté chyby Čo sa stalo Čo povie prekladač číslo bez úvodzoviek (DEFINE N=10) error ACT006: DEFINE expects a string constant with the replacement text priradenie do mena z DEFINE (WIDTH=5) chyba – prekladač vidí 20=5 DEFINE s menom, ktoré už má premenná zrážka mien; veľké a malé písmená sa nerozlišujú, DEFINE HEAD a premenná head je to isté meno Kde DEFINE platí DEFINE na začiatku súboru platí do konca súboru. DEFINE napísaný vnútri rutiny platí len do konca tej rutiny.\nVyskúšaj si Zmeň rozmery škatule a znak rámu. Pridaj DEFINE INSIDE=\"'.\" a vyplň ním vnútro škatule namiesto medzery. Vyskúšaj pascu so SIZE – so zátvorkami aj bez nich. Zhrnutie DEFINE MENO=\"text\" – prekladač všade nahradí meno textom. Text je vždy v úvodzovkách. Nezaberá pamäť a nedá sa meniť za behu. V reťazcoch sa nenahrádza. Výpočet v DEFINE patrí do zátvoriek. Späť: 16. Kde premenná platí · Ďalej: 18. Polia\n","t":"17. Mená pre čísla: DEFINE","u":"17-define/"},{"c":"Na čo to je Dvanásť mesiacov, sto nepriateľov, tisíc bodov obrazovky – na to nechceš dvanásť, sto ani tisíc premenných. Pole je rad hodnôt rovnakého typu pod jedným menom. Jednotlivé hodnoty (prvky) sa rozlišujú číslom – indexom.\nAko sa to píše Deklarácia:\nAction! BYTE ARRAY scores(10) ; 10 prvkov typu BYTE CARD ARRAY squares(10) ; 10 prvkov typu CARD INT ARRAY heights(50) ; 50 prvkov typu INT BYTE ARRAY days=[31 28 31 30] ; pole s hodnotami; veľkosť sa spočíta sama Použitie prvku:\nAction! scores(0)=100 ; zápis do prvého prvku x=scores(3) ; čítanie štvrtého prvku scores(i)=scores(i)+1 Číslo v zátvorke pri deklarácii je počet prvkov. Indexy idú od 0. Pole s 10 prvkami má prvky (0) až (9). Prvok (10) neexistuje. Index môže byť číslo, premenná aj výraz. Počiatočné hodnoty sa píšu do hranatých zátvoriek a oddeľujú sa medzerami (čiarky medzi nimi prekladač tiež prijme). Celý program Súbor examples/arrays.act:\nAction! ; Arrays: many values under one name PROC Main() BYTE ARRAY days=[31 28 31 30 31 30 31 31 30 31 30 31] CARD ARRAY squares(10) ; 10 elements: squares(0) to squares(9) BYTE i, biggest CARD total FOR i=0 TO 9 ; fill the array in a loop DO squares(i)=i*i OD Print(\"Squares: \") FOR i=0 TO 9 DO PrintC(squares(i)) Put(' ) OD PutE() Print(\"Days in March: \") PrintBE(days(2)) ; January is days(0) total=0 FOR i=0 TO 11 DO total==+days(i) OD Print(\"Days in a year: \") PrintCE(total) days(1)=29 ; an element can be changed Print(\"February in a leap year: \") PrintBE(days(1)) biggest=0 FOR i=0 TO 11 DO IF days(i)\u003ebiggest THEN biggest=days(i) FI OD Print(\"The longest month has \") PrintB(biggest) PrintE(\" days\") RETURN Preklad a spustenie action26 arrays.act --sim Čo uvidíš Squares: 0 1 4 9 16 25 36 49 64 81 Days in March: 31 Days in a year: 365 February in a leap year: 29 The longest month has 31 days Ako to funguje Pole a slučka FOR patria k sebe: počítadlo slučky je index.\nNaplnenie: squares(i)=i*i pre i od 0 do 9. Výpis: tá istá slučka, len sa prvok číta. Súčet: pred slučkou total=0, v slučke total==+days(i). Hľadanie najväčšieho: biggest začne na 0 a každý prvok, ktorý je väčší, ho nahradí. days(2) je marec, nie február – január má index 0. Posun o jednotku je najčastejší zdroj chýb pri poliach.\nPole ako parameter Rutina môže dostať pole. V parametri sa píše bez veľkosti:\nAction! PROC Fill(BYTE ARRAY a, BYTE count) BYTE i FOR i=0 TO count-1 DO a(i)=i*2 OD RETURN Volanie: Fill(scores, 10). Na rozdiel od obyčajnej premennej (kapitola 14) sa pole nekopíruje – rutina pracuje priamo s poľom volajúceho a zmeny v ňom ostanú. Veľkosť poľa rutina nepozná, preto sa odovzdáva zvlášť.\nNajväčšie nebezpečenstvo: index mimo poľa Action! nekontroluje, či je index v rozsahu poľa. Zápis za koniec poľa prepíše to, čo leží v pamäti za ním – zvyčajne iné premenné:\nAction! BYTE ARRAY a(3) BYTE x x=7 a(3)=9 ; a má len prvky 0, 1, 2 PrintBE(x) ; vypíše 9 Prekladač nič nehlási, program beží a chyba sa prejaví inde a neskôr. Keď sa premenná „sama“ mení, hľadaj pole pred ňou a slučku, ktorá ide o jeden prvok ďalej (TO 10 namiesto TO 9).\nČasté chyby Čo sa stalo Čo sa stane index mimo poľa prepíše sa cudzia pamäť; bez hlásenia slučka FOR i=1 TO 10 nad poľom s 10 prvkami prvok (0) sa vynechá a (10) je mimo poľa priradenie do celého poľa (a=5) error ACT010: illegal assignment: cannot assign to BYTE ARRAY 'a' pole bez hodnôt a bez veľkosti (BYTE ARRAY a) nie je to pole s pamäťou, len ukazovateľ – kapitola 20 Prvky poľa bez počiatočných hodnôt nemusia byť nulové. Pred použitím ich naplň.\nVyskúšaj si Vypíš mesiace, ktoré majú 30 dní – ich čísla od 1 do 12, nie indexy. Načítaj päť čísel do poľa a vypíš ich v opačnom poradí. (Odpočítavať treba cez WHILE, kapitola 13.) Vypočítaj priemer prvkov poľa squares. Zhrnutie TYP ARRAY meno(počet) deklaruje pole; prvky sú meno(0) až meno(počet−1). TYP ARRAY meno=[h1 h2 h3] deklaruje pole s hodnotami. Pole sa spracúva slučkou FOR. Pole ako parameter sa nekopíruje. Index mimo poľa sa nekontroluje a prepíše inú pamäť. Späť: 17. Mená pre čísla · Ďalej: 19. Reťazce\n","t":"18. Polia: ARRAY","u":"18-polia/"},{"c":"Na čo to je Reťazec je text uložený v programe: meno hráča, hlásenie, riadok zo súboru. V Action! je to obyčajné pole znakov s jedným pravidlom navyše.\nAko sa to píše Action! CHAR ARRAY name=\"Atari\" ; reťazec s textom CHAR ARRAY buffer(40) ; prázdne miesto pre reťazec: dĺžka + 39 znakov Pravidlo: prvok (0) je dĺžka textu, znaky sú v prvkoch (1), (2) …\nPrvok name(0) name(1) name(2) name(3) name(4) name(5) Obsah 5 A t a r i Z toho plynie, že reťazec môže mať najviac 255 znakov (viac sa do jedného bajtu dĺžky nezmestí) a že pole pre text s n znakmi potrebuje n+1 bajtov.\nKnižnica má na reťazce štyri rutiny:\nRutina Čo robí SCopy(kam, odkiaľ) skopíruje celý reťazec SCopyS(kam, odkiaľ, od, do) skopíruje časť: znaky s číslami od až do SAssign(kam, odkiaľ, od, do) vloží reťazec do iného na pozície od až do SCompare(a, b) porovná dva reťazce; vráti záporné číslo, nulu alebo kladné číslo Celý program Súbor examples/strings.act:\nAction! ; Strings: texts in CHAR ARRAYs PROC Order(CHAR ARRAY a, b) ; a string as a parameter INT result result=SCompare(a, b) Print(a) IF result\u003c0 THEN Print(\" comes before \") ELSEIF result=0 THEN Print(\" is the same as \") ELSE Print(\" comes after \") FI PrintE(b) RETURN PROC Main() CHAR ARRAY name=\"Atari\" ; a string with its text CHAR ARRAY copy(20), part(20), line(40) BYTE i Print(\"The text: \") PrintE(name) Print(\"Its length: \") PrintBE(name(0)) Print(\"First letter: \") Put(name(1)) PutE() Print(\"Spelled: \") FOR i=1 TO name(0) DO Put(name(i)) Put(' ) OD PutE() SCopy(copy, name) ; copy the whole string copy(1)='S ; change one character Print(\"Changed copy: \") PrintE(copy) Print(\"The original: \") PrintE(name) SCopyS(part, \"Action! language\", 1, 7) Print(\"A part: \") PrintE(part) SCopy(line, \"Hello, \") ; join two strings SAssign(line, name, line(0)+1, line(0)+name(0)) Print(\"Joined: \") PrintE(line) Order(\"apple\", \"banana\") Order(\"pear\", \"pear\") Order(\"zebra\", \"ant\") RETURN Preklad a spustenie action26 strings.act --sim Čo uvidíš The text: Atari Its length: 5 First letter: A Spelled: A t a r i Changed copy: Stari The original: Atari A part: Action! Joined: Hello, Atari apple comes before banana pear is the same as pear zebra comes after ant Ako to funguje name(0) je dĺžka, name(1) prvý znak. Slučka FOR i=1 TO name(0) prejde všetky znaky – to je bežný spôsob, ako spracovať text znak po znaku. SCopy(copy, name) – cieľ je prvý, zdroj druhý. Tak je to pri všetkých rutinách na reťazce. copy(1)='S mení jeden znak ako prvok poľa. Originál name ostáva nedotknutý, lebo copy je vlastné pole. SCopyS(part, \"Action! language\", 1, 7) vyberie znaky 1 až 7. Zdrojom môže byť aj text priamo v úvodzovkách. Spojenie dvoch reťazcov Action! nemá ako jednu rutinu. Skladá sa zo SCopy (prvá časť) a SAssign (druhá časť za koniec prvej). line(0)+1 je prvá voľná pozícia; SAssign reťazec podľa potreby predĺži. SCompare porovnáva podľa abecedy – presnejšie podľa kódov znakov. Na presnej hodnote výsledku nezáleží, len na tom, či je záporný, nulový alebo kladný. Procedúra Order ukazuje reťazec ako parameter: CHAR ARRAY a bez veľkosti. Ako každé pole sa nekopíruje.\nČasté chyby Čo sa stalo Čo sa stane porovnanie cez = (IF a=b THEN) prekladač mlčí; porovnajú sa adresy polí, nie texty – dva rôzne reťazce s rovnakým textom „nie sú rovnaké“ priradenie textu do poľa s veľkosťou (buffer=\"hello\") error ACT010: illegal assignment: cannot assign to CHAR ARRAY – použi SCopy cieľ je menší ako kopírovaný text prepíše sa pamäť za poľom, bez hlásenia zámena poradia v SCopy skopíruje sa opačným smerom veľké a malé písmená pri SCompare \"Apple\" a \"apple\" sú rôzne; veľké písmená majú menšie kódy, takže \"Zebra\" je pred \"ant\" Na porovnanie textov teda vždy SCompare(a, b)=0, nikdy a=b.\nDEFINE STRING=\"CHAR ARRAY\" z kapitoly 17 robí deklarácie reťazcov čitateľnejšími: STRING name(40).\nVyskúšaj si Načítaj meno cez InputS a vypíš ho odzadu. Spočítaj, koľkokrát je v načítanom texte písmeno a. Načítaj dve slová a vypíš ich v abecednom poradí. Zhrnutie Reťazec je CHAR ARRAY; prvok 0 je dĺžka, znaky sú od prvku 1. Pole pre n znakov musí mať aspoň n+1 bajtov. SCopy kopíruje, SCopyS vyberá časť, SAssign vkladá, SCompare porovnáva. Cieľ je vždy prvý parameter. Reťazce sa neporovnávajú znakom = a nepriraďujú znakom =. Späť: 18. Polia · Ďalej: 20. Ukazovatele\n","t":"19. Reťazce: CHAR ARRAY","u":"19-retazce/"},{"c":"Na čo to je Každá premenná leží niekde v pamäti – na svojej adrese. Adresa je číslo od 0 do 65535, ako číslo domu na dlhej ulici. Ukazovateľ je premenná, v ktorej je adresa inej premennej. Cez ukazovateľ sa dá k tej premennej dostať, aj keď nepoznáš jej meno.\nHodí sa to v dvoch prípadoch: keď má rutina zmeniť premennú volajúceho, a keď sa prechádza pamäťou bajt po bajte.\nAko sa to píše Action! BYTE POINTER p ; ukazovateľ na BYTE CARD POINTER q ; ukazovateľ na CARD Zápis Číta sa Význam @x „adresa x“ adresa premennej x p=@x do p ulož adresu x – p teraz ukazuje na x p^ „to, na čo ukazuje p“ hodnota na adrese uloženej v p p^=5 ulož 5 tam, kam p ukazuje Typ pred slovom POINTER hovorí, čo na danej adrese leží: BYTE POINTER číta a zapisuje jeden bajt, CARD POINTER dva.\nCelý program Súbor examples/pointers.act:\nAction! ; Pointers: variables that hold an address PROC Swap(BYTE POINTER a, b) BYTE keep keep=a^ a^=b^ b^=keep RETURN PROC Main() BYTE x, y, i BYTE POINTER p BYTE ARRAY data=[5 8 13 21] x=10 y=20 p=@x ; p holds the address of x Print(\"p points at x: \") PrintBE(p^) p^=15 ; store through the pointer Print(\"x is now \") PrintBE(x) p=@y ; the same pointer, another variable Print(\"p points at y: \") PrintBE(p^) Swap(@x, @y) ; the routine changes our variables Print(\"After Swap: x=\") PrintB(x) Print(\" y=\") PrintBE(y) p=data ; the name of an array is its address Print(\"The array: \") FOR i=1 TO 4 DO PrintB(p^) Put(' ) p==+1 ; move to the next byte OD PutE() RETURN Preklad a spustenie action26 pointers.act --sim Čo uvidíš p points at x: 10 x is now 15 p points at y: 20 After Swap: x=20 y=15 The array: 5 8 13 21 Ako to funguje p=@x – v p je adresa premennej x. p^ je potom to isté ako x. p^=15 zapíše 15 na tú adresu. Keď potom vypíšeš x, je v ňom 15, hoci si do x priamo nič nepriradil. p=@y – ten istý ukazovateľ môže postupne ukazovať na rôzne premenné. Rutina, ktorá mení premenné volajúceho Z kapitoly 14 vieš, že procedúra dostáva kópie. Swap má premenné vymeniť, takže kópie jej nestačia. Dostane preto ich adresy (Swap(@x, @y)) a cez a^ a b^ pracuje priamo s premennými x a y v Main.\nTakto môže rutina „vrátiť“ viac hodnôt naraz.\nUkazovateľ a pole Meno poľa bez indexu je adresa jeho prvého prvku. Preto p=data (bez @) nastaví p na začiatok poľa. p==+1 potom posunie ukazovateľ o jeden bajt a slučka prejde pole bez indexov.\nPlatí to aj naopak: ukazovateľ sa dá indexovať ako pole, p(2) je bajt dva miesta za adresou v p.\nPole deklarované bez veľkosti a bez hodnôt (BYTE ARRAY a) je vlastne ukazovateľ: nemá vlastné prvky a treba mu najprv priradiť adresu.\nČasté chyby Čo sa stalo Čo sa stane p=x namiesto p=@x do p sa uloží hodnota x ako adresa; p^ potom číta náhodné miesto v pamäti použitie ukazovateľa, do ktorého si nič nepriradil čítanie alebo zápis na náhodnú adresu; zápis môže zhodiť program aj počítač p==+1 pri CARD POINTER posunie adresu o 1 bajt, nie o jeden CARD – na ďalší CARD treba p==+2 typ ukazovateľa nesedí s tým, na čo ukazuje CARD POINTER na BYTE premennú zapíše dva bajty a prepíše aj susednú premennú Prekladač tieto chyby nehlási. Ukazovateľ je silný nástroj práve preto, že ti dovolí siahnuť kamkoľvek do pamäte – aj tam, kam nemáš.\nPri treťom riadku si pomôžeš indexom: q(1) pri CARD POINTER q je druhý CARD, index sa veľkosťou prvku násobí sám.\nVyskúšaj si Napíš procedúru Reset(BYTE POINTER p), ktorá vynuluje premennú, na ktorú dostane adresu. Napíš procedúru MinMax(BYTE a, b, BYTE POINTER min, max), ktorá uloží menšie z dvoch čísel do min^ a väčšie do max^. Prejdi pole data ukazovateľom a spočítaj súčet jeho prvkov. Zhrnutie Ukazovateľ je premenná s adresou inej premennej. @x je adresa x; p^ je hodnota na adrese v p. Rutina, ktorá dostane adresu, môže zmeniť premennú volajúceho. Meno poľa je adresa jeho začiatku. Ukazovateľ treba najprv nastaviť; chyby s ukazovateľmi prekladač nezachytí. Späť: 19. Reťazce · Ďalej: 21. Záznamy\n","t":"20. Ukazovatele: POINTER, ^, @","u":"20-ukazovatele/"},{"c":"Na čo to je Hráč má polohu, počet životov a skóre. Sú to štyri premenné, ktoré patria k sebe. Záznam (record) ich spojí do jedného celku s vlastným menom, takže sa dajú odovzdať rutine naraz.\nAko sa to píše Najprv sa opíše typ záznamu – aké položky má:\nAction! TYPE Player=[BYTE x, y, lives CARD score] TYPE Meno=[ … ] – v hranatých zátvorkách sú položky, zapísané ako deklarácie premenných. Položky toho istého typu oddeľuje čiarka. Medzi skupinami typov sa čiarka nepíše – za lives nasleduje rovno CARD. Položky môžu byť len základných typov: BYTE, CHAR, CARD, INT. TYPE sa píše mimo rutín, na začiatok súboru. Potom sa meno typu používa ako každý iný typ:\nAction! Player hero, enemy ; dve premenné typu Player Player POINTER who ; ukazovateľ na záznam hero.x=10 ; položka sa píše za bodku who.score==+100 ; cez ukazovateľ rovnako, bez ^ Celý program Súbor examples/records.act:\nAction! ; Records: several values that belong together TYPE Player=[BYTE x, y, lives CARD score] PROC Show(Player POINTER who) Print(\"at \") PrintB(who.x) Put(',) PrintB(who.y) Print(\" lives \") PrintB(who.lives) Print(\" score \") PrintCE(who.score) RETURN PROC Hit(Player POINTER who, CARD points) who.score==+points RETURN PROC Main() Player hero, enemy hero.x=10 hero.y=5 hero.lives=3 hero.score=0 enemy.x=30 enemy.y=12 enemy.lives=1 enemy.score=500 Print(\"Hero: \") Show(hero) Print(\"Enemy: \") Show(enemy) Hit(hero, 250) hero.x==+1 Print(\"Hero: \") Show(hero) RETURN Preklad a spustenie action26 records.act --sim Čo uvidíš Hero: at 10,5 lives 3 score 0 Enemy: at 30,12 lives 1 score 500 Hero: at 11,5 lives 3 score 250 Ako to funguje Player hero, enemy vytvorí dva záznamy. Každý má vlastné x, y, lives a score. hero.x=10 zapíše do položky x záznamu hero. Záznam sa rutine odovzdáva cez ukazovateľ. Parameter je Player POINTER who. Pri volaní stačí napísať meno záznamu: Show(hero) – meno záznamu bez bodky je, podobne ako meno poľa, jeho adresa. Vnútri rutiny sa položky píšu rovnako: who.x. Znak ^ tu netreba. Hit(hero, 250) záznam mení. Keďže rutina dostala adresu, mení priamo hero v Main. Jedna rutina Show obslúži hrdinu aj nepriateľa. To je hlavný zmysel záznamov: rutiny sa píšu pre typ, nie pre jednu konkrétnu premennú.\nPole záznamov Action! nemá Player ARRAY. Viac záznamov za sebou sa robí poľom bajtov a ukazovateľom, ktorý sa posúva o veľkosť záznamu. Meno typu vo výraze je veľkosť záznamu v bajtoch.\nSúbor examples/records-array.act:\nAction! ; An array of records: a block of bytes and a pointer that walks through it TYPE Star=[BYTE x, y CARD points] DEFINE COUNT=\"3\" PROC Main() BYTE ARRAY room(12) ; room for COUNT records of 4 bytes Star POINTER s BYTE i FOR i=0 TO COUNT-1 DO s=room+i*Star ; the address of record number i s.x=i*10 s.y=i+1 s.points=(i+1)*100 OD FOR i=0 TO COUNT-1 DO s=room+i*Star Print(\"Star \") PrintB(i) Print(\": x=\") PrintB(s.x) Print(\" y=\") PrintB(s.y) Print(\" points=\") PrintCE(s.points) OD Print(\"One record takes \") PrintB(Star) PrintE(\" bytes\") RETURN action26 records-array.act --sim Star 0: x=0 y=1 points=100 Star 1: x=10 y=2 points=200 Star 2: x=20 y=3 points=300 One record takes 4 bytes s=room+i*Star vypočíta adresu záznamu číslo i: začiatok poľa plus i-krát veľkosť záznamu. Záznam Star má dva BYTE a jeden CARD, teda 4 bajty; tri záznamy potrebujú 12 bajtov.\nČasté chyby Čo sa stalo Čo povie prekladač alebo program položka, ktorá v zázname nie je (hero.speed) error ACT008: undeclared name 'speed' priradenie celého záznamu (enemy=hero) error ACT010: illegal assignment: cannot assign to Player 'enemy' – kopíruj položku po položke ukazovateľ na záznam bez priradenej adresy zápis na náhodné miesto v pamäti meno typu a meno premennej sa líšia len veľkosťou písmen (TYPE P, premenná p) je to to isté meno – veľké a malé písmená sa nerozlišujú pole pre záznamy je malé záznamy za koncom poľa prepíšu inú pamäť Mená položiek sú mená ako každé iné. Dva typy záznamov v jednom programe preto nemôžu mať položku s rovnakým menom – prekladač ohlási error ACT006: 'x' is already declared. Pomáha predpona: px, py pre hráča, sx, sy pre hviezdu.\nVyskúšaj si Pridaj do Player položku CHAR symbol a vypisuj ju v Show. Napíš PROC Move(Player POINTER who, BYTE dx, dy), ktorá posunie hráča. V druhom programe zmeň COUNT na 5. Čo ešte treba zmeniť? Zhrnutie TYPE Meno=[položky] opíše záznam; potom je Meno typ. Položka sa píše záznam.položka. Rutine sa záznam odovzdáva ako Meno POINTER; pri volaní stačí meno záznamu. Meno typu vo výraze je veľkosť záznamu. Pole záznamov = pole bajtov + ukazovateľ posúvaný o veľkosť záznamu. Späť: 20. Ukazovatele · Ďalej: 22. Bity\n","t":"21. Záznamy: TYPE","u":"21-zaznamy/"},{"c":"Na čo to je Bajt je osem bitov – ôsmich prepínačov, z ktorých každý je buď 0, alebo 1. Počítač Atari má veľa nastavení uložených tak, že každý bit bajtu znamená niečo iné: jeden zapína inverzné písmo, iný hovorí, či je stlačené tlačidlo. Bitové operácie dovolia pracovať s jednotlivými bitmi.\nKapitolu môžeš pri prvom čítaní preskočiť a vrátiť sa k nej, keď budeš bity potrebovať.\nDvojková sústava v skratke Každý bit má svoju hodnotu – mocninu dvojky. Bity sa číslujú sprava, od 0:\nBit 7 6 5 4 3 2 1 0 Hodnota 128 64 32 16 8 4 2 1 Číslo je súčet hodnôt bitov, ktoré sú 1. Napríklad 12 je 00001100: bit 3 (hodnota 8) a bit 2 (hodnota 4), 8 + 4 = 12.\nAko sa to píše Operátor Slovom Čo robí s každou dvojicou bitov a \u0026 b a AND b výsledný bit je 1, len keď sú oba 1 a % b a OR b výsledný bit je 1, keď je aspoň jeden 1 a ! b a XOR b výsledný bit je 1, keď sú bity rôzne a LSH n posunie bity o n miest doľava (násobenie dvoma, n-krát) a RSH n posunie bity o n miest doprava (delenie dvoma, n-krát) Znak a slovo sú to isté: a \u0026 b je a AND b. Sú to tie isté AND a OR ako v podmienkach (kapitola 9) – tam spájajú porovnania, tu pracujú s bitmi čísel.\nK čomu sa hodia:\nChcem Zápis Príklad zistiť, či je bit zapnutý IF x \u0026 maska THEN IF x\u0026128 THEN zapnúť bit x==%maska x==%128 vypnúť bit x==\u0026(255−maska) x==\u0026127 prepnúť bit na opačný x==!maska x==!128 Maska je číslo, ktoré má jednotky na bitoch, o ktoré ide.\nCelý program Súbor examples/bits.act:\nAction! ; Bits: looking inside a byte PROC Bits(BYTE value) ; write a byte as eight binary digits BYTE i, mask mask=128 FOR i=1 TO 8 DO IF value\u0026mask THEN Put('1) ELSE Put('0) FI mask==RSH 1 OD RETURN PROC Show(BYTE value) Bits(value) Print(\" = \") PrintBE(value) RETURN PROC Main() BYTE a, b a=12 b=10 Print(\"a \") Show(a) Print(\"b \") Show(b) Print(\"a AND b \") Show(a\u0026b) Print(\"a OR b \") Show(a%b) Print(\"a XOR b \") Show(a!b) Print(\"a LSH 1 \") Show(a LSH 1) Print(\"a RSH 2 \") Show(a RSH 2) a=5 a==%128 ; switch bit 7 on Print(\"bit 7 on \") Show(a) a==\u0026127 ; switch bit 7 off Print(\"bit 7 off \") Show(a) RETURN Preklad a spustenie action26 bits.act --sim Čo uvidíš a 00001100 = 12 b 00001010 = 10 a AND b 00001000 = 8 a OR b 00001110 = 14 a XOR b 00000110 = 6 a LSH 1 00011000 = 24 a RSH 2 00000011 = 3 bit 7 on 10000101 = 133 bit 7 off 00000101 = 5 Ako to funguje Porovnaj stĺpce nad sebou:\na 00001100 b 00001010 a AND b 00001000 jednotka len tam, kde ju majú obe a OR b 00001110 jednotka tam, kde ju má aspoň jedno a XOR b 00000110 jednotka tam, kde sa líšia a LSH 1 posunie všetko o miesto doľava: z 12 je 24, dvojnásobok. a RSH 2 posunie o dve miesta doprava: 12 delené 4 je 3. Bity, ktoré „vypadnú“ z kraja, sa stratia. a==%128 zapne bit 7 a ostatné nechá: z 5 je 133. a==\u0026127 – 127 je 01111111, všetky bity okrem siedmeho. AND s ním bit 7 vypne a ostatné nechá. Procedúra Bits ukazuje, ako sa bity čítajú: maska začne na 128 (bit 7) a každým krokom sa posunie doprava (mask==RSH 1). value\u0026mask je nenulové práve vtedy, keď je daný bit v value zapnutý – a podmienka bez porovnania platí, keď je výsledok nenulový.\nČasté chyby Čo sa stalo Čo sa stane % v zmysle „percentá“ alebo „zvyšok po delení“ v Action! je % bitové OR; zvyšok je MOD ! v zmysle „nie“ v Action! je ! bitové XOR; opak podmienky sa píše obráteným porovnaním posun BYTE hodnoty za 8 bitov (1 LSH 8) výsledok je 0 – počíta sa v BYTE a bit vypadne; pre väčšie posuny použi CARD premennú x\u0026mask=mask bez zátvoriek error ACT023: illegal conditional expression – porovnanie má prednosť pred \u0026; píš (x\u0026mask)=mask Vyskúšaj si Vypíš v dvojkovej sústave čísla 0 až 15. Napíš BYTE FUNC IsOdd(BYTE n), ktorá zistí nepárnosť bitovou operáciou (nepárne číslo má zapnutý bit 0). Kód malého písmena je o 32 väčší ako kód veľkého – líšia sa bitom 5. Preveď znak 'a na veľké písmeno vypnutím toho bitu. Zhrnutie Bajt má 8 bitov s hodnotami 1, 2, 4 … 128. \u0026 (AND) vyberá a vypína bity, % (OR) zapína, ! (XOR) prepína. LSH a RSH posúvajú bity – násobia a delia dvoma. Test bitu: IF x\u0026maska THEN. Späť: 21. Záznamy · Ďalej: 23. Program vo viacerých súboroch\n","t":"22. Bity: \u0026, %, !, LSH, RSH","u":"22-bity/"},{"c":"Na čo to je Rutiny, ktoré sa hodia do viacerých programov, nechceš zakaždým kopírovať. Dáš ich do vlastného súboru a program si ho vloží príkazom INCLUDE. Tak vzniká vlastná knižnica.\nDruhá polovica kapitoly je o SET – pokyne, ktorým sa v starých programoch nastavuje prekladač.\nINCLUDE: ako sa to píše Action! INCLUDE \"D:MENO.ACT\" Prekladač na tomto mieste prečíta celý súbor MENO.ACT, akoby bol jeho text napísaný priamo tu. Potom pokračuje ďalším riadkom.\nD: je označenie disketovej jednotky na Atari. action26 ho preskočí – zaujíma ho len meno súboru. Píše sa preto, aby program preložil aj pôvodný Action!. Súbor sa hľadá v priečinku, kde leží program, ktorý ho vkladá. Meno bez prípony dostane .ACT. INCLUDE patrí tam, kde by mohol stáť obsah súboru – rutiny knižnice teda vkladaj na začiatok, pred rutiny, ktoré ich volajú. Celý program Knižnica – súbor examples/shapes.act:\nAction! ; A small library: routines that draw with characters. ; This file is not a program of its own. Other programs INCLUDE it. PROC ShapeLine(BYTE width, CHAR c) BYTE i FOR i=1 TO width DO Put(c) OD PutE() RETURN PROC ShapeBox(BYTE width, height, CHAR c) BYTE row FOR row=1 TO height DO ShapeLine(width, c) OD RETURN Program – súbor examples/include.act:\nAction! ; A program in two files INCLUDE \"D:SHAPES.ACT\" ; the routines of shapes.act are now known PROC Main() ShapeLine(12, '=) ShapeBox(6, 2, '#) ShapeLine(12, '=) RETURN Preklad a spustenie Prekladá sa len hlavný program. Knižnicu si nájde sám:\naction26 include.act --sim Čo uvidíš ============ ###### ###### ============ Ako to funguje Keď prekladač narazí na INCLUDE \"D:SHAPES.ACT\", otvorí shapes.act, preloží obe procedúry a vráti sa do include.act. Pre Main sú potom ShapeLine a ShapeBox známe, ako keby boli v tom istom súbore nad ňou.\nMená v knižnici začínajú rovnakým slovom (Shape…). Action! nemá oddelené priestory mien – všetky rutiny všetkých vložených súborov sú na jednej hromade. Spoločná predpona bráni tomu, aby sa meno z knižnice zrazilo s menom v programe.\nKnižnica v inom priečinku Keď knižnice držíš na jednom mieste pre viac programov, povedz prekladaču voľbou -I, kde má hľadať:\naction26 include.act -I C:\\Atari\\lib --sim Volieb -I môže byť viac. Program sa pritom nemení – v zdrojáku ostáva INCLUDE \"D:SHAPES.ACT\".\nDo pamäte sa dostane len to, čo treba? Nie celkom. Rutiny z knižnice jazyka (Print, Graphics …) action26 pribalí len tie, ktoré program volá. Rutiny z tvojho vloženého súboru sa preložia všetky, aj nepoužité. Veľkú knižnicu sa preto oplatí deliť do menších súborov.\nSET: nastavenie prekladača Action! SET adresa=hodnota Pôvodný Action! bežal na Atari a jeho nastavenia boli bajty v pamäti. SET počas prekladu zapísal hodnotu na danú adresu a tým prekladač prestavil. action26 týmto zápisom rozumie.\nStretneš najmä túto dvojicu – hovorí, od ktorej adresy má byť program v pamäti:\nSúbor examples/set.act:\nAction! ; SET: this program is placed at address $5000 instead of $2000 SET $E=$5000 SET $491=$5000 PROC Main() Print(\"This routine starts at address \") PrintCE(Main) RETURN action26 set.act --sim This routine starts at address 20480 20480 je desiatkovo $5000. Bez dvoch riadkov SET by program začínal na $2000 (8192).\nVo vlastných programoch SET nepotrebuješ. To isté spraví voľba prekladača --org $5000 alebo riadok ;@ORG $5000 na začiatku zdrojáka (kapitoly 32 a 33). Dobré je SET poznať, aby ťa v cudzom programe neprekvapil.\nČasté chyby Čo sa stalo Čo povie prekladač vkladaný súbor neexistuje alebo je inde error ACT203: INCLUDE file not found: D:SHAPES.ACT INCLUDE je až pod rutinou, ktorá knižnicu volá error ACT008: undeclared name ten istý súbor vložený dvakrát error ACT006 – rutiny sú deklarované dvakrát súbor vkladá sám seba, priamo alebo cez iný súbor error ACT204 Vyskúšaj si Pridaj do shapes.act procedúru ShapeTriangle(BYTE size, CHAR c) a zavolaj ju z programu. Presuň shapes.act do podpriečinka lib a prelož program s voľbou -I lib. Zmeň v set.act adresu na $3000. Akú adresu program vypíše? Zhrnutie INCLUDE \"D:MENO.ACT\" vloží na dané miesto obsah iného súboru. Súbor sa hľadá vedľa programu a v priečinkoch z voľby -I. Mená v knižnici začínaj spoločnou predponou. SET adresa=hodnota nastavuje prekladač; najčastejšie určuje adresu programu. V nových programoch ho nahrádza --org. Späť: 22. Bity · Ďalej: 24. Pamäť počítača\n","t":"23. Program vo viacerých súboroch: INCLUDE a SET","u":"23-include/"},{"c":"Na čo to je Atari sa ovláda cez pamäť. Farba pozadia, poloha kurzora, posledný stlačený kláves, stav joysticku – to všetko sú bajty na známych adresách. Kto vie čítať a zapisovať pamäť, vie z počítača dostať všetko, čo knižnica neponúka.\nPamäť Atari v skratke Pamäť je rad 65536 bajtov s adresami 0 až 65535 ($0000 až $FFFF). Nie je to jednoliaty priestor:\nAdresy Čo tam je $0000–$00FF nultá stránka – pracovné bunky systému a jazyka $0100–$01FF zásobník procesora $0200–$05FF premenné operačného systému (farby, klávesnica, časovače) $0600–$06FF šiesta stránka – 256 bajtov, ktoré systém nepoužíva; voľné pre programy $0700–… DOS, ak je nahraný $2000–… tvoj program (action26 ho sem predvolene ukladá) …–$BFFF voľná pamäť a na jej konci pamäť obrazovky $D000–$D7FF registre čipov: grafika, zvuk, joysticky $C000–$CFFF, $D800–$FFFF operačný systém v ROM (pamäť len na čítanie) Zoznam užitočných adries je v prílohe D.\nAdresy premenných v RAM ($0000–$05FF) a registrov sú vo všetkých verziách operačného systému rovnaké. Vnútro ROM nie: Atari 800, Atari XL/XE aj voľná náhrada AltirraOS majú na tých istých adresách v ROM iný kód. Do ROM sa preto skáče len cez oficiálne vstupné body – tabuľku od $E450 (napríklad $E456 pre vstup a výstup). Program, ktorý volá rutinu z vnútra ROM na pevnej adrese, beží len s jednou verziou systému.\nAko sa to píše Rutiny knižnice Rutina Čo robí Peek(adresa) funkcia – vráti bajt z adresy PeekC(adresa) funkcia – vráti CARD z adresy a adresy + 1 Poke(adresa, hodnota) zapíše bajt na adresu PokeC(adresa, hodnota) zapíše CARD na adresu a adresu + 1 Peek je anglicky „nakuknúť“, poke „štuchnúť“. Mená pochádzajú z jazyka BASIC.\nPremenná na adrese Action! BYTE background=710 To je deklarácia z kapitoly 6, pred ktorou si mal byť opatrný: číslo bez hranatých zátvoriek je adresa. Premenná background nedostane vlastné miesto – je bajtom na adrese 710. Zápis background=148 robí to isté ako Poke(710, 148), len sa lepšie číta a je rýchlejší.\nRovnako sa dá položiť na adresu pole:\nAction! BYTE ARRAY page6(256)=1536 Celý program Súbor examples/memory.act:\nAction! ; Memory: reading and writing bytes by their address BYTE background=710 ; this variable IS the byte at address 710 BYTE ARRAY page6(256)=1536 ; an array placed at address 1536 ($600) PROC Main() BYTE value CARD word Poke(1536, 65) ; write 65 to address 1536 value=Peek(1536) ; read it back Print(\"Address 1536 holds \") PrintBE(value) PokeC(1538, 50000) ; a CARD takes two bytes: 1538 and 1539 word=PeekC(1538) Print(\"Addresses 1538-1539 hold \") PrintCE(word) Print(\"Low byte \") PrintB(Peek(1538)) Print(\", high byte \") PrintBE(Peek(1539)) page6(4)=7 ; the same memory through the array Print(\"page6(4) is address 1540: \") PrintBE(Peek(1540)) Print(\"page6(0) is address 1536: \") PrintBE(page6(0)) background=148 ; the same as Poke(710, 148) Print(\"Address 710 holds \") PrintBE(Peek(710)) RETURN Preklad a spustenie action26 memory.act --sim Čo uvidíš Address 1536 holds 65 Addresses 1538-1539 hold 50000 Low byte 80, high byte 195 page6(4) is address 1540: 7 page6(0) is address 1536: 65 Address 710 holds 148 Ako to funguje Poke(1536, 65) a Peek(1536) – zápis a čítanie jedného bajtu. Adresa 1536 je začiatok šiestej stránky, kde programu nič nezavadzia. CARD zaberá dva bajty a nižší je prvý. 50000 je 195 × 256 + 80. Na adrese 1538 je 80 (nižší bajt), na 1539 je 195 (vyšší). Toto poradie platí na Atari všade. page6 je pole položené na šiestu stránku. page6(4) a adresa 1540 sú to isté miesto. page6(0) ukazuje 65, ktoré tam zapísal Poke na začiatku. background=148 zapíše na adresu 710. V simulátore vidíš len číslo; v emulátore sa zmení farba pozadia na modrú, lebo 710 je bunka, z ktorej systém berie farbu pozadia textovej obrazovky. Skús to v emulátore – pridaj na koniec GetD(7), aby program počkal na kláves (kapitola 2):\naction26 memory.act --run Niekoľko adries na hranie Adresa Meno v knihách Čo robí 710 COLOR2 farba pozadia textovej obrazovky 709 COLOR1 jas písma 712 COLOR4 farba okraja 752 CRSINH 1 = kurzor je skrytý 82 LMARGN ľavý okraj textu (predvolene 2) 764 CH kód posledného stlačeného klávesu; 255 = žiadny 20 RTCLOK počítadlo, ktoré sa zväčší 50-krát (v USA 60-krát) za sekundu 53770 RANDOM pri každom čítaní náhodné číslo Farba je jedno číslo: 16 × odtieň + jas. 148 je odtieň 9 a jas 4.\nČasté chyby Čo sa stalo Čo sa stane BYTE x=710, keď si chcel počiatočnú hodnotu x je bajt na adrese 710; každý zápis mení farbu pozadia Poke na adresu, ktorú nepoznáš môže sa stať čokoľvek – od ničoho po zamrznutie počítača Poke do ROM ($C000 a vyššie okrem registrov) nič – do pamäte len na čítanie sa zapísať nedá Peek z registra čipu vráti iné, ako si zapísal je to normálne: veľa registrov má iný význam pri čítaní a pri zápise Zápis na zlú adresu počítač nepoškodí – stačí ho vypnúť a zapnúť. V emulátore a simulátore sa nemôže stať vôbec nič zlé, takže skúšaj smelo.\nVyskúšaj si V emulátore zmeň farbu okraja (adresa 712) a jas písma (709). Vypíš Peek(53770) desaťkrát v slučke – v emulátore dostaneš zakaždým iné číslo. Deklaruj BYTE left=82, nastav left=10 a vypíš niekoľko riadkov textu. Čo sa stane v emulátore? Zhrnutie Pamäť má adresy 0 až 65535; mnohé majú pevný význam. Peek/Poke čítajú a píšu bajt, PeekC/PokeC dvojbajtové číslo. BYTE meno=adresa je premenná na danej adrese; BYTE meno=[hodnota] je premenná s počiatočnou hodnotou. Dvojbajtové číslo má nižší bajt na nižšej adrese. Šiesta stránka ($600–$6FF) je voľná pre programy. Koľko pamäte ti ešte ostáva po preklade, povie --memory (kapitola 32). Späť: 23. Program vo viacerých súboroch · Ďalej: 25. Strojový kód\n","t":"24. Pamäť počítača: Peek, Poke a premenné na adrese","u":"24-pamat/"},{"c":"Na čo to je Procesor Atari (6502) rozumie len číslam – strojovému kódu. Prekladač mení tvoj program práve na také čísla. Action! dovoľuje vložiť strojový kód do programu aj priamo, a zavolať rutinu, ktorá už niekde v pamäti je (napríklad v operačnom systéme).\nTúto kapitolu nemusíš vedieť použiť. Stačí vedieť, čo ten zápis znamená, keď ho stretneš v cudzom programe. Staré programy z časopisov ho používajú často – na miestach, kde záležalo na rýchlosti.\nAko sa to píše Blok kódu Action! [$EE $00 $06] Čísla v hranatých zátvorkách prekladač vloží do programu presne tak, ako sú, bajt za bajtom. Nič nekontroluje. Číslo väčšie ako 255 sa vloží ako dva bajty (nižší prvý). V bloku môže stáť aj meno premennej alebo rutiny – vloží sa jej adresa.\nBlok môže stáť medzi príkazmi rutiny alebo tvoriť celé jej telo.\nRutina zo strojového kódu Action! PROC Bump=*() [$EE $00 $06 $60] =* znamená „táto rutina začína práve tu a jej telo si napíšem sám“. Prekladač k nej nepridá nič – ani uloženie parametrov. Kód musí sám skončiť inštrukciou návratu ($60).\nRutina na pevnej adrese Action! PROC CIO=$E456(BYTE a, x) Hovorí: „na adrese $E456 už rutina je, len jej dávam meno“. Žiadne telo nenasleduje. Takto sa volajú rutiny operačného systému. Argumenty sa odovzdajú v registroch procesora: prvý bajt v registri A, druhý v X, tretí v Y.\nCelý program Súbor examples/machine.act:\nAction! ; Machine code inside an Action! program BYTE counter=1536 ; a byte at address $0600 PROC Bump=*() ; a routine written in machine code [$EE $00 $06 ; INC $0600 - add 1 to the byte at $0600 $60] ; RTS - return PROC Main() counter=5 Bump() Bump() Print(\"After two calls: \") PrintBE(counter) [$CE $00 $06] ; DEC $0600 - a code block between statements Print(\"After the code block: \") PrintBE(counter) RETURN Preklad a spustenie action26 machine.act --sim Čo uvidíš After two calls: 7 After the code block: 6 Ako to funguje $EE $00 $06 je inštrukcia procesora INC $0600: pripočítaj 1 k bajtu na adrese $0600. Prvý bajt je kód inštrukcie, ďalšie dva adresa (nižší bajt prvý – ako v kapitole 24). $60 je RTS, návrat z rutiny. counter je premenná položená na adresu $0600 (1536), takže strojový kód a program v Action! menia ten istý bajt. Bump() sa volá ako každá iná procedúra. [$CE $00 $06] uprostred Main je DEC $0600 – odčítaj 1. Vykoná sa v poradí medzi okolitými príkazmi. Komentáre za bajtmi hovoria, aká inštrukcia to je. Bez nich je blok kódu len rad čísel, ktorým nikto nerozumie – ani autor o mesiac neskôr.\nKedy to použiť Skoro nikdy. action26 prekladá Action! do rýchleho kódu a to, čo sa kedysi písalo v strojovom kóde, dnes zvyčajne netreba. Výnimky:\nobsluha prerušení (napríklad zmena farby na každom riadku obrazovky), volanie rutiny operačného systému, ktorú knižnica nemá, prepis starého programu, ktorý bloky kódu už obsahuje. Ak sa chceš strojovému kódu venovať, action26 má pohodlnejší spôsob než čísla: blok ASM … ENDASM, do ktorého sa píšu inštrukcie menami (inc counter). Je to rozšírenie nad rámec pôvodného Action! a opisuje ho kapitola 37.\nČasté chyby Čo sa stalo Čo sa stane chýba $60 na konci rutiny =* procesor pokračuje do toho, čo v pamäti nasleduje preklep v jednom čísle iná inštrukcia; program zvyčajne spadne blok kódu zmení register, s ktorým okolitý program počíta chyba na inom mieste, ťažko hľadateľná meno rutiny na adrese s nesprávnou adresou skok do neznáma Prekladač v bloku kódu nekontroluje nič.\nVyskúšaj si Pridaj tretie volanie Bump() a over výsledok. Zmeň prvý bajt bloku v Main z $CE na $EE. Čo sa vypíše? Prelož program s voľbou --listing machine.lst a otvor vzniknutý súbor v editore. Nájdi v ňom svoje bajty – a pozri, ako prekladač preložil ostatné riadky. action26 machine.act --listing machine.lst Zhrnutie [ … ] vloží do programu bajty presne tak, ako sú napísané. PROC Meno=*() je rutina, ktorej telo je celé zo strojového kódu. PROC Meno=adresa(…) dá meno rutine, ktorá už v pamäti je. Prekladač strojový kód nekontroluje; komentuj každú inštrukciu. Späť: 24. Pamäť počítača · Ďalej: 26. Formátovaný výpis a prevody\n","t":"25. Strojový kód: blok [ … ] a rutina na adrese","u":"25-strojovy-kod/"},{"c":"Na čo to je Veta „Pedro is 12 years old.“ potrebovala doteraz štyri príkazy: Print, Print, PrintB, PrintE. PrintF to zvládne jedným. Druhá polovica kapitoly je o prevode čísla na text a späť.\nPrintF: ako sa to píše Action! PrintF(\"text so značkami\", hodnota1, hodnota2, …) Prvý parameter je formát: text, v ktorom sú na miestach hodnôt značky začínajúce znakom %. Ďalšie parametre sú hodnoty, ktoré sa na miesta značiek dosadia – v poradí, v akom idú.\nZnačka Čo vypíše %U číslo bez znamienka (BYTE alebo CARD) %I číslo so znamienkom (INT) %C znak %S reťazec %H číslo šestnástkovo, so znakom $ %E koniec riadka %% samotný znak % Hodnôt môže byť najviac päť.\nPrevody: ako sa to píše Rutina Smer Príklad StrB(číslo, reťazec) BYTE → text StrB(age, text) StrC(číslo, reťazec) CARD → text StrC(score, text) StrI(číslo, reťazec) INT → text StrI(change, text) ValB(reťazec) text → BYTE age=ValB(text) ValC(reťazec) text → CARD score=ValC(\"1234\") ValI(reťazec) text → INT change=ValI(\"-77\") Str… sú procedúry: výsledok uložia do reťazca, ktorý im dáš. Val… sú funkcie: vrátia číslo.\nCelý program Súbor examples/printf.act:\nAction! ; PrintF and the conversions between numbers and strings PROC Main() CHAR ARRAY name=\"Pedro\", text(10) BYTE age CARD score, number INT change age=12 score=40000 change=-25 PrintF(\"%S is %U years old.%E\", name, age) PrintF(\"Score %U, change %I%E\", score, change) PrintF(\"%U in hexadecimal is %H%E\", score, score) PrintF(\"A character: %C, a percent sign: %%%E\", 'A) StrC(score, text) ; a number into a string Print(\"As a string: \") PrintE(text) Print(\"It has \") PrintB(text(0)) PrintE(\" characters\") number=ValC(\"1234\") ; a string into a number Print(\"ValC(\"\"1234\"\") plus 1 is \") PrintCE(number+1) change=ValI(\"-77\") Print(\"ValI(\"\"-77\"\") times 2 is \") PrintIE(change*2) RETURN Preklad a spustenie action26 printf.act --sim Čo uvidíš Pedro is 12 years old. Score 40000, change -25 40000 in hexadecimal is $9C40 A character: A, a percent sign: % As a string: 40000 It has 5 characters ValC(\"1234\") plus 1 is 1235 ValI(\"-77\") times 2 is -154 Ako to funguje V prvom PrintF sú dve značky a dve hodnoty: %S dostane name, %U dostane age. %E na konci ukončí riadok – PrintF to sám nespraví. %U a %I sa líšia tým, ako číslo čítajú. −25 vypísané cez %U by bolo 65511. %H vypíše to isté číslo šestnástkovo. Hodí sa pri práci s adresami. StrC(score, text) uloží do text reťazec \"40000\". Od tej chvíle je to obyčajný reťazec: má dĺžku 5 v text(0) a dá sa s ním robiť všetko z kapitoly 19. ValC(\"1234\") vráti číslo 1234, s ktorým sa dá počítať. Kedy prevody potrebuješ: keď chceš číslo zarovnať, vložiť do dlhšieho textu, alebo spracovať vstup znak po znaku. InputB() z kapitoly 8 nerobí nič iné ako InputS a potom ValB.\nČasté chyby Čo sa stalo Čo sa stane menej hodnôt ako značiek na mieste chýbajúcej hodnoty sa vypíše nezmysel zlá značka pre typ (%S pre číslo) číslo sa použije ako adresa reťazca – vypíše sa nezmysel chýba %E ďalší výpis pokračuje na tom istom riadku reťazec pre Str… je malý prepíše sa pamäť za ním; StrC potrebuje až 6 bajtov, StrI 7 Val… dostane text, ktorý nezačína číslom vráti 0 Val… číta číslice od začiatku textu a skončí pri prvom znaku, ktorý číslicou nie je. Medzery na začiatku preskočí.\nVyskúšaj si Vypíš jedným PrintF riadok malej násobilky: 3 x 7 = 21. Načítaj riadok cez InputS a preveď ho na číslo cez ValC. Správa sa to rovnako ako InputC()? Vypíš číslo zarovnané doprava na 5 miest: preveď ho cez StrC, zisti dĺžku a vypíš pred ním chýbajúce medzery. Zhrnutie PrintF(formát, hodnoty…) vypíše text s dosadenými hodnotami. %U číslo, %I číslo so znamienkom, %C znak, %S reťazec, %H šestnástkovo, %E koniec riadka. StrB, StrC, StrI menia číslo na reťazec. ValB, ValC, ValI menia reťazec na číslo. Späť: 25. Strojový kód · Ďalej: 27. Grafika\n","t":"26. Formátovaný výpis a prevody: PrintF, Str…, Val…","u":"26-printf/"},{"c":"Na čo to je Atari vie okrem textu kresliť body a čiary vo farbe. Táto kapitola ukáže textovú obrazovku s farbami a kurzorom na ľubovoľnom mieste a potom obrázok z čiar.\nOd tejto kapitoly potrebuješ emulátor. Simulátor (--sim) obrazovku nekreslí. Programy sa spúšťajú voľbou --run a na konci čakajú na kláves.\nAko sa to píše Rutina Čo robí Graphics(režim) prepne obrazovku do grafického režimu a vymaže ju SetColor(register, odtieň, jas) nastaví farbu jedného z piatich farebných registrov color=číslo premenná knižnice: ktorou farbou sa bude kresliť Plot(stĺpec, riadok) nakreslí bod DrawTo(stĺpec, riadok) nakreslí čiaru z posledného bodu do zadaného Fill(stĺpec, riadok) vyplní plochu (vysvetlenie nižšie) Position(stĺpec, riadok) nastaví kurzor – kde bude ďalší výpis textu Locate(stĺpec, riadok) funkcia – vráti farbu bodu (v textovom režime kód znaku) Súradnice: bod (0, 0) je vľavo hore. Stĺpec rastie doprava, riadok nadol. Vždy sa píše najprv stĺpec, potom riadok.\nGrafické režimy Najpoužívanejšie (všetky sú v prílohe D):\nRežim Druh Rozmer Farby 0 text 40 × 24 znakov 1 farba písma, 1 pozadia 1 veľký text 20 × 20 znakov + 4 riadky textu 5 2 ešte väčší text 20 × 10 znakov + 4 riadky textu 5 3 body 40 × 20 + 4 riadky textu 4 5 body 80 × 40 + 4 riadky textu 4 7 body 160 × 80 + 4 riadky textu 4 8 body 320 × 160 + 4 riadky textu 1 farba, 2 jasy Režimy 1 až 8 nechávajú dole textové okno so štyrmi riadkami, do ktorého píše Print. Keď k číslu režimu pripočítaš 16 (Graphics(7+16)), okno zmizne a grafika zaberie celú obrazovku.\nFarby Farba je odtieň (0 až 15) a jas (párne číslo 0 až 14).\nOdtieň Farba Odtieň Farba 0 sivá 8 nebeská modrá 1 zlatá 9 svetlomodrá 2 oranžová 10 tyrkysová 3 červenooranžová 11 zelenomodrá 4 ružová 12 zelená 5 fialová 13 žltozelená 6 fialovomodrá 14 oranžovozelená 7 modrá 15 svetlooranžová Presný odtieň závisí od televíznej normy (v Európe PAL, v USA NTSC).\nV režime 7 platí:\ncolor= Kreslí farbou z registra Nastaví sa cez 0 pozadie (maže) SetColor(4, …) 1 register 0 SetColor(0, …) 2 register 1 SetColor(1, …) 3 register 2 SetColor(2, …) Všimni si posun: color=1 kreslí farbou registra 0.\nProgram 1: textová obrazovka Súbor examples/textscreen.act:\nAction! ; The text screen: colours and the place of the cursor PROC Main() BYTE i Graphics(0) ; clear the screen SetColor(2, 9, 4) ; the background is blue SetColor(1, 0, 14) ; the letters are bright SetColor(4, 9, 4) ; the border is the same blue Position(12, 2) Print(\"THE TEXT SCREEN\") FOR i=0 TO 9 DO Position(5+i*3, 5+i) ; column, row PrintB(i) OD Position(2, 19) Print(\"Press any key\") GetD(7) RETURN action26 textscreen.act --run Uvidíš modrú obrazovku s nadpisom hore a číslicami 0 až 9 usporiadanými šikmo nadol. Position postaví kurzor a nasledujúci Print píše od toho miesta.\nV režime 0 má register 2 farbu pozadia, register 1 jas písma (odtieň písma je vždy rovnaký ako pozadie) a register 4 okraj.\nProgram 2: kreslenie Súbor examples/graphics.act:\nAction! ; Graphics: a house in graphics mode 7 (160 x 80 points, 4 colours) PROC Main() BYTE i, found Graphics(7) ; 160 x 80 points and 4 lines of text below SetColor(0, 2, 8) ; colour 1 is orange SetColor(1, 12, 10) ; colour 2 is green SetColor(2, 9, 6) ; colour 3 is blue SetColor(4, 0, 0) ; the background is black color=1 ; a frame around the picture Plot(0, 0) DrawTo(159, 0) DrawTo(159, 79) DrawTo(0, 79) DrawTo(0, 0) color=2 ; the walls Plot(50, 60) DrawTo(50, 35) DrawTo(110, 35) DrawTo(110, 60) DrawTo(50, 60) color=3 ; the roof Plot(45, 35) DrawTo(80, 15) DrawTo(115, 35) color=1 ; a filled door Plot(86, 59) DrawTo(86, 45) DrawTo(74, 45) Fill(74, 59) color=3 ; a dotted path FOR i=0 TO 9 DO Plot(80+i*4, 70) OD found=Locate(50, 40) ; which colour has the point 50,40? PrintE(\"A house in graphics mode 7\") Print(\"The point 50,40 has colour \") PrintBE(found) Print(\"Press any key\") GetD(7) Graphics(0) RETURN Preklad a spustenie action26 graphics.act --run Čo uvidíš Čiernu obrazovku s oranžovým rámom. V strede domček: zelené steny, modrá strecha, oranžové vyplnené dvere a pod ním bodkovaná modrá cestička. V textovom okne dole:\nA house in graphics mode 7 The point 50,40 has colour 2 Press any key Ako to funguje Graphics(7) prepne režim. Obrazovka má 160 stĺpcov (0–159) a 80 riadkov (0–79). Štyri SetColor určia, čo znamenajú čísla farieb. color=1 vyberie farbu pre nasledujúce kreslenie. Platí, kým ju nezmeníš. Čiara sa kreslí dvojicou Plot a DrawTo: Plot položí prvý bod, DrawTo ťahá čiaru do ďalšieho. Ďalší DrawTo pokračuje tam, kde predošlý skončil – tak vznikne lomená čiara. Locate(50, 40) prečíta farbu bodu. Na tom mieste je ľavá stena, kreslená farbou 2. PrintE v grafickom režime píše do textového okna. Graphics(0) na konci vráti textový režim. Ako funguje Fill Fill vypĺňa plochu zľava doprava, kým nenarazí na nakreslený bod. Treba mu preto pripraviť pravý okraj a povedať, kadiaľ ide ľavý:\nPlot(86, 59) a DrawTo(86, 45) – pravá strana dverí, zdola nahor. DrawTo(74, 45) – horná strana, doľava. Kurzor ostal v ľavom hornom rohu. Fill(74, 59) – ťahá čiaru z ľavého horného rohu do ľavého dolného a z každého jej bodu vypĺňa doprava, až po pravú stranu. Časté chyby Čo sa stalo Čo sa stane bod mimo obrazovky (Plot(200, 10) v režime 7) chyba 141 – program skončí hlásením Err: 141 zabudnuté color= kreslí sa farbou, ktorá ostala naposledy; ak je to 0 – pozadie –, nie je nič vidieť zámena riadka a stĺpca obrázok je preklopený alebo mimo obrazovky SetColor(1, …) v nádeji, že zmení color=1 color=1 je register 0 nepárny jas zaokrúhli sa nadol; jas 9 je to isté ako 8 program vlastní premennú color zakryje premennú knižnice a kreslenie prestane meniť farbu Posledný riadok je všeobecná pasca: meno premennej nesmie byť rovnaké ako meno rutiny alebo premennej knižnice, a veľké a malé písmená sa nerozlišujú. Premenná stick zakryje funkciu Stick, premenná position procedúru Position.\nVyskúšaj si Pridaj domčeku okno – malý štvorec vedľa dverí. Nakresli v slučke FOR desať zvislých čiar vedľa seba, každú o 10 bodov ďalej. Zmeň režim na Graphics(7+16). Čo sa stane s textovým oknom a s výpismi? Zhrnutie Graphics(n) zapne režim; Graphics(0) je text. SetColor(register, odtieň, jas) nastaví farbu; color=n vyberie, ktorou sa kreslí. Plot bod, DrawTo čiara z posledného bodu, Fill výplň doprava po okraj. Position nastaví kurzor pre text, Locate prečíta bod. Súradnice sú (stĺpec, riadok) a začínajú vľavo hore. Späť: 26. Formátovaný výpis a prevody · Ďalej: 28. Zvuk\n","t":"27. Grafika: Graphics, SetColor, Plot, DrawTo, Fill, Position, Locate","u":"27-grafika/"},{"c":"Na čo to je Atari má zvukový čip so štyrmi hlasmi – môže hrať štyri tóny naraz. Rutina Sound nastaví jeden hlas, SndRst všetky stíši.\nZvuk počuješ len v emulátore (--run), simulátor je ticho.\nAko sa to píše Action! Sound(hlas, výška, skreslenie, hlasitosť) SndRst() Parameter Hodnoty Význam hlas 0 až 3 ktorý zo štyroch hlasov výška 0 až 255 väčšie číslo = hlbší tón skreslenie párne čísla 0 až 14 10 je čistý tón; ostatné dávajú šum a bzučanie (výbuchy, motory) hlasitosť 0 až 15 0 je ticho Tón znie, kým ho nezmeníš alebo nevypneš. Sound hlas len nastaví a program beží ďalej. Ako dlho tón znie, určuje to, čo program robí potom – preto treba čakanie.\nTóny Tón C D E F G A H C výška 121 108 96 91 81 72 64 60 Celý program Súbor examples/sound.act:\nAction! ; Sound: a scale and a siren BYTE clock=20 ; this byte grows by 1 fifty times a second PROC Wait(BYTE ticks) clock=0 WHILE clock\u003cticks DO OD RETURN PROC Main() BYTE ARRAY notes=[121 108 96 91 81 72 64 60] ; C D E F G A B C BYTE i, pitch PrintE(\"A scale...\") FOR i=0 TO 7 DO Sound(0, notes(i), 10, 8) ; voice, pitch, pure tone, volume Wait(15) OD SndRst() ; silence Wait(25) PrintE(\"A siren...\") FOR i=1 TO 3 DO FOR pitch=40 TO 100 STEP 4 DO Sound(0, pitch, 10, 10) Wait(1) OD OD SndRst() PrintE(\"Two voices together...\") Sound(0, 121, 10, 8) Sound(1, 81, 10, 8) Wait(50) SndRst() PutE() Print(\"Press any key\") GetD(7) RETURN Preklad a spustenie action26 sound.act --run Čo uvidíš a počuješ A scale... A siren... Two voices together... Press any key Najprv zaznie stupnica ôsmich tónov, potom trikrát klesajúca siréna a nakoniec dva tóny naraz.\nAko to funguje Čakanie Sound nečaká, takže dĺžku tónu si program musí odmerať sám. Atari má na adrese 20 počítadlo, ktoré operačný systém zväčší o 1 pri každom obrázku na obrazovke – v Európe 50-krát za sekundu, v USA 60-krát.\nAction! BYTE clock=20 je premenná na tejto adrese (kapitola 24). Procedúra Wait ju vynuluje a v prázdnej slučke čaká, kým nenarastie na požadovanú hodnotu. Wait(50) je teda asi sekunda, Wait(15) necelá tretina.\nTúto procedúru budeš používať stále – v hrách určuje rýchlosť.\nZvyšok Stupnica: výšky tónov sú v poli, slučka ich prehrá jeden po druhom, každý 15 tikov. Siréna: výška sa mení po malých krokoch a rýchlo – ucho to vníma ako plynulé klesanie. Pripomínam: rastúce číslo je klesajúci tón. Dva hlasy: hlas 0 a hlas 1 znejú naraz, lebo každý Sound nastavuje iný hlas. SndRst() vypne všetky štyri hlasy naraz. Časté chyby Čo sa stalo Čo sa stane číslo hlasu väčšie ako 3 program skončí hlásením Err: 100 chýba čakanie za Sound tón sa hneď prepíše ďalším alebo ho ukončí SndRst; nič nepočuť chýba SndRst na konci posledný tón znie ďalej, aj keď program skončil hlasitosti všetkých hlasov dokopy viac ako 32 zvuk je skreslený Vyskúšaj si Zahraj stupnicu odzadu – od vysokého C po hlboké. Zmeň skreslenie v stupnici z 10 na 8 a potom na 4. Ako znie? Zahraj jednoduchú melódiu: daj výšky tónov do jedného poľa a ich dĺžky do druhého. Zhrnutie Sound(hlas, výška, skreslenie, hlasitosť) zapne tón na jednom zo štyroch hlasov. Väčšia výška je hlbší tón; skreslenie 10 je čistý tón. Tón znie, kým ho nevypneš – dĺžku určuje čakanie. SndRst() stíši všetko. Čakanie sa robí cez počítadlo na adrese 20. Späť: 27. Grafika · Ďalej: 29. Joystick a náhoda\n","t":"28. Zvuk: Sound a SndRst","u":"28-zvuk/"},{"c":"Na čo to je Hra potrebuje vedieť, čo robí hráč, a potrebuje náhodu. Táto kapitola ukazuje čítanie joysticku a náhodné čísla.\nOba programy sú pre emulátor. V emulátore atari800 sa joystick zvyčajne ovláda šípkami alebo číselnou klávesnicou a tlačidlo pravým klávesom Ctrl – presné nastavenie nájdeš v jeho ponuke (kláves F1).\nAko sa to píše Funkcia Čo vráti Stick(port) smer joysticku v porte 0 až 3 STrig(port) tlačidlo joysticku: 0 = stlačené, 1 = pustené Paddle(port) poloha otočného ovládača (paddle) 0 až 7: číslo 1 až 228 PTrig(port) tlačidlo paddla: 0 = stlačené Rand(rozsah) náhodné číslo od 0 po rozsah − 1; Rand(0) dá 0 až 255 Prvý joystick je v porte 0.\nHodnoty Stick 14 10 6 11 15 7 9 5 13 Stred je 15, hore 14, dole 13, vľavo 11, vpravo 7; šikmé smery sú medzi nimi.\nČísla nie sú náhodné. Každý smer je jeden bit, ktorý sa pri vychýlení vynuluje:\nBit Hodnota Smer 0 1 hore 1 2 dole 2 4 vľavo 3 8 vpravo 15 je 1111 – nič nie je vychýlené. 14 je 1110 – bit „hore“ je nula. Preto sa smer najpohodlnejšie skúša bitovým \u0026 z kapitoly 22: (joy\u00261)=0 znamená „hore“. Šikmý smer tak vyjde sám – platia dve podmienky naraz.\nProgram 1: hviezdička na obrazovke Súbor examples/joystick.act:\nAction! ; Joystick: move a star around the screen, the button ends the program BYTE clock=20 ; grows by 1 fifty times a second BYTE cursorOff=752 ; 1 hides the cursor PROC Wait(BYTE ticks) clock=0 WHILE clock\u003cticks DO OD RETURN PROC Main() BYTE x, y, joy Graphics(0) cursorOff=1 Position(2, 0) Print(\"Joystick moves, the button ends\") x=20 y=10 DO Position(x, y) Put('*) Wait(3) IF STrig(0)=0 THEN ; 0 means the button is pressed EXIT FI joy=Stick(0) IF joy#15 THEN ; 15 means the stick is in the middle Position(x, y) Put(' ) ; rub out the old star IF (joy\u00261)=0 AND y\u003e2 THEN y==-1 FI ; up IF (joy\u00262)=0 AND y\u003c22 THEN y==+1 FI ; down IF (joy\u00264)=0 AND x\u003e2 THEN x==-1 FI ; left IF (joy\u00268)=0 AND x\u003c37 THEN x==+1 FI ; right FI OD Position(2, 23) Print(\"Bye!\") RETURN action26 joystick.act --run Na obrazovke je hviezdička, ktorá sa hýbe podľa joysticku. Tlačidlo program ukončí.\nAko to funguje Toto je hlavná slučka hry v najjednoduchšej podobe. Každý prechod:\nnakreslí hviezdičku na aktuálne miesto, chvíľu počká (Wait(3) – bez toho by hviezdička lietala rýchlejšie, než sa dá ovládať), pozrie na tlačidlo a prípadne skončí, prečíta joystick; ak je vychýlený, zmaže starú hviezdičku medzerou a zmení súradnice. Podmienky y\u003e2, y\u003c22, x\u003e2, x\u003c37 držia hviezdičku na obrazovke.\nPremenná sa volá joy, nie stick. Meno stick by zakrylo funkciu Stick (veľké a malé písmená sa nerozlišujú) a prekladač by Stick(0) odmietol s error ACT021: illegal array.\nProgram 2: kocka Súbor examples/dice.act:\nAction! ; Rand: throwing a die PROC Main() BYTE i, throw BYTE ARRAY counts(7) Zero(counts, 7) Print(\"Ten throws: \") FOR i=1 TO 10 DO throw=Rand(6)+1 ; Rand(6) gives 0 to 5 PrintB(throw) Put(' ) counts(throw)==+1 OD PutE() FOR i=1 TO 6 DO PrintB(i) Print(\" came \") PrintB(counts(i)) PrintE(\" times\") OD PutE() Print(\"Press any key\") GetD(7) RETURN action26 dice.act --run Výpis je pri každom spustení iný, napríklad:\nTen throws: 3 1 5 2 2 4 3 6 2 1 1 came 2 times 2 came 3 times 3 came 2 times 4 came 1 times 5 came 1 times 6 came 1 times Press any key Ako to funguje Rand(6) dá číslo 0 až 5. Kocka má 1 až 6, preto +1. counts je pole počítadiel: counts(throw)==+1 zväčší počítadlo pre hodené číslo. Pole má 7 prvkov, aby sa dali použiť indexy 1 až 6 priamo; prvok 0 ostane nevyužitý. Zero(counts, 7) pole pred použitím vynuluje (kapitola 31). V simulátore náhoda nefunguje. Rand číta zvukový čip, ktorý simulátor nemá, a vracia stále to isté číslo. Programy s Rand skúšaj v emulátore.\nPaddle Paddle je otočný ovládač – koliesko. Paddle(0) vráti číslo podľa natočenia, približne 1 až 228. Typické použitie je pálka v hre Breakout: x=Paddle(0)/2 prevedie natočenie na stĺpec v režime 7. Paddle sa pripájali po dvoch do jedného portu, preto je ich až osem (0 až 7).\nČasté chyby Čo sa stalo Čo sa stane IF STrig(0)=1 v zmysle „stlačené“ je to naopak: stlačené je 0 premenná s menom stick alebo strig zakryje funkciu knižnice; error ACT021: illegal array Rand(6) v zmysle 1 až 6 dáva 0 až 5 slučka hry bez čakania pohyb je príliš rýchly a trhaný súradnica typu BYTE klesne pod 0 pretočí sa na 255 a kurzor je mimo obrazovky (chyba 141) – preto kontroly okrajov Vyskúšaj si Zmeň hviezdičku na iný znak a zrýchli pohyb. Nechaj za hviezdičkou stopu – nezmazávaj starú polohu. Polož na náhodné miesto obrazovky znak O (Rand(36)+2, Rand(20)+2) a ukonči program, keď naň hviezdička príde. Zhrnutie Stick(0) vráti smer: 15 je stred, bity 1, 2, 4, 8 znamenajú hore, dole, vľavo, vpravo a pri vychýlení sú nulové. STrig(0) je 0, keď je tlačidlo stlačené. Rand(n) dá 0 až n−1. Hra je slučka: nakresli, počkaj, prečítaj ovládač, pohni. Premenné nepomenúvaj rovnako ako rutiny knižnice. Späť: 28. Zvuk · Ďalej: 30. Súbory\n","t":"29. Joystick a náhoda: Stick, STrig, Paddle, PTrig, Rand","u":"29-ovladace/"},{"c":"Na čo to je Čo program vypočíta, sa po vypnutí stratí – pokiaľ to neuloží do súboru na disketu. Rovnakým spôsobom, akým sa číta a píše súbor, komunikuje Atari so všetkými zariadeniami: s obrazovkou, klávesnicou aj tlačiarňou.\nZariadenia a kanály Každé zariadenie má meno z jedného písmena a dvojbodky:\nMeno Zariadenie E: editor – obrazovka a klávesnica spolu (to, cez čo si doteraz písal a čítal) K: klávesnica – jeden stlačený kláves, bez čakania na RETURN S: obrazovka v grafickom režime P: tlačiareň D: disketa; za dvojbodkou je meno súboru: D:NOTES.TXT C: kazeta Meno súboru na diskete má najviac 8 znakov, bodku a najviac 3 znaky prípony, veľkými písmenami.\nProgram so zariadením nehovorí priamo, ale cez kanál – očíslovanú „linku“ 0 až 7. Najprv kanál otvorí, potom cez neho číta alebo píše, a nakoniec ho zavrie.\nKanál Kto ho používa 0 E: – otvorený od začiatku; sem píše Print a odtiaľ číta InputS 1 až 5 voľné pre tvoj program 6 S: – otvára ho Graphics 7 K: – preto GetD(7) čaká na kláves Ako sa to píše Action! Open(kanál, \"meno\", režim, 0) … Close(kanál) Režim Význam 4 čítanie 8 zápis – súbor sa vytvorí; ak existoval, prepíše sa 9 pripisovanie na koniec existujúceho súboru 12 čítanie aj zápis 6 čítanie zoznamu súborov na diskete (meno je potom maska, napr. \"D:*.*\") Rutiny, ktoré poznáš, majú verziu pre kanál – s písmenom D (device) v mene a číslom kanála ako prvým parametrom:\nNa obrazovku Na kanál Print(s), PrintE(s) PrintD(k, s), PrintDE(k, s) PrintB(n), PrintBE(n) PrintBD(k, n), PrintBDE(k, n) PrintC, PrintI PrintCD, PrintID (a s E na konci) Put(c), PutE() PutD(k, c), PutDE(k) InputS(s) InputSD(k, s) InputB(), InputC(), InputI() InputBD(k), InputCD(k), InputID(k) – GetD(k) – funkcia, vráti jeden znak (bajt) Koniec súboru: EOF je pole knižnice. Keď čítanie z kanála k narazí na koniec súboru, EOF(k) prestane byť nula.\nCelý program Súbor examples/files.act:\nAction! ; Files: write three lines to a disk file and read them back PROC Main() CHAR ARRAY line(80) BYTE count Open(1, \"D:NOTES.TXT\", 8, 0) ; 8 = write (a new file) PrintDE(1, \"The first line\") PrintDE(1, \"The second line\") PrintD(1, \"Number \") PrintBDE(1, 42) Close(1) PrintE(\"The file is written.\") PutE() count=0 Open(1, \"D:NOTES.TXT\", 4, 0) ; 4 = read DO InputSD(1, line) IF EOF(1) THEN EXIT FI count==+1 PrintB(count) Print(\": \") PrintE(line) OD Close(1) PutE() PrintB(count) PrintE(\" lines read.\") RETURN Preklad a spustenie Tento program beží aj v simulátore:\naction26 files.act --sim Simulátor má „disketu“ len v pamäti: súbor existuje, kým program beží, a potom zmizne.\nV emulátore potrebuje program skutočnú disketu s operačným systémom diskov (DOS). Ako sa to robí, je v kapitole 34; v skratke – skopíruj si obraz diskety s DOS-om (napríklad dos25.atr) a napíš:\naction26 files.act --atr dos25.atr --run Program sa uloží na disketu tak, aby sa po zapnutí Atari sám spustil, a súbor NOTES.TXT na nej ostane.\nČo uvidíš The file is written. 1: The first line 2: The second line 3: Number 42 3 lines read. Ako to funguje Zápis. Open(1, \"D:NOTES.TXT\", 8, 0) otvorí na kanáli 1 nový súbor. PrintDE(1, …) doň píše presne to, čo by PrintE napísal na obrazovku. Tretí riadok vznikne z dvoch príkazov, ako na obrazovke. Close(1) súbor zavrie – až vtedy je naozaj celý na diskete.\nČítanie. Súbor sa otvorí znova, tentoraz v režime 4. Slučka číta riadok po riadku cez InputSD. Po každom čítaní sa pozrie na EOF(1): keď je nenulové, riadok sa už neprečítal a slučka končí.\nTest konca súboru je za čítaním a pred spracovaním riadka. Koniec sa totiž zistí až pri pokuse čítať ďalej.\nPosledný parameter Open je pri bežnej práci vždy 0.\nČítanie po bajtoch Textové súbory sa čítajú po riadkoch cez InputSD. Iné súbory – obrázky, dáta hry – sa čítajú po bajtoch:\nAction! Open(1, \"D:PICTURE.DAT\", 4, 0) DO value=GetD(1) IF EOF(1) THEN EXIT FI … ; spracuj value OD Close(1) Zápis po bajtoch je PutD(1, value).\nĎalšie operácie s diskom Rutina Čo robí XIO(k, 0, 33, 0, 0, \"D:MENO.TXT\") zmaže súbor XIO(k, 0, 32, 0, 0, \"D:STARE.TXT,NOVE.TXT\") premenuje súbor XIO(k, 0, 35, 0, 0, \"D:MENO.TXT\") zamkne súbor proti zmazaniu; 36 odomkne Note(k, @sektor, @posun) zapamätá si miesto v otvorenom súbore (do CARD sektor a BYTE posun) Point(k, sektor, posun) vráti sa na zapamätané miesto XIO je všeobecný príkaz pre zariadenie; kanál k musí byť voľný (zatvorený). Tieto operácie a zoznam súborov (režim 6) skúšaj v emulátore s disketou – simulátor vie spoľahlivo len čítať, písať a pripisovať. Note a Point dovoľujú skákať v súbore – napríklad vrátiť sa na začiatok záznamu bez čítania všetkého pred ním.\nČasté chyby Čo sa stalo Čo sa stane súbor na čítanie neexistuje Err: 170 a program skončí kanál je už otvorený Err: 129 čítanie alebo zápis na neotvorený kanál Err: 133 chýba Close po zápise koniec súboru sa na disketu nedostane režim 8 na existujúci súbor starý obsah je preč v emulátore nie je disketa s DOS-om Err: 130 – zariadenie D: neexistuje riadok v súbore je dlhší ako pole InputSD prepíše pamäť; použi InputMD(k, pole, veľkosť), ktorá dĺžku stráži Chyba pri práci so zariadením program ukončí výpisom Err: a čísla. Ako ju zachytiť a pokračovať, ukáže nasledujúca kapitola. Čísla chýb sú v prílohe C.\nVyskúšaj si Zmeň režim druhého Open zo 4 na 9 a namiesto čítania pripíš do súboru ďalší riadok. Potom súbor prečítaj. Nechaj používateľa písať riadky (InputS) a ukladaj ich do súboru, kým nezadá prázdny riadok (dĺžka 0). Vypíš obsah diskety: otvor \"D:*.*\" v režime 6 a čítaj riadky ako zo súboru. (V emulátore s disketou.) Zhrnutie Zariadenia majú mená E:, K:, S:, P:, D:meno. Open(kanál, meno, režim, 0) otvorí, Close(kanál) zavrie. Režim 4 číta, 8 píše, 9 pripisuje. Rutiny s D v mene pracujú s kanálom: PrintDE, InputSD, GetD, PutD. EOF(kanál) je nenulové po dosiahnutí konca súboru. Bez Close zápis nie je dokončený. Späť: 29. Joystick a náhoda · Ďalej: 31. Bloky pamäte a chyby\n","t":"30. Súbory: Open, Close a vstup a výstup cez kanály","u":"30-subory/"},{"c":"Na čo to je Prvá polovica kapitoly: tri rutiny, ktoré spravia naraz to, na čo by si inak písal slučku – vynulujú, vyplnia alebo skopírujú kus pamäte. Sú napísané v strojovom kóde a sú mnohonásobne rýchlejšie ako slučka FOR.\nDruhá polovica: čo sa stane, keď za behu programu nastane chyba, a ako ju zachytiť.\nBloky: ako sa to píše Rutina Čo robí Zero(adresa, počet) vynuluje počet bajtov od adresy SetBlock(adresa, počet, hodnota) vyplní počet bajtov hodnotou MoveBlock(kam, odkiaľ, počet) skopíruje počet bajtov Adresa je najčastejšie meno poľa (kapitola 20: meno poľa je jeho adresa). Pri MoveBlock je cieľ prvý, ako pri SCopy.\nPočet je v bajtoch. Pole CARD ARRAY t(10) má 20 bajtov.\nChyby: ako to funguje Keď rutina knižnice narazí na problém – súbor neexistuje, bod je mimo obrazovky –, zavolá procedúru Error s číslom chyby. Tá, ktorá je v knižnici, vypíše\nErr: 170 a program ukončí.\nError sa dá vymeniť za vlastnú:\nAction! PROC MyError(BYTE code) … RETURN … Error=MyError Priradenie Error=MyError presmeruje všetky ďalšie chyby do tvojej procedúry. Tá dostane číslo chyby ako parameter. Keď sa vráti, program pokračuje za rutinou, v ktorej chyba nastala.\nBreak() je rutina, ktorá sama vyvolá chybu 128 – tú istú, ako keď používateľ stlačí kláves BREAK.\nCelý program Súbor examples/blocks.act:\nAction! ; Blocks of memory, and an error handler of our own BYTE ARRAY a(10), b(10) PROC Show(BYTE ARRAY t) BYTE i FOR i=0 TO 9 DO PrintB(t(i)) Put(' ) OD PutE() RETURN PROC MyError(BYTE code) PutE() Print(\"Something went wrong, error \") PrintBE(code) IF code=170 THEN PrintE(\"The file does not exist.\") FI RETURN PROC Main() Zero(a, 10) ; ten bytes of zeros Print(\"Zero: \") Show(a) SetBlock(a, 10, 7) ; ten bytes with the value 7 Print(\"SetBlock: \") Show(a) a(0)=1 a(1)=2 a(2)=3 MoveBlock(b, a, 10) ; copy ten bytes from a to b Print(\"MoveBlock: \") Show(b) Error=MyError ; from now on errors call MyError Open(1, \"D:MISSING.TXT\", 4, 0) Close(1) PrintE(\"The program goes on.\") RETURN Preklad a spustenie action26 blocks.act --sim Čo uvidíš Zero: 0 0 0 0 0 0 0 0 0 0 SetBlock: 7 7 7 7 7 7 7 7 7 7 MoveBlock: 1 2 3 7 7 7 7 7 7 7 Something went wrong, error 170 The file does not exist. The program goes on. Ako to funguje Zero(a, 10) – desať núl. Hodí sa pred každým použitím poľa počítadiel. SetBlock(a, 10, 7) – desať sedmičiek. MoveBlock(b, a, 10) – pole b je kópiou poľa a. Takto sa kopírujú polia; priradenie b=a nefunguje (kapitola 18). Error=MyError – od tohto riadka chyby neukončia program. Open neexistujúceho súboru zavolá MyError(170), tá vypíše hlásenie a po jej RETURN program ide ďalej. Vlastná obsluha chýb má jednu povinnosť: program po nej beží ďalej, aj keď sa operácia nepodarila. Tu sa súbor neotvoril, takže čítať z neho nemá zmysel. Skutočný program si preto v obsluhe poznačí, že nastala chyba (do globálnej premennej), a za rizikovou operáciou sa na ňu pozrie:\nAction! BYTE failed PROC MyError(BYTE code) failed=code RETURN … failed=0 Open(1, \"D:DATA.TXT\", 4, 0) IF failed THEN PrintE(\"Cannot open the file.\") ELSE … ; čítaj súbor Close(1) FI Najčastejšie čísla chýb Číslo Význam 128 stlačený kláves BREAK 129 kanál je už otvorený 130 zariadenie neexistuje (napr. D: bez DOS-u) 133 kanál nie je otvorený 136 koniec súboru – nevolá Error, len nastaví EOF(kanál) 137 riadok je dlhší ako miesto preň 138 zariadenie neodpovedá (vypnutá disketová jednotka) 141 kurzor alebo bod mimo obrazovky 162 disketa je plná 170 súbor neexistuje Úplný zoznam je v prílohe C.\nČasté chyby Čo sa stalo Čo sa stane počet v prvkoch namiesto v bajtoch pri CARD ARRAY spracuje sa len polovica poľa MoveBlock s prehodeným cieľom a zdrojom skopíruje sa opačným smerom a zdroj je prepísaný blok dlhší ako pole prepíše sa pamäť za poľom kopírovanie v rámci toho istého poľa smerom nahor (cieľ je vyššie ako zdroj a prekrývajú sa) kópia si prepíše vlastný zdroj; MoveBlock kopíruje od začiatku vlastná Error sa volá Error nahradí knižničnú úplne – aj to je dovolený spôsob Vyskúšaj si Deklaruj CARD ARRAY t(5), naplň ho a vynuluj cez Zero. Koľko bajtov treba? Doplň do programu premennú failed podľa ukážky a vypíš Cannot open the file. Zavolaj v programe Break() a pozri, aké číslo dostane MyError. Zhrnutie Zero, SetBlock a MoveBlock pracujú s blokom bajtov naraz a rýchlo. Počet je v bajtoch; pri MoveBlock je cieľ prvý. Chyba za behu volá Error(číslo); predvolená vypíše Err: číslo a skončí. Error=MojaProcedura chyby presmeruje; program potom pokračuje. Koniec súboru nie je chyba – hlási ho EOF(kanál). Späť: 30. Súbory · Ďalej: 32. Prekladač action26\n","t":"31. Bloky pamäte a chyby: Zero, SetBlock, MoveBlock, Error, Break","u":"31-bloky-a-chyby/"},{"c":"Doteraz si z prekladača používal tri veci: action26 program.act, --sim a --run. Táto kapitola prejde ostatné voľby. Od tejto kapitoly ide o veci, ktoré pôvodný Action! na Atari nemal.\nTvar príkazu action26 program.act [voľby] Voľby sa píšu za meno programu, v ľubovoľnom poradí. Úplný zoznam vypíše:\naction26 --help Výstup Voľba Čo robí -o súbor meno výsledného súboru; bez nej je to meno programu s príponou .xex --listing súbor výpis preloženého programu: adresy, bajty a inštrukcie procesora --asm súbor zdroják v assembleri 6502, z ktorého sa dá program zostaviť znova --map súbor zoznam mien s adresami --lab súbor zoznam mien pre ladiace nástroje emulátorov --memory po preklade vypíše, koľko pamäte program zaberá a koľko ešte ostáva voľnej, vrátane pamäte pod ROM --memory-map to isté, ale s výpisom každého kúska pamäte po adresách --reserve od-do pamäť, ktorú program používa len za behu a nie je v súbore (napríklad buffer obrázka $A100-$B7BF); dá sa zadať viackrát --mem-lo adresa, --mem-top adresa v akom rozsahu pamäte sa voľné miesto počíta (predvolene $0700 až $BBFF) --org adresa adresa, od ktorej program v pamäti začína (predvolene $2000) action26 hello.act -o HELLO.XEX --listing hello.lst Koľko pamäte ešte ostáva Pri väčšom programe, napríklad textovke, sa hodí vedieť, či sa ešte zmestí ďalší text. --memory to po preklade napíše:\naction26: memory [######################--------] 76 % full used by the program: 35121 bytes still free: 11215 bytes biggest free piece: 5826 bytes (a new text or routine has to fit into one piece) free under the ROM: 1380 bytes (biggest piece 1060) Voľná pamäť je rozdelená na kúsky. Nový text alebo rutina sa musí zmestiť do jedného, preto je dôležité hlavne číslo „biggest free piece“. Počíta sa po preklade, takže pamäť, ktorú program alokuje až za behu, v ňom nie je. Polia deklarované na pevnej adrese (ARRAY a(256)=$0700) sa započítajú samé. Buffery, ktoré program používa len za behu a nemá ich ako polia, povedz cez --reserve, napríklad --reserve $A100-$B7BF; inak by sa počítali ako voľné. Rozsah, v ktorom sa počíta, zúž cez --mem-lo a --mem-top.\nPamäť pod ROM ($C000–$CFFF a $D800–$FFF9) a v bankách program zvyčajne využíva na texty a tabuľky; jej voľné miesto je v prehľade na samostatnom riadku, lebo je to iný kus pamäte ako hlavná RAM.\nChceš vidieť, kde presne sú voľné kúsky, použi --memory-map. Každý kúsok je na vlastnom riadku, s adresou od–do:\naction26: memory $0700-$BBFF action26: program $0700-$09F3 756 bytes action26: free $09F4-$0C57 612 bytes action26: program $0C58-$0CE3 140 bytes ... action26: free $9433-$9F5F 2861 bytes Pri väčšom programe si podľa toho nájdeš diery, ktoré sa dajú vyplniť, a vidíš aj hranicu, od ktorej voľné miesto pokračuje až po koniec pamäte (tam sa dá umiestniť halda pre Alloc/Free).\nČo je v listingu Listing ukazuje, na čo sa program preložil. Pre hello.act z kapitoly 2 začína takto:\n; org $2000 2000 Main: 2000 A2 20 LDX #\u003e__L2 2002 A9 0E LDA #\u003c__L2 2004 4C 1C 20 JMP PrintE 2007 __start: 2007 A9 00 LDA #$00 2009 85 B7 STA $B7 200B 4C 00 20 JMP Main 200E __L2: 200E 0D 48 65 6C 6C 6F 2C 20 .BYTE ... 2016 41 74 61 72 69 21 ; runtime: print 201C PrintE: Vľavo je adresa, za ňou bajty v pamäti a vpravo inštrukcia procesora. Vidno tri veci:\nprocedúra Main má tri inštrukcie: do registrov dá adresu textu a skočí do PrintE; text Hello, Atari! je uložený hneď za ňou (0D je jeho dĺžka, 13); za programom nasleduje runtime – rutiny knižnice. action26 pribalí len tie, ktoré program používa. Preto má celý hello.xex 277 bajtov. Listing nemusíš vedieť čítať. Je užitočný, keď chceš vedieť, koľko miesta čo zaberá, alebo keď sa učíš assembler.\nSpúšťanie Voľba Čo robí --sim spustí program vo vstavanom simulátore; klávesnica je klávesnica tvojho počítača --sim-stats ako --sim, na konci vypíše počet vykonaných inštrukcií --sim-limit n simulátor skončí najneskôr po n miliónoch inštrukcií (predvolene 10) --sim-mem druh akú pamäť má simulovaný počítač: 64, 130xe a väčšie (kapitola 38) --run spustí program v emulátore atari800 --emulator súbor kde je atari800.exe, ak nie je v priečinku atari800 vedľa prekladača Čo simulátor vie a čo nie:\nVie Nevie výpis textu a vstup z klávesnice kresliť obrazovku, farby, grafické režimy súbory na D: (len v pamäti, počas behu) zvuk výpočty, polia, reťazce, ukazovatele joystick a paddle rozšírenú pamäť (--sim-mem) náhodné čísla (Rand vracia stále to isté) časovač na adrese 20 Simulátor je rýchly spôsob, ako skúšať logiku programu. Na všetko, čo má byť vidieť a počuť, je emulátor.\n--sim-stats sa hodí na porovnanie dvoch verzií programu – ktorá je rýchlejšia:\naction26 for.act --sim-stats action26: 6900 instruction(s) executed Program, ktorý beží dlhšie ako desať miliónov inštrukcií, simulátor zastaví hlásením instruction limit reached. Ak to nie je nekonečná slučka, limit zväčši: --sim-limit 100.\nZdrojový text Voľba Čo robí -I priečinok kde hľadať súbory z INCLUDE (kapitola 23) -D meno=text zavedie DEFINE meno=\"text\" pred začiatkom programu --case-sensitive rozlišuje veľké a malé písmená v menách --modern zapne rozšírenia jazyka (kapitoly 35 až 39) --no-config ignoruje nastavenia napísané v zdrojáku (kapitola 33) -D: meno z príkazového riadka Súbor examples/stars-count.act používa meno COUNT, ktoré v programe nikto nedeklaroval:\nAction! ; A name given on the command line: action26 stars-count.act -D COUNT=7 PROC Main() BYTE i FOR i=1 TO COUNT DO Put('*) OD PutE() RETURN action26 stars-count.act -D COUNT=7 --sim ******* Bez -D prekladač ohlási error ACT008: undeclared name 'COUNT'. Hodí sa to, keď z jedného zdrojáka robíš viac verzií programu – skúšobnú a ostrú, anglickú a slovenskú.\nOptimalizácia Voľba Čo robí -O2 najmenší a najrýchlejší kód – predvolené -O1 menej úprav -O0 kód v takom tvare, aký by dal pôvodný Action! Program sa správa vo všetkých troch prípadoch rovnako, líši sa veľkosť a rýchlosť. Pre for.act z kapitoly 13: 665 bajtov s -O0, 612 s -O1 a 589 s -O2.\n-O0 má zmysel, keď porovnávaš výsledok s pôvodným prekladačom alebo keď program obsahuje strojový kód, ktorý sa spolieha na presný tvar okolitého kódu.\nNečitateľný súbor Voľba Čo robí --scramble zakóduje výsledný súbor, aby sa v ňom nedalo nič prečítať --scramble-fx meno to isté, a kým sa program po nahratí dekóduje, na obrazovke beží efekt --scramble-level číslo to isté, s úrovňou zakódovania: 1 (predvolená) alebo silnejšia 2 --scramble-key číslo kľúč, od ktorého sa kóduje (napríklad $3A7F); s ním dá každý preklad rovnaký súbor Texty, ktoré program vypisuje, ležia v súbore XEX tak, ako si ich napísal. Kto súbor otvorí v editore, prečíta si ich – pri textovej hre aj riešenie. Súbor examples/secret.act:\nAction! ; A file nobody can read: action26 secret.act --scramble PROC Main() PrintE(\"The password is SESAME.\") RETURN Prelož ho najprv obyčajne a nechaj Windows pohľadať v súbore slovo SESAME:\naction26 secret.act findstr /m SESAME secret.xex secret.xex findstr /m vypíše meno súboru, v ktorom slovo našiel. Teraz to isté s --scramble:\naction26 secret.act --scramble findstr /m SESAME secret.xex Tentoraz nevypíše nič – slovo v súbore nie je. Program pritom robí presne to isté:\naction26 secret.act --scramble --sim The password is SESAME. Čo prekladač urobil Hotový program prekódoval bajt po bajte a pridal k nemu krátky dekodér. Ten sa po nahratí súboru spustí ako prvý, vráti pamäť do pôvodného stavu a až potom spustí tvoj program. V zdrojáku nemeníš nič a program o dekodéri nevie. Aj samotný dekodér je v súbore zakódovaný: pred ním leží krátky prvý stupeň (24 bajtov), ktorý ho pri prvom zavolaní rozkóduje na mieste. Zo súboru sa tak nedá prečítať ani kód dekodéra, ani jeho kľúč.\nČo to stojí, povie --verbose:\naction26: scrambled 275 bytes (level 1, key $A7), decoder at $0600 (108 bytes), file 112 bytes longer Súbor je dlhší asi o 110 bajtov – tu 399 namiesto 287. Pamäť programu sa nezmenšila. Dekodér leží mimo neho, na adrese $0600 (ak tam program sám niečo nahráva, tak hneď za programom), a po štarte ho program môže pokojne prepísať. Štart trvá o chvíľu dlhšie. Hra s 26 kilobajtmi sa dekóduje asi pol sekundy. Nie je to ochrana. Kto program spustí v emulátore, vidí v jeho pamäti všetko už dekódované. Zakódovanie bráni len tomu, aby si texty niekto prečítal priamo zo súboru.\nSilnejšie zakódovanie: --scramble-level 2 Bežné --scramble kóduje každý bajt pomocou bajtu pred ním. Je to rýchle a dekodér je krátky, no kto ten postup pozná, napíše si program, ktorý súbor rozkóduje bez spúšťania. Voľba --scramble-level vyberá úroveň zakódovania:\nÚroveň Ako kóduje Dekodér 26 KB trvá 1 každý bajt XOR bajt pred ním (predvolená, to isté ako --scramble) 108 bajtov 0,50 s 2 každý bajt XOR číslo z 16-bitového generátora pseudonáhodných čísel (LFSR) +12 asi 0,9 s action26 secret.act --scramble-level 2 --scramble-level už znamená --scramble, oboje písať netreba. Efekty fungujú rovnako, napríklad --scramble-level 2 --scramble-fx bars.\nPri úrovni 2 čísla, ktorými sa bajty kódujú, vôbec nezávisia od programu a generátor beží bez prerušenia cez celý súbor – v súbore do 64 KB sa teda nikde neopakujú. Kto ich chce odstrániť, musí generátor napodobniť a poznať číslo, od ktorého začína – kľúč. Bez voľby --scramble-key si prekladač pri každom preklade vyberie nový náhodný kľúč, takže ten istý zdroják dá zakaždým iný súbor. Ak chceš, aby bol súbor pri každom preklade rovnaký (napríklad na porovnanie dvoch verzií), kľúč zadaj sám:\naction26 secret.act --scramble-level 2 --scramble-key $3A7F --verbose action26: scrambled 275 bytes (level 2, key $3A7F), decoder at $0600 (120 bytes), file 124 bytes longer Kľúč je číslo od $0001 do $FFFF; nula nejde, generátor by z nej vyrábal len nuly. Pri úrovni 1 je kľúč jeden bajt od $01 do $FF, bez voľby platí $A7.\nKľúč ani tu nie je v súbore čitateľne, dekodér je zakódovaný rovnako ako pri úrovni 1. Čitateľný ostane len prvý stupeň a tabuľka, ktoré úseky pamäte sa majú dekódovať.\nAni úroveň 2 nie je ochrana: emulátor ukáže pamäť už dekódovanú a kto prvý stupeň pochopí, dostane sa ďalej. Len to dá podstatne viac práce.\nEfekty: --scramble-fx Pol sekundy, počas ktorej sa na obrazovke nič nedeje, vyzerá ako zaseknutý počítač. Staré programy na Atari preto pri rozbaľovaní kreslili pruhy. --scramble-fx meno zakóduje súbor rovnako ako --scramble a pridá do dekodéra efekt:\naction26 secret.act --scramble-fx bars --run Efekt uvidíš len v emulátore (--run) alebo na skutočnom Atari – simulátor (--sim) obrazovku nekreslí. Pri takom malom programe iba preblikne; poriadne ho vidno pri programe s desiatkami kilobajtov.\nMeno Čo je na obrazovke Dekodér 26 KB trvá none nič – to isté ako --scramble +0 bajtov 0,50 s bars farebné pásy cez celú obrazovku +6 0,68 s bars-border farebné pásy len na okrajoch +3 0,58 s mono čiernobiele pásy cez celú obrazovku +8 0,72 s mono-border čiernobiele pásy na okrajoch +5 0,64 s rainbow pravidelná dúha cez celú obrazovku +6 0,68 s rainbow-border dúha na okrajoch +3 0,58 s slow široké pomalé pásy cez celú obrazovku +6 0,50 s slow-border široké pomalé pásy na okrajoch +3 0,50 s dots bodky po celej obrazovke – znaky sa zmenia na zrnenie +3 0,58 s dots-bars bodky a farebné pásy naraz +9 0,76 s blank obrazovka zhasne, nič sa nekreslí +20 0,36 s bars-blank obrazovka zhasne, farebné pásy cez celú plochu +23 0,42 s inc obrazovka zhasne, biele čiarky na tmavočervenej ploche +28 0,48 s inc-border biele čiarky na tmavočervených okrajoch +8 0,66 s Ako si vybrať:\nČo najrýchlejší štart: blank. Zhasnutá obrazovka neberie procesoru čas, preto je dekódovanie rýchlejšie než úplne bez efektu. Efekt zadarmo: slow a slow-border. Farbu menia len raz za 256 bajtov, takže nič nespomalia. Nech obrazovka ostane čitateľná: varianty -border kreslia len do okrajov; text v strede ostane, ako bol. Ako za starých čias: bars alebo inc – ten kreslí to, čo rozbaľovač Super Packer. Tri veci, ktoré je dobré vedieť:\n„Celá obrazovka“ platí pre bežnú textovú obrazovku, na ktorej sa program nahráva. dots je vidno len v textových režimoch. Farby aj znaky sa po dekódovaní vrátia samy, program nemusí nič upratovať. Pri programe s dátami v skrytej pamäti (kapitola 38) beží dekodér po kúskoch počas celého nahrávania. Efekty so zhasnutou obrazovkou (blank, bars-blank, inc) vtedy blikajú. Voľbu si program môže niesť v sebe, riadkom ;@compile --scramble-fx bars na začiatku zdrojáka (kapitola 33). Rovnako ;@compile --scramble-level 2 --scramble-key $3A7F.\nČasté chyby Hlásenie Príčina error ACT200: invalid effect for --scramble-fx: stars (none, bars, …) efekt s takým menom nie je; v zátvorke sú všetky, ktoré prekladač pozná error ACT200: missing effect after --scramble-fx (none, bars, …) za --scramble-fx chýba meno efektu; bez efektu stačí --scramble warning ACT232: --scramble-fx inc on the command line overrides bars in the source zdroják si pýta jeden efekt a príkazový riadok iný; platí príkazový riadok error ACT200: invalid level for --scramble-level: 3 (1, 2) takú úroveň prekladač nepozná; sú len 1 a 2 error ACT200: invalid value for --scramble-key: $1FFFF (a number up to $FFFF, e.g. $3A7F) kľúč je 16-bitové číslo, najviac $FFFF error ACT200: --scramble-key for --scramble-level 1 is a byte from $01 to $FF úroveň 1 má kľúč len jeden bajt; dlhší kľúč patrí k úrovni 2 error ACT200: --scramble-key must not be 0 with --scramble-level 2 generátor úrovne 2 nemôže začínať od nuly; zvoľ iný kľúč Zbalený súbor Voľba Čo robí --pack-xex zbalí výsledný súbor; Atari si ho počas nahrávania samo rozbalí Disketová mechanika Atari je pomalá. Kratší súbor sa preto nahrá rýchlejšie a na disketu sa ich zmestí viac. Starí programátori na to mali programy ako Super Packer; v Action26 stačí voľba. Program pm-lanes.act z kapitoly 42:\naction26 pm-lanes.act --pack-xex --verbose action26: packed 1 segments, loader at $0600 (180 bytes), buffer at $294D, file 2393 -\u003e 1959 bytes Súbor sa skrátil z 2393 bajtov na 1959. Spúšťa sa rovnako ako predtým (--run, z DOS-u, z diskety s autorunom) a program o zbalení nevie.\nČo prekladač urobil Každý kus programu zbalil (formátom ZX02, ktorý poznáš z PACK ZX02 v kapitole 39) a pridal krátky rozbaľovač so 180 bajtmi. DOS najprv nahrá rozbaľovač, potom zbalený kus a hneď ho zavolá; rozbaľovač kus rozbalí na jeho miesto. Až keď je všetko rozbalené, spustí sa tvoj program.\nPamäť programu sa nezmenšila. Rozbaľovač leží na adrese $0600 (ak tam program sám niečo nahráva, tak za programom) a zbalené dáta za programom. Oboje treba len počas nahrávania, po štarte ich program môže pokojne prepísať. Funguje s hocijakým DOS-om, aj s dátami v skrytej pamäti (kapitola 38) – aj tie sa zbalia. Malému programu nepomôže. Rozbaľovač má 180 bajtov, takže secret.act z predchádzajúcej časti by narástol z 287 na 455 bajtov. Oplatí sa to až pri programoch s niekoľkými kilobajtmi, hlavne s textami a obrázkami, ktoré sa dobre balia. Voľbu si program môže niesť v sebe riadkom ;@compile --pack-xex (kapitola 33).\nZbalený a zakódovaný Zbalený súbor sa v editore číta horšie, no texty z neho nezmiznú. Kus, ktorý sa v programe neopakuje, si zbaľovač uloží tak, ako je:\naction26 secret.act --pack-xex findstr /m SESAME secret.xex secret.xex Ak sa texty nemajú dať prečítať, pridaj --scramble:\naction26 secret.act --pack-xex --scramble findstr /m SESAME secret.xex Teraz findstr nenájde nič. Prekladač najprv zbalí a potom zakóduje zbalené dáta; rozbaľovač ich pri nahrávaní najprv rozkóduje a potom rozbalí. Funguje to s oboma úrovňami aj s kľúčom (--scramble-level 2, --scramble-key), len efekty --scramble-fx so zbalením nejdú. Rozbaľovač narastie na 231 bajtov (s úrovňou 2 na 245).\nZakódujú sa všetky kusy programu, ktoré sa dajú zbaliť, aj keď sa zbalením neskrátia. Čitateľné ostanú len drobnosti: adresa štartu a nastavenia pod adresou $0400, napríklad farby.\nČasté chyby Hlásenie Príčina error ACT200: --pack-xex cannot show an effect: --scramble-fx bars only without --pack-xex (…) zbalený súbor sa dá zakódovať, ale bez efektu; nechaj --scramble alebo --scramble-level error ACT200: --pack-xex: no segment gets shorter program je taký malý, že by sa zbalením len predĺžil; prelož ho bez --pack-xex Upozornenia a chyby Voľba Čo robí --strict upozorní na všetko, čo by pôvodný Action! odmietol --quirks napodobní aj známe chyby pôvodného prekladača --wextra ďalšie upozornenia – napríklad volanie s menším počtom argumentov --werror upozornenia sú chyby: program s varovaním sa nepreloží --max-errors n po koľkých chybách prestať (predvolene 20) --verbose vypíše, čo prekladač robí: veľkosť, adresy --strict použi, keď má tvoj program bežať aj v pôvodnom Action! na skutočnom Atari. --quirks použi, keď prekladáš starý program, ktorý sa spolieha na chyby originálu, a potrebuješ, aby sa správal presne ako kedysi. Vylučuje sa s --modern. --wextra --werror je dobrá dvojica pre vlastné programy: prekladač je prísnejší a nedovolí varovania prehliadať. Návratová hodnota Pre toho, kto prekladač volá zo skriptu: 0 znamená úspech, 1 chyby v programe, 2 chybu v príkazovom riadku.\nZhrnutie -o mení meno výstupu, --listing ukáže preložený kód. --sim je na logiku, --run na všetko, čo má byť vidieť a počuť. -I pridáva priečinky pre INCLUDE, -D zavádza mená. Predvolená optimalizácia -O2 je najlepšia; -O0 napodobňuje originál. --scramble urobí súbor nečitateľným za cenu asi 110 bajtov a pol sekundy pri štarte; --scramble-fx k tomu pridá efekt na obrazovke a --scramble-level 2 silnejšie kódovanie s náhodným alebo zadaným kľúčom. --pack-xex zbalí súbor, aby sa rýchlejšie nahral; oplatí sa pri programoch s niekoľkými kilobajtmi. S --scramble sa zbalené dáta aj zakódujú. --strict stráži zlučiteľnosť s pôvodným Action!, --modern zapína rozšírenia. --memory po preklade povie, koľko pamäte ešte ostáva a aký veľký je najväčší voľný kus; --memory-map ukáže každý kúsok po adresách, --reserve povie, čo si program zaberá za behu. Späť: 31. Bloky pamäte a chyby · Ďalej: 33. Nastavenia v zdrojáku\n","t":"32. Prekladač action26","u":"32-prekladac/"},{"c":"Na čo to je Program, ktorý potrebuje voľbu --modern alebo inú adresu, by si musel pamätať každý, kto ho prekladá. Lepšie je, keď si to program povie sám. action26 číta nastavenia z komentárov na začiatku zdrojáka.\nSú to komentáre – pôvodný Action! ich preskočí a program sa ním dá preložiť ďalej.\nAko sa to píše Riadky na začiatku súboru, pred prvým riadkom programu:\nRiadok Je to isté ako voľba ;@strict --strict ;@quirks --quirks ;@modern --modern ;@ORG $5000 --org $5000 ;@version 1.3.0.20 najstaršia verzia prekladača, ktorá zdroj preloží; novšia je v poriadku, staršia skončí chybou (štvrté číslo je revízia z File Version) ;@compile voľby voľby, ako by boli na príkazovom riadku ;@CONFIG nič – nepovinný nadpis nad nastaveniami Bodkočiarka a zavináč musia stáť tesne pri sebe a na začiatku riadka. Na veľkosti písmen nezáleží. Za nastavením môže byť obyčajný komentár. Nastavenia môžu stáť aj pod úvodnými komentármi (názov programu, autor), ale pred prvým riadkom, ktorý nie je komentár. Platia len v hlavnom súbore. V súbore vloženom cez INCLUDE sa ignorujú s varovaním. Celý program Súbor examples/config.act:\nAction! ; Settings written in the source ; ;@strict ; warn about everything the original Action! refuses ;@ORG $5000 ; put the program at address $5000 PROC Main() Print(\"This program starts at address \") PrintCE(Main) RETURN Preklad a spustenie Žiadne voľby okrem --sim netreba – program si ich nesie v sebe:\naction26 config.act --sim Čo uvidíš This program starts at address 20480 20480 je $5000. Porovnaj so set.act z kapitoly 23, ktorý to isté robil dvoma riadkami SET.\n;@compile ;@compile berie voľby v rovnakom tvare ako príkazový riadok. Riadkov môže byť viac:\nAction! ;@compile --modern -O1 ;@compile -I lib -D COUNT=7 Povolené sú len voľby, ktoré menia preklad: -I, -D, --set, --org, -O0/-O1/-O2, --max-errors, --initad, --scramble, --scramble-fx, --scramble-level, --scramble-key, --pack-xex, --case-sensitive, --quirks, --modern, --strict, --wextra, --werror.\nHodí sa to na všetko, čo má pre daný program platiť vždy. Hra, ktorej texty nemá nikto čítať zo súboru, si napríklad zakódovanie aj s efektom pýta sama (kapitola 32, časť Nečitateľný súbor):\nAction! ;@compile --scramble-fx bars Hra na diskete, ktorá sa má rýchlo nahrať a zároveň nemá prezradiť texty, si pýta zbalenie aj zakódovanie (kapitola 32, časť Zbalený a zakódovaný):\nAction! ;@compile --pack-xex --scramble Voľby, ktoré zapisujú súbory alebo niečo spúšťajú (-o, --listing, --atr, --run, --sim …), v zdrojáku nie sú dovolené. Stiahnutý cudzí program tak nemôže pri preklade prepísať súbor ani nič spustiť.\nCesta v -I sa berie od priečinka, kde zdroják leží – nie od miesta, odkiaľ prekladač spúšťaš.\nKeď sa zdroják a príkazový riadok nezhodnú Príkazový riadok má prednosť. Prekladač na nezhodu upozorní:\naction26 config.act --org $6000 --sim config.act(4,1): warning ACT232: --org $6000 on the command line overrides $5000 in the source This program starts at address 24576 Keď chceš nastavenia zo zdrojáka vypnúť úplne, použi --no-config:\naction26 config.act --no-config --sim This program starts at address 8192 ;@strict a ;@modern spolu Dá sa zapnúť oboje. Program sa preloží s rozšíreniami a pri každom z nich dostaneš upozornenie, že pôvodný Action! by ho neprijal:\nprogram.act(3,1): warning ACT219: CONST is a language extension of --modern, the original compiler does not know it Hodí sa to, keď chceš vedieť, čo všetko by si musel prepísať, aby program bežal aj v origináli.\nČasté chyby Čo sa stalo Čo povie prekladač preklep v mene (;@stirct) warning ACT231: unknown configuration directive ';@stirct' ignored nastavenie až za prvým riadkom programu warning ACT231 – ignoruje sa medzera medzi ; a @ je to obyčajný komentár; nič sa nenastaví a nič sa nehlási ;@modern spolu s ;@quirks error ACT231 – vylučujú sa výstupná voľba v ;@compile (-o, --run) error ACT231 Vyskúšaj si Zmeň v config.act adresu na $3000 a over výpis. Pridaj ;@compile -D NAME=\"\\\"Atari\\\"\" a v programe vypíš PrintE(NAME). (Úvodzovky vnútri sa píšu \\\".) Napíš medzi ; a @ medzeru a pozri, na akej adrese program začne. Zhrnutie Nastavenia prekladu sa dajú napísať do komentárov na začiatku hlavného súboru. ;@modern, ;@strict, ;@quirks a ;@ORG adresa sú skratky; ;@compile berie voľby ako príkazový riadok. Povolené sú len voľby, ktoré menia preklad, nie výstupné súbory ani spúšťanie. Príkazový riadok má prednosť; --no-config nastavenia zo zdrojáka vypne. Späť: 32. Prekladač action26 · Ďalej: 34. Disky\n","t":"33. Nastavenia v zdrojáku: ;@modern, ;@strict, ;@ORG, ;@compile","u":"33-nastavenia-v-zdrojaku/"},{"c":"Na čo to je Skutočné Atari nahráva programy z diskety. Emulátory a moderné náhrady disketových jednotiek používajú namiesto diskety obraz – jeden súbor s príponou .atr, v ktorom je celý obsah diskety. action26 vie s takými súbormi pracovať priamo: uložiť na ne program, vypísať obsah, kopírovať súbory tam a späť.\nKapitola nemá program v Action!. Sú v nej príkazy, ktoré si môžeš vyskúšať s programom hello-key.act z kapitoly 2.\nČo je DOS Samotné Atari disketám nerozumie. Program, ktorý ho to naučí, sa volá DOS (Disk Operating System) a je na diskete. Po zapnutí si ho Atari z diskety nahrá – tomu sa hovorí bootovanie. Až potom existuje zariadenie D:.\nZ toho plynie: disketa, z ktorej má Atari naštartovať, musí obsahovať DOS. DOS-ov je viac druhov (Atari DOS 2.5, MyDOS, SpartaDOS …); action26 pozná najbežnejšie. Obraz diskety s DOS-om si treba zaobstarať – sú voľne dostupné na stránkach o Atari.\nProgram na disketu: --atr action26 hello-key.act --atr dos25.atr Prekladač program preloží a uloží na disketu dos25.atr tak, aby sa po naštartovaní sám spustil. Na diskete s Atari DOS 2.5 to znamená súbor AUTORUN.SYS:\naction26: stored AUTORUN.SYS on dos25.atr (DOS 2, single density, Atari DOS 2) (Túto správu vypíše s voľbou --verbose.) S --run sa disketa hneď spustí v emulátore:\naction26 hello-key.act --atr dos25.atr --run Toto je spôsob, ako spúšťať programy, ktoré pracujú so súbormi (kapitola 30).\nPracuj na kópii. --atr do obrazu diskety zapisuje. Pôvodný obraz s DOS-om si odlož a pre každý projekt si sprav kópiu.\nKeď disketa neexistuje Ak súbor .atr neexistuje, prekladač vytvorí novú prázdnu disketu a program na ňu uloží. Taká disketa však nemá DOS a Atari z nej nenaštartuje. Prekladač to povie:\naction26: note: my.atr has no DOS, so the program does not start by itself; copy a DOS disk (DOS 2, MyDOS, WolfDOS, SpartaDOS, BW-DOS, LiteDOS) and use that with --atr to get a bootable disk Vlastné meno súboru --atr-name uloží program pod zvoleným menom namiesto automaticky spúšťaného:\naction26 hello-key.act --atr dos25.atr --atr-name HELLO.COM Program sa potom nespustí sám; nahráš ho z ponuky DOS-u.\nČo je na diskete: --atr-list action26 --atr-list dos25.atr dos25.atr: DOS 2, single density (720 sectors of 128 bytes), Atari DOS 2 boots DOS SYS 037 DUP SYS 042 RAMDISK COM 009 SETUP COM 070 COPY32 COM 056 DISKFIX COM 057 FILECOPY COM 025 AUTORUN SYS 004 8 file(s), 407 free sector(s) Prvý riadok hovorí druh diskety a či sa z nej dá naštartovať. Číslo za menom súboru je jeho veľkosť v sektoroch – disketa je rozdelená na sektory po 128 bajtoch.\nKopírovanie súborov: --atr-put a --atr-get Na disketu:\naction26 --atr-put dos25.atr notes.txt NOTES.TXT action26: notes.txt -\u003e dos25.atr:NOTES.TXT (25 bytes) Z diskety:\naction26 --atr-get dos25.atr NOTES.TXT back.txt action26: NOTES.TXT -\u003e back.txt (25 bytes) Posledné meno je v oboch prípadoch nepovinné; bez neho sa použije to isté meno. Súbor sa kopíruje bajt po bajte, bez zmeny.\nTakto dostaneš na disketu dáta pre svoj program (obrázky, texty, úrovne hry) a z diskety to, čo program uložil.\nJe disketa v poriadku: --atr-check action26 --atr-check dos25.atr dos25.atr: DOS 2, single density the file system is consistent Hodí sa pri starých obrazoch diskiet, ktoré môžu byť poškodené.\nTexty: ATASCII a --to-text, --to-atascii Textový súbor na Atari sa od textového súboru na PC líši koncom riadka. Na PC je to dvojica znakov (CR a LF), na Atari jeden znak s kódom 155 ($9B). Ostatné bežné znaky sú rovnaké.\nZdroják si action26 prečíta v oboch tvaroch. Prevod potrebuješ, keď má textový súbor čítať program na Atari, alebo keď chceš zdroják poslať niekomu, kto ho otvorí v pôvodnom Action!.\nZ PC na Atari:\naction26 --to-atascii notes.txt NOTES.ATA Z Atari na PC:\naction26 --to-text NOTES.ATA notes2.txt Bez druhého mena dostane výsledok príponu .ACT, resp. .txt. Vstupný súbor sa nikdy neprepíše.\nPreklad priamo z diskety Keď je zdroják na obraze diskety – napríklad starý program z časopisu –, netreba ho vyťahovať. Stačí pred meno napísať disketu a dvojbodku:\naction26 dos25.atr:HELLO.ACT --sim Súbory z INCLUDE sa potom hľadajú na tej istej diskete. Obraz diskety môže byť aj v -I:\naction26 program.act -I toolkit.atr Prehľad Príkaz Čo robí action26 prog.act --atr disk.atr uloží program na disketu tak, aby sa spustil sám … --atr-name MENO.COM uloží ho pod týmto menom action26 --atr-list disk.atr vypíše súbory action26 --atr-put disk.atr súbor MENO skopíruje súbor na disketu action26 --atr-get disk.atr MENO súbor skopíruje súbor z diskety action26 --atr-check disk.atr skontroluje disketu action26 --to-atascii vstup výstup text z PC na Atari action26 --to-text vstup výstup text z Atari na PC action26 disk.atr:PROG.ACT preloží zdroják, ktorý leží na diskete Časté chyby Čo sa stalo Čo sa stane disketa bez DOS-u Atari z nej nenaštartuje; D: v programe dá chybu 130 zápis na jediný exemplár obrazu s DOS-om obraz je zmenený; nabudúce pracuj na kópii textový súbor skopírovaný na disketu bez prevodu program na Atari vidí celý súbor ako jeden dlhý riadok meno dlhšie ako 8 + 3 znaky disketa také mená nevie Zhrnutie Obraz diskety je súbor .atr. Aby z neho Atari naštartovalo, musí obsahovať DOS. --atr uloží preložený program na disketu, s --run ju hneď spustí. --atr-list, --atr-put, --atr-get a --atr-check pracujú so súbormi na diskete. Texty pre programy na Atari preveď cez --to-atascii. Späť: 33. Nastavenia v zdrojáku · Ďalej: 35. Rozšírenia jazyka\n","t":"34. Disky: obrazy diskiet ATR a prevod textov","u":"34-disky/"},{"c":"Na čo to je Jazyk Action! je z roku 1983 a niektoré veci, ktoré sú dnes bežné, v ňom chýbajú. action26 ich vie doplniť. Sú vypnuté, kým si o ne nepovieš – starý program sa tak nikdy nepokazí tým, že má napríklad premennú menom CASE.\nRozšírenia zapneš riadkom na začiatku zdrojáka:\nAction! ;@modern alebo voľbou --modern na príkazovom riadku. Program s rozšíreniami pôvodný Action! nepreloží. Ak má tvoj program bežať aj v ňom, túto a ďalšie kapitoly nepoužívaj.\nKaždé rozšírenie má v tejto kapitole vlastný krátky program. Všetky sa prekladajú rovnako – ;@modern si nesú v sebe:\naction26 m-const.act --sim CONST: pomenované konštanty Na čo to je DEFINE z kapitoly 17 nahrádza text a má pascu: DEFINE SIZE=\"5+5\" a SIZE*2 dá 15. CONST je pomenovaná hodnota: prekladač ju vypočíta raz a ďalej s ňou narába ako s číslom.\nAko sa to píše Action! CONST MENO=výraz CONST MENO1=výraz, MENO2=výraz CONST TYP MENO=výraz Výraz môže obsahovať čísla, znaky, skoršie konštanty a operátory. Hodnota sa píše bez úvodzoviek.\nCelý program Súbor examples/m-const.act:\nAction! ;@modern ; CONST: named values worked out by the compiler CONST WIDTH=20, HEIGHT=3 CONST CELLS=WIDTH*HEIGHT ; a constant may use earlier ones CONST SIZE=5+5 CONST CHAR FRAME='# PROC Main() BYTE x, y FOR y=1 TO HEIGHT DO FOR x=1 TO WIDTH DO Put(FRAME) OD PutE() OD Print(\"Cells: \") PrintBE(CELLS) Print(\"SIZE*2: \") PrintBE(SIZE*2) ; 20 - with DEFINE it would be 15 RETURN #################### #################### #################### Cells: 60 SIZE*2: 20 Ako to funguje CELLS je 60 už pri preklade – v programe sa nič nenásobí. SIZE*2 je 20, lebo SIZE je hodnota 10, nie text 5+5. Konštanta nezaberá pamäť a nedá sa do nej priradiť.\nENUM: vlastný typ s pomenovanými hodnotami Na čo to je Stav semaforu, smer pohybu, druh nepriateľa – veci, ktoré majú niekoľko pevných možností. S číslami (0 = červená, 1 = zelená) sa ľahko pomýliš. ENUM dá možnostiam mená a prekladač stráži, aby sa nepomiešali s obyčajnými číslami.\nAko sa to píše Action! TYPE Meno=ENUM [PRVA, DRUHA, TRETIA] Meno premenna premenna=Meno.PRVA Hodnota sa píše s menom typu a bodkou: Light.RED. Členy dostanú čísla 0, 1, 2 …\nCelý program Súbor examples/m-enum.act:\nAction! ;@modern ; ENUM: a type of your own with named values TYPE Light=ENUM [RED, GREEN, YELLOW] Light FUNC Next(Light now) IF now=Light.RED THEN RETURN(Light.GREEN) FI IF now=Light.GREEN THEN RETURN(Light.YELLOW) FI RETURN(Light.RED) PROC Show(Light l) CASE l OF WHEN Light.RED THEN PrintE(\"red - stop\") WHEN Light.GREEN THEN PrintE(\"green - go\") WHEN Light.YELLOW THEN PrintE(\"yellow - wait\") ESAC RETURN PROC Main() Light l=[Light.RED] BYTE i FOR i=1 TO 5 DO Show(l) l=Next(l) OD Print(\"The last value as a number: \") PrintBE(BYTE(l)) RETURN red - stop green - go yellow - wait red - stop green - go The last value as a number: 2 Ako to funguje Light sa používa ako každý typ: pre premennú, parameter aj výsledok funkcie. Prekladač nedovolí l=1 ani PrintB(l) – hodnota typu Light nie je číslo. Keď číslo naozaj potrebuješ, povieš to výslovne: BYTE(l). Opačne Light(2) spraví z čísla člen.\nCASE: výber z viacerých možností Na čo to je Dlhá reťaz IF … ELSEIF … ELSEIF …, ktorá skúša stále tú istú premennú, sa číta ťažko. CASE ju zapíše prehľadne.\nAko sa to píše Action! CASE výraz OF WHEN hodnota THEN príkazy WHEN hodnota1, hodnota2 THEN ; viac hodnôt príkazy WHEN od TO do THEN ; rozsah vrátane hraníc príkazy WHEN od TO do IF podmienka THEN ; rozsah a navyše podmienka príkazy ELSE príkazy ; keď nesedelo nič ESAC Vykoná sa prvá vetva, ktorá sedí, a žiadna ďalšia. ELSE je nepovinné. ESAC (CASE odzadu) príkaz končí.\nCelý program Súbor examples/m-case.act:\nAction! ;@modern ; CASE: choose one branch by a value PROC Describe(BYTE n) PrintB(n) Print(\": \") CASE n OF WHEN 0 THEN PrintE(\"zero\") WHEN 1 TO 9 THEN PrintE(\"one digit\") WHEN 10, 100 THEN PrintE(\"ten or a hundred\") WHEN 11 TO 99 IF n MOD 11=0 THEN PrintE(\"two digits, both the same\") WHEN 11 TO 99 THEN PrintE(\"two digits\") ELSE PrintE(\"a big number\") ESAC RETURN PROC Main() Describe(0) Describe(7) Describe(10) Describe(33) Describe(42) Describe(100) Describe(200) RETURN 0: zero 7: one digit 10: ten or a hundred 33: two digits, both the same 42: two digits 100: ten or a hundred 200: a big number Ako to funguje Číslo 33 sedí do rozsahu 11 TO 99 a spĺňa aj podmienku za IF (je deliteľné jedenástimi), takže sa vykoná prvá z dvoch vetiev. Číslo 42 do rozsahu sedí, ale podmienku nespĺňa – ide sa na ďalšiu vetvu. Podmienke pri WHEN sa hovorí stráž.\nPrekladač stráži aj teba: keby sa tá istá hodnota vyskytla v dvoch vetvách bez stráže, druhá by sa nikdy nevykonala – a to je chyba prekladu (ACT234).\nPorovnanie, IF a CASE ako hodnota; pretypovanie Na čo to je V pôvodnom Action! patrí porovnanie len do podmienky. S rozšíreniami je porovnanie aj hodnota – 1, keď platí, 0, keď neplatí. Hodnotou môže byť aj celý IF a CASE. A pretypovanie povie, v akom type sa má počítať.\nAko sa to píše Zápis Hodnota (a\u003eb) 1 alebo 0 IF podm THEN x ELSE y FI x alebo y; ELSE je povinné CASE v OF WHEN … THEN x … ELSE y ESAC hodnota zvolenej vetvy BYTE(x), CARD(x), INT(x), CHAR(x) x čítané ako daný typ Celý program Súbor examples/m-value.act:\nAction! ;@modern ; Comparisons, IF and CASE as values, and casts PROC Main() CHAR ARRAY text=\"one, two, three, four\" BYTE a, b, bigger, commas, i CHAR grade CARD sum a=7 b=12 bigger=IF a\u003eb THEN a ELSE b FI ; IF as a value Print(\"The bigger one: \") PrintBE(bigger) commas=0 FOR i=1 TO text(0) DO commas==+(text(i)=',) ; a comparison is 1 or 0 OD Print(\"Commas in the text: \") PrintBE(commas) grade=CASE b OF ; CASE as a value WHEN 0 TO 4 THEN 'C WHEN 5 TO 9 THEN 'B ELSE 'A ESAC Print(\"Grade: \") Put(grade) PutE() a=200 b=100 sum=a+b ; BYTE + BYTE overflows Print(\"200 + 100 as BYTE: \") PrintCE(sum) sum=CARD(a)+b ; the cast makes it a CARD sum Print(\"200 + 100 with CARD(a): \") PrintCE(sum) RETURN The bigger one: 12 Commas in the text: 3 Grade: A 200 + 100 as BYTE: 44 200 + 100 with CARD(a): 300 Ako to funguje bigger=IF a\u003eb THEN a ELSE b FI nahrádza štyri riadky s IF a dvoma priradeniami. commas==+(text(i)=',) pripočíta 1 za každú čiarku a 0 za každý iný znak – počítanie bez IF. Posledná časť rieši pascu z kapitoly 7: BYTE + BYTE sa počíta v BYTE a pretečie. CARD(a) povie „ber a ako CARD“, a tým sa celý súčet počíta v CARD. Časté chyby Čo sa stalo Čo povie prekladač chýba ;@modern chyby na prvom rozšírení – napr. error ACT011: unexpected '*' pri CONST priradenie do konštanty chyba – konštanta nie je premenná číslo do premennej typu ENUM (l=1) error ACT237 tá istá hodnota v dvoch vetvách CASE error ACT234 IF ako hodnota bez ELSE error ACT235 ;@modern spolu s ;@quirks error ACT231 Vyskúšaj si Prepíš define.act z kapitoly 17 pomocou CONST. Pridaj semaforu štvrtý stav RED_YELLOW medzi červenú a zelenú. Napíš CASE, ktorý podľa čísla mesiaca vypíše ročné obdobie. Zhrnutie ;@modern zapne rozšírenia; pôvodný Action! taký program nepreloží. CONST je pomenovaná hodnota vypočítaná pri preklade. TYPE X=ENUM […] je typ s pomenovanými hodnotami, ktorý sa nemieša s číslami. CASE … OF … WHEN … ESAC vyberá jednu vetvu podľa hodnoty; pozná rozsahy a stráže. Porovnanie je 1 alebo 0; IF a CASE môžu byť hodnotou; CARD(x) volí typ výpočtu. Podrobnejšie lekcie ku každému rozšíreniu sú v priečinku examples/modern/ (lekcie 6 až 11).\nSpäť: 34. Disky · Ďalej: 36. Rozšírenia pre dáta\n","t":"35. Rozšírenia jazyka: CONST, ENUM, CASE, hodnoty z porovnaní, pretypovanie","u":"35-modern-jazyk/"},{"c":"Aj táto kapitola je o rozšíreniach action26 – každý program začína riadkom ;@modern (kapitola 35).\nViacrozmerné polia Na čo to je Šachovnica, mapa hry, tabuľka – dáta, ktoré majú riadky a stĺpce. V pôvodnom Action! sa to robí jedným dlhým poľom a výpočtom indexu riadok*šírka+stĺpec. S rozšírením napíšeš dva indexy a výpočet spraví prekladač.\nAko sa to píše Action! BYTE ARRAY grid(4,6) ; 4 riadky, 6 stĺpcov grid(2,5)=7 ; riadok 2, stĺpec 5 Rozmery sú čísla alebo konštanty. Indexy idú v každom rozmere od 0. Rozmerov môže byť aj viac ako dva.\nCelý program Súbor examples/m-grid.act:\nAction! ;@modern ; A two-dimensional array: rows and columns CONST ROWS=4, COLS=6 BYTE ARRAY grid(ROWS,COLS) PROC Main() BYTE r, c FOR r=0 TO ROWS-1 DO FOR c=0 TO COLS-1 DO grid(r,c)=(r+1)*(c+1) OD OD FOR r=0 TO ROWS-1 DO FOR c=0 TO COLS-1 DO IF grid(r,c)\u003c10 THEN Put(' ) FI PrintB(grid(r,c)) Put(' ) OD PutE() OD Print(\"Row 2, column 5: \") PrintBE(grid(2,5)) RETURN action26 m-grid.act --sim 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 Row 2, column 5: 18 Ako to funguje Dve vnorené slučky – vonkajšia po riadkoch, vnútorná po stĺpcoch – sú bežný spôsob, ako prejsť celú tabuľku. V pamäti ležia prvky riadok za riadkom: grid(r,c) je prvok číslo r*COLS+c.\nPočiatočné hodnoty sa píšu ako jeden rad v tomto poradí:\nAction! BYTE ARRAY glider(3,3)=[0 1 0 0 0 1 1 1 1] Na rozdiel od jednorozmerných polí tu prekladač stráži aspoň to, čo vie: nesprávny počet indexov a index daný číslom mimo rozmeru sú chyby prekladu (ACT238). Index z premennej sa nekontroluje ani tu.\nKeď pole odovzdáš rutine ako parameter, rutina dostane len adresu a vidí ho ako jednorozmerné.\nŠpeciálne znaky v texte: \\{…} Na čo to je Niektoré znaky sa do zdrojáka nedajú napísať z klávesnice PC: koniec riadka uprostred textu, inverzné písmo, pípnutie, pohyb kurzora. S rozšírením ich zapíšeš menom.\nAko sa to píše Zápis Čo vloží \\{RETURN} koniec riadka \\{CLEAR} vymazanie obrazovky \\{UP} \\{DOWN} \\{LEFT} \\{RIGHT} pohyb kurzora \\{BELL} pípnutie \\{TAB}, \\{ESC}, \\{DELETE}, \\{INSERT} príslušné riadiace znaky \\{$41} znak s daným kódom \\{INV:text} text inverzným písmom \\{SCREEN:text} text prevedený na kódy pre priamy zápis do pamäte obrazovky Platí v reťazcoch aj v znakových konštantách ('\\{RETURN}).\nCelý program Súbor examples/m-escapes.act:\nAction! ;@modern ; Special characters written by name PROC Main() Print(\"First line\\{RETURN}Second line\\{RETURN}\") Print(\"The letter with the code $41: \\{$41}\\{RETURN}\") IF 'A='\\{$41} THEN PrintE(\"'A and '\\{$41} are the same character\") FI RETURN action26 m-escapes.act --sim First line Second line The letter with the code $41: A 'A and 'A are the same character Ako to funguje Jeden Print vypíše dva riadky, lebo text obsahuje koniec riadka. Text s \\{RETURN} vypisuj cez Print, nie PrintE: PrintE skončí pri prvom konci riadka, ktorý v texte nájde.\nInverzné písmo, pípnutie a pohyb kurzora uvidíš a počuješ len v emulátore – skús Print(\"\\{CLEAR}\\{INV: TITLE }\\{BELL}\").\nDlhé texty: PrintU Na čo to je Reťazec v Action! má najviac 255 znakov, lebo jeho dĺžka je v jednom bajte. Úvodný text hry alebo návod býva dlhší. PrintU vypisuje text, ktorý nemá dĺžkový bajt a končí dohodnutým znakom.\nAko sa to píše Action! PrintU(\"dlhý text\", znak) PrintU(adresa, znak) PrintU(adresa, znak, najviac) Druhý parameter je ukončovací znak – taký, ktorý sa v texte nevyskytuje. Keď je text napísaný priamo vo volaní, prekladač ukončovací znak na jeho koniec doplní sám. Tretí, nepovinný parameter obmedzí počet vypísaných znakov.\nPrintUD(kanál, …) robí to isté na kanál (kapitola 30).\nCelý program Súbor examples/m-longtext.act:\nAction! ;@modern ; PrintU: a text longer than 255 characters PROC Main() PrintU(\"Action! was written by Clinton Parker and published by Optimized Systems Software in 1983. It came on a cartridge with an editor, a compiler and a monitor. Programs in Action! run many times faster than programs in Atari BASIC, and they are far shorter than the same programs written in assembler.\", '~) PutE() RETURN action26 m-longtext.act --sim Action! was written by Clinton Parker and published by Optimized Systems Software in 1983. It came on a cartridge with an editor, a compiler and a monitor. Programs in Action! run many times faster than programs in Atari BASIC, and they are far shorter than the same programs written in assembler. Ako to funguje Text má 297 znakov – do obyčajného reťazca by sa nezmestil. PrintU ho vypisuje od začiatku, kým nenarazí na znak ~. Rovnako vypíše text, ktorý program načítal zo súboru do poľa, ak si na jeho koniec zapíše ukončovací znak.\nČasté chyby Čo sa stalo Čo povie prekladač nesprávny počet indexov (grid(1)) error ACT238: 'grid' has 2 dimensions and needs 2 indexes, got 1 index daný číslom mimo rozmeru error ACT238: index 4 is outside 0..3 of dimension 1 of 'grid' preklep v mene znaku (\\{RETRUN}) error ACT240: unknown escape so zoznamom platných mien ukončovací znak je aj vnútri textu error ACT007: the text contains its stop byte text nad 255 znakov mimo PrintU error ACT001 Vyskúšaj si Zmeň tabuľku na 9 × 9 – malú násobilku. Deklaruj pole 3 × 3 s počiatočnými hodnotami a vypíš ho. V emulátore vypíš nadpis inverzným písmom a pod ním dlhý text cez PrintU. Zhrnutie BYTE ARRAY a(riadky, stĺpce) je pole s dvoma indexmi; prekladač prepočíta index sám. \\{MENO} v texte vloží znak, ktorý sa nedá napísať: \\{RETURN}, \\{CLEAR}, \\{INV:text} … PrintU(text, znak) vypíše text ľubovoľnej dĺžky ukončený daným znakom. Podrobnejšie: lekcie 12, 14 a 15 v examples/modern/.\nSpäť: 35. Rozšírenia jazyka · Ďalej: 37. Miesto v pamäti a assembler\n","t":"36. Rozšírenia pre dáta: viacrozmerné polia, špeciálne znaky, dlhé texty","u":"36-modern-data/"},{"c":"Rozšírenia action26 pre tých, ktorí chcú rozhodovať o tom, kde v pamäti veci ležia, a písať kúsky programu priamo v assembleri. Programy začínajú riadkom ;@modern (kapitola 35).\nKapitola nadväzuje na 24 (pamäť) a 25 (strojový kód).\nORG … ENDORG: premenné na zvolenom mieste Na čo to je Prekladač ukladá premenné tam, kde je program. Niekedy chceš inak:\nNultá stránka (adresy 0 až 255) je najrýchlejšia pamäť procesora 6502. Premenná v nej robí slučky rýchlejšími a ukazovateľ v nej prekladač použije priamo. Hardvér Atari niektoré dáta chce na konkrétnych adresách. Ako sa to píše Action! ORG adresa deklarácie ENDORG Všetko medzi ORG a ENDORG sa uloží od danej adresy. Za ENDORG prekladač pokračuje tam, kde bol predtým.\nPre programy sú v nultej stránke voľné adresy $C8 až $FF. Nižšie adresy patria operačnému systému a prekladaču.\nALIGN: zarovnanie na násobok Na čo to je Vlastná znaková sada musí začínať na adrese, ktorá je násobkom 1024. Pamäť pre pohyblivé objekty (hráčov a strely) na násobku 2048. ALIGN posunie nasledujúcu premennú na najbližšiu takú adresu.\nAko sa to píše Action! ALIGN n n je mocnina dvoch: 2, 4, 8 … 256, 1024, 2048 …\nCelý program Súbor examples/m-org.act:\nAction! ;@modern ; ORG and ALIGN: choosing where variables live ORG $CB ; the zero page: the fastest memory there is BYTE fast CARD address ENDORG BYTE normal ; back where the program is ALIGN 256 ; the next variable starts at a multiple of 256 BYTE ARRAY table(16) PROC Main() PrintF(\"fast is at %H%E\", @fast) PrintF(\"address is at %H%E\", @address) PrintF(\"normal is at %H%E\", @normal) PrintF(\"table is at %H%E\", table) RETURN action26 m-org.act --sim fast is at $00CB address is at $00CC normal is at $2000 table is at $2100 Ako to funguje fast a address ležia v nultej stránke, od $CB. normal je za ENDORG, takže je znova pri programe – na jeho začiatku, $2000. table by inak nasledovala hneď za normal ($2001). ALIGN 256 ju posunul na najbližší násobok 256, $2100. Preskočené bajty v súbore XEX nie sú. ORG nie je to isté ako BYTE x=$CB z kapitoly 24. Tam si adresy každej premennej počítaš sám; v bloku ORG ich prekladač ukladá za sebou a stráži, aby sa neprekrývali.\nASM … ENDASM: assembler s menami Na čo to je Blok [ … ] z kapitoly 25 chce inštrukcie ako čísla. V bloku ASM sa píšu menami – tak, ako ich uvádzajú knihy o procesore 6502 – a dajú sa v ňom použiť mená premenných z programu.\nAko sa to píše Action! ASM inštrukcie ENDASM ASM a ENDASM stoja každé samo na riadku. Na riadku je jedna inštrukcia. Komentár začína bodkočiarkou. Návestie (meno miesta, na ktoré sa skáče) začína v prvom stĺpci; inštrukcie sú odsadené. Mená premenných, polí a rutín programu znamenajú ich adresy. Prekladač k bloku nič nepridá. Ak blok tvorí celé telo rutiny, musí skončiť inštrukciou rts. Celý program Súbor examples/m-asm.act:\nAction! ;@modern ; ASM: assembler instructions by name inside an Action! program BYTE counter BYTE ARRAY page6(256)=$600 PROC Bump() ; add 1 to counter ASM inc counter rts ENDASM PROC FillPage(BYTE value) ; fill the 256 bytes of page 6 ASM lda value ldx #0 loop sta $0600,x inx bne loop rts ENDASM PROC Main() counter=5 Bump() Bump() Print(\"counter: \") PrintBE(counter) FillPage(42) Print(\"page6(0) and page6(255): \") PrintB(page6(0)) Put(' ) PrintBE(page6(255)) RETURN action26 m-asm.act --sim counter: 7 page6(0) and page6(255): 42 42 Ako to funguje Bump je to isté ako v kapitole 25, ale namiesto [$EE $00 $06 $60] stojí inc counter a rts. Adresu premennej dosadí prekladač. FillPage má parameter. Ten je – ako každý parameter v Action! – obyčajná premenná na pevnom mieste, takže ho assembler prečíta menom: lda value. loop je návestie. bne loop skáče späť, kým register X po pripočítaní jednotky nie je nula – teda 256-krát. Vyplnenie 256 bajtov takto trvá zlomok času oproti slučke FOR. Na takéto miesta assembler patrí: krátky kus, ktorý sa vykonáva veľmi často.\nČasté chyby Čo sa stalo Čo povie prekladač chýba ENDORG, alebo ORG v bloku ORG error ACT233 ALIGN s číslom, ktoré nie je mocnina dvoch error ACT233: ALIGN needs a power of two from 1 to $8000 blok ORG na adresách, ktoré používa prekladač ($80–$87, $A0–$AF, $C0–$C7) warning ACT233 blok ORG prekrýva program alebo iný blok error ACT225 neznáme meno v bloku ASM error ACT008: undeclared name skok v ASM na miesto ďalej ako 127 bajtov error ACT223 chýba rts na konci rutiny z assembleru procesor pokračuje do ďalšej rutiny Vyskúšaj si Zmeň ALIGN 256 na ALIGN 1024 a pozri adresu table. Napíš v assembleri PROC ClearPage(), ktorá vynuluje šiestu stránku. Prelož m-asm.act s --listing m-asm.lst a nájdi v listingu svoj blok. Zhrnutie ORG adresa … ENDORG uloží deklarácie od danej adresy; voľná nultá stránka je $C8–$FF. ALIGN n posunie ďalšiu premennú na násobok n. ASM … ENDASM je assembler s menami inštrukcií a menami z programu. Rutina, ktorej telo je blok ASM, končí inštrukciou rts. Ktoré miesta v pamäti ešte ostali voľné, ukáže --memory-map (kapitola 32); polia na adrese z ORG sa v ňom počítajú ako obsadené. Podrobnejšie: lekcie 2 až 5 a 13 v examples/modern/ (znaková sada, hráči a strely, vlastný zoznam displeja, dúha cez prerušenie).\nSpäť: 36. Rozšírenia pre dáta · Ďalej: 38. Skrytá pamäť\n","t":"37. Miesto v pamäti a assembler: ORG, ENDORG, ALIGN, ASM … ENDASM","u":"37-modern-pamat/"},{"c":"Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35).\nNa čo to je Procesor Atari vidí naraz 64 kilobajtov. Počítač má však pamäte viac, než program bežne vidí – na dvoch miestach:\n1. RAM pod ROM. Na adresách $C000–$FFFF je operačný systém v pamäti ROM. Počítače XL a XE majú na tých istých adresách aj obyčajnú pamäť RAM, len je zakrytá. Je to asi 14 kilobajtov, ktoré bežný program nevidí.\n2. Banky. Atari 130XE má 128 kilobajtov. Druhých 64 je rozdelených na štyri banky po 16 kilobajtov. V jednej chvíli je vidieť jedna z nich, a to v „okne“ na adresách $4000–$7FFF, namiesto bežnej pamäte, ktorá tam inak je. Rozšírené počítače majú bánk 16 aj 64.\nPrepínať medzi tým ručne je práca s registrom PORTB, zakazovaním prerušení a rizikom, že si program odpojí pamäť pod vlastnými nohami. Rutiny action26 to robia za teba.\nAko sa to píše Všetky rutiny majú ako prvý parameter číslo banky:\nbanka 0 je bežná pamäť – a v nej tieto rutiny vidia aj RAM pod ROM, banky 1, 2, 3 … sú banky rozšírenej pamäte; ich adresy sú $4000–$7FFF. Rutina Čo robí XBanks() funkcia – počet bánk: 0 na obyčajnom XL, 4 na 130XE, viac na rozšírených XPeek(banka, adresa), XPeekC(…) prečíta bajt / CARD XPoke(banka, adresa, hodnota), XPokeC(…) zapíše bajt / CARD XMoveBlock(kam_banka, kam, odkiaľ_banka, odkiaľ, počet) skopíruje blok medzi ľubovoľnými dvoma miestami XSetBlock(banka, adresa, počet, hodnota), XZero(banka, adresa, počet) vyplní / vynuluje blok XPrint(banka, adresa, znak) vypíše text ukončený znakom, ako PrintU XRead(kanál, banka, adresa, počet) funkcia – načíta zo súboru do banky, vráti počet bajtov XWrite(kanál, banka, adresa, počet) zapíše z banky do súboru XBank(banka) nechá banku v okne natrvalo – dá sa potom čítať obyčajným poľom XAntic(banka) ukáže banku obrazovému čipu – obrazovka z banky Sú to obdoby rutín Peek, Poke, MoveBlock, SetBlock, Zero a PrintU s jedným parametrom navyše.\nProgram 1: banky a RAM pod ROM Súbor examples/m-banks.act:\nAction! ;@modern ; Hidden memory: the banks of a 130XE and the RAM under the ROM PROC Main() BYTE banks, i banks=XBanks() Print(\"Banks of extended memory: \") PrintBE(banks) IF banks=0 THEN PrintE(\"This program needs a 130XE.\") RETURN FI FOR i=1 TO banks ; the same address in each bank DO XPoke(i, $4000, i*10) OD Print(\"Address $4000 in the banks: \") FOR i=1 TO banks DO PrintB(XPeek(i, $4000)) Put(' ) OD PutE() XPoke(0, $C000, 99) ; bank 0 is the ordinary memory, also under the ROM Print(\"XPeek sees the RAM under the ROM: \") PrintBE(XPeek(0, $C000)) RETURN Preklad a spustenie Simulátoru treba povedať, že má byť 130XE:\naction26 m-banks.act --sim --sim-mem 130xe Banks of extended memory: 4 Address $4000 in the banks: 10 20 30 40 XPeek sees the RAM under the ROM: 99 Bez --sim-mem simuluje obyčajných 64 kilobajtov a program to spozná:\nBanks of extended memory: 0 This program needs a 130XE. V emulátore nastav typ počítača na 130XE (v ponuke emulátora) a spusti program cez --run.\nAko to funguje XBanks() zistí, koľko bánk počítač má. Vždy sa najprv opýtaj – program, ktorý siahne do banky, ktorá neexistuje, skončí chybou 101. Slučka zapíše na tú istú adresu $4000 v každej banke inú hodnotu. Druhá slučka ich prečíta späť: sú štyri rôzne. To je dôkaz, že ide o štyri rôzne kusy pamäte. XPoke(0, $C000, 99) zapíše do RAM pod operačným systémom. Obyčajný Poke($C000, 99) by nespravil nič (zápis do ROM) a Peek($C000) by vrátil bajt operačného systému. Program 2: dáta nahrané rovno do banky Dlhé texty a obrázky nemusia zaberať miesto v programe. S ORG adresa BANK n ich prekladač pripraví tak, že sa pri nahrávaní programu uložia rovno do banky.\nSúbor examples/m-bankdata.act:\nAction! ;@modern ; A text loaded into a bank together with the program ORG $4000 BANK 1 CHAR ARRAY story=\"Once upon a time there was an Atari with twice the memory of the others. The upper half was hidden, and only those who knew the right register could reach it.~\" ENDORG PROC Main() IF XBanks()=0 THEN PrintE(\"This program needs a 130XE.\") RETURN FI Print(\"The text lives in bank \") PrintBE(BankOf(story)) XPrint(BankOf(story), story, '~) PutE() RETURN action26 m-bankdata.act --sim --sim-mem 130xe The text lives in bank 1 Once upon a time there was an Atari with twice the memory of the others. The upper half was hidden, and only those who knew the right register could reach it. Ako to funguje ORG $4000 BANK 1 … ENDORG je blok ORG z kapitoly 37 s číslom banky. Rovnako ORG $C000 … ENDORG (adresa od $C000, bez BANK) uloží dáta do RAM pod ROM. Text v takom bloku nemá dĺžkový bajt a môže byť dlhší ako 255 znakov. Ukončovací znak (~) píšeš na jeho koniec sám. Meno z takého bloku je len adresa. story(3) ani Print(story) nejdú – program dáta nevidí, kým sú v banke. Meno sa odovzdáva rutinám X…. BankOf(story) je číslo banky, v ktorej story leží. Keď dáta neskôr presunieš do inej banky, zvyšok programu sa nemení. Dáta a program zvlášť Veľké dáta sa dajú dať do samostatného súboru, aby sa program pri vývoji nahrával rýchlo:\naction26 m-bankdata.act --data-only -o story.dat action26 m-bankdata.act --code-only -o story.xex Na Atari sa najprv nahrá story.dat (uloží dáta do banky a vráti sa), potom story.xex. Program s --code-only pri štarte skontroluje, či sú dáta nahrané, a ak nie, povie to a skončí.\nXBank: banka ako obyčajné pole XPeek a XPoke pri každom volaní banku zapnú a vypnú. Keď s bankou pracuješ dlhšie, je rýchlejšie nechať ju v okne:\nAction! BYTE ARRAY window(16384)=$4000 ; pole na adrese okna XBank(2) ; v okne je banka 2 window(100)=7 ; obyčajný prístup do poľa XBank(0) ; späť bežná pamäť Jedno pravidlo: kým je v okne banka, nesmie v okne ležať nič z tvojho programu – ani kód, ani premenné. Program od $2000 sa do okna ($4000) dostane, až keď prerastie 8 kilobajtov. Prekladač na to upozorní varovaním ACT242.\nNa čo si dať pozor Opýtaj sa XBanks() skôr, než siahneš do banky. RAM disk používa tie isté banky. Ak má používateľ v DOS-e zapnutý RAM disk, zápis do bánk mu zničí súbory. Adresy $D000–$D7FF nie sú pamäť, ale registre čipov. Zápis tam cez XPoke skončí chybou 102. Rutiny X… sú pomalšie ako Peek a Poke; na veľké presuny použi XMoveBlock, nie slučku s XPoke. Časté chyby Čo sa stalo Čo sa stane banka, ktorá neexistuje Err: 101 zápis do registrov alebo vektorov pod ROM Err: 102 čítanie mena z bloku ORG … BANK priamo (story(0)) error ACT243 program a XBank s kódom v okne warning ACT242; program sa môže zrútiť spustenie na počítači bez rozšírenej pamäte XBanks() vráti 0 – program to má ošetriť Vyskúšaj si Spusti m-banks.act s --sim-mem 1088 – počítač s megabajtom pamäte. Koľko bánk nájde? Ulož do banky 2 čísla 0 až 255 na adresy $4000 až $40FF a vypíš súčet toho, čo prečítaš späť. Presuň text v druhom programe pod ROM: ORG $C000 … ENDORG. Čo vypíše BankOf(story)? Zhrnutie XL a XE majú RAM skrytú pod ROM; 130XE navyše štyri banky po 16 KB v okne $4000–$7FFF. Rutiny XPeek, XPoke, XMoveBlock, XPrint … berú banku a adresu; banka 0 je bežná pamäť vrátane RAM pod ROM. XBanks() povie, koľko bánk je. ORG adresa BANK n nahrá dáta do banky spolu s programom; BankOf(meno) vráti jej číslo. XBank(n) nechá banku v okne pre obyčajné pole. Podrobnejšie: lekcie 27 až 31 v examples/modern/.\nSpäť: 37. Miesto v pamäti a assembler · Ďalej: 39. Dáta zo súboru a kompresia\n","t":"38. Skrytá pamäť: RAM pod ROM a banky 130XE","u":"38-skryta-pamat/"},{"c":"Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35).\nNa čo to je Hra potrebuje obrázky, mapy úrovní a texty. Prepisovať ich do zdrojáka ako čísla v hranatých zátvorkách je otrava. A keď ich je veľa, do pamäte Atari sa nezmestia.\nFILE vloží do programu obsah súboru tak, ako je. PACK ho vloží zbalený (komprimovaný) – zaberie menej a program si ho za behu rozbalí. Zbalené texty šetria miesto pri hrách s množstvom textu. FILE: súbor ako pole Ako sa to píše Action! BYTE ARRAY meno=FILE \"súbor\" BYTE ARRAY meno=FILE \"súbor\" odkiaľ koľko Prekladač súbor prečíta pri preklade a jeho bajty sa stanú počiatočnými hodnotami poľa. Nepovinné čísla vyberú len časť súboru: od ktorého bajtu a koľko bajtov.\nSúbor sa hľadá ako pri INCLUDE – vedľa zdrojáka a v priečinkoch z voľby -I.\nCelý program Súbor examples/motto.txt obsahuje jeden riadok textu ukončený znakom ~:\nAction! is fast, small and readable.~ Súbor examples/m-file.act:\nAction! ;@modern ; FILE: the bytes of a file become part of the program BYTE ARRAY motto=FILE \"motto.txt\" PROC Main() PrintU(motto, '~) ; the text in the file ends with ~ PutE() RETURN action26 m-file.act --sim Action! is fast, small and readable. Ako to funguje Po preklade je text súčasťou programu – na Atari už súbor motto.txt netreba. Pole motto má toľko prvkov, koľko mal súbor bajtov. Vypisuje sa cez PrintU (kapitola 36), lebo to nie je reťazec s dĺžkovým bajtom.\nNajčastejšie sa takto vkladajú obrázky: BYTE ARRAY picture=FILE \"title.mic\" a potom MoveBlock do pamäte obrazovky.\nPACK a Unpack: zbalené dáta Ako sa to píše Action! BYTE ARRAY meno=PACK FILE \"súbor\" BYTE ARRAY meno=PACK [čísla] Action! veľkosť=Unpack(meno, kam) PACK pred zdrojom dát povie prekladaču, aby ich uložil zbalené. Unpack ich za behu rozbalí na adresu kam a vráti, koľko bajtov rozbalil. Cieľ musí mať miesto na celé rozbalené dáta.\nSpôsob balenia vyberie prekladač sám – ten, s ktorým je celý program najmenší. Dá sa aj predpísať: PACK RLE … alebo PACK ZX02 ….\nCelý program Súbor frame.dat má 240 bajtov: šesť riadkov po 40 znakov, ktoré tvoria rám.\nSúbor examples/m-pack.act:\nAction! ;@modern ; PACK: data stored packed, unpacked when the program runs BYTE ARRAY packed=PACK FILE \"frame.dat\" ; 240 bytes: 6 rows of 40 BYTE ARRAY picture(240) PROC Main() CARD size, i size=Unpack(packed, picture) Print(\"Unpacked bytes: \") PrintCE(size) FOR i=0 TO size-1 DO Put(picture(i)) IF i MOD 40=39 THEN PutE() FI OD RETURN action26 m-pack.act --sim Unpacked bytes: 240 ######################################## # # # # # ****************** # # # ######################################## Ako to funguje S voľbou --verbose prekladač povie, čo spravil:\naction26: PACK packed: ZX02, 240 -\u003e 23 bytes 240 bajtov sa zbalilo do 23. Dáta s dlhými úsekmi rovnakých bajtov – a také sú obrázky aj mapy – sa balia veľmi dobre.\nKedy sa to oplatí. K zbaleným dátam sa do programu pribalí rozbaľovacia rutina (asi 140 až 470 bajtov podľa spôsobu balenia). Pri 240 bajtoch dát je teda program so PACK v skutočnosti väčší ako s obyčajným FILE. Pri obrázku cez celú obrazovku je to naopak: 7680 bajtov sa zbalí na niekoľko stoviek. Prekladač to pri automatickom výbere počíta – keď sa balenie neoplatí, uloží dáta nezbalené.\nZbalené texty Na čo to je Textová hra má desiatky viet, v ktorých sa opakujú tie isté slová. Zbalené texty ukladajú najčastejšie dvojice znakov do spoločného slovníka a v textoch ich nahrádzajú jedným bajtom.\nAko sa to píše Action! CHAR ARRAY meno=PACK \"text\" PrintPacked(meno) ; vypíše PrintPackedE(meno) ; vypíše a ukončí riadok PrintPackedE(\"text\") ; text priamo vo volaní sa zbalí tiež UnpackText(meno, reťazec) ; rozbalí do obyčajného reťazca Celý program Súbor examples/m-texts.act:\nAction! ;@modern ; Packed texts: the words that repeat are stored once CHAR ARRAY hall=PACK \"You are in the hall of an old house. There is a door to the north.\" CHAR ARRAY kitchen=PACK \"You are in the kitchen of an old house. There is a door to the south.\" PROC Main() CHAR ARRAY plain(100) PrintPackedE(hall) PrintPackedE(kitchen) PrintPackedE(\"You are in the garden of an old house. There is a door to the west.\") UnpackText(hall, plain) ; into an ordinary string Print(\"The first text has \") PrintB(plain(0)) PrintE(\" characters.\") RETURN action26 m-texts.act --sim You are in the hall of an old house. There is a door to the north. You are in the kitchen of an old house. There is a door to the south. You are in the garden of an old house. There is a door to the west. The first text has 66 characters. Ako to funguje S --verbose:\naction26: PACK texts: 3 text(s), 205 -\u003e 121 bytes with the dictionary of 40 pair(s) Tri vety majú spolu 205 znakov a zaberú 121 bajtov vrátane slovníka. Čím viac textov a čím viac sa v nich slová opakujú, tým väčšia úspora.\nZbalený text nie je reťazec Action!: Print, SCompare ani indexovanie s ním nefungujú. Vypisuje sa rutinami PrintPacked…; keď ho potrebuješ ako reťazec, rozbaľ ho cez UnpackText.\nTexty v samostatnom súbore Texty hry sa pohodlnejšie píšu do obyčajného textového súboru, jeden text na riadok. Zbalí ho nástroj:\naction26 --pack-text rooms.txt rooms.ptx action26: rooms.txt -\u003e rooms.ptx (3 text(s), 68 -\u003e 60 bytes, 13 pair(s) in the dictionary) V programe:\nAction! BYTE ARRAY rooms=FILE \"rooms.ptx\" UsePackedTexts(rooms) ; odteraz platí slovník tohto súboru PrintPackedE(PackedText(rooms, 2)) ; text číslo 2 (číslujú sa od 0) UsePackedTexts(0) prepne späť na slovník textov napísaných v programe.\nFormát 2: menej miesta pri mnohých textoch Hra s celými stovkami textov ušetrí ešte viac, keď ich zbalí vo formáte 2:\naction26 --pack-text2 rooms.txt rooms.pt2 Formát 2 robí dve veci inak:\nKód dostanú len znaky, ktoré v textoch naozaj sú. Ostatné kódy idú na dvojice – a čím viac dvojíc, tým kratšie texty. Súbor si nepamätá miesto každého textu, len každého šestnásteho. Ostatné nájde tak, že preskočí najviac 15 textov pred hľadaným. V programe sa používajú rutiny s dvojkou na konci:\nAction! BYTE ARRAY rooms=FILE \"rooms.pt2\" UsePackedTexts2(rooms) ; odteraz platia texty tohto súboru PrintPackedE(PackedText2(rooms, 2)) ; text číslo 2 UsePackedTexts2(0) prepne späť na texty napísané v programe. UsePackedTexts2 vezme aj súbor z obyčajného --pack-text; pre ten ostáva PackedText.\nKedy sa to oplatí? Rutiny formátu 2 sú o asi 200 bajtov väčšie a tabuľka znakov tiež niečo stojí, takže pár krátkych viet (ako v rooms.txt hore) vyjde vo formáte 2 dokonca väčších. Pri textoch celej hry je to naopak – napríklad 814 textov hry Ataristův protiútok zaberie 24 814 bajtov namiesto 26 726, o 7 % menej.\nNástroje na príkazovom riadku Dáta sa dajú zbaliť aj mimo programu – napríklad súbor, ktorý si program načíta z diskety:\nPríkaz Čo robí action26 --pack vstup výstup zbalí súbor (spôsob vyberie sám) … --algo rle / zx02 / stored predpíše spôsob … --columns 40 dáta sú obrázok so 40 bajtmi na riadok – skúsi baliť po stĺpcoch action26 --unpack vstup výstup rozbalí späť action26 --pack-text vstup výstup zbalí riadky textového súboru action26 --pack-text2 vstup výstup to isté vo formáte 2 – pri mnohých textoch menej miesta action26 --pack frame.dat frame.pak action26: frame.dat -\u003e frame.pak (RLE+, rows of 40, 240 -\u003e 15 bytes, 6%) Takto zbalený súbor rozbalí na Atari tá istá rutina Unpack, keď ho program načíta do pamäte.\nKeď meno výstupu končí na .w8p, vznikne súbor vo formáte W8P – formát obrázkov z programu mic2w8p, používaný v niektorých hrách. Na Atari ho rozbalia rutiny UnpackW8P(súbor, kam, najviac) z pamäte a UnpackW8PD(kanál, kam, najviac) z otvoreného súboru.\nPrehľad rutín Rutina Čo robí Unpack(zbalené, kam) rozbalí dáta z PACK alebo z --pack; vráti veľkosť UnpackRLE(zbalené, kam), UnpackZX02(zbalené, kam) to isté pre jeden konkrétny spôsob balenia – menší program PackRLE(odkiaľ, koľko, kam) zbalí pamäť priamo na Atari; vráti dĺžku PrintPacked(text), PrintPackedE(text) vypíše zbalený text PrintPackedD(kanál, text), PrintPackedDE(…) to isté na kanál UnpackText(text, reťazec) rozbalí zbalený text do reťazca UsePackedTexts(súbor), PackedText(súbor, číslo) texty zo súboru z --pack-text UsePackedTexts2(súbor), PackedText2(súbor, číslo) texty zo súboru z --pack-text2 UnpackW8P(…), UnpackW8PD(…) súbory W8P Časté chyby Čo sa stalo Čo sa stane súbor pre FILE neexistuje error ACT203 cieľ pre Unpack je menší ako rozbalené dáta prepíše sa pamäť za ním Print na zbalený text vypíše nezmysel Unpack na dáta, ktoré nie sú zbalené Err: 105, ak nesedí hlavička; inak program zapíše nezmysly kamkoľvek zbalený text dlhší ako 255 bajtov chyba prekladu – rozdeľ ho súbor z --pack-text2 s UsePackedTexts a PackedText (alebo naopak) vypíše nezmysel alebo nič – k formátu 2 patria rutiny s dvojkou zdroj a cieľ Unpack sa prekrývajú poškodené dáta Vyskúšaj si Zmeň obsah motto.txt a prelož m-file.act znova. Musel si meniť program? Prelož m-pack.act s --verbose a potom s PACK RLE FILE …. Ktorý spôsob dal menšie dáta? Pridaj do m-texts.act ďalšie tri vety o miestnostiach a sleduj vo --verbose, ako sa mení pomer. Zhrnutie =FILE \"súbor\" vloží bajty súboru do poľa pri preklade. =PACK … ich vloží zbalené; Unpack(pole, kam) ich rozbalí. Balenie sa oplatí pri väčších dátach – rozbaľovacia rutina tiež niečo zaberá. CHAR ARRAY t=PACK \"text\" je zbalený text; vypisuje sa cez PrintPacked…. --pack, --unpack a --pack-text robia to isté so súbormi na PC; --pack-text2 zbalí veľa textov tesnejšie. Podrobnejšie: lekcie 38 až 45 v examples/modern/.\nSpäť: 38. Skrytá pamäť · Ďalej: 40. Hráči a strely\n","t":"39. Dáta zo súboru a kompresia: FILE, PACK, Unpack, zbalené texty","u":"39-kompresia/"},{"c":"Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35).\nNa čo to je Pohyblivé postavičky v hrách na Atari väčšinou nie sú nakreslené do obrázka. Kreslí ich zvlášť obvod GTIA navrch obrazovky – hráči (players) a strely (missiles). Atari ich má osem:\n4 hráči (0–3): úzke pásy široké 8 bodov a vysoké cez celú obrazovku, 4 strely (4–7 v rutinách action26): rovnaké pásy široké len 2 body; strela má farbu „svojho“ hráča (strela 0 hráča 0 …). Hráč sa hýbe bez toho, aby pokazil obrázok pod sebou, a počítač sám povie, či do niečoho narazil (kapitola 41). Tomu, čo sa takto kreslí, sa hovorí Player/Missile grafika, skrátene PMG.\nV pôvodnom Action! sa PMG robí zápismi do registrov (PMBASE, SDMCTL, GRACTL, HPOSP0 …) a treba vedieť, kde a ako zarovnať pamäť – ukážka examples/pmg.act. Action26 má na to rutiny, ktoré sa volajú rovnako ako v Action! Tool Kite.\nProgram 1: loď cez obrazovku Súbor examples/pm-ship.act:\nAction! ;@modern ; A ship that flies across the screen: player 0 BYTE ARRAY ship=[$18 $3C $7E $FF $DB $FF $24 $42] PROC Main() BYTE x, y=[120] PrintE(\"A ship made of player 0\") PMGraphics(1) ; players on, one line per byte PMCreate(0, ship, 8, 1, 48, y) ; player 0: 8 rows, width 1, x=48 PMColor(0, 1, 10) ; yellow Print(\"Its shape lives at \") PrintCE(PMAdr(0)+y) FOR x=48 TO 200 DO PMWait() ; one step per frame IF x\u002616 THEN y==+1 ELSE y==-1 FI ; up and down in steps of 16 PMMove(0, x, y) OD Print(\"The ship stopped at x=\") PrintB(PMX(0)) Print(\", y=\") PrintBE(PMY(0)) RETURN Preklad a spustenie action26 pm-ship.act --run V emulátore preletí žltá loď cik-cak zľava doprava (asi 3 sekundy) a program skončí. Simulátor hráčov nevidí, ale program v ňom prebehne a vypíše:\naction26 pm-ship.act --sim A ship made of player 0 Its shape lives at 11384 The ship stopped at x=200, y=127 Ako to funguje Tvar je pole bajtov, jeden bajt na riadok. Bit s hodnotou 1 je bod hráča, 0 je priehľadné miesto. Loď vyzerá takto ($18 = 00011000):\n$18 ...XX... $3C ..XXXX.. $7E .XXXXXX. $FF XXXXXXXX $DB XX.XX.XX $FF XXXXXXXX $24 ..X..X.. $42 .X....X. Rutina Čo robí PMGraphics(1) zapne hráčov a strely; 1 = jeden riadok obrazovky na bajt, 2 = dva riadky (bajt je dvakrát vyšší), 3 = ako 2, ale y v riadkoch obrazovky, 0 = vypne PMCreate(n, tvar, riadky, šírka, x, y) nakreslí tvar do hráča n (0–3) alebo strely (4–7): riadky = počet bajtov tvaru, šírka 1, 2 alebo 4 PMColor(n, odtieň, jas) farba hráča – rovnako ako SetColor (kapitola 27) PMMove(n, x, y) presunie objekt na nové miesto PMWait() počká, kým sa nakreslí ďalší obraz (50 alebo 60-krát za sekundu) PMX(n), PMY(n) funkcie – kde objekt je PMAdr(n) funkcia – adresa pamäte hráča n Súradnice sú tie, ktoré pozná hardvér, nie body obrazovky:\nRozsah Viditeľné x 0–255 asi 48–200 (hráč šírky 1); 48 je ľavý okraj textu y pri PMGraphics(1) a (3) 0–255 asi 32–223; riadok textu r začína na 32 + 8*r y pri PMGraphics(2) 0–127 asi 16–111 Mimo viditeľnej časti je objekt jednoducho skrytý – tak sa dá aj „schovať“.\nPrečo PMWait. Obraz sa kreslí 50-krát za sekundu (v Amerike 60). Bez čakania by slučka prebehla celú obrazovku skôr, než by sa stihla ukázať.\nPamäť. Tvary hráčov číta obrazový čip z pamäte, ktorá musí začínať na násobku 2 KB (pri PMGraphics(2) a (3) 1 KB). Prekladač ju vyhradí sám za koniec programu – PMAdr(0) ukáže, kde je. --memory-map ju vypíše ako PMG. Kto ju chce mať inde (napr. v banke, kapitola 42), povie to pred PMGraphics rutinou PMMemory(pole).\nKoniec programu hráčov vypne sám – aj keď program skončí chybou alebo klávesom RESET. Inak by loď ostala svietiť na obrazovke DOS-u.\nProgram 2: vták mávajúci krídlami Súbor examples/pm-bird.act:\nAction! ;@modern ; A bird that flaps its wings and glides down: PMShape and mode 3 BYTE ARRAY bird=[$81 $C3 $E7 $7E $3C $18 $00 $00 ; wings up $00 $18 $3C $7E $E7 $C3 $81 $00] ; wings down PROC Main() BYTE frame PMGraphics(3) ; two lines per byte, y in lines PMCreate(0, bird, 8, 2, 100, 40) ; double width PMColor(0, 15, 10) ; orange FOR frame=0 TO 119 DO PMWait() IF (frame\u00267)=0 THEN ; another picture every 8 frames PMShape(0, bird+(frame\u00268), 8) FI PMVPos(0, 40+frame) ; one line down every frame OD Print(\"The bird landed on line \") PrintBE(PMY(0)) RETURN action26 pm-bird.act --sim The bird landed on line 159 Ako to funguje Dva obrázky v jednom poli. bird má 16 bajtov: prvých 8 sú krídla hore, ďalších 8 dole. bird+8 je adresa druhého obrázka. frame\u00268 je striedavo 0 a 8, takže PMShape(0, bird+(frame\u00268), 8) mení obrázok každých 8 snímok – vták máva. PMShape vymení tvar na tom istom mieste; PMVPos posunie objekt len zvisle, PMHPos(n, x) len vodorovne. Runtime si pamätá tvar a polohu, takže zmaže len riadky, ktoré objekt opustil – to je rýchle. Šírka 2 (PMCreate(…, 2, …) alebo PMWidth(0, 2)) roztiahne každý bod na dvojnásobok; šírka 4 na štvornásobok. PMGraphics(3). Pri dvoch riadkoch na bajt by sa hráč hýbal zvisle po dvoch riadkoch. Režim 3 počíta y po riadkoch a nepárne y doladí registrom VDELAY – pohyb je plynulý a pamäť stále polovičná. Ďalšie rutiny Rutina Čo robí PMWidth(n, w) šírka 1, 2 alebo 4 PMClear(n) zmaže objekt (strela len svoje 2 body) PMPriority(p) kto je vpredu: 1 hráči nad všetkým, 4 obrázok nad hráčmi; +16 štyri strely ako piaty hráč, +32 viacfarebné hráče PMMemory(pole) vlastné miesto pre pamäť hráčov PMGraphics(0) vypne hráčov a strely Mená čísel. Súbor examples/modern/HARDWARE.ACT (INCLUDE) má pre ne mená: PM_SINGLE, PM_DOUBLE, PM_WIDE, PRI_PLAYFIELD …\nGraphics nechá hráčov zapnutých. Obrazový režim sa dá zmeniť aj počas hry; hráči ostanú na mieste.\nProgram si hráčov kreslí aj sám. Do pamäte z PMAdr(n) sa dá zapisovať ako do poľa (BYTE POINTER). Objekt, ktorý nemá tvar z PMCreate, sa potom pri PMMove posúva tak, že sa celý pás pootočí (ako v Tool Kite) – pomalšie, ale funguje.\nNa čo si dať pozor Hráč je jeden pás cez celú výšku obrazovky. Ten istý hráč nemôže byť naraz na dvoch miestach vedľa seba – dva objekty nad sebou áno (kapitola 42). Tvar sa nekopíruje. Runtime si pamätá adresu poľa. Keď pole zmeníš, nový tvar sa ukáže až pri ďalšom PMMove, PMVPos alebo PMShape. Strela má tvar len z dvoch spodných bitov každého bajtu: [1 1 1] je strela široká jeden bod, [3 3 3] dva body. PMGraphics všetko vynuluje: tvary a polohy treba nastaviť až po ňom. Časté chyby Čo sa stalo Čo sa stane program bez ;@modern error ACT008: undeclared name 'PMGraphics' PMMemory s poľom, ktoré nezačína na celej stránke ($xx00) Err: 107 PMMemory s poľom, ktoré nie je na násobku 2 KB (1 KB pri PMGraphics(2)) Err: 107 pri PMGraphics hráč „zmizne“ x alebo y mimo viditeľnej časti, alebo chýba PMColor (farba 0 = čierna) loď preletí obrazovku hneď chýba PMWait() v slučke Vyskúšaj si Ovládaj loď joystickom: v slučke s=Stick(0) a podľa bitov zmeň x a y (kapitola 29). Hotové je to v examples/modern/players.act. Zmeň v prvom programe PMGraphics(1) na PMGraphics(2) a y=[120] na y=[60]. Ako sa zmenil tvar lode? Daj vtákovi tretí obrázok (krídla rovno) a striedaj tri. Zhrnutie Hráči 0–3 a strely 4–7 sú pásy, ktoré GTIA kreslí navrch obrazovky. PMGraphics ich zapne, PMCreate nakreslí tvar, PMMove, PMHPos, PMVPos hýbu, PMShape mení tvar, PMColor a PMWidth farbu a šírku. Pamäť pre ne vyhradí prekladač; koniec programu ich vypne. Súradnice sú hardvérové: x asi 48–200, y asi 32–223. Podrobnejšie: lekcia 4 examples/modern/players.act, opis všetkých rutín v docs/runtime.md.\nSpäť: 39. Dáta zo súboru a kompresia · Ďalej: 41. Zrážky\n","t":"40. Hráči a strely: Player/Missile grafika","u":"40-pmg/"},{"c":"Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35). Nadväzuje na kapitolu 40.\nNa čo to je Hra potrebuje vedieť, či strela trafila, či loď narazila do steny alebo do nepriateľa. Atari to vie samo: obvod GTIA si pri kreslení každého obrazu zapisuje, ktorý hráč alebo strela sa prekryl s ktorým hráčom a s ktorou farbou obrázka. Program tieto zrážky (collisions) len prečíta.\nDruhá možnosť je spočítať zrážku v programe z polôh a rozmerov objektov. Obe majú svoje výhody – tento program ukazuje obe naraz.\nProgram: kameň padá na loď Súbor examples/pm-hit.act:\nAction! ;@modern ; A rock falls on a ship: a collision from the hardware and from PMOverlap BYTE ARRAY ship=[$18 $3C $7E $FF $FF $DB $81 $81], rock=[$3C $7E $FF $FF $FF $FF $7E $3C] PROC Main() BYTE y, hw=[0], sw=[0] PMGraphics(1) PMCreate(0, ship, 8, 1, 120, 180) ; the ship at the bottom PMCreate(1, rock, 8, 1, 120, 100) ; the rock above it PMColor(0, 1, 12) PMColor(1, 2, 6) PMWait() HitClr() FOR y=101 TO 190 DO PMWait() ; the rock at y-1 is on the screen now IF hw=0 AND PMHitPM(1)\u00261 THEN ; player 1 met player 0 hw=y-1 FI HitClr() PMVPos(1, y) ; the rock one row lower IF sw=0 AND PMOverlap(0, 1) THEN ; the rectangles overlap at once sw=y FI OD Print(\"PMOverlap: the rock hit the ship at y=\") PrintBE(sw) Print(\"Hardware: the rock hit the ship at y=\") PrintBE(hw) RETURN Preklad a spustenie action26 pm-hit.act --sim PMOverlap: the rock hit the ship at y=173 Hardware: the rock hit the ship at y=0 Simulátor nemá obvod GTIA, preto hardvér v ňom zrážku nehlási (0). V emulátore (--run) vypíše program oba riadky s y=173: kameň v riadkoch 173–180 sa dotkne lode v riadku 180.\nAko to funguje Zrážky z hardvéru:\nRutina Vráti PMHitPM(n) bity 0–3: s ktorými hráčmi sa objekt n zrazil (bit 0 = hráč 0, hodnota 1; bit 1 = hráč 1, hodnota 2 …) PMHitPF(n) bity 0–3: s ktorými farbami obrázka (playfield 0–3) sa objekt n zrazil PMHit(n, c) 1 alebo 0: c 0–3 je hráč, 4–7 farba obrázka 0–3 (ako v Tool Kite) HitClr() všetky zrážky vynuluje PMHitPM(1)\u00261 je teda „hráč 1 narazil do hráča 0“. Rovnako by platilo PMHitPM(0)\u00262 – zrážku hráčov hlási hardvér u oboch.\nDve pravidlá hardvérových zrážok:\nBity sa len pridávajú. Raz nastavený bit ostane, kým program nezavolá HitClr(). Bez neho by jeden náraz platil navždy. Zrážka sa zistí až pri kreslení. Hneď po PMVPos registre ešte hovoria o starej polohe. Preto slučka robí vždy to isté: počkaj na obraz (PMWait) → prečítaj → HitClr → pohni. Program si preto pamätá y-1 – zrážku našiel obraz, v ktorom bol kameň ešte o riadok vyššie. Zrážka z programu: PMOverlap(a, b) vráti 1, keď sa prekrývajú obdĺžniky dvoch objektov (poloha, šírka a počet riadkov tvaru, ktoré si runtime pamätá). Funguje hneď po pohybe, aj pre neviditeľný objekt a aj pre dve strely (hardvér zrážku strely so strelou nepozná). Je to však len obdĺžnik: prázdne rohy tvaru sa rátajú tiež. Hardvér naopak hlási len skutočne nakreslené body.\nZrážky s obrázkom a strely PMHitPF(n) hlási, do ktorej farby obrázka objekt narazil. Pozor na textový režim: písmená v GRAPHICS 0 sa hlásia ako farba 2 (hodnota 4), hoci ich farbu nastavuje SetColor(1, …):\nAction! IF PMHitPF(4)\u00264 THEN ; strela 0 (objekt 4) narazila do textu PMClear(4) FI Strely sú objekty 4–7. Tvar strely sú dva spodné bity každého bajtu ([1 1 1] – úzka, [3 3 3] – široká) a strela má farbu svojho hráča:\nAction! BYTE ARRAY shot=[1 1 1 1] PMCreate(4, shot, 4, 1, x+3, 170) ; strela 0 z lode PMVPos(4, sy) ; letí hore IF PMHitPM(4)\u00262 THEN … ; strela 0 trafila hráča 1 Celá hra so strelou, textom a životmi je lekcia examples/modern/collide.act.\nNa čo si dať pozor Zrážka strely so strelou neexistuje – na to je PMOverlap. Hráč s farbou rovnakou ako pozadie sa stále zráža (kolízia nepozerá na farbu, len na body). Pri piatom hráčovi (PMPriority(1+16)) sa strely stále hlásia ako strely. V simulátore (--sim) sú zrážky z hardvéru vždy nesprávne alebo nulové – skúšaj ich v emulátore. Časté chyby Čo sa stalo Prečo zrážka platí stále, aj keď sa objekty už rozišli chýba HitClr() zrážka sa nezistí, hoci sa objekty prekrývajú čítaš hneď po pohybe, nie po PMWait() zrážka s textom sa nehlási pri PMHitPF(n)\u00262 text v GRAPHICS 0 je farba 2: \u00264 PMOverlap hlási zrážku o kúsok skôr ráta obdĺžniky, nie body Vyskúšaj si Posuň kameň v programe na x=126 (len dva stĺpce nad pravým okrajom lode). Kedy nahlási zrážku PMOverlap a kedy hardvér? Daj lodi strelu: PMCreate(4, shot, 4, 1, 123, 175) a v slučke ju posúvaj hore. Kedy ju zastaví PMHitPM(4)\u00262? Vypíš na obrazovku riadok textu a nechaj kameň padať cez neho. Zistí to PMHitPF(1)? Zhrnutie PMHitPM, PMHitPF, PMHit čítajú zrážky z hardvéru, HitClr ich vynuluje. Poradie v slučke: PMWait → čítaj → HitClr → pohni. Text v GRAPHICS 0 je farba obrázka 2 (bit s hodnotou 4). PMOverlap porovná obdĺžniky hneď, aj pre strely a skryté objekty. Podrobnejšie: lekcia 46 examples/modern/collide.act, ukážka examples/pmgM.act.\nSpäť: 40. Hráči a strely · Ďalej: 42. Viac objektov, banky a menu\n","t":"41. Zrážky","u":"41-pmg-zrazky/"},{"c":"Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35). Nadväzuje na kapitoly 40 a 41.\nNa čo to je Štyria hráči sú pre hru málo. Hry na Atari preto ukazujú jedného hráča na viacerých miestach: obrazovka sa rozdelí na pásy a v každom má hráč inú polohu a farbu. Prepína ich krátky program, ktorý počítač spustí uprostred kreslenia obrazu – prerušenie display listu (DLI). Action26 ho má hotové: stačí povedať, kde pásy začínajú a čo v nich má byť.\nKapitola ukazuje aj dve menšie veci: hráčov v banke 130XE a hráča ako zvýraznenie riadku v menu.\nProgram: traja nepriatelia z jedného hráča Súbor examples/pm-lanes.act:\nAction! ;@modern ; Three enemies made of one player: sprites in bands BYTE ARRAY enemy=[$3C $7E $DB $FF $FF $A5 $81 $C3] PROC Main() BYTE i, t Graphics(0) PMGraphics(1) FOR i=0 TO 2 DO PMSprite(8+i, 0, i+1) ; sprite 8+i is player 0 in band i+1 PMBand(i+1, 4+6*i) ; bands from text rows 4, 10 and 16 PMCreate(8+i, enemy, 8, 1, 50+20*i, 32+8*(5+6*i)) ; on rows 5, 11, 17 OD PMColor(8, 4, 8) ; red PMColor(9, 12, 10) ; green PMColor(10, 8, 12) ; blue PMBands(4) ; band 0 (the top) and bands 1-3 FOR t=1 TO 100 DO PMWait() FOR i=0 TO 2 DO PMHPos(8+i, PMX(8+i)+1) ; each one in its own band OD OD FOR i=0 TO 2 DO Print(\"Enemy \") PrintB(i+1) Print(\" stopped at x=\") PrintBE(PMX(8+i)) OD RETURN Preklad a spustenie action26 pm-lanes.act --run V emulátore idú zľava doprava traja nepriatelia – červený, zelený a modrý – každý v inom pruhu obrazovky, hoci sú všetci hráč 0. Simulátor nemá display list, takže pásy v ňom nie sú, ale program prebehne:\naction26 pm-lanes.act --sim Enemy 1 stopped at x=150 Enemy 2 stopped at x=170 Enemy 3 stopped at x=190 Ako to funguje Rutina Čo robí PMSprite(s, n, pás) objekt s (8–15) je sprite: kreslí sa do hráča n (0–3) a ukazuje sa v páse pás PMBand(pás, riadok) pás 1–7 začína riadkom obrazovky (v GRAPHICS 0 riadkom textu) PMBands(počet) zapne pásy 0 až počet-1; PMBands(0) ich vypne Pás 0 je vrch obrazovky. Pásy 1–7 začínajú riadkom z PMBand; riadky musia s číslom pásu rásť. Sprite je objekt ako každý iný: PMCreate, PMMove, PMShape, PMClear kreslia jeho tvar do pásu hráča (len jeho riadky), PMHPos a PMColor zmenia jeho polohu a farbu – ale len v jeho páse. Na to, kde sa ktorý riadok zobrazí, nemá vplyv nič iné: tvar spritu musí ležať v riadkoch jeho pásu. Hráč bez spritu v páse si tam drží vlastnú polohu a farbu. Zrážky hlási hardvér pre celého hráča – PMHitPM(8) je zrážka hráča 0 v ktoromkoľvek páse. Ktorý sprite to bol, povie PMOverlap. Šírka (PMWidth) tiež patrí celému hráčovi. Na čo si dať pozor Pásy majú byť od seba aspoň dva riadky textu a prvý riadok pásu nech je v tvare prázdny – nová poloha sa zapisuje práve počas neho. Graphics(n) postaví nový display list: po ňom treba zavolať PMBands znova. Program, ktorý má vlastné prerušenie display listu (kapitola 37, ASM), pásy nepoužije. Koniec programu, PMBands(0) aj PMGraphics pásy vypnú a vrátia všetko, ako bolo. Väčšia hra – loď, ktorá sa vyhýba nepriateľom v troch pruhoch – je lekcia examples/modern/bands.act.\nHráči v banke 130XE Obrazový čip číta tvary hráčov z pamäte rovnako ako obrazovku. Keď je pamäť hráčov v okne $4000–$7FFF, XAntic (kapitola 38) určí, či ju číta z bežnej pamäte alebo z banky:\nAction! BYTE ARRAY pm(1024)=$4000 ; pamäť hráčov v okne PMMemory(pm) XBank(1) PMGraphics(2) PMCreate(0, down, 8, 2, 60, 50) ; obrázok v banke 1 XBank(0) PMGraphics(2) PMCreate(0, up, 8, 2, 60, 50) ; obrázok v bežnej pamäti … XAntic(1) ; ukáž banku 1 XAntic(0) ; ukáž bežnú pamäť Dva obrázky na tej istej adrese a prepínanie XAntic dajú animáciu, pri ktorej sa nekreslí ani bajt. Procesor a obrazový čip však nemôžu vidieť naraz dve rôzne banky – striedať sa dá bežná pamäť a jedna banka. Celý program je lekcia examples/modern/pmbank.act (potrebuje 130XE).\nHráč ako zvýraznenie v menu Hráč so šírkou 4 má 32 bodov – to je šírka ôsmich znakov textu. Dvaja vedľa seba dajú pruh cez 16 znakov, ktorý sa dá posúvať po riadkoch menu bez prekresľovania textu:\nAction! SetBlock(bar, 8, $FF) ; tvar: 8 plných riadkov = jeden riadok textu PMCreate(0, bar, 8, 4, 60, 32+8*riadok) ; stĺpec 3: x = 48 + 4*3 PMCreate(1, bar, 8, 4, 92, 32+8*riadok) PMColor(0, 9, 4) PMColor(1, 9, 4) ; tmavá farba … PMVPos(0, 32+8*riadok) PMVPos(1, 32+8*riadok) Hráč je pred textom, ale písmená v ňom ostanú čitateľné: podľa opisu obvodu GTIA im v textovom režime nechá jas textu a dá im odtieň hráča. Preto má byť pruh tmavý. Celé menu s joystickom je lekcia examples/modern/cursor.act.\nKoľko to stojí Rutiny hráčov zaberajú v programe od asi 500 bajtov (len hráči, bez striel) po asi 2 kilobajty (všetko vrátane spritov a pásov). Prekladač pribalí len to, čo program naozaj volá – napríklad kód pre strely len vtedy, keď program použije objekt 4–7, a kód pre pásy len s PMSprite, PMBand alebo PMBands. Program bez hráčov nemá z toho nič.\nVyskúšaj si Pridaj štvrtý pás a štvrtého nepriateľa (PMSprite(11, 0, 4), PMBand(4, 21)). Daj do pásu 2 aj hráča 1 ako sprite (PMSprite(12, 1, 2)) – dvaja nepriatelia v jednom páse. Prelož pm-ship.act a pm-lanes.act s --memory-map a porovnaj, koľko bajtov má program. Koľko pridali sprity a pásy? Zhrnutie PMSprite, PMBand, PMBands ukážu jedného hráča vo viacerých pásoch obrazovky s inou polohou a farbou. Sprite (objekt 8–15) má vlastný tvar a polohu; zrážky a šírka patria celému hráčovi. PMMemory s poľom v okne a XAntic ukážu hráčov z banky 130XE. Hráč so šírkou 4 je dobré zvýraznenie riadku menu. Podrobnejšie: lekcie 47 až 49 v examples/modern/, opis v docs/runtime.md.\nSpäť: 41. Zrážky · Ďalej: Príloha A – Jazyk na jednej strane\n","t":"42. Viac objektov, banky a menu","u":"42-pmg-viac/"},{"c":"Ťahák. Vysvetlenie každej veci je v kapitole uvedenej v zátvorke.\nKostra programu Action! ; komentár do konca riadka DEFINE MAX=\"10\" ; mená pre texty a čísla (17) TYPE Point=[BYTE x, y] ; typ záznamu (21) BYTE score ; globálne premenné (16) PROC Helper(BYTE n) ; procedúra (3, 14) BYTE i ; lokálne premenné – pred prvým príkazom … RETURN BYTE FUNC Twice(BYTE n) ; funkcia (15) RETURN(n*2) PROC Main() ; program začína v POSLEDNEJ rutine … RETURN Hodnoty (5) Zápis Príklad desiatkové číslo 65 šestnástkové číslo $41 znak 'A reťazec \"text\", úvodzovka vnútri \"\" Typy (6, 18–21) Typ Bajtov Rozsah BYTE, CHAR 1 0 až 255 CARD 2 0 až 65535 INT 2 −32768 až 32767 typ POINTER 2 adresa typ ARRAY meno(n) n prvkov indexy 0 až n−1 TYPE Meno=[…] súčet položiek záznam Deklarácie Action! BYTE a, b ; premenné BYTE lives=[3] ; s počiatočnou hodnotou BYTE colour=710 ; na adrese (24) BYTE ARRAY t(10) ; pole BYTE ARRAY days=[31 28 31] ; pole s hodnotami CHAR ARRAY name=\"Atari\" ; reťazec: name(0) je dĺžka (19) CHAR ARRAY buffer(40) ; miesto pre reťazec BYTE POINTER p ; ukazovateľ (20) Point here ; záznam Point POINTER pp ; ukazovateľ na záznam Operátory (7, 9, 22) Od najvyššej priority; pri rovnakej zľava doprava.\nPriorita Operátory Význam 1 ( ) zátvorky 2 - (pred hodnotou), @ záporné číslo, adresa premennej 3 * / MOD LSH RSH násobenie, delenie, zvyšok, posun bitov 4 + - sčítanie, odčítanie 5 = # \u003c\u003e \u003c \u003e \u003c= \u003e= porovnania 6 AND \u0026 a zároveň / bitové AND 7 OR % alebo / bitové OR 8 XOR ! bitové XOR Typ výsledku: samé BYTE → BYTE; BYTE s INT → INT; čokoľvek s CARD → CARD.\nPríkazy Action! x=výraz ; priradenie (7) x==+1 x==-1 x==*2 ; skrátené priradenie p^=5 t(i)=x r.pole=1 ; cez ukazovateľ, do prvku, do položky Meno(a, b) ; volanie procedúry x=Meno(a, b) ; volanie funkcie IF podm THEN … FI ; (9) IF podm THEN … ELSE … FI IF podm THEN … ELSEIF podm THEN … ELSE … FI DO … OD ; nekonečná slučka (10) WHILE podm DO … OD ; (11) DO … UNTIL podm OD ; (12) FOR i=a TO b DO … OD ; (13) FOR i=a TO b STEP s DO … OD EXIT ; von z najbližšej slučky RETURN ; koniec procedúry RETURN(výraz) ; koniec funkcie s výsledkom [$A9 $00] ; blok strojového kódu (25) Pokyny prekladaču (17, 23) Pokyn Význam DEFINE MENO=\"text\" nahrádza meno textom INCLUDE \"D:SUBOR.ACT\" vloží súbor SET adresa=hodnota nastaví prekladač MODULE dovolí globálne deklarácie medzi rutinami Vyhradené slová Nedajú sa použiť ako mená:\nAND ARRAY BYTE CARD CHAR DEFINE DO ELSE ELSEIF EXIT FI FOR FUNC IF INCLUDE INT LSH MOD MODULE OD OR POINTER PROC RETURN RSH SET STEP THEN TO TYPE UNTIL WHILE XOR Menami nemajú byť ani rutiny a premenné knižnice (Print, Stick, color, device, EOF …) – vlastná premenná s takým menom ich zakryje. Veľké a malé písmená sa nerozlišujú.\nRozšírenia action26 (;@modern, 35–42) Action! CONST MAX=10 ; konštanta TYPE Light=ENUM [RED, GREEN] ; vymenovaný typ; hodnota Light.RED BYTE ARRAY grid(4,6) ; viacrozmerné pole CASE x OF ; výber WHEN 1 THEN … WHEN 2, 3 THEN … WHEN 4 TO 9 THEN … WHEN 10 TO 20 IF podm THEN … ELSE … ESAC y=(a\u003eb) ; porovnanie ako 1/0 y=IF a\u003eb THEN a ELSE b FI ; IF ako hodnota y=CARD(a)+b ; pretypovanie \"text\\{RETURN}\" ; špeciálne znaky ORG $CB … ENDORG ; deklarácie na adrese ORG $4000 BANK 1 … ENDORG ; dáta v banke ALIGN 1024 ; zarovnanie ASM … ENDASM ; assembler BYTE ARRAY d=FILE \"súbor\" ; súbor ako pole BYTE ARRAY d=PACK FILE \"súbor\" ; zbalený CHAR ARRAY t=PACK \"text\" ; zbalený text Päť pascí, ktoré treba vedieť naspamäť Program začína v poslednej rutine. BYTE x=5 je premenná na adrese 5; počiatočná hodnota je BYTE x=[5]. Výraz zo samých BYTE sa počíta v BYTE – 200+100 je 44. Indexy polí idú od 0 a nikto ich nekontroluje. Lokálne premenné nezanikajú – rekurzia nefunguje. Ďalej: Príloha B – Knižnica na jednej strane · Obsah\n","t":"Príloha A – Jazyk na jednej strane","u":"a-jazyk/"},{"c":"Všetky rutiny, ktoré môžeš volať bez deklarácie. V zátvorke je kapitola. k znamená kanál 0 až 7, s reťazec.\nVýstup (4, 26, 30) Rutina Čo robí Print(s), PrintE(s) text; s E aj koniec riadka PrintD(k, s), PrintDE(k, s) text na kanál Put(c), PutE() znak; koniec riadka PutD(k, c), PutDE(k) to isté na kanál PrintB(n), PrintBE(n), PrintBD(k, n), PrintBDE(k, n) číslo BYTE PrintC(n), PrintCE(n), PrintCD(k, n), PrintCDE(k, n) číslo CARD PrintI(n), PrintIE(n), PrintID(k, n), PrintIDE(k, n) číslo INT PrintF(formát, a, b, c, d, e) formátovaný výpis; %U %I %C %S %H %E %% Vstup (8, 30) Rutina Čo robí InputS(s), InputSD(k, s) načíta riadok do reťazca InputMD(k, s, veľkosť) načíta riadok, najviac veľkosť−1 znakov InputB(), InputBD(k) funkcia – načíta číslo BYTE InputC(), InputCD(k) funkcia – načíta číslo CARD InputI(), InputID(k) funkcia – načíta číslo INT GetD(k) funkcia – jeden znak z kanála; GetD(7) čaká na kláves Súbory a zariadenia (30) Rutina Čo robí Open(k, s, režim, 0) otvorí; režim 4 čítanie, 8 zápis, 9 pripísanie, 12 oboje, 6 zoznam súborov Close(k) zavrie XIO(k, 0, príkaz, a1, a2, s) príkaz zariadeniu: 32 premenuj, 33 zmaž, 35 zamkni, 36 odomkni Note(k, @sektor, @posun) zapamätá miesto v súbore Point(k, sektor, posun) vráti sa na miesto Grafika (27) Rutina Čo robí Graphics(režim) zapne grafický režim; +16 bez textového okna SetColor(register, odtieň, jas) farba registra 0 až 4 Plot(stĺpec, riadok) bod DrawTo(stĺpec, riadok) čiara z posledného bodu Fill(stĺpec, riadok) výplň doprava po okraj Position(stĺpec, riadok) kurzor Locate(stĺpec, riadok) funkcia – farba bodu alebo kód znaku Zvuk a ovládače (28, 29) Rutina Čo robí Sound(hlas, výška, skreslenie, hlasitosť) tón na hlase 0 až 3 SndRst() ticho Stick(port) funkcia – joystick; 15 stred, 14 hore, 13 dole, 11 vľavo, 7 vpravo STrig(port) funkcia – tlačidlo; 0 = stlačené Paddle(port) funkcia – paddle, 1 až 228 PTrig(port) funkcia – tlačidlo paddla; 0 = stlačené Rand(rozsah) funkcia – náhodné číslo 0 až rozsah−1; Rand(0) 0 až 255 Reťazce a prevody (19, 26) Rutina Čo robí SCopy(kam, odkiaľ) kópia SCopyS(kam, odkiaľ, od, do) časť reťazca SAssign(kam, odkiaľ, od, do) vloženie do reťazca SCompare(a, b) funkcia – záporné, 0, kladné StrB(n, s), StrC(n, s), StrI(n, s) číslo → reťazec ValB(s), ValC(s), ValI(s) funkcie – reťazec → číslo Pamäť (24, 31) Rutina Čo robí Peek(adresa), PeekC(adresa) funkcie – bajt / CARD z pamäte Poke(adresa, hodnota), PokeC(adresa, hodnota) zápis bajtu / CARD Zero(adresa, počet) vynuluje blok SetBlock(adresa, počet, hodnota) vyplní blok MoveBlock(kam, odkiaľ, počet) skopíruje blok Chyby (31) Rutina Čo robí Error(kód) obsluha chýb; Error=MojaProc ju presmeruje Break() vyvolá chybu 128 Premenné knižnice Premenná Adresa Význam color 765 farba pre Plot, DrawTo, Fill device 183 kanál, na ktorý píšu rutiny bez D (predvolene 0) EOF 1472 pole 8 bajtov: EOF(k) je nenulové po konci súboru na kanáli k Len s ;@modern (36, 38–42) Rutina Čo robí PrintU(text, znak, najviac), PrintUD(k, …) text ukončený znakom, aj nad 255 znakov XBanks() funkcia – počet bánk rozšírenej pamäte XPeek(b, a), XPeekC(b, a), XPoke(b, a, v), XPokeC(b, a, v) pamäť v banke a pod ROM XMoveBlock(kb, kam, ob, odkiaľ, počet) kópia medzi bankami XSetBlock(b, a, počet, v), XZero(b, a, počet) vyplnenie v banke XPrint(b, a, znak), XPrintD(k, b, a, znak) výpis textu z banky XRead(k, b, a, počet), XWrite(k, b, a, počet) súbor ↔ banka XBank(b), XAntic(b) banka v okne natrvalo; banka pre obrazový čip BankOf(meno) číslo banky, v ktorej meno leží Unpack(z, kam), UnpackRLE(z, kam), UnpackZX02(z, kam) funkcie – rozbalia dáta PackRLE(odkiaľ, koľko, kam) funkcia – zbalí pamäť PrintPacked(t), PrintPackedE(t), PrintPackedD(k, t), PrintPackedDE(k, t) výpis zbaleného textu UnpackText(t, s) zbalený text → reťazec UsePackedTexts(súbor), PackedText(súbor, číslo) texty zo súboru z --pack-text UsePackedTexts2(súbor), PackedText2(súbor, číslo) texty zo súboru z --pack-text2 UnpackW8P(súbor, kam, najviac), UnpackW8PD(k, kam, najviac) súbory W8P PMGraphics(r), PMMemory(pole), PMAdr(n) Player/Missile grafika: 1 jeden riadok na bajt, 2 dva riadky, 3 dva riadky s y po riadku, 0 vypne; vlastná pamäť; adresa pásu PMCreate(n, tvar, riadky, šírka, x, y), PMShape(n, tvar, riadky), PMClear(n) tvar playera (0–3) alebo strely (4–7) PMMove(n, x, y), PMHPos(n, x), PMVPos(n, y), PMX(n), PMY(n) poloha PMWidth(n, w), PMColor(n, odtieň, jas), PMPriority(p) šírka, farba, priorita PMHitPF(n), PMHitPM(n), PMHit(n, c), HitClr() zrážky s obrazom a s playermi PMWait(), PMOverlap(a, b) čaká na snímku; prekrytie dvoch objektov PMSprite(s, n, pás), PMBand(pás, riadok), PMBands(počet) viac objektov jedným playerom v pásoch obrazovky Ďalej: Príloha C – Chyby · Obsah\n","t":"Príloha B – Knižnica na jednej strane","u":"b-kniznica/"},{"c":"Chyby sú dvojakého druhu: tie, ktoré nájde prekladač (program sa nepreloží), a tie, ktoré nastanú za behu (program sa preložil, ale niečo sa pokazilo).\nAko čítať hlásenie prekladača hello.act(2,10): error ACT001: missing double quote in string Súbor, v zátvorke riadok a stĺpec, potom druh (error chyba, warning upozornenie, note doplnenie k predošlému), číslo a popis.\nOpravuj vždy prvú chybu; ďalšie bývajú jej následkom. Miesto je tam, kde si prekladač chybu všimol – skutočná príčina môže byť o kúsok skôr. Po 20 chybách prekladač prestane (dá sa zmeniť voľbou --max-errors). Chyby prekladu s číslami pôvodného Action! Čísla 0 až 28 a 61 sú rovnaké ako v pôvodnom Action!. Niektoré sa týkali len obmedzenej pamäte Atari a v action26 ich nestretneš.\nČíslo Hlásenie Čo zvyčajne znamená ACT001 missing double quote in string chýba úvodzovka na konci textu, alebo je text dlhší ako 255 znakov ACT002 nested DEFINE DEFINE, ktorý sa odvoláva sám na seba ACT005 SET directive syntax error zle zapísaný SET ACT006 declaration error meno je už použité; deklarácia za príkazom; zlý tvar deklarácie ACT007 invalid argument list chýba zátvorka za menom rutiny; priveľa argumentov ACT008 variable not declared neznáme meno – preklep, chýbajúca deklarácia, rutina napísaná až pod volaním ACT009 not a constant na mieste, kde má byť číslo známe pri preklade, je premenná ACT010 illegal assignment priradenie do poľa, záznamu alebo konštanty; volanie bez zátvoriek ACT011 unknown error prekladač narazil na niečo, čo nečakal – často následok predošlej chyby ACT012 missing THEN za podmienkou IF chýba THEN; == namiesto = ACT013 missing FI IF bez FI ACT015 missing DO WHILE alebo FOR bez DO ACT016 missing TO FOR bez TO ACT017 bad expression zle zapísaný výraz ACT018 unmatched parentheses chýba alebo prebýva zátvorka ACT019 missing OD slučka bez OD; UNTIL nie je tesne pred OD ACT021 illegal array reference index za niečím, čo nie je pole – často premenná s menom knižničnej rutiny ACT023 illegal conditional expression porovnanie mimo podmienky; 1\u003ca\u003c3; chýbajú zátvorky okolo x\u0026maska ACT024 illegal FOR statement zle zapísaný FOR ACT025 illegal EXIT EXIT mimo slučky ACT027 illegal TYPE declaration zle zapísaný TYPE ACT028 illegal RETURN RETURN(x) v procedúre; RETURN bez hodnoty vo funkcii Čísla 0, 3, 4, 14, 20, 22, 26 a 61 sú o nedostatku pamäte pôvodného prekladača.\nHlásenia action26 Číslo Druh Význam ACT200 chyba zlý príkazový riadok ACT201, ACT202 chyba súbor sa nedá otvoriť / zapísať ACT203 chyba súbor z INCLUDE alebo FILE sa nenašiel ACT204, ACT205 chyba INCLUDE vkladá sám seba; príliš hlboké vnorenie ACT209 varovanie znak, ktorý do jazyka nepatrí, bol preskočený ACT211 chyba desatinné číslo – Action! ich nemá ACT212 varovanie premenná, ktorú nikde nepoužívaš ACT213 varovanie menej argumentov ako parametrov (len s --wextra) ACT214 varovanie položka patrí inému typu záznamu ACT215 varovanie číslo sa do typu nezmestí a skráti sa ACT216 chyba program nemá žiadnu rutinu ACT217 varovanie delenie nulou ACT219 varovanie --strict: toto by pôvodný Action! odmietol ACT220–ACT227 chyba assembler (blok ASM; 225 aj prekrytie blokov ORG) ACT228 varovanie veľkosť poľa daná premennou ACT231, ACT232 chyba / varovanie nastavenia v zdrojáku (;@…): zlé; prebité príkazovým riadkom ACT233 chyba / varovanie ORG, ENDORG, ALIGN ACT234 chyba CASE ACT235, ACT236 chyba / varovanie IF a CASE ako hodnota ACT237 chyba ENUM ACT238, ACT239 chyba / varovanie viacrozmerné polia ACT240 chyba špeciálny znak \\{…} ACT241–ACT243 chyba / varovanie rozšírená pamäť a okno bánk ACT244 varovanie súbor W8P typu, ktorý sa na Atari nedá rozbaliť Chyby za behu Keď rutina knižnice narazí na problém, program vypíše\nErr: 170 a skončí – pokiaľ nemáš vlastnú obsluhu chýb (kapitola 31).\nChyby knižnice action26 Číslo Význam 100 Sound s číslom hlasu väčším ako 3 101 banka rozšírenej pamäte neexistuje 102 prístup do zakázanej oblasti (registre, vektory) 103, 104 XAntic: nezlučiteľná banka; rozšírenie to nevie 105 zbalené dáta v neznámom formáte 106 poškodený súbor W8P 107 Player/Missile grafika: pamäť z PMMemory chýba, nezačína na celej stránke alebo nie je na násobku 2 KB (1 KB) Chyby zariadení Číslo Význam 128 stlačený kláves BREAK 129 kanál je už otvorený 130 zariadenie neexistuje 131 kanál je otvorený len na zápis 132 neplatný príkaz 133 kanál nie je otvorený 134 zlé číslo kanála 135 kanál je otvorený len na čítanie 136 koniec súboru (nehlási sa ako chyba; nastaví EOF) 137 riadok je dlhší ako miesto preň 138 zariadenie neodpovedá 139 zariadenie odmietlo príkaz 141 kurzor alebo bod mimo obrazovky 144 chyba zariadenia – disketa chránená proti zápisu alebo poškodená 146 zariadenie túto operáciu nevie 147 málo pamäte na grafický režim Chyby diskety Číslo Význam 160 zlé číslo jednotky 161 priveľa otvorených súborov 162 disketa je plná 164 poškodený súbor 165 zlé meno súboru 167 súbor je zamknutý 169 adresár je plný 170 súbor neexistuje Chyby, ktoré nikto nehlási Najviac času zaberú chyby, pri ktorých prekladač mlčí a program beží – len zle. Všetky sú opísané v kapitolách:\nPríznak Pravdepodobná príčina Kapitola premenná sa „sama“ mení index mimo poľa, pridlhý reťazec 18, 19 výpočet dáva malé nezmyselné číslo výraz zo samých BYTE pretiekol 7 program sa zacyklí FOR s BYTE do 255; chýbajúci RETURN; podmienka, ktorá sa nikdy nezmení 13, 3, 11 rutina „nemení“ premennú dostala kópiu, nie adresu 14, 20 rutina počíta zle pri volaní zo seba rekurzia 16 výpis je nezmysel text v Put, číslo v Print, zlá značka v PrintF 4, 26 dva rovnaké texty „nie sú rovnaké“ porovnanie reťazcov cez = 19 farba pozadia sa mení sama BYTE x=710 namiesto BYTE x=[710] 6, 24 Ďalej: Príloha D – Atari v číslach · Obsah\n","t":"Príloha C – Chyby","u":"c-chyby/"},{"c":"Znaky (ATASCII) Atari má vlastnú tabuľku znakov. Písmená, číslice a bežné znamienka sú na rovnakých kódoch ako v ASCII.\nKódy Znaky 0–26 grafické znaky (čiary, rohy, kartové symboly) 27 ESC 28, 29, 30, 31 kurzor hore, dole, vľavo, vpravo 32 medzera 33–47 ! \" # $ % \u0026 ' ( ) * + , - . / 48–57 číslice 0–9 58–64 : ; \u003c = \u003e ? @ 65–90 veľké písmená A–Z 91–95 [ \\ ] ^ _ 96 grafický znak (kosoštvorec) 97–122 malé písmená a–z 123, 124 grafický znak, | 125 vymazanie obrazovky 126 zmazanie znaku vľavo 127 tabulátor 155 koniec riadka ($9B) 253 pípnutie 128–255 tie isté znaky inverzne (kód + 128), okrem riadiacich Riadiace znaky (28–31, 125–127, 253) sa pri výpise vykonajú – Put(125) vymaže obrazovku. Ak ich chceš vidieť ako znak, vypíš pred nimi ESC: Put(27) Put(125).\nGrafické režimy Rozmer s textovým oknom (4 riadky textu dole) a bez neho (Graphics(režim+16)).\nRežim Druh S oknom Bez okna Farby 0 text – 40 × 24 1 farba písma a pozadie 1 text, dvojnásobná šírka 20 × 20 20 × 24 5 2 text, dvojnásobná šírka aj výška 20 × 10 20 × 12 5 3 body 40 × 20 40 × 24 4 4 body 80 × 40 80 × 48 2 5 body 80 × 40 80 × 48 4 6 body 160 × 80 160 × 96 2 7 body 160 × 80 160 × 96 4 8 body 320 × 160 320 × 192 1 farba, 2 jasy 9 body – 80 × 192 16 jasov jednej farby 10 body – 80 × 192 9 farieb 11 body – 80 × 192 16 farieb jedného jasu 12, 13 text s farebnými znakmi 40 × 20, 40 × 10 40 × 24, 40 × 12 5 14 body 160 × 160 160 × 192 2 15 body 160 × 160 160 × 192 4 Režimy 12 až 15 majú len počítače XL a XE.\nFarebné registre Register Adresa Režim 0 Režimy 3, 5, 7, 15 0 708 – color=1 1 709 jas písma color=2 2 710 pozadie color=3 3 711 – – 4 712 okraj pozadie, color=0 Hodnota registra je 16 × odtieň + jas. Odtiene sú v kapitole 27.\nUžitočné adresy Čas Adresa Meno Význam 18, 19, 20 RTCLOK počítadlo obrázkov; adresa 20 sa zväčší 50-krát (PAL) alebo 60-krát (NTSC) za sekundu, 19 pri pretečení 20 77 ATRACT po niekoľkých minútach bez klávesu začne Atari meniť farby, aby šetrilo obrazovku; Poke(77, 0) to odloží Obrazovka a text Adresa Meno Význam 82, 83 LMARGN, RMARGN ľavý a pravý okraj textu (2 a 39) 84 ROWCRS riadok kurzora 85, 86 COLCRS stĺpec kurzora 88, 89 SAVMSC adresa pamäte obrazovky (PeekC(88)) 559 SDMCTL 0 vypne obrazovku (program beží rýchlejšie), 34 ju zapne 560, 561 SDLSTL adresa zoznamu displeja 708–712 COLOR0–COLOR4 farebné registre 752 CRSINH 1 skryje kurzor 756 CHBAS znaková sada: 224 veľké písmená, 226 malé písmená a grafika 765 FILDAT premenná color Klávesnica a ovládače Adresa Meno Význam 764 CH kód posledného stlačeného klávesu; 255 = žiadny. Po prečítaní tam zapíš 255 53279 CONSOL tlačidlá START, SELECT, OPTION: 7 nič, 6 START, 5 SELECT, 3 OPTION 632–635 STICK0–3 joysticky (to isté vracia Stick) 644–647 STRIG0–3 tlačidlá joystickov 624–631 PADDL0–7 paddle Ostatné Adresa Meno Význam 106 RAMTOP koniec pamäte v stránkach po 256 bajtov 1536–1791 – šiesta stránka: 256 voľných bajtov 53770 RANDOM náhodné číslo pri každom čítaní 54017 PORTB prepínanie ROM a bánk (rieši XBank a spol.) 54283 VCOUNT práve kreslený riadok obrazovky, delený dvoma Hráči a strely Pre rutiny PM… (kapitoly 40–42) netreba nič z toho; adresy sa hodia pri čítaní cudzích programov.\nAdresa Meno Význam 53248–53255 HPOSP0–3, HPOSM0–3 zápis: vodorovná poloha hráčov a striel (viditeľné asi 48–200) 53248–53263 M0PF … P3PL čítanie: zrážky (strela/hráč s obrázkom, s hráčom) 53256–53260 SIZEP0–3, SIZEM šírka: 0 normálna, 1 dvojitá, 3 štvornásobná 53276 VDELAY posun o riadok pri dvoch riadkoch na bajt 53277 GRACTL 3 = hráči a strely sa ukazujú 53278 HITCLR zápis čohokoľvek vynuluje zrážky 54279 PMBASE stránka pamäte hráčov (násobok 8 alebo 4) 559 SDMCTL 62 = obraz, hráči a strely, jeden riadok na bajt; 46 = dva riadky 623 GPRIOR priorita hráčov a obrázka 704–707 PCOLR0–3 farby hráčov (a ich striel) Súradnica Viditeľná časť x hráča šírky 1 48–200 (stĺpec textu c je 48 + 4*c) y, jeden riadok na bajt 32–223 (riadok textu r je 32 + 8*r) y, dva riadky na bajt 16–111 Kódy klávesov Hodnota na adrese 764. Nie je to kód znaku, ale číslo klávesu.\nKláves Kód Kláves Kód Kláves Kód Kláves Kód A 63 N 35 0 50 RETURN 12 B 21 O 8 1 31 medzera 33 C 18 P 10 2 30 ESC 28 D 58 Q 47 3 26 TAB 44 E 42 R 40 4 24 zmazanie 52 F 56 S 62 5 29 CAPS 60 G 61 T 45 6 27 , 32 H 57 U 11 7 51 . 34 I 13 V 16 8 53 / 38 J 1 W 46 9 48 ; 2 K 5 X 22 + 6 \u003c 54 L 0 Y 43 * 7 \u003e 55 M 37 Z 23 - 14 = 15 So SHIFT je kód o 64 väčší, s CONTROL o 128.\nZariadenia Meno Zariadenie E: editor – obrazovka s klávesnicou K: klávesnica S: obrazovka P: tlačiareň D:, D1: až D8: disketové jednotky C: kazetový magnetofón R: sériový port (s ovládačom) H: priečinok PC v emulátore Zvuk Tón C D E F G A H C výška v Sound 121 108 96 91 81 72 64 60 O oktávu vyššie je výška približne polovičná, o oktávu nižšie dvojnásobná.\nĎalej: Príloha E – Slovníček a kam ďalej · Obsah\n","t":"Príloha D – Atari v číslach","u":"d-atari/"},{"c":"Slovníček Pojem Čo znamená adresa číslo miesta v pamäti, 0 až 65535 argument hodnota, ktorú dávaš rutine pri volaní assembler zápis strojového kódu menami inštrukcií (inc counter) ATASCII tabuľka znakov Atari ATR súbor s obrazom diskety bajt základná jednotka pamäte; osem bitov; hodnota 0 až 255 banka kus rozšírenej pamäte (16 KB), ktorý sa dá zapnúť do okna v adresnom priestore bit najmenší kúsok informácie: 0 alebo 1 cartridge zásuvný modul s programom; pôvodný Action! bol cartridge deklarácia oznámenie prekladaču, že existuje premenná, pole, typ alebo rutina DLI prerušenie display listu: krátky program, ktorý počítač spustí uprostred kreslenia obrazu (pásy hráčov v kapitole 42) DOS program na diskete, ktorý učí Atari pracovať so súbormi emulátor program, ktorý sa správa ako Atari (atari800, Altirra) funkcia rutina, ktorá vracia hodnotu (FUNC) globálna premenná premenná deklarovaná mimo rutín; vidia ju všetky rutiny pod ňou GTIA obvod, ktorý kreslí farby, hráčov a strely a hlási zrážky hráč (player) pás široký 8 bodov cez celú výšku obrazovky, ktorý GTIA kreslí navrch obrázka index číslo prvku v poli; začína od 0 kanál očíslovaná linka (0 až 7), cez ktorú program hovorí so zariadením knižnica hotové rutiny, ktoré môžeš volať (Print, Graphics …) komentár text za ; – poznámka pre človeka, prekladač ho preskočí konštanta hodnota známa pri preklade listing výpis preloženého programu s adresami a inštrukciami lokálna premenná premenná deklarovaná v rutine; patrí len jej nultá stránka prvých 256 bajtov pamäte; najrýchlejšie miesto pre procesor 6502 parameter premenná rutiny, do ktorej sa pri volaní uloží argument PMG Player/Missile grafika: hráči a strely (kapitoly 40–42) pole rad hodnôt rovnakého typu pod jedným menom (ARRAY) prekladač program, ktorý mení zdroják na strojový kód; tu action26 premenná pomenované miesto v pamäti pretečenie výsledok sa do typu nezmestil a „pretočil sa“ procedúra rutina, ktorá nevracia hodnotu (PROC) RAM pamäť, do ktorej sa dá zapisovať register bunka procesora alebo čipu; aj farebný register rekurzia rutina volá samu seba; v Action! nefunguje reťazec text v CHAR ARRAY; prvý bajt je dĺžka ROM pamäť len na čítanie; je v nej operačný systém runtime rutiny knižnice, ktoré prekladač pribalí do programu rutina procedúra alebo funkcia simulátor časť action26, ktorá program spustí bez emulátora (--sim) slučka kus programu, ktorý sa opakuje (DO … OD) sprite pohyblivá postavička; v action26 objekt 8–15, ktorý sa kreslí do niektorého hráča (kapitola 42) strela (missile) úzky pás (2 body) vo farbe svojho hráča strojový kód čísla, ktorým rozumie procesor typ druh hodnoty: BYTE, CARD, INT, CHAR, záznam ukazovateľ premenná, v ktorej je adresa (POINTER) výraz zápis výpočtu, ktorý dá hodnotu XEX súbor s preloženým programom pre Atari záznam niekoľko položiek spojených do jedného typu (TYPE) zdroják program v textovej podobe, ako ho píše človek zrážka prekrytie hráča alebo strely s iným hráčom alebo s obrázkom, ktoré hlási GTIA Slová jazyka a ich pôvod Slová Action! sú anglické. Pomôže vedieť, čo znamenajú:\nSlovo Anglicky Význam PROC procedure procedúra FUNC function funkcia RETURN return návrat IF … THEN … ELSE if, then, else ak, tak, inak FI, OD, ESAC – IF, DO, CASE napísané odzadu – koniec príkazu DO do rob WHILE while kým UNTIL until až kým FOR … TO … STEP for, to, step pre, po, krok EXIT exit von BYTE byte bajt CARD cardinal číslo bez znamienka INT integer celé číslo CHAR character znak ARRAY array pole POINTER pointer ukazovateľ TYPE type typ DEFINE define definuj INCLUDE include vlož MOD modulo zvyšok po delení LSH, RSH left shift, right shift posun doľava, doprava Kam ďalej Príklady. V priečinku examples/ je takmer tisíc programov v Action!: hry, ukážky grafiky a zvuku, programy z časopisov. Čítať cudzie programy je najlepší spôsob, ako sa zlepšovať. Prehľad je v examples/README.md.\nLekcie rozšírení. examples/modern/ má 49 lekcií k rozšíreniam action26 – každá je program s podrobným popisom. Kapitoly 35 až 42 tejto knihy sú ich skrátením.\nPôvodný manuál. The ACTION! Reference Manual od Optimized Systems Software je predlohou tejto knihy. Je po anglicky a obsahuje aj časti o editore a monitore cartridge.\nKnihy o Atari. Mapping the Atari (Ian Chadwick) opisuje každú adresu v pamäti počítača. De Re Atari vysvetľuje grafiku, zvuk a prerušenia do hĺbky. Obe sú voľne dostupné na internete.\nDokumentácia action26. Priečinok docs/ opisuje prekladač presne a úplne – jazyk (language.md), knižnicu (runtime.md) a rozdiely oproti pôvodnému Action! (differences.md). Je písaná pre tých, ktorí už jazyk poznajú.\nČo si napísať ako prvé. Hádanie čísla. Had, ktorý rastie. Kresliaci program ovládaný joystickom. Textová hra s tromi miestnosťami. Každý z nich použije väčšinu toho, čo je v tejto knihe.\nObsah\n","t":"Príloha E – Slovníček a kam ďalej","u":"e-slovnik/"}]