# MEG-4 Felhasználói KéziKönyv

Üdvözöl a MEG-4, a Szabad és Nyílt Forráskódú virtuális fantasy konzol kézikönyve!

TIPP

Ez a kézikönyv használható internet nélkül. Csak válaszd a jobb-klikk menüben az "Oldal mentése" menüpontot. De megtalálható magában a MEG-4 emulátorban is, bármikor üsd csak le az `F1` gombot.

Következő

# Indítás

## Böngésződben

Ha nem akarsz semmit sem telepíteni, akkor csak látogasd meg a weboldalt, ahol egy böngésződbe ágyazott emulátor fut.

## Telepítés

Menj a repóba és töltsd le az operációs rendszerednek megfelelő binárist.

### Windows

1. meg4-i686-win-sdl.zip letöltése
2. csomagold ki a `C:\Program Files` mappába és kész!

Egy egy hordozható futtatható, semmilyen hagyományos telepítési eljárást nem igényel.

### Linux

1. meg4-x86_64-linux-sdl.tgz letöltése
2. csomagold ki az `/usr` mappába és kész!

Alternatívaként letöltheted az Ubuntu vagy épp a RaspiOS deb csomagot is, amit aztán ezzel a paranccsal telepíthetsz:

    sudo dpkg -i meg4_*.deb

## Futtatás

Amikor elindítod a MEG-4 emulátort, automatikusan érzékeli a számítógéped nyelvét, és ha lehetséges, a saját nyelveden köszönt. Az első képernyő, ami fogad, a "MEG-4 Flopi Meghajtó" képernyő:

MEG-4 Flopi Meghajtó

Csak húzd rá a flopilemezt a meghajtóra, vagy balklikkelj a meghajtón és megjelenik a fájlválasztó. Ezek a flopik sima PNG képek extra adatokkal, egy üres lemez például így néz ki:

MEG-4 Flopi

Egyéb formátumok is támogatottak, lásd a fájlformátumok fejezetet bővebb infóért, hogy mik. Amint a flopi betöltésre került, a képernyő automatikusan átvált a játékképernyőre.

Alternatívaként leütheted itt az `Esc` gombot, hogy behozd a szerkesztő képernyőket, és nulláról elkészíts egy saját játékot.

### Parancssori opciók

Windows alatt `-` helyett `/` karakterrel kezdődnek a kapcsolók (mert ez a Windows módi, például `/n`, `/vv`), ezt leszámítva minden kapcsoló és opció ugyanaz.

Kattints jobb-klikkel a `meg4.exe`-re, a felugró menüben válaszd a Parancsikon létrehozása menüpontot. Majd jobb-klikk az újonnan létrejött parancsikonon, és a felugró menüben válaszd a Tulajdonságok menüpontot.

Parancssori opciók megadása Windows alatt A megjelenő ablakban, a Cél mezőben tudod állítani a parancssori opciókat. Kattints az OK gombra az elmentéshez. Ezentúl a program helyett erre a parancsikonra kattints, és az adott opciókkal fog elinduli a program. Ha szeretnéd, akár több parancsikonod is lehet, különböző opciókkal.

    meg4 [-L <xx>] [-z] [-n] [-w] [-v|-vv] [-s] [-d <mappa>] [flopi]

Opció | Leírás
--- | ---
`-L <xx>` | A kapcsoló paramétere "en", "es", "de", "fr" stb. lehet. A megadásával egy adott szótárat használ az emulátor, és nem detektálja a nyelvet. Ha nincs a megadott szótár, akkor angolra vált.
`-z` | Linux alatt alapból a GTK függvénykönyvtárakat futáskor linkeli, hogy a fájlválasztót megnyissa. Ennek a kapcsolónak a hatására inkább a `zenity` programot fogja meghívni (a zenitynek telepítve kell lennie a gépeden).
`-n` | Mindenképp a "nearest" (legközelebbi pixel) interpolációs metódust használja. Alapból csak akkor használatos, ha az emulátor ablakmérete a 320 x 200 egész többszöröse. Ez utóbbit ki is kényszeríti ablakos módban.
`-w` | Ablakos módban indul (alapértelmezetten teljesképernyős)
`-v, -vv` | Szószátyár mód. `meg4` részletes infókat fog kiírni a szabvány kimenetre (valamint a programod trace hívásai is itt jelennek meg), ezért ez a kapcsoló terminálból hívandó.
`-s` | Strace mód, rendszerhívások listázása (csak ha DEBUG támogatással lett fordítva).
`-d <mappa>` | Opcionális, ha meg van adva, akkor a flopikat ebben a könyvtárban fogja tárolni, és nem használ fájlválasztót.
`flopi` | Ha meg van adva, akkor automatikusan betölti az itt megadott flopit (vagy bármilyen más támogatott formátumú fájlt) induláskor.

ElőzőKövetkező

# Fájlformátumok

Habár a beépített szerkesztők elég királyak, ennek ellenére a MEG-4 mindenféle formátum importját és exportját is támogatja, hogy segítse a tartalomkészítést, és ténylegesen szórakoztatóvá tegye a MEG-4 használatát.

## Flopik

A MEG-4 a programokat "flopi"-kon tárolja. Ezek olyan képfájlok, amik egy igazi flopi lemezt ábrázolnak. Ilyen formátumban menthetsz a `Ctrl`+`S` leütésével, vagy a > `Elment` menüpont kiválasztásával (lásd interfész). Be fogja kérni a lemez feliratát, ami egyben a programod neve is lesz. Ilyen flopilemezek betöltéséhez üsd le a `Ctrl`+`L`-t, vagy csak simán húzd rá ezeket a képfájlokat a MEG-4 Flopi Meghajtóra.

Az alacsonyszintű specifikáció itt érhető el (angol nyelvű).

## Projektformátum

Kényelmed érdekében van egy projektformátum is, ami egy tömörített zip a konzol adataival, benne kizárólag jólismert és általánosan támogatott formátumú fájlokkal, hogy a kedvenc programoddal vagy eszközöddel is módosíthasd őket. Ebben a formátumban való mentéshez válaszd a > `ZIP Export` menüpontot. A betöltéshez csak simán húzd rá az ilyen zip fájlt a MEG-4 Flopi Meghajtóra.

TIPP

Az egyik teszt eszköz, a converter használható flopilemezek zip-é konvertálására. Az advcomp fordító pedig kalandjáték JSON fájlokat tud játszható zip projektfájlokká konvertálni.

A projektfájlban lévő fájlok:

### metainfo.txt

Sima szöveges fájl, a MEG-4 Förmver verziójával és a programod nevével.

### program.X

A programod forráskódja, amit a kód szerkesztővel hoztál létre, sima szöveges fájl. Bármelyik szövegszerkesztővel módosíthatod. Exportáláskor a sorvégejelek CRLF-re fordítódnak, hogy Windowson is működjön, importáláskor pedig teljesen mindegy, hogy a sorvége NL vagy CRLF, mindkettő működik.

A forráskódnak egy speciális sorral kell kezdődnie, a `#!` karakterekkel, amiket a használt programozási nyelv neve követ, például `#!c` vagy `#!lua`. Ennek a nyelvkódnak meg kell egyeznie a kiterjesztéssel a fájlnévben, pl.: program.c vagy program.lua.

### sprites.png

Egy indexelt, 256 x 256 pixeles PNG fájl, mind a 256 színnel és egyenként 8 x 8 pixeles 1024 szprájttal, amit a szprájt szerkesztőben csináltál. Ez a képfájl szerkeszthető a következő programokkal: GrafX2, GIMP, Paint stb. Importálásnál truecolor képek is betölthetők, ezek az alap MEG-4 palettára lesznek konvertálva, a legkissebb súlyozott sRGB távolság metódussal. Ez működik, de nem néz ki túl jól, ezért inkább azt javaslom, hogy eleve palettás képeket importálj be. Szprájtok beolvashatók még Truevision TARGA (.tga) képformátumban is, ha indexáltak és a méretük a megfelelő 256 x 256 pixeles.

### map.tmx

A térkép szerkesztőben létrehozott térkép, olyan formátumban, ami használható a Tiled MapEditor programmal. Csakis CSV kódolt .tmx kerül mentésre, de importálásnál kezeli a base64 kódolt és tömörített .tmx fájlokat is (mindenfélét, kivéve zstd). Továbbá PNG és TARGA képek is használhatók betöltéskor, amennyiben indexáltak és a méretük megfelel az elvárt 320 x 200 pixelesnek. Az ilyen képek palettája nem használt, kivéve, hogy a szprájtbank szelektor értéke a paletta első elemének (0-ás index) alfa csatornájában tárolódik.

### font.bdf

A betűkészlet, amit a betű szerkesztőben hoztál létre, olyan formátumban, amit sok program ismer, például xmbdfed vagy gbdfed. A módosításhoz nyilvánvalóan inkább a saját SFNEdit programomat ajánlom elsősorban, de a FontForge is tökéletesen megfelel a célnak. Betöltésnél az X11 Bitmap Distribution Format (.bdf) formátumon túl támogatott még a PC Screen Font 2 (.psfu, .psf2), Scalable Screen Font (.sfn), és a FontForge saját natív SplineFontDB (.sfd, csak a bitmapes változat) formátuma is.

### sounds.mod

Az általad létrehozott hangeffektek, Amiga MOD formátumban. Lásd a zenesávokat alább. A zene nevének `MEG-4 SFX`-nek kell lennie.

Mind a 31 hullámminta ebben a fájlban tárolódik, a patternekből viszont csak az első használt, és abból is csak egy csatorna (64 hangjegy összesen, a 64 hangeffektnek egy-egy).

### musicXX.mod

A létrehozott zenesávok, Amiga MOD formátumban. Az XX szám a fájlnévben egy kétjegyű hexadecimális szám, ami a sáv számának felel meg (`00`-tól `07`-ig). A zene nevének `MEG-4 TRACKXX`-nek kell lennie, ahol az XX ugyanaz a hexa szám, mint a fájlnévben. Rengeteg programmal lehet szerkeszteni ezeket a fájlokat, csak guglizz a "music tracker"-re, például MilkyTracker vagy OpenMPT, de az igazi retro életérzéshez ajánlom inkább a FastTracker II modernizált klónját, ami fut Linuxon és Windowson egyaránt.

A zenefájlok hullámmintáiból csak azok kerülnek betöltésre, amikre a zene kottája hivatkozik.

Egy hatalmas adatbázis található letölthető Amiga MOD fájlokkal a modarchive.org-on. De nem minden fájl .mod, amit letöltesz onnan (néhány .xm, .it vagy .s3m stb.); ezeket először be kell töltened egy trackerbe és .mod-ként lementeni.

FIGYELEM

Az Amiga MOD formátum sokkal többet tud, mint amire a MEG-4 DSP csipje képes. Tartsd ezt észben, amikor külsős programmal szerkeszted a .mod fájlokat! A hullámok nem lehetnek hosszabbak 16376 mintánál, és a 16 patternnél (1024 sornál) hosszabb zenék csonkolódnak importáláskor. A pattern order lineárissá lesz konvertálva, és bár a pattern break 0xD le van kezelve, az összes többi pattern parancsot egyszerűen figyelmen kívül hagyja. Továbbá ha több sávot is be akarsz importálni, akkor azok osztozni fognak a 31 közös hullámmintán.

Zenét be lehet még importálni MIDI fájlokból is, de ezek a fájlok csak a kottát tartalmazzák, az Amiga MOD fájlokkal ellentétben a hullámmintákat nem. A General MIDI Patch szabványosította azonban a hangszerkódokat, és a MEG-4 tartalmaz néhány alapértelmezett hangmintát ezekhez, de a helyszűke miatt nem épp a legjobb minőségűek, emiatt a saját hullámminták betöltése erősen ajánlott, ha MIDI fájlt akarsz importálni.

### memXX.txt

A memóriaátfedők hexdumpjai (amik jellegükből adódóan bináris adatok). Itt az XX egy kétjegyű hexadecimális szám, `00`-tól `FF`-ig, ami az átfedő számát jelenti. Maga a formátum egyszerű, ugyanaz, mint a hexdump -C kimenete, és sima szövegszerkesztővel módosítható. Importálásnál bináris fájlokat is elfogad, amennyiben a nevük memXX.bin. Például, ha szeretnél egy fájlt beágyazni a MEG-4 programodba, akkor csak nevezd át mem00.bin-re, húzd rá az emulátorra, és ezután bármikor betöltheted a programodban a memload funkció hívásával.

## Egyéb formátumok

Általában a hullámminták automatikusan betöltődnek az Amiga MOD fájlokból, de a hangmintákat külön-külön is importálhatod és exportálhatod .wav (RIFF Wave 44100 Hz, 8-bit, mono) formátumban. Ezek szerkeszthetők például az Audacity programmal. Amennyiben az importálandó fájlneve dspXX.wav, ahol az XX egy hexadecimális szám `01` és `1F` között, akkor a hullámminta az adott pozícióra töltődik be, egyébként az első szabad helyre.

Betölthetsz MEG-4 Színtémákat "GIMP Palette" fájlokból. Ezek sima szöveges fájlok, egy rövid fejléccel, és minden sorban piros, zöld és kék numerikus színértékekkel. Mindegyik színsor az interfész egy adott elemének színéért felelős, példának lásd a src/misc/theme.gpl alap téma definícióját. A témafájlok szerkeszthetők még vizuálisan a GIMP és a Gpick programokkal is.

Alapból a MEG-4 a Raspberry Pi 3B+ GPIO tüskekiosztását használja, de tetszőleges beállítás betölthető egy egyszerű szöveges fájlból. Ennél az első sornak "GPIO Layout"-nak kell lennie, a második sor a board neve, a harmadik sor az eszközfájl, a többi pedig egy fizikai tüske - GPIO regiszter offszet összerendelés lista (ahol a -1 jelenti azt, hogy a tüskéhez nincs GPIO regiszter, például táp vagy földelés). Példának lásd src/misc/gpio.txt.

Lehetséges még AdvGame 2.0 Kalandjáték fájlokat is importálni, habár a kattintós felületű játékok szöveges kalandjátékká lesznek redukálva.

Továbbá betölthetők PICO-8 kertridzsek (mindkét .p8 és .p8.png formátumban) valamint TIC-80 kertridzsek (mindkét .tic és .tic.png formátumban) is, de a beimportált forráskódot kézzel kell majd szerkesztened, mivel a címkiosztásuk és a függvényeik eltérnek a MEG-4-étől. De legalább a többi kelléked meglesz. A TIC-80 projektfurmátuma nem támogatott, mivel az ilyen fájlok felismerhetetlenek. Ha mégis ilyen fájlt szeretnél beimportálni, akkor előbb át kell konvertálnod a `prj2tic` programmal, ami megtalálható a TIC-80 forrás repójában.

Exportálni kertridzsekbe nem lehet, mivel a MEG-4 sokkal többet tud, mint a vetélytársai. Egyszerűen nincs hely minden MEG-4 funkciónak azokban a fájlokban.

ElőzőKövetkező

# Felhasználói bemenetek

## Játékpad

Az első játékpad és joystick leképezésre kerül a billentyűzetre, és együtt működnek. Például nem számít, hogy a kontrolleren nyomod-e le a Ⓧ gombot, vagy a billentyűzeten a `X` billentyűt, mindkét esetben mind a játékpad lenyomott jelzője, mind a billentyű lenyomott jelzője beállításra kerül. A leképezés megváltoztatható szkenkódok MEG-4 memóriába írásával, bővebb infóért lásd a memóriatérkép fejezetet. Az alapértelmezett leképezés a kurzornyilak az irányok ◁, △, ▽, ▷; a `Szóköz` az Ⓐ elsődleges gomb, a `C` a Ⓑ másodlagos gomb és az `X` az Ⓧ, `Y` az Ⓨ. A Konami Kód is működik (lásd `KEY_CHEAT` szkenkód).

## Mutató

A koordináták és az egérgombok lenyomott állapota könnyedén lekérdezhető a MEG-4 memóriájából. A görgetés (mind a függőleges, és ha van, vízszintes támogatott), úgy van kezelve, mintha fel / le vagy balra / jobbra egérgombok lennének.

## Billentyűzet

A kényelem érdekében számos gyorsbillentyűvel és beviteli metódussal rendelkezik. A programozáshoz szükséges összes karakter elérhető egy `Alt` kombinációval, függetlenül attól, hogy a platform milyen billentyűzetkiosztással rendelkezik:

Bal `Alt` kombinációk

Billentyűkombináció | Leírás
--- | ---
`GUI` | Vagy Super, néha logó van rajta. UNICODE kódpont beviteli mód.
`AltGr` | A jobb Alt billentyű, Kompozit beviteli mód üresen nyomva.
`Alt`+`U` | Ha a billentyűzeteden nem lenne `GUI` gomb, ez is UNICODE kódpont beviteli mód.
`Alt`+`Space` | Kompozit vésztartalék, az `AltGr` gomb nélküli billentyűzetehez.
`Alt`+`I` | Ikon (emoji) beviteli mód.
`Alt`+`G` | Görög beviteli mód.
`Alt`+`J` | Hiragana beviteli mód.
`Alt`+`K` | Katakana beviteli mód.
`Alt`+`C` | Cirill beviteli mód.
`Ctrl`+`S` | Flopi mentése.
`Ctrl`+`L` | Flopi betöltése.
`Ctrl`+`R` | Programod futtatása.
`Ctrl`+`⏎Enter` | Teljesképernyős mód váltogatása.
`Ctrl`+`A` | Mindent kijelöl.
`Ctrl`+`I` | Kijelölés megfordítása.
`Ctrl`+`X` | Kivágás, másolás vágólapra majd törlés.
`Ctrl`+`C` | Másolás vágólapra.
`Ctrl`+`V` | Beillesztés vágólapról.
`Ctrl`+`Z` | Visszavonás.
`Ctrl`+`Y` | Újrabeillesztés.
`F1` | Beépített súgó oldalak (a kézikönyv API Referencia fejezete, lásd interfész).
`F2` | Kód Szerkesztő
`F3` | Szprájt Szerkesztő
`F4` | Térkép Szerkesztő
`F5` | Betű Szerkesztő
`F6` | Hangeffektek
`F7` | Zenesávok
`F8` | Memóriaátfedők
`F9` | Vizuális Szerkesztő
`F10` | Debuggoló
`F11` | Teljesképernyős mód váltogatása.
`F12` | Képernyő mentése `meg4_scr_(unix időbélyeg).png` néven.

### UNICODE Kódpont beviteli mód

Ebben a módban hexa számok adhatók meg (`0`-tól `9`-ig és `A`-tól `F`-ig). Ahelyett, hogy külön-külön vinné be ezeket a gombokat, az általuk leírt kódpontot viszi be, mintha az a billentyűzeten egy különálló gomb lett volna. Például a következő sorozat `GUI`, `2`, `e`, `⏎Enter` egy pontot `.` visz be, mivel a `U+0002E` kódpont az a `.` pont karakter.

MEGJEGYZÉS

Csak az Alap Többnyelvű Sík (Basic Multilingual Plane, `U+00000`-tól `U+0FFFF`-ig) támogatott, néhány kivétellel az emoji tartományára a `U+1F600`-tól kezdve. Minden más kódpontot egyszerűen figyelmen kívül hagy.

Ez a beviteli mód automatikusan kilép bevitel után.

### Kompozit mód

Kompozit módban ékezet, kettőspont, hullám, hurok stb. adható a karakterekhez. Például a következő sorozat `AltGr`, `a`, `'` egy `á`-t, vagy az `AltGr`, `s`, `s` egy `ß`-t, míg az `AltGr`, `c`, `,` egy `ç`-t, stb. eredményez. Használható a `Shift` a betűvel együtt, hogy a nagybetűs formát adja végeredményül.

Ez a beviteli mód automatikusan kilép bevitel után.

### Ikon mód

Ikon módban olyan speciális ikon karakterek vihetők be, amik az emulátor bevitelét ábrázolják (például a következő sorozat `Alt`+`I`, `m` egy `🖱` egér (mouse) ikont, vagy az `Alt`+`I`, `a` a játékpad `Ⓐ` gombjának ikonját) valamint emoji ikonokat ábrázolnak (például `Alt`+`I`, `;`, `)` egy `😉` karaktert fog bevinni, míg az `Alt`+`I`, `<`, `3` egy `❤` karaktert eredményez).

Ez a beviteli mód automatikusan kilép bevitel után.

### Katakana és Hiragana mód

Hasonló az ikon módhoz, de itt a kiejtett hangok Romaji betűit kell beírni egy ázsiai karakterhez. Például a következő sorozat `Alt`+`K`, `n`, `a`, `n`, `i`, `k`, `a` úgy értelemződik, mint három hang, ezért három karaktert fog bevinni, `ナニヵ`. Továbbá az írásjelek is úgy működnek, ahogy elvárjuk, például az `Alt`+`K`, `.` a japán teljes állj `。` karaktert illeszti be.

Használható a `Shift` az első betűvel együtt, hogy a végeredmény a nagybetűs változat legyen, például `Alt`+`K`, `Shift`+`s`, `u` eredménye `ス` és nem `ㇲ`.

Ez a beviteli mód aktív marad bevitel után is, üss `Esc` gombot a normál beviteli módhoz való visszatéréshez.

### Cirill mód

A KOI8-RU kódlapon alapul, de néhány betű már szám- és szimbólum gombokra lett leképezve. Például a következő sorozat `Alt`+`C`, `Shift`+`l`, `e`, `n`, `i`, `n` eredménye `Ленин`.

Ez a beviteli mód aktív marad bevitel után is, üss `Esc` gombot a normál beviteli módhoz való visszatéréshez.

### Görög mód

Próbál fonetikusan helyes lenni, de a latin ábécé nem feleltethető meg egy-az-egyben. Például a következő sorozat `Alt`+`G`, `Shift`+`p`, `l`, `a`, `t`, `o` `n`, eredménye `Πλατων`.

Ez a beviteli mód aktív marad bevitel után is, üss `Esc` gombot a normál beviteli módhoz való visszatéréshez.

MEGJEGYZÉS

Ez a funkció adattáblákkal került implementálásra, újabb kombinációk könnyedén, bármikor hozzáadhatók a `src/inp.c` fájlhoz programozói ismeretek nélkül is.

ElőzőKövetkező

# Interfész

Alapból a kép homályos lesz, hogy jobban hasonlítson a régi CRT monitorokra. Ez kikapcsolható a `-n` (vagy `/n` Windowson) parancssori kapcsolóval, ilyenkor azonban nem minden pixel lesz egyforma méretű. Ez ellensúlyozható azzal, ha ablakos módba váltunk, ahol a képernyőméret mindig 320 x 200 pixel egész többszöröse lesz.

## Játékképernyő

Alapból a játékképernyő fogad, ahol a programod fut (illetve a MEG-4 Flopi Meghajtó, ha nincs betöltve program). Ha ezen a képernyőn leütöd az `Esc` gombot, akkor átvált szerkesztő módba.

## Szerkesztő képernyők

Ha bármelyik szerkesztő képernyőn ütsz `Esc`-et (nincs újrafordítás) vagy nyomsz `Ctrl`+`R`-t (újrafordítja a programodat), akkor visszakerülsz a játékképernyőre.

Minden szerkesztő témázható, az egész felület átszínezhető, csak rá kell húzni egy GIMP Palette fájlt a képernyőre. Bővebben lásd az egyéb formátumok fejezetet.

Súgó és a menü

Minden szerkesztőnél felül látható a menüsor. Ha itt a ikonra kattintasz, egy felugrómenü fog megjelenni, ahonnan különböző funkciók érhetők el, bár a legtöbb gyorsbillentyűvel is behozható (lásd billentyűzet). Ugyancsak innen érhetők el a súgó oldalai, habár ez is ugyancsak mindig behozható bármelyik szerkesztőben az `F1` leütésével.

## Súgó oldalak

A súgó oldalain a hivatkozások kattinthatók, és a `Backspace` leütésével visszalép egy oldalt az oldaltörténetben. Ha az oldaltörténet üres, akkor a Tartalomjegyzéket hozza be. A súgó kivétel a szabály alól, mert itt az `Esc` leütése nem a játékképernyőt hozza be, hanem visszavisz arra a képernyőre, ahonnan a súgót behoztad.

Kereséshez kattinthatsz a menüben fent jobbra a keresődobozra, vagy csak kezd el gépelni, amire keresni szeretnél.

A beépített súgó igazándiból egy nagyon egyszerű MarkDown megjelenítő, és pontosan ugyanazokat a fájlokat jeleníti meg, amikből ez a kézikönyv is generálódott (de a kézikönyv, amit épp olvasol, jóval több fejezet tartalmaz, a beépített súgóból csak az API referencia érhető el).

ElőzőKövetkező

# Kód Szerkesztő

Kattints a ceruza ikonra (vagy `F2`) a program forráskódjának írásához.

A kód három alrészből áll, az egyiken szövegesen tudod a forráskódot szerkeszteni (ez), a Vizuális Szerkesztőben ugyanezt struktrogrammokkal teheted meg, a programod gépi kódú megfelelőjét pedig a debuggolóban láthatod.

Kód Szerkesztő

Itt az egész felület egy nagy forráskód szerkesztő (1). Alul látható a státuszsor (2), az aktuális sor és oszlop értékekkel, valamint a kurzor alatti karakter UNICODE kódpontjával, továbbá ha épp egy API funkció paraméterei között áll a kurzor, akkor egy gyorssúgóval a paraméterek listájáról (ami érvényes minden programozási nyelv esetén).

## Programozási nyelv

A programnak egy speciális sorral kell kezdődnie, az első két karakter `#!`, amit a használni kívánt nyelv kódja zár. Az alapértelmezett a MEG-4 C (az ANSI C egyszerűsített változata), de több nyelv is a rendelkezésedre áll. A teljes listát balra, a tartalomjegyzékben a "Programozás" címszó alatt találod.

## Felhasználói funkciók

A választott nyelvtől függetlenül van két funkció, amit neked kell implementálni. Nincs paraméterük, sem visszatérési értékük.

- `setup` funkció elhagyható, és csak egyszer fut le, amikor a programod betöltődik.
- `loop` funkció kötelező, és mindig lefut, amikor egy képkocka generálódik. 60 FPS (képkocka per másodperc) mellett ez azt jelenti, hogy a futására 16.6 milliszekundum áll rendelkezésre, de ebből a MEG-4 "hardver" elvesz 2-3 milliszekundumot, így 12-13 ezredmásodperced marad, amit a függvényed kitölthet. Ezt lekérdezheted a performancia számláló MMIO regiszterből, lásd memóriatérkép. Ha ennél tovább tart a `loop` funkció futása, akkor a képernyő töredezni fog, és az emulátor kevésbé lesz reszponzív, mint lenni szokott.

## Plusz billentyűkombók

A normál billentyűkön és beviteli módokon túl, kódszerkesztéskor még számos más, szövegszerkesztés orientált gyorsbillentyű is elérhető.

A menüből ugyancsak eléhető a keresés, következő, sorraugrás, visszavonás, újrabeillesztés, valamint a könyvjelzők és funkciók definíciójának listája is.

ElőzőKövetkező

# Szprájt Szerkesztő

A bélyegző ikonra kattintva (vagy `F3`) jön elő a szprájtok szerkesztése.

Az itt szerkesztett szprájtokat az spr paranccsal jelenítheted meg, illetve ezeket használva a dlg egy dialógusablakot generál, az stext pedig szöveget ír ki.

Szprájt Szerkesztő

A szerkesztőnek három fő mezője van, kettő felül, egy pedig alul.

## Szprájt Szerkesztő Mező

Balra fent van a szerkesztő mező (1). Itt tudod módosítani a szprájtot. A elhelyezi a kijelölt pixelt a szprájton, míg a törli őket.

Ha lenyomjuk a `Shift`-et, akkor vonalat húzhatunk a legutóbb módosított pontból.

## Szprájtválasztó

Jobbra mellette látható a szprájtválasztó (2). Az a szprájt, amit itt kiválasztasz lesz szerkeszthető balra. Egyszerre több egymásmelletti szprájt is kiválasztható, és ilyenkor egyszerre, együtt szerkesztheted őket.

## Paletta

Alul helyezkedik el a pixel paletta (3). Az első elem nem módosítható, mert az a törlésre van fenntartva. Ha azonban bármelyik másik pixelt választod, akkor a gomb a színpaletta ikonnal aktívvá válik. Erre kattintva felugrik a HSV színválasztó ablak (5), ahol megadhatod a kiválasztott palettaelem színét.

Az alapértelmezett MEG-4 paletta 32 színt használ a DawnBringer32 palettáról, 8 szürkeárnyalatot, valamint 6 x 6 x 6 piros, zöld, kék átmenetkombinációt.

## Eszköztár

Szprájt eszköztár

A szerkesztőmező alatt található az eszköztár a gombokkal (4). Ezekkel könnyedén módosíthatod a szprájtot, eltolhatod különböző irányokba, elforgathatod órajárással megegyező irányban, tükrözheted, stb. Ha van aktív kijelölés, akkor ezek az eszközök csak a kijelölt pixelekre hatnak, egyébként az egész szprájtra. A forgatáshoz úgy kell kijelölni, hogy a kijelölés ugyanolyan magas legyen, mint széles különben a forgatás nem fog működni.

A kitöltés csak a szomszédos, azonos színű pixelekre vonatkozik, hacsak nincs kijelölés. Kijelöléssel a teljes kijelölt terület kitöltésre kerül, függetlenül attól, hogy milyen pixelek lettek kijelölve.

## Kijelölések

Kétfajta kijelölés van: doboz és varázspálca. Az előbbi négyzet alakban jelöl ki, utóbbi minden szomszédos, azonos színű pixelt kijelöl. A `Shift` lenyomva tartásával bővíthető a kijelölés, míg a `Ctrl` lenyomva tartásával kivághatsz a kijelölésből, és csökkentheted.

A `Ctrl`+`A` lenyomásával minden kijelölődik, a `Ctrl`+`I` pedig invertálja (megfordítja) a kijelölést, azaz ami eddig nem volt kijelölve, az ki lesz, ami meg ki volt, az nem lesz.

Amikor van aktív kijelölés, akkor a `Ctrl`+`C` lenyomásával a kijelölt terület a vágólapra másolható. Később lenyomhatod a `Ctrl`+`V` gombokat a beillesztéshez. A beillesztés pontosan úgy működik, mint a festés, csak itt egy pixel helyett a vágólapod tartalma egy nagy ecset lesz. Érdemes megjegyezni, hogy a vágólapra másolt üres pixelek is az ecset részét képezik. Ha nem szeretnéd, hogy az ecset töröljön, akkor csak a nem üres pixeleket jelöld ki (használhatod a `Ctrl`+ kombót az üres pixelek kijelölésének megszüntetéséhez) a vágólapra másolás előtt, így az üres pixelek nem kerülnek a vágólapra, és emiatt az ecsetben sem fognak megjelenni.

ElőzőKövetkező

# Térkép Szerkesztő

A kirakós ikonra kattintva (vagy `F4`) felhozza a térkép szerkesztőt. Itt egy térképen helyezheted el a szprájtokat.

Az itt összerakott térképet (vagy egy részét) a map illetve a maze (lásd alább) paranncsal tudod megjeleníteni a képernyőn.

Térkép Szerkesztő

A térkép különleges abból a szempontból, hogy egyszerre csak 256 különböző szprájtot képes megjeleníteni a összes rendelkezésre álló 1024 szprájtból. Minden szprájtbank esetén a legeslegelső szprájt fenn van tartva a "nincs térképelem" számára, így a 0-ás, 256-os, 512-es valamint a 768-as szprájt nem használható a térképen.

## Térkép Szerkesztő Mező

Felül a nagy részen láthatod és szerkesztheted a térképet (1). Egy nagy térképként látszik, 320 oszloppal és 200 sorral. Használhatod a nagyítás és kicsinyítés gombokat az eszköztáron, vagy az egérgörgőket is a nagyításhoz. A jobb egérgombot lenyomva tartva és az egeret mozgatva tologathatod a térképet, vagy használhatod a görgetősávokat is jobbra illetve alul.

A balklikkel szprájtokat helyezhetsz el a térképen. A legelső szprájt kiválasztásával lehet törölni a térképen (a jobb egérgomb itt nem töröl, hanem mozgatja a térképet).

Ha lenyomjuk a `Shift`-et, akkor vonalat húzhatunk a legutóbb módosított pontból.

## Eszköztár

A térképszerkesztő mező alatt található az eszköztár (2), ugyanaz, mint a szprájt szerkesztő képernyőn, ugyanazokkal a funkciókkal és ugyanazokkal a gyorsgombokkal (csak itt van még egy Wang csempe eszköz és használhatók szprájtminták is, lásd alább). Az eszközgombok mellett vannak a nagyítás és kicsinyítés gombok, ezek után pedig a szprájtbankválasztó a szprájtpaletta választáshoz (de csak a szerkesztőben. Amikor a programod fut, akkor a 0007F címen lévő bájtot kell állítani a bankok váltásához, lásd Grafikus Feldolgozó Egység).

## Szprájtpaletta

A gomboktól jobbra helyezkedik el a szprájtválasztó paletta (3), ahol kiválaszthatod, melyik szprájttal akarsz rajzolni. Amint korábban már megjegyeztük, a paletta legelső eleme minden 256-os szprájtbankból nem használható, az a "nincs térképelem" számára van fenntartva. Ha törölni szerenél a térképen, akkor válaszd ezt az első elemet, és "rajzolj" azzal.

A szprájtszerkesztővel ellentétben (ahol csak egyetlen színt választhatsz a palettáról), itt, a térképen több, egymásmelleti szprájt is kiválasztható a palettáról egyszerre. Festéskor mindet rá fogja tenni a térképre, (pont úgy, mintha a beillesztést használnád), ezen kívül a kitöltés is ecsetként fogja használni őket, egy nagy, többszprájtos mintával kitöltve a kijelölt területet.

Sőt, mi több, a kitöltésnél `Shift`+-el kattintva, véletlenszerűen fog választani a kijelölt szprájtok közül. Például, tegyük fel, hogy van 4 féle különböző szprájtod fákkal. Ha kijelölöd öket, majd kitöltöd az erdőnek szánt részt a térképen, akkor ezek a szprájtok libasorban, egymásután ismételve kerülnek elhelyezésre, ami nem néz ki túl jól erdőként. Viszont ha lenyomva tartod a `Shift`-et, miközben a kitöltéssel kattintasz, akkor minden mezőhöz véletlenszerűen választ egyet a kijelölt 4 fa-szprájt közül, ami már sokkal inkább néz ki igazi erdőnek.

## Wang csempék

Amikor a Wang csempe eszköz van kiválasztva, akkor a Wang csempekészlet terület (4) aktívvá válik. Ezzel a szerszámmal könnyedén lehet utakat, folyókat, várfalakat, stb. rajzolni.

Wang csempe eszköz

Azonban mielőtt használhatnánk, előbb be kell konfigurálni. Összesen 64 különfélé csempekészlet adható meg (pl. egy a folyónak, egy az útnak, stb.), és mindegyik készlet 16 különböző szprájtot tartalmaz, minden kombinációhoz egyet.

A csempekészletet úgy kell beállítani, hogy előbb a szprájtpalettán kiválasztunk egy szprájtot, majd a Wang csempe gombjára kattintva megadjuk, hogy melyik kombinációt ábrázolja. Amennyiben több szprájt is ki van választva, úgy egyszerre több csempe is beállítódik (attól a gombtól kezdve, amelyikre kattintottunk).

MEGJEGYZÉS

A Wang csempekészletbeállítások megőrződnek, el lesznek mentve a flopira.

Ha már van egy Wang csempekészlet beállítva, akkor a szerszám pontosan ugyanúgy használható, mint a ceruza, csak épp automatikusan fogja kiválasztani, hogy melyik csempére van épp szüksége ahhoz, hogy folyamatos mintákat rajzoljon a térképre.

## 3D-s útvesztő

A térkép 3 dimenziós labirintusként is megjeleníthető a maze funkcióval. Ehhez a teknőc pozícióját és irányát használja fel, mint a játékos nézőpontját az útvesztőre, de hogy a csempén belüli pozicíókat is kezelni tudja, a teknőc koordinátái ilyenkor 128-al fel vannak szorozva (eredetileg 8-at használtam, hogy egyezzen a térkép pixelszámával, de a mozgás túl darabos volt úgy). Tehát például a (64,64) a térkép bal felső mezőjének közepét jelenti, a (320,192) pedig a harmadik oszlop második sor közepe.

Itt a `scale` nagyítás paraméter is másképp értelmeződik: amikor 0, akkor a labirintus 32 x 8 csempét tud használni, ahogy az a szprájtpalettán látszik, csempénként egy szprájt, 8 x 8 pixel méretben. Ha 1, akkor viszont 16 x 16 csempét, ahol minden csempe 2 x 2 szprájt, tehát 16 x 16 pixel méretű. 3 esetén 4 x 4 fajta csempéd lehet, azaz összesen 16 féle, mindegyik 64 x 64 pixeles. Ebben az esetben a térkép ezeket a nagyobb csempéket választja, ezért a csempe sorszáma és a szprájt sorszáma csak akkor egyezik meg, ha a nagyítás értéke 0. Például ha a térképen az 1-es id van és a nagyítás is 1-es, akkor az 1-es szprájt helyett ez a 2-es, 3-as, 34-es, 35-ös szprájtokat jelenti.

    Csempe id 1 scale 0 esetén      Csempe id 1 scale 1 esetén
    +---+===+---+---+-              +---+---+===+===+-
    |  0|::1|  2|  3| ...           |  0|  1|::2|::3| ...
    +---+===+---+---+-              +---+---+===+===+-
    | 32| 33| 34| 35| ...           | 32| 33|:34|:35| ...
    +---+---+---+---+-              +---+---+===+===+-

Ettől függetlenül a térképre az 1-es szprájtot kell a palettáról elhelyezned, hogy ezeket a szprájtokat kapd. Szokás szerint a 0-ás csempe a nincs térképelemet jelenti.

Ha a `sky` (ég) paraméter meg van adva, akkor az a csempe, mint a labirintus mennyezete lesz megjelenítve. Másrészről a `grd` (ground, föld) csak ott jelenik meg talajként, ahol nincs térképelem megadva. A csempeazonosítókat zónákra oszthatod híváskor, ettől függ, hogy az adott csempe miképp jelenik meg (talaj, fal vagy szprájt). Minden olyan csempe, ami a `wall`-nál nagyobb vagy azzal egyenlő, nem lesz átjárható, és olyan kockaként jelenik meg, ahol a csempe szprájtjai kerülnek a kocka oldalaira, átlátszóság nélkül. Azok a csempék, amik nagyobbak vagy egyenlőek az `obj`-ban (tárgy) megadottnál, szintén átjárhatatlanok lesznek, de ezek megfelelőre méretezett 2D-s szprájtként jelennek meg, arccal mindig a játékos (a teknőc pozíciója) felé fordulva, és ezeknél értelmezett az alfa csatorna, szóval a falakkal ellentétben a tárgyak lehetnek átlátszóak.

Csempe id | Leírás
--- | ---
0 | Mindig járható, `grd` talajként jelenik meg helyette
1 <= x < `door` | Járható, talajként jelenik meg
`door` <= x < `wall` | Falként jelenik meg, mégis átjárható (ajtó)
`wall` <= x < `obj` | Nem átjárható, falként jelenik meg
`obj` <= x | Nem átjárható, tárgy szprájtként jelenik meg

Hozzáadhatsz nem játékos karaktereket (illetve további tárgyakat) is a labirintushoz a térképtől függetlenül (egy int tömbben, ami x, y, csempe id hármasokat tartalmaz, a koordináták 128-al felszorozva). Ezek mind átjárhatóak lesznek, és pont úgy jelennek meg, mint a tárgy szprájtok; az ezekkel való ütközést, mozgatásukat és minden egyebet neked kell implementálni a játékodban. A `maze` parancs csupán megjeleníti ezeket. Annyi szívességet azonban megtesz neked, hogyha az adott NJK direktben látja a játékost akkor a tömbben a csempe id legmagasabb 4 bitjét beállítja. Hogy melyiket, az a kettejük távolságától függ: a legmagasabb bit (0x80000000) azt jelzi, közelebb vannak, mint 8 térképmező, a következő bit (0x40000000) azt, hogy közelebb, mint 4 mező, a következő (0x20000000) azt, hogy közelebb, mint 2 mező, és végül a legutolsó bit (0x10000000) azt, hogy ugyanazon vagy szomszédos térképmezőn állnak.

Mindezeken felül ez a parancs gondoskodik a labirintusban való navigálásról is, a `▴` / △ előre mozgatja a teknőst, a `▾` / ▽ hátra; a `◂` / ◁ balra fordul, a `▸` / ▷ jobbra fordul (a játékpad billentyűzetkiosztása megváltoztatható, lásd memóriatérkép). Az összes többi játékpad gomb lekezelése és az interakciók kivitelezése a játékodtól függ, így a Te feladatod leprogramozni ezeket, a `maze` csak a játékos mozgatásában és a falakkal való ütközésben segít.

MEGJEGYZÉS

Ne feledd, hogy a teknőc pozícióját mindig 128-al le kell osztani, hogy megkapd, a térkép melyik mezőjén tartózkodik épp a játékos.

ElőzőKövetkező

# Betű Szerkesztő

Kattints a betű ikonra (vagy `F5`) a betűkészlet módosításához.

Az itt szerkesztett betűtípust fogja használni, amikor a width megméri a szöveg méretét, és amikor a text paranccsal kiírsz.

Betű Szerkesztő

Ennek az oldalnak az elrendezése hasonló, mint a szprájt szerkesztő, csak nincs paletta. Balra található a glifszerkesztési terület (1), jobbra pedig a glifválasztó (2). (A glif egy adott betű, azaz UNICODE kódpont megjelenített alakja).

## Glifszerkesztő

Elég egyszerű, balklikk beállítja a kinézetet (előtér), a pedig törli (háttér).

Ha lenyomjuk a `Shift`-et, akkor vonalat húzhatunk a legutóbb módosított pontból.

## Glifválasztó

Kereshetsz UNICODE kódpontra, de ha csak leütsz egy billentyűt, akkor a glifválasztó a glifjére fog ugrani. Ha a billentyűzeten nincs meg valamelyik gomb, akkor a szokásos beviteli módok is használhatók, lásd billentyűzet.

## Eszköztár

Az elérhető eszközök itt szűkösebbek, eltolás, forgatás és tükrözés van csak, nincsen kijelölés. De a glifválasztóban a kimásolás (`Ctrl`+`C`) és a beillesztés (`Ctrl`+`V`) a megszokott módon működik.

ElőzőKövetkező

# Hangeffektek

A hangszoró ikonra kattinva (vagy `F6`) szerkeszthetők a hangeffektek.

A hangeffekteket a programodból az sfx paranccsal tudod megszólaltatni.

Hangeffektek

Balra található a hanghullám szerkesztő és az eszköztára (1), jobbra a hangeffekt választó (2), alattuk pedig a hangeffekt szerkesztő (3).

## Effektválasztó

Jobbra látható a hangeffektek listája (2), mind hangjegyként ábrázolva (technikailag minden hangeffekt egy hangjegy, konfigurálható hanghullámmal és speciális effekt opciókkal). A kívánt hangeffektre kattintva a listában az szerkeszthetővé válik (vagy `▴` / `▾` gombokkal is választható).

## Effektszerkesztő

Alul a zongora (3), pontosan úgy néz ki, és úgy is műküdik, mint a zenei sávok hangjegyszerkesztője, csak pár opcióval kevesebb. Bővebb infót és a billentyűzetkosztást ott találod.

FONTOS

Amikor egy hangeffekt kiválasztódik, az akkori állapota elmentődik az előzményekbe. Erre bármikor vissza lehet állítani a visszavonás kombináció lenyomásával, amíg az a hangeffekt marad a kiválasztott. Ha volt visszavonás, akkor az újrabeillesztés is használható mindaddig, amíg nem módosítjuk. (A módosítások nem mentődnek az előzményekbe egyesével, csak az az állapot, amikor a hangeffekt ki lett választva.)

## Hanghullám eszköztár

Alapból a hanghullám (1) nem módosítható, csak azt mutatja, hogy melyik hullámot használja az aktuális hangeffekt. Rá kell kattintani a lakat ikonos gombra, hogy szerkeszthetővé váljon (de persze előbb győzödj meg róla, hogy a hangeffektednek választottál ki hullámmintát).

Hanghullám eszköztára

Amikor a lakat nyitva, akkor a hangmintára kattintva módosítani lehet azt.

FIGYELEM

Ha módosítasz egy hanghullámot, akkor az azonnali hatállyal megváltoztat minden egyes olyan hangeffektet és hangsávot, ami azt a hanghullámot használja.

FONTOS

Amikor kilakatolunk egy hanghullámot, az akkori állapota elmentődik az előzményekbe. Erre bármikor vissza lehet állítani az visszavonás kombináció lenyomásával. (A módsítások nem mentődnek az előzményekbe egyesével, csak a hanghullám abban a pillanatban, amikor kilakatolásra került.)

Az eszköztárat használva állítható a finomhangolás (-8-tól 7-ig), a hangerő (0-tól 64-ig) és az ismétlés. Az ismétlés gombra kattintva az lenyomva marad, ilyenkor kijelölhetsz egy "loop" részt a hullámból. Ezután amikor a hanghullám egyszer végig lejátszódik, utánna a kijelölt rész elejére fog ugrani, és onnan veszi a mintákat a végtelenségig ismételve a kijelölt részt.

A kényelmed kedvéért van még 4 alapértelmezett hanghullám generáló, egy gomb az alapértelmezett hullámminta betöltésére a soundfontból (amit a General MIDI is használ) és mindenféle eszköz a hullám hosszának állításához, forgatásához, növeléséhez, kicsinyítéséhez, negálásához, tükrözéséhez stb. Az utolsó előtti gomb a végtelenségig játsza a hanghullámot az épp aktuális beállításaival (akkor is, ha nincs loop megadva).

Végezetül a legutolsó gomb, az Export kiexportálja a hanghullámot RIFF Wave formátumban. Ezt szerkesztheted egy külsős programmal, majd a visszatöltéshez csak húzd rá a módosított fájlt a MEG-4 ablakára.

ElőzőKövetkező

# Zenesávok

Kattints a hangjegy ikonra (vagy `F7`) a zenék szerkesztéséhez.

Az itt szerkesztett zenesávokat a programodban a music paranccsal tudod lejátszani.

Látni fogsz öt oszlopot, és alul egy zongorát.

Zenesávok

## Sávok

Balra az első oszlopban lehet kiválasztani, melyik zenei sávot szeretnénk szerkeszteni (1).

Billentyűkombináció | Leírás
--- | ---
`Page Up` | Előző sávra vált.
`Page Down` | Következő sávra vált.
`Szóköz` | Elindítja / leállítja a sáv lejátszását.

A sávválasztó alatt látszanak a DSP státusz regiszterek (2), de ez a blokk csak akkor kel életre, ha folyamatban van a lejátszás.

## Csatornák

Mellette négy hasonló oszlop található, mindegyikben hangjegyek (3). Ez az a négy csatorna, amit a zenelejátszó egyidejűleg képes megszólaltatni. Ez hasonló a kottához, bővebb infóért lásd a General MIDI fejezetet alább.

Billentyűkombináció | Leírás
--- | ---
`◂` | Előző csatornára vált.
`▸` | Következő csatornára vált.
`▴` | Egy sorral feljebb lép.
`▾` | Egy sorral lejjebb lép.
`Home` | Első sorra ugrik.
`End` | Utolsó sorra ugrik.
`Ins` | Sor beszúrása. Minden, ami alatta van, eggyel lejjebb kerül.
`Del` | Sor törlése. Minden, ami alatta van, eggyel feljebb kerül.
`Backspace` | Hangjegy törlése.

## Hangjegyszerkesztő

A csatornák alatt látható a hangjegyszerkesztő (4), néhány gombbal balra és egy nagy zongorával jobbra.

FONTOS

Amikor egy hangjegy kiválasztódik, az akkori állapota elmentődik az előzményekbe. Erre bármikor vissza lehet állítani a visszavonás kombináció lenyomásával, amíg az a hangeffekt marad a kiválasztott. Ha volt visszavonás, akkor az újrabeillesztés is használható mindaddig, amíg nem módosítjuk. (A módosítások nem mentődnek az előzményekbe egyesével, csak az az állapot, amikor a hangjegy ki lett választva.)

A hangjegyeknek három részük van, az első a hangmagasság (a szerkesztőben felül), ami újabb három alrészből áll. Az első a hang maga, mint pl. `C` vagy `D`. Aztán a `-` karakter ha egészhang, illetve `#` félhangok esetében. A harmadik rész pedig simán az oktáv, `0`-tól (legmélyebb) `7`-ig (legmagasabb). A 440 Hz normál zenei A hang például ezért úgy van írva, hogy `A-4`. A zongora segítségével könnyedén választhatsz hangmagasságot.

A hangmagasság után következik a korábban említett hangszer (a hangjegy középső része), ami a kívánt hullámmintát választja ki, `01`-től `1F`-ig. A 0-ás érték `..`-ként jelenik meg, és azt jelenti, használd a korábban beállított hangmintát tovább.

Végezetül adhatsz speciális effekteket a hangjegyhez (a hangjegy utolsó része), mint például arpeggio (akkordként szólal meg), portamento, vibrato, tremolo stb. A teljes listát megtalálod a hangjegyeffekteknél. Ennek van egy numerikus paramétere, ami általában azt jelenti, hogy "mennyire". Három hexa számként jelenik meg, ahol az első az effekt típusa, a maradék kettő pedig a paraméter, vagy pedig `...` ha nincs beállítva. Például a `C00` azt jelenti, állítsd a hangerőt nullára, azaz némítsd el a csatornát.

### Billentyűzet

Zongora billentyűzetkiosztás

1. hullámminta választók
2. effekt választók
3. oktáv választók
4. zongora klaviatúra

Billentyűkombináció | Leírás
--- | ---
`1` - `0` | Hullámminta választás 1-től 10-ig (illetve `Shift`-el 11-től 20-ig).
`Q` | Minden effekt törlése a hangjegyen (de a hangmagasságot és a hullámmintát ne).
`W` | Arpeggio dúr.
`E` | Arpeggio moll.
`R` | Csúsztatás egész hanggal felfelé.
`T` | Csúsztatás fél hanggal felfelé.
`Y` | Csúsztatás fél hanggal lefelé.
`U` | Csúsztatás egész hanggal felfelé.
`I` | Vibrato kicsi.
`O` | Vibrato nagy.
`P` | Tremolo kicsi.
`[` | Tremolo nagy.
`]` | Csatorna elnémítása "effekt".
`Z` | Egy oktávval méllyebbre lép.
`.` | Egy oktávval magasabbra lép.
`X` | C hang az aktuális oktávon.
`D` | C# hang az aktuális oktávon.
`C` | D hang az aktuális oktávon.
`F` | D# hang az aktuális oktávon.
`V` | E hang az aktuális oktávon.
`B` | F hang az aktuális oktávon.
`H` | F# hang az aktuális oktávon.
`N` | G hang az aktuális oktávon.
`J` | G# hang az aktuális oktávon.
`M` | A hang az aktuális oktávon.
`K` | A# hang az aktuális oktávon.
`,` | H (B) hang az aktuális oktávon.

MEGJEGYZÉS

Angol kiosztás billentyűit tartalmazza ez a táblázat. Azonban nemigazán számít, milyen billentyűzetkiosztást használsz, csak az számít, ezek a gombok hol vannak az angolon. Például, ha AZERTY kiosztásod van, akkor neked az `A` gomb lesz az effektek törlése funkció, QWERTZ esetén pedig a `Z` lefele csúsztatja a hangot, és a `Y` fog oktávot váltani.

Fontos megjegyezni, hogy nem minden funkciónak van gyorsbillentyűje. Például 31 hullámmintád lehet, de csak az első 20 érhető el gyorsgombokkal. Ugyanígy effektekből is nagyságrendekkel több van, mint ahánynak gyorsgombja van.

## General MIDI

Zenék (legalábbis a kottáik) importálhatók MIDI fájlokból. Nagyon leegyszerűsítve a dolgot, amikor egy klasszikus zenei kottát számítógépen tárolnak digitalizált formában, akkor ahhoz a MIDI formátumot használják. Namost ezek alkalmasak egy hangszerhez vagy akár egy komplett zenekarnak is, szóval sokkal több mindent tudnak tárolni, mint amire a MEG-4 képes, emiatt

FIGYELEM

Nem minden MIDI fájlt lehet tökéletesen beimportálni.

Mielőtt továbbmennék, muszáj ejteni pár szót a kifejezésekről, mivel sajnálatos módon a MIDI specifikáció és a MEG-4 is ugyanazt a nevezéktant használja - csak épp tök mást értenek alatta.

- MIDI dal: egy .mid fájl (az SMF2 formátum nem támogatott).
- MIDI sáv: egy sor a klasszikus kottán.
- MIDI csatorna: csak azért létezik, mert a MIDI-t idióták alkották, akik azt hitték, jó poén mindent egy sávba zsúfolni amikor a fájlokat mentik, egyébként pontosan és egy-az-egyben ugyanaz, mint a sáv. 16 ilyened lehet.
- MIDI hangszer: egy kód (amit a General MIDI Patch szabványosított), ez írja le, hogy melyik hangszert használja egy adott csatorna (kivéve, ha az a 10-es csatorna, ne is kérdezd miért), összesen 128 féle hangszerkód van belőle.
- MIDI hang: egy hang, C a -1. oktávontól a G a 9. oktávonig tartományban, 128 különböző hangjegy összesen.
- MIDI konkurrens hangok: azon hangok száma, amik egyszerre szólhatnak egy adott pillanatban. Mivel 16 csatorna és 128 hangjegy van a MIDI-ben, így ez 2048.
- MEG-4 sáv: egy dal, ezekből 8 lehet összesen.
- MEG-4 minta: a hulláminta mint PCM adatok sorozata, megfeleltethető a hangszereknek, összesen 31 ilyened lehet.
- MEG-4 csatorna: azon hangok száma, amik egyszerre szólhatnak egy adott pillanatban, ez 4.
- MEG-4 hang: egy hang, C a 0. oktávontól a B a 7. oktávonig tartományban, 96 különböző hangjegy összesen.

A félreértések elkerülése végett csakis egy MEG-4 sávról lesz szó, és a továbbiakban a "sáv" a MIDI csatornákat jelenti, a "csatorna" pedig a MEG-4 csatornáit.

### Hangszerek

Ami a hangszereket illeti, összesen 16 család van, 8 hangszerrel mindegyikben. A MEG-4 nem tud ilyen sok, 128 különböző hullámmintát tárolni, ezért családonként csak kettőt rendel hozzá (a 15. és 16. család a speciális effekteké, nem használt):

Család | SF | Patch | Hogy kéne szólnia | SF | Patch | Hogy kéne szólnia
--- | --- | --- | --- | --- | --- | ---
Piano | 01 | 1-4 | Akusztikus zongora | 02 | 5-8 | Elektromos zongora
Chromatic | 03 | 9-12 | Csemballó | 04 | 13-16 | Csőharangok
Organ | 05 | 17-20 | Templomi orgona | 06 | 21-24 | Harmónika
Guitar | 07 | 25-28 | Akusztikus gitár | 08 | 29-32 | Elektromos gitár
Bass | 09 | 33-36 | Akusztikus Basszus | 0A | 37-40 | Basszusgitár
Strings | 0B | 41-44 | Hegedű | 0C | 45-48 | Zenekari hárfa
Ensemble | 0D | 49-52 | Vonósegyüttes | 0E | 53-56 | Kórus ááá
Brass | 0F | 57-60 | Trombita | 10 | 61-64 | Kürt
Reed | 11 | 65-68 | Szaxofon | 12 | 69-72 | Oboa
Pipe | 13 | 73-76 | Fuvola | 14 | 77-80 | Fújt üveg
Synth Lead | 15 | 81-84 | Szintetizátor 1 | 16 | 85-88 | Szintetizátor 2
Synth Pad | 17 | 89-92 | Szintetizátor 3 | 18 | 93-96 | Szintetizátor 3

Általánosítva, a General MIDI hangszerből a `(patch - 1) / 4 + 1`-dik soundfont hullámminta lesz.

Fontos megjegyezni, hogy a MEG-4 dinamikusan osztja ki a hullámmintákat, szóval ezek a számok a soundfontbeli hullámok sorszámai. Ha például a MIDI fájlod csak két hangszert használ, zongorát és elektromos gitárt, akkor a zongora kerül az 1-es hullámhelyre, és a gitár a 2-esre. Előre betölthetsz minden hangmintát a soundfontból a hangeffektek szerkesztőben, ekkor a beimportált MIDI fájlod pontosan ezeket a hullám sorszámokat fogja használni.

### Kották

A MEG-4 mintái megfeleltethetők a klasszikus zenei kottának, de amíg a klasszikus kottán az idő balról jobbra halad és egy MIDI sáv csak egy hangszert jelenhet, addig a MEG-4 kottán az idő fentről lefelé halad és szabadon változtathatod, egy adott csatorna mikor melyik hullámot használja. Itt egy konkrét példa (a General MIDI specifikációból):

Klasszikus kotta balra, MEG-4 kotta megfelelője jobbra

Balra három sávunk van, Electric Piano 2 (elektromos zongora), Harp (hárfa) és Bassoon (fagott). Az első hangjegy, amit le kell játszani a fagotton, mindjárt két hangjegy egyszerre. Vegyük észre a kottán a basszuskulcsot, így ezek a hangok a C a 3. oktávon és C a 4. oktávon, és mindkettő 4 negyedes, azaz teljes egész hangok.

Jobbra van a MEG-4 kotta megfelelője. Az első sorban látható ez a két fagott hang: `C-3` az első csatornán és `C-4` a másodikon. A minta `12` (hexa, feltéve, hogy a soundfontot előre betöltöttük kézzel, egyébként a szám más lenne) az oboa hullámmintát választja, ami nem igazán fagott, de ez a legközelebbi, amink van a soundfontban. A `C30` rész jelenti a gyorsulást, amivel megszólaltatják a hangot, ez nálunk megfeleltethető a hangerőnek (minnél erősebben csapsz egy zongora billentyűre, annál hangosabb lesz a hangja). A MEG-4 hangonkénti hangereje 0-tól (csend) 64-ig (40 hexában, teljes hangerő) terjed. Ezért a 30 hexában a teljes hangerő 75%-a.

A következő lejátszandó hang a hárfán található, negyed hanggal a fagott után, G a 4. oktávon és 3 negyedig tart. A MEG-4 kottán ezt `G-4`-ként látod, a negyedik sorban (mivel akkor kezdődik), és mivel az 1-es 2-es csatornán még szól a fagott, ezért a 3-as csatornán. Ha ezt a hangot az 1-es vagy 2-es csatornára raktuk volna, akkor a csatornán épp lejátszott hang elhallgatott volna, és lecserélődött volna az újra. A minta itt a `0C` (hexában), ami a zenekari hárfa hullámmintáját jelenti.

Az utolsó hang a legelső MIDI sávon található, félhanggal az indulás után kezdődik, egy E az 5. oktávon és 2 negyedes, azaz félhangnyi időtartamú. Mivel félhanggal később kezdődik, ezért az `E-5`-öt a 8. sorban találod, és mivel már van három hangunk amik még tartanak, ezért a 4. csatornára került. A minta `02` jelentése válaszd az elektromos zongorát, ami nem ugyanaz, mint a MIDI Electric Piano 2, de elég közel áll hozzá.

Namost van két egész hangunk, egy háromnegyedes és egy feles; ezek rendre a sáv elején, negyeddel később illetve fél hanggal később kezdődtek. Ez azt jelenti, hogy mindnek egyszerre kell, hogy vége legyen. Ezt a 16. sorban (10 hexában) láthatod, minden csatornán van egy `C00` "állítsd a hangerőt 0-ra" parancs.

### Tempó

A MIDI suttyomban 120 BPM-et (beat per minute, percenkénti ütésszám) feltételez, és csak egy negyedhang osztót ad meg. Aztán megadhatja a negyedhang hosszát milliomodmásodpercekben, vagy nem. A lényeg, hogy bonyolult, és nem minden kombináció fordítható át értelmesen a MEG-4-re. Az importálót úgy írtam meg, hogy eldobja a felhalmozódó kerekítési hibákat, és csakis a két egymásutáni hang relatív időközével foglalkozik. Emiatt a MEG-4 dal tempója sosem lesz pontosan ugyanaz, mint a MIDI dalé, de nagyon hasonlóan kell szólnia, és túlságosan eltérnie sem szabad tőle.

A MEG-4 tempója sokkal egyszerűbb. Fixen 3000 tikked van percenként, és az alapértelmezett tempó 6 tikk soronként. Ez azt jelenti, hogy 125 BPM-hez minden negyedik sorba kell hangjegyeket rakni (mivel 3000 / 6 / 4 = 125). Ha a tempót átállítod (lásd `Fxx` parancs) ennek a felére, 3 tikkre soronként, akkor minden sor fele annyi ideig fog kitartani, ezért 250 BPM-et kapsz ha minden negyedik sort használod. 3-as tempó mellett minden nyolcadik sorba kell a hangjegyeket rakni a 125 BPM-hez. Ha a tempót 12-re állítod, akkor minden sor kétszer annyi ideig fog tartani, ezért minden negyedik sor 62.5 BPM-et jelent, és minden második sort kell használni a 125 BPM-hez. Remélem világos.

Ez csak azt állítja, hogy mikortól szólaljon meg egy hang, és teljesen független attól, hogy az mennyi ideig fog szólni. Ez utóbbihoz vagy egy új hangot kell használnod ugyanazon a csatornán, vagy pedig egy `C00` "állítsd a hangerőt 0-ra" effektet, pont annál a sornál, amikor a hangot el akarod vágni. Ha e kettő között átállítod a tempót, az nem fogja a hangot befolyásolni, csakis azt, hogy meddig szóljon (mivel másik időpontban fogja elérni azt a sort, amiben a kikapcsolás van).

Azonban a hangok akkor is elhalnak, ha a hullámmintájuk véget ér. Hogy ez mikor következik be, az függ a hangmagasságtól és a minták számától is (a C-4 hangmagasság tikkenként 882 mintát kell küldjön a hangszóróra). Van azonban egy trükk: a hullámmintán megadhatsz egy ún. "loop"-ot, ami azt jelenti, miután minden minta elfogyott, akkor a kijelölt tartományt fogja ismételni a végtelenségig (szóval mindenképp el kell vágnod, kölönben a hang tényleg sosem fog elhallgatni).

ElőzőKövetkező

# Memóriaátfedők

Kattints a RAM ikonra (vagy `F8`) a memóriaátfedők szerkesztéséhez.

Az átfedők nagyon hasznosak, mivel lehetővé teszik, hogy a RAM bizonyos része több különböző, egymást átfedő adatot tartalmazzon, és így több adatot legyen képes kezelni, mint amennyi a memóriába beleférne. Ezekkel dinamikusan, futás közben betölthetsz szprájtokat, térképeket, betűkészleteket vagy épp bármilyen tetszőleges adatot a memload funkció hívásával.

Van egy másik, nagyon hasznos tulajdonságuk is: ha meghívod a memsave funkciót a programodból, akkor az átfedő adatai a felhasználó számítógépére kerülnek lementésre. A `memload` legközelebbi hívásakor a betöltendő adatok már nem a flopidról, hanem a felhasználó számítógépéről fognak érkezni. Ezzel könnyedén egy permanens tároló alakítható ki, például az elért pontszámok tárolására.

Memóriaátfedők

## Átfedőválasztó

Az oldal tetején látható a memóriaátfedő kiválasztó, minden egyes átfedő méretével (1). A sötétebb bejegyzések azt jelzik, hogy az adott átfedő nincs megadva. Összesen 256 átfedő áll rendelkezésedre, 00-tól FF-ig.

## Átfedő tartalma

A tábla alatt láthatod az átfedő adatait hexdump formájában (csak akkor, ha nem üres átfedő van épp kiválasztva, 2).

A hexdump egy pofonegyszerű formátum, az első oszlop tartalmazza a címet, ami mindig 16-al osztható. Ezt követi az adott címen található 16 bájt hexa formában, majd ugyanaz a 16 bájt karakterként. Ennyi.

## Átfedő menü

A menüsorban fent (3), megadhatsz egy memóriacímet és egy méretet, majd az Elment gombra kattintva le fogja tárolni a memória adatait a kijelölt átfedőbe. A Betölt gomb használatával visszatölthető a memória tartalma a megadott címre, de ekkor a méret azt jelenti, maximum ennyi bájtot szabad betölteni.

Az Export gombra kattintva megjelenik a fájlmentés ablak, ahol lementheted és módosíthatod a bináris tartalmat egy külsős programmal. Az átfedő visszatöltéséhez a fájlt úgy kell elnevezni, hogy `memXX.bin`, ahol az `XX` a használni kívánt átfedő száma 00-tól FF-ig, és csak simán rá kell húzni ezt a fájlt a MEG-4 ablakára.

ElőzőKövetkező

# Vizuális Szerkesztő

Kattints a folyamatábra ikonra (vagy `F9`) a programod struktogrammokkal való szerkesztéséhez.

A kód három alrészből áll, az egyik vizuálisan, struktogrammokkal teszi lehetővé a forráskód szerkesztését (ez), a szöveges szerkesztés a Kód Szerkesztőben lehetséges, míg a programod gépi kódú változatát a debuggoló mutatja.

TODO

ElőzőKövetkező

# Debuggoló

Kattints a katica ikonra (vagy `F10`) a programod gépi kódú ellenőrzéséhez.

A kód három alrészből áll, az egyik a programod gépi kódú változatát mutatja (ez), a forráskód szöveges szerkesztése a Kód Szerkesztőben lehetséges, míg a Vizuális Szerkesztőben ugyanezt struktrogrammokkal teheted meg.

FIGYELEM

A debuggoló csak a beépített nyelvek esetén működik. Nem elérhető olyan harmadik fél által fejlesztett nyelvek esetén, mint például a Lua, ezeknél nincs és nem is lehetséges a támogatás.

Itt megtekinthető, hogy a CPU miként látja a programodat. A `Space` leütésével lépésenként hajthatod végre a programodat, és közben láthatod, hogy változnak a regiszterek és a memória. A menüben a Kód / Adat gombbal (1, vagy a `Tab` billentyűvel) váltogathatsz kód- és adatnézet között.

Debuggoló

## Kódnézet

Balra láthatod a hívásvermet (2). Ez arra használatos, hogy nyomonkövessük a függvényhívásokat. Tartalmazza azt a forráskód sort is, ahonnan a függvény meghívódott. Ez egy hivatkozás, rákattintva előjön a Kód Szerkesztő, a kérdéses sorra pozícionálva. A lista tetején mindig az a sor látható, ami jelen pillanatban épp végrehajtódik.

Jobbra van az utasítás bájtkódlista Assemblyben, amiket a CPU ténylegesen végrehajt (3).

## Adatnézet

Balra látható a programod globális változóinak listája, az épp aktuális értékeikkel (2).

Jobbra van a verem (3), ami több részre oszlik. Minden, ami a BP regiszter felett helyezkedik el, az az éppen futó program paraméterlistája, és minden ami ezalatt, de még az SP regiszter fölött található, azok meg a lokális változók.

## Regiszterek

Függetlenül attól, hogy melyik nézet az aktív, a CPU regiszterei mindig látszanak alul (4). Harmadik fél által biztosított nyelvek esetén csak az FLG, TMR és a PC regiszter elérhető. Bővebb leírást az egyes regiszterekről a mnemonikok címszó alatt találsz.

ElőzőKövetkező

# C

Ha ezt a nyelvet választod, akkor kezd a programodat a `#!c` sorral.

## Példa program

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

`#!c /* globális változók */ int számláló = 123; float szám = 3.1415; addr_t cím = 0x0048C; str_t sztring = "valami"; uint32_t tömb[10]; /* Induláskor lefuttatandó dolgok */ void setup() { /* lokális változók */ int lokálisvagyok = 123; } /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ void loop() { /* MEG-4 stílusú kimenet */ printf("a számláló %d, balshift %d\n", számláló, getkey(KEY_LSHIFT)); }`

## Leírás

A konzol alapértelmezett nyelve a MEG-4 C. Ez, bár maga a nyelv roppant egyszerű, mégis valamivel haladóbb programozóknak való. Ha abszolút kezdő vagy, akkor javaslom inkább a BASIC nyelv használatát.

Szándékosan egy lebutított ANSI C-nek lett megalkotva, hogy megkönnyítse a programozás tanulását. Emiatt eléggé korlátozott, nem tud mindent, amit az ANSI C elvár, azonban ha lecseréled a

    #!c

sort erre

    1
    2
    3

`#include <stdint.h> typedef char* str_t; typedef void* addr_t;`

akkor egy MEG-4 C forrás minden probléma nélkül le fog fordulni bármelyik szabványos ANSI C fordítóval (gcc, clang, tcc stb.).

Van egy nem szabványos kulcsszava, a `debug;`, amit akárhová elhelyezhetsz a programodban, és ami meghívja a beépített debuggolót. Ezt követően lépésről lépésre hajthatod végre a programodat, ellenőrizve, hogy épp mit csinál.

A továbbiakban a C nyelv laza bemutatása következik, arra fókuszálva, hogy miben speciális a MEG-4 C.

## Előfordító

Mivel csak egyetlen forrásfájl van, és a rendszerfüggvények prototípusai csont nélkül támogatottak, ezért nincs szükség fejlécfájlokra. Emiatt az előfordító csak a nagyon egyszerű (nem makró) define-okat, valamint a feltételes kódblokkokat támogatja csak.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

`/* lecseréli a (defvált) összes előfordulását a (kifejezés)-re */ #define (defvált) (kifejezés) /* kódblokk használata, ha a (defvált) lett definiálva */ #ifdef (defvált) /* kódblokk használata, ha a (defvált) nem lett definiálva */ #ifndef (defvált) /* kódblokk használata, ha a (kifejezés) igaz */ #if (kifejezés) /* egyébként blokk */ #else /* lezárja a feltételesen behúzandó kódblokkot */ #endif`

Létrehozhatsz felsorolást az `enum` kulcsszóval, vesszővel elválasztva, kapcsoszárójelek között. Minden elemnek eggyel nagyobb lesz az értéke, mint az azt megelőzőé. Ez pontosan úgy működik, mintha több define sort írtál volna be. Például a következő két kód ugyanazt csinálja:

    1
    2
    3

`#define A 0 #define B 1 #define C 2`

    1

`enum { A, B, C };`

Továbbá lehetséges direkt értéket is hozzárendelni az egyenlőségjellel, például:

    1

`enum { EGY = 1, KETTŐ, HÁROM, ÖT = 5, HAT };`

## Literálok

A MEG-4 C elfogad tízes számrendszerbeli számokat (akár integer egészszámok, vagy lebegőpontosak, tudományos jelöléssel vagy annélkül). Hexadecimális számokat a `0x` előtaggal kell kezdeni, a binárisokat `0b`-vel, a nyolcas számrendszerbelieket `0`-val; a karaktereket aposztrófok közé, a sztringeket pedig macskakörömbe kell tenni:

    1
    2
    3
    4
    5
    6
    7
    8

`42 3.1415 .123e-10 0777 0b00100110 0x0048C 'á' "Viszlát és kösz a halakat!\n"`

## Változók

A BASIC-el ellentétben a változókat itt deklarálni kell. Ezt két helyen lehet megtenni: a legfelső szinten, vagy minden funkció elején. Az előbbiekből lesznek a globális változók (amiket minden funkció elér), utóbbiakból pedig a lokális változók, amiket csakis az a funkció lát, amelyiknek a törzsében deklarálva lettek. Mégegy különbség, hogy a globális változók inicializálhatók (induláskor érték adható nekik a `=` után), míg a lokális változók nem, azoknak külön, kifejezett paranccsal kell értéket adni.

A deklaráció két részből áll: egy típusból és egy névből. A MEG-4 C támogat minden ANSI C típust: `char` (előjeles bájt), `short` (előjeles szó), `int` (előjeles egészszám), `float` (lebegőpontos szám). Ezek elé odarakható az `unsigned`, aminek hatására előjel nélküli lesz a típus. ANSI C alatt az `int` elhagyható a `short` után, de MEG-4 alatt el kell hagyni. Tehát a `short int` nem érvényes típus, a `short` önmagában viszont az. Továbbá a MEG-4 C nemcsak támogatja, de kifejezetten preferálja a szabványos egészszám típusokat (amiket ANSI C alatt az stdint.h rögzít). Ezeknek pár egyszerű szabálya van: ha a típus előjel nélküli, akkor `u` betűvel kezdődik; aztán az `int` jelenti, hogy egészszám, amit a tároláshoz használt bitek száma követ, majd végül a `_t` zárja, ami arra utal, hogy típus. Például az `int` és az `int32_t` ugyanaz, akárcsak az `unsigned short` és az `uint16_t`. Példák:

    1
    2
    3
    4
    5

`int a = 42; uint8_t b = 0xFF; short c = 0xFFFF; str_t d = "Valami"; float e = 3.1415;`

Az ANSI C-vel ellentétben, ami csakis angol betűket fogad el változónevekben, a MEG-4 C bármit megenged, ha az nem számmal kezdődik és nem egy kulcsszó. Például, az `int déjà_vu;` teljesen érvényes (vedd észre a nem angol karaktereket a névben).

## Tömbök és mutatók

Több, azonos típusú elem rendelhető egyetlen változóhoz, ezeket hívjuk tömböknek. A mutató olyan speciális változó, amiben egy olyan memóriacím van, ami azonos típusú elemek listájára mutat. A hasonlóság e kettő között nem véletlen, de vannak apró eltérések.

Tömbökre nincs külön parancs, mint BASIC esetében, egyszerűen csak meg kell adni az elemszámot `[` és `]` között a név után.

    1

`int tömb[10];`

A tömb elemeire hivatkozni ugyancsak a `[` és `]` között megadott indexszel lehet. Az index 0-tól indul, és ellenőrzésre kerül, hogy a deklarációban megadott méreten belüli-e. A MEG-4 C összesen 4 dimenziót támogat.

Mutatót úgy kell deklarálni, hogy a név elé `*`-ot teszünk. A C nem ismer sztring típust, és mivel a sztringek igazából karakterek egymásután a memóriában, ezért helyette karaktermutatót `char*` használunk. Ez furcsa lehet elsőre, ezért a MEG-4 C definiál egy `str_t` típust, de ez igazából pont ugyanaz, mintha `char*`-ot írtunk volna.

Mivel a mutató mindig egy címet tartalmaz, ezért értékül egy címet kell neki adni (a `&` a változók címét jelenti), és a mutató egy címet fog visszaadni. Ahhoz, hogy címen lévő értéket kapjuk, fel kell oldani a mutatót. Ez kétféleképp tehető meg: vagy `*`-ot kell elé írni, vagy pedig utánna `[` és `]` között egy indexet, pont úgy, mint a tömbök esetében. Például a következő kettő hivatkozás a második printf-ben ugyanaz:

    1
    2
    3
    4
    5

`int változó = 1; int *mutató = &változó; printf("mutató értéke (cím): %x\n", mutató); printf("mutatott érték: %x %x\n", *mutató, mutató[0]);`

A mutatók és a tömbök nem keverhetők, mivel az nem lenne egyértelmű. Például

    1

`int *a[10];`
Jelentheti az, hogy egy darab mutató, ami 10 egymásutánni egészszámra mutat (`*(int[10])`), vagy jelenthetné azt is, hogy 10 darab független mutató, amik mind egy-egy, nem feltétlenül egymásutánni egészszámra mutatnak (`(*int)[10]`). Nem egyértelmű melyik, ezért a mutatók és a tömbök nem vegyíthetők egy deklaráción belül.

FIGYELEM

A tömbökkel ellentétben a mutató feloldásakor nincs méretellenőrzés!

## Műveletek

Precedenciájuk szerint csökkenő sorrendben:

Aritmetikai

    * / %
    + -

Az első a szorzás, osztás, a `%` pedig a modulus (azaz osztás utáni maradék, pl. `10 % 3` az 1), összeadás, kivonás.

Relációs

    != ==
    <= >= < >

Nem egyenlő, egyenlő, kissebb egyenlő, nagyobb egyenlő, kissebb, nagyobb.

Logikai

    !
    &&
    ||

Tagadás (0-ból 1 lesz, minden nem nullából pedig 0), és (csak akkor 1, ha mindkét paramétere nem 0), vagy (legalább az egyik paramétere nem 0).

Bitenkénti

    ~
    &
    |
    << >>

Bitenkénti tagadás, bitenkénti és, bitenkénti vagy, bitenkénti eltolás balra, illetve jobbra. Vegyük észre, hogy ezek ugyanazok a műveletek, mint a logikaiak, azonban míg azok az egész értékre vonatkoznak, ezek minden kettes számrendszerbeli helyiértékre külön-külön. Például a logikai tagadás `!0x0100 == 0`, míg a bitenkénti tagadás `~0x0100 == 0x1011`. A bitenkénti eltolás pedig a kettőhatvánnyal való szorzásnak illetve osztásnak felel meg. Ha például egy értéket 1-el balra eltolunk, az pont ugyanaz, mintha 2-vel felszoroztuk volna.

Léptető

    ++ --

Növelés és csökkentés. Ezeket előtagként és utótagként is lehet használni. Ha előtag, például `++a`, akkor megnöveli a változó értékét, majd visszaadja a megnövelt értéket. Ha azonban utótag `a++`, akkor szintén megnöveli az értéket, de a nővelés előtti értéket adja vissza.

    1
    2

`a = 0; b = ++a * 3; /* a == 1, b == 3 */ a = 0; b = a++ * 3; /* a == 1, b == 0 */`

Feltételes

    ?:

Ez egy háromértékes kifejezés, három operandussal, amiket `?` és `:` választ el. Ha az első operandus igaz, akkor az egész kifejezés lecserélődik a második operandusra, egyébként a harmadikra. Emiatt a második és a harmadik operandus típusának meg kell egyeznie. Például `a >= 0 ? "pozitív" : "negatív"`.

Értékadás

    = *= /= %= += -= ~= &= |= <<= >>=

Az első elvégzi a műveletet, majd az eredményt a változóba helyezi. A többi ezen a változón végzi el a műveletet, majd az eredményt ugyanebbe a változóba helyezi. Például e kettő ugyanaz: `a *= 3;` és `a = a * 3;`.

A többi nyelvvel ellentétben a C-ben az értékadás is egy művelet. Ez azt jelenti, hogy bárhol előfordulhatnak egy kifejezésben, például `a > 0 && (b = 2)`. Ezért van az, hogy az értékadás a `=`, míg a logikai egyenlő `==`, hogy lehessen használni mindkettőt ugyanabban a kifejezésben.

Van még a címe operátor, a `&`, ami a változó címét adja vissza. Ez akkor használatos, ha valahol a MEG-4 API `addr_t` cím paramétert vár.

Az operátorok a precedenciasorrendjük szerint hajtódnak végre, például a `1+2*3` két operátort tartalmaz, a `+`-t és `*`-t, azonban a `*` precedenciája magasabb, így először a `2*3` számítódik ki, és csak azután az `1+6`. Ezért a végeredmény 7 és nem 9.

## Vezérlésirányítás

Míg a BASIC alatt a vezérlésátadás elsősorban címkékkel történik, addig a C ún. strukturált nyelv, azaz inkább az utasításokat megfelelő blokkokba helyezve tagolja a programot. Ha egynél több utasítást akarunk egyben kezelni, akkor azokat `{` és `}` közé kell tenni (de lehet egy utasítás is a blokkon belül).

Mint minden más, a feltételes vezérlésátadások is ilyen blokkokat használnak:

    1
    2
    3
    4
    5

`if(a != b) { printf("a nem egyenlő b-vel\n"); } else { printf("a egyenlő b-vel\n"); }`

Megadható egy `else` ág, ami akkor fut le, ha a kifejezés értéke hamis, de az `else` használata nem kötelező.

Többféle lehetséges érték esetén használható a `switch` utasítás. Itt minden `case` úgy viselkedik, mint egy cimke, és attól függően lesz kiválasztva, hogy a kifejezés értéke mennyi.

    1
    2
    3
    4
    5
    6

`switch(a) { case 1: printf("a értéke 1.\n"); case 2: printf("a értéke vagy 1 vagy 2.\n"); break; case 3: printf("a értéke 3.\n"); break; default: printf("a értéke valami más.\n"); break; }`

Van egy speciális cimke, a `default` (jelentése alapértelmezett), amire akkor ugrik a program, ha az értékhez nincs külön `case`. Ezek a blokkok összefüggőek, azaz ha a vezérlés az egyik `case` cimkére adódik, akkor az a blokk, illetve minden további, azt követő blokk is végrehajtódik. A fenti példában ha az `a` értéke 1, akkor mindkét printf le fog futni. Ha ezt nem akarjuk, akkor a `break` utasítást kell használni, hogy kilépjünk a `switch`-ből.

A C nyelv háromféle ismétléstípust ismer: elöltesztelős ciklus, hátultesztelős ciklus és számlálóciklus.

Az elöltesztelős ciklus előbb ellenőrzi a kifejezés értékét, és csak akkor futtatja le a ciklusmagot, ha az nem hamis.

    1
    2
    3

`while(a != 1) { ... }`

A hátultesztelős ciklus mindenképp lefuttatja a ciklusmagot legalább egyszer, csak ezt követően ellenőrzi a kifejezést és akkor ismétel, ha az igaz.

    1
    2
    3

`do { ... } while(a != 1);`

A számlálóciklus C-ben eléggé univerzális. Három kifejezést vár, rendre: inicialiálás, feltétel, léptetés. Mivel szabadon adhatod meg ezeket, ezért lehetséges akár több változót is használni vagy bármilyen kifejezést megadni (nem feltétlenül számlálóst). Példa:

    1
    2
    3

`for(a = 0; a < 10; a++) { ... }`

Ez pontosan ugyanaz, mintha ezt írtuk volna:

    1
    2
    3
    4
    5

`a = 0; while(a < 10) { ... a++; }`

A ciklusmag blokkjából is ki lehet lépni a `break` (megszakít) utasítással, de itt használható még a `countinue` (folytatás) is, ami ugyancsak megszakítja a ciklusmag blokkjának futtatását, de ahelyett, hogy kilépne, a következő iterációtól folytatja.

    1
    2
    3
    4
    5

`for(a = 0; a < 100; a++) { if(a < 10) continue; if(a > 50) break; printf("a értéke 10 és 50 között: %d\n", a); }`

## Függvények

FONTOS

Csak függvénytörzsön belül használhatók utasítások.

A programodat fel kell darabolnod kissebb programokra, amiket aztán többször is lefuttathatsz, ezeket hívjuk függvényeknek. A deklarálásukhoz meg kell adni a visszatérési értékük típusát, a nevüket, a paramétereik listáját `(` és `)` zárójelek között, majd pedig a függvénytörzsüket egy `{` és `}` közötti blokkban. Kettő ezek közül, a `setup` és a `loop` különleges jelentéssel bír, bővebben lásd a kód szerkesztő-nél. A C nyelv nem tesz különbséget alrutinok és függvények között; itt minden függvény. Az egyetlen különbség az, hogy azok a függvények, amik nem adnak vissza semmit, a visszatérési értékük típusa `void` (semmi).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

`void ott_vagyunk_már(int A) { if(A > 0) { printf("Nem, még nem\n"); return; } printf("IGEN! Dolgok, amiker érkezéskor akartál megtenni\n"); return; } void setup() { /* egyszer */ ott_vagyunk_már(1); /* aztán mégegyszer */ ott_vagyunk_már(0); }`

A függvényeket a programodból simán a nevükkel hívhatod, zárójelben a paramétereikkel (a zárójel mindenképp kötelező, akkor is, ha nincs paramétere). Nincs külön parancs, és nincs különbség a hívásban aközött, ha van visszatérési érték, vagy ha nincs.

A függvényből visszatérni a hívóra a `return;` utasítással kell. Amennyiben a függvénynek van visszatérési értéke, akkor azt a `return` után kell egy kifejezésben megadni, aminek a típusa pont ugyanolyan kell legyen, mint a függvényé. A `return` használata (akár van visszatérési érték, akár nincs) kötelező.

    1
    2
    3
    4
    5
    6
    7
    8
    9

`str_t sztringesfüggvényem() { return "egy sztring"; } void setup() { a = sztringesfüggvényem(); }`

## Elérhető függvények

C nyelvben nincs speciális kiíró vagy bekérő parancs; egész egyszerűen csak MEG-4 API hívásokat kell meghívni. A getc egy karaktert olvas be, a gets egy sztringet, kiírni sztringeket pedig a printf-el lehet.

A MEG-4 C pontosan úgy használja a MEG-4 API függvényeit, ahogy azok ebben a leírásban szerepelnek, nincs semmiféle trükközés, nincs átnevezés, se utótagok sem konverzió.

ElőzőKövetkező

# BASIC

Ha ezt a nyelvet választod, akkor kezd a programodat a `#!bas` sorral.

## Példa program

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

`#!bas REM globális változók LET számláló% = 123 LET szám = 3.1415 LET cím% = $0048C LET sztring$ = "valami" DIM tömb(10) REM Induláskor lefuttatandó dolgok SUB setup REM lokális változók LET lokálisvagyok = 123 END SUB REM Minden képkockánál lefuttatandó dolgok, 60 FPS SUB loop REM BASIC stílusú print PRINT "Épp"; " futok" REM MEG-4 stílusú kimenet printf("a számláló %d, balshift %d\n", számláló%, getkey%(KEY_LSHIFT)) END SUB`

## Dialektus

A BASIC egy mozaikszó, Beginners' All-purpose Symbolic Instruction Code, ami annyit tesz, Kezdők Általános célú Szimbólikus Utasítás Kódja. Kifejezetten azzal a céllal hozta létre Kemény János 1963-ban, hogy gyerekeket tanítsanak vele programozni. A MEG-4 BASIC azért ennél kicsit modernebb, tudja a teljes ANSI X3.60-1978 (ECMA-55) szabványt és még jónéhány dolgot az ANSI X3.113-1987 (ECMA-116) szabványból is, apró eltérésekkel. Az azonosítók hosszabbak lehetnek két karakternél, és a lebegőpontos valamint integer aritmetikája is 32 bites. A legfontosabb különbségek: nincs interaktív mód, így az utasításokat nem kell sorszámozni (helyette lehet cimkéket használni), illetve a BASIC kulcsszavak kis-nagybetű érzéketlenek, ahogy azt a specifikáció elvárja, ellenben a változó és függvénynevek kis-nagybetű érzékenyek. Az összes MEG-4 API függvényhívás kisbetűs; a többit szabadon választhatod, de azok is kis-nagybetű érzékenyek (például az `ALMA`, `Alma` és az `alma` három különböző változót takar).

Van egy nem szabványos kulcsszava, a `DEBUG`, amit akárhová elhelyezhetsz a programodban, és ami meghívja a beépített debuggolót. Ezt követően lépésről lépésre hajthatod végre a programodat, ellenőrizve, hogy épp mit csinál.

Következzen a részletes leírás példákkal és minden eltérés kiemelve.

## Literálok

A MEG-4 BASIC elfogad tízes számrendszerbeli számokat (akár integer egészszámok, vagy lebegőpontosak, tudományos jelöléssel vagy annélkül). Hexadecimális számokat a `$` karakterrel kell kezdeni (nincs a specifikációban, de így csinálta a Commodore BASIC és nagyjából az összes többi 80-as évekbeli dialektus is), a sztringeket pedig macskakörömbe kell tenni:

    1
    2
    3
    4
    5

`42 3.1415 .123e-10 $0048C "Viszlát és kösz a halakat!\n"`

FIGYELEM

A specikiáció szerint 7 bites ASCII-nak kellene lennie, de a MEG-4 BASIC nullával lezárt UTF-8 kódolt sztringeket használ. Elfogad továbbá C-beli kiemelő kódokat is (például `\"` a macskaköröm, `\t` a tab, `\n` az újsor karakter), és a sztringek maximális hossza 255 bájtnyi (a specifikáció 18 bájtot vár el).

## Változók

A változókat nem kell deklarálni, helyette az azonosítójuk utolsó betűje adja meg a típusukat. Ez lehet `%` egészszámoknál, `$` sztringeknél, és ez nincs a specifikációban, de a MEG-4 BASIC esetében a `!` bájtot, a `#` pedig duplabájtot jelent (szó). Bármi más lebegőpontos számot tároló változót eredményez.

    1
    2
    3
    4
    5

`LET A% = 42 LET B! = $FF LET C# = $FFFF LET D$ = "sztring" LET E = 3.1415`

A konverzió bájt, integer és a lebegőpontos számok között teljesen automatikus. Azonban ha egy sztringet akarsz szám változóba tenni, vagy szám literált egy sztring változóba, az hibát eredményez (ezekhez használnod kell a `STR$` illetve `VAL` hívásokat).

Amikor értéket adsz egy változónak, a `LET` parancs elhagyható.

Literálok megadhatók még a programodban a `DATA` állítások segítségével is, amiket aztán a `READ` utasítás rendel változókhoz. A `READ` pontosan annyi adatot olvas be, ahány változó meg lett adva a paramétereként, és többször is hívható. Hogy visszaállítsuk, hogy a legelső `DATA` utasítástól kezdve olvasson a `READ` megint, ahhoz a `RESTORE` parancsot kell kiadni.

    1
    2
    3
    4

`RESTORE READ név$, jövedelem DATA "Jóska", 1234 DATA "Pista", 2345`

Van pár speciális változó, amiket a rendszer biztosít. Az `RND` egy lebegőpontos véletlenszámot ad vissza, 0 és 1 között, az `INKEY$` visszaadja a felhasználó által leütött billentyűt vagy üres sztringet, `TIME` a gép bekapcsolása óta eltelt ezredmásodpercek számát, míg a `NOW%` a greenwichi középidő szerinti 1970 január 1.-e éjfél óta eltelt másodperceket adja vissza.

## Tömbök

Több, azonos típusú elem rendelhető egyetlen változóhoz, ezeket hívjuk tömböknek.

    1
    2
    3

`DIM A(10) DIM B(10, 10) DIM C(1 TO 6)`

A BASIC specifikáció elvárja a kétdimenziós tömbök kezelését, de a MEG-4 BASIC 4 dimenziót is támogat. A tömb elemei lehetnek bájtok, egészszámok, lebegőpontos számok vagy sztringek. Dinamikusan nem lehet átméretezni őket a `REDIM`-el, minden tömb statikusan lesz lefoglalva akkorára, amekkora a `DIM`-nél meg lett adva. Ha a méret nincs kiírva, akkor egy dimenziót és 10 elemet feltételez.

FIGYELEM

Az elemek indexe 1-től indul (mint az ANSI szerint, és nem 0-tól, mint az ECMA-55 szerint). Az `OPTION BASE` utasítás nem támogatott, viszont az induló index átállítható minden tömb esetén a `TO` kulcsszóval.

## Műveletek

Precedenciájuk szerint csökkenő sorrendben:

Aritmetikai

    ^
    * / MOD
    + -

Az első a hatványozás (pl. b a négyzeten `b^2`), aztán szorzás, osztás, a `MOD` pedig a modulus (azaz osztás utáni maradék, pl. `10 MOD 3` az 1), összeadás, kivonás.

Relációs

    <> =
    <= >= < >

Nem egyenlő, egyenlő, kissebb egyenlő, nagyobb egyenlő, kissebb, nagyobb.

Logikai

    NOT
    AND
    OR

Tagadás (0-ból 1 lesz, minden nem nullából pedig 0), és (csak akkor 1, ha mindkét paramétere nem 0), vagy (legalább az egyik paramétere nem 0).

Van egy nem szabványos operátor, a `@` a változó címét adja vissza. Ez akkor használatos, ha valahol a MEG-4 API `addr_t` cím paramétert vár.

Az operátorok a precedenciasorrendjük szerint hajtódnak végre, például a `1+2*3` két operátort tartalmaz, a `+`-t és `*`-t, azonban a `*` precedenciája magasabb, így először a `2*3` számítódik ki, és csak azután az `1+6`. Ezért a végeredmény 7 és nem 9.

## Vezérlésirányítás

Az `END` utasítás leállítja a vezérlést (kilép a programod).

A MEG-4 BASIC nem használ már sorszámokat, helyette cimékkel támogatja a `GOTO` parancsot, például:

    1
    2
    3

`ez_egy_cimke: GOTO ez_egy_cimke`

FIGYELEM

Néhány BASIC dialektus megengedi, hogy több `:`-el elválasztott parancsot egy sorba írj. MEG-4 BASIC alatt a `:` a cimkét jelenti, ezért minden parancsot külön sorba kell írni (ahogy azt az ECMA-55 is elvárja).

A feltételes vezérlésátadások szintén cimkéket használnak:

    1
    2

`IF a$ <> b$ THEN ez_egy_cimke ON a GOTO cimke1, cimke2, cimke3 ELSE egyébcimke`

Az `ON` .. `GOTO` mindenképp egy numerikus kifejezést vár, és az annyadik cimkére ugrik, 1-től kezdve (ha a kifejezés nulla vagy negatív, az mindenképpen az `ELSE` ágnak minősül). Nincs `ON` .. `GOSUB`, mert a GOSUB nem fogad el cimkéket a MEG-4 BASIC-ben.

FIGYELEM

A `GOSUB` utasítás nem fogad el cimkéket, és kicsit másképp működik MEG-4 BASIC alatt, lásd alább.

Az `IF` utasítás elfogad egyaránt numerikus és relációs kifejezést (minden nem nulla eredményt igaznak vesz), sőt mi több, a többsoros `IF` .. `THEN` .. `ELSE` .. `END IF` blokkok is támogatottak (de a `SELECT CASE` nem).

    1
    2
    3
    4
    5

`IF var >= 0 THEN PRINT "var értéke pozitív" ELSE PRINT "var értéke negatív" END IF`

Kivételként egy parancs lehet az egysoros `IF` után, amennyiben az a `GOTO` vagy az `END`:

    1
    2

`IF a < 0 THEN GOTO cimke IF b > 42 THEN END`

Az ismétlő utasítás, a számlálósciklus elöltesztelős (nem futtatja le a blokkot, ha az indulóérték nagyobb (vagy kissebb), mint a határ), és így néz ki:

    1
    2
    3

`FOR i = 1 TO 100 STEP 2 ... NEXT i`

Ez a `FOR` .. `NEXT` lényegében pontosan ugyanaz, mint:

    1
    2
    3
    4
    5
    6
    7
    8
    9

`LET i = 1 LET lim = 100 LET inc = 2 sor1: IF (i - lim) * SGN(inc) > 0 THEN sor2 ... LET i = i + inc GOTO sor1 sor2:`

A ciklusváltozónak lebegőpontos típusú változónak kell lennie. A `STEP` opcionális (ha nincs megadva, akkor 1.0), utánna a léptetés lehet egy lebegőpontos literál vagy egy másik lebegőpontos változó. A kiindulási érték és a határ lehet összetettebb kifejezés is, de azoknak is lebegőpontos számot kell visszaadniuk.

    1
    2
    3

`FOR i = (1+2+a)*3 TO 4*(5+6)/b+c STEP j ... NEXT i`

FIGYELEM

A specifikációval ellentétben, ami több változót is megenged a `NEXT` után, a MEG-4 BASIC csak egyet fogad el. Ezért ha egymásbaágyazott ciklusaid vannak, akkor több `NEXT` parancsot kell használnod, pontosan annyit, mint ahány `FOR` utasításod van.

    1
    2
    3
    4
    5

`FOR y = 1 TO 10 FOR x = 1 TO 100 ... NEXT x NEXT y`

A MEG-4 BASIC nem ismer többfajta ciklust mint például a C, de egy nem-számlálós elöltesztelős ciklus helyett írhatod ezt:

    1
    2
    3
    4
    5

`megint: IF a > 0 THEN ... GOTO megint END IF`

A hátultesztelős ciklus helyett pedig ezt:

    1
    2
    3

`megint: ... IF a > 0 THEN megint`

## Alrutinok és függvények

FONTOS

Azok az utasítások, amik nincsenek egyetlen alrutinban sem, úgy lesznek kezelve, mintha a `setup` alrutinban lennének.

A programodat feldarabolhatod kissebb programokra, amiket aztán többször is lefuttathatsz, ezeket hívjuk alrutinoknak. Ezeket `SUB` és `END SUB` közötti blokkban kell elhelyezni. Kettő ezek közül, a `setup` és a `loop` különleges jelentéssel bír, bővebben lásd a kód szerkesztő-nél. Ahogy már megjegyeztük, a MEG-4 BASIC-ben a `GOSUB` nem fogad el cimkéket, mégpedig azért, mert itt csakis ilyen alrutinneveket lehet paraméterül adni neki.

    1
    2
    3
    4
    5
    6
    7
    8

`SUB alrutinom PRINT "valami, amit többször is szeretnél lefuttatni" END SUB REM egyszer GOSUB alrutinom REM aztán mégegyszer GOSUB alrutinom`

A vezérlés a `GOSUB` sornál adódik át, és a `GOSUB` utánni sorra tér vissza, amikor `END SUB` (vagy az opcionális `RETURN`) parancshoz ér. Az alrutinok elérik a globális változókat és saját paramétereik is lehetnek.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

`SUB ott_vagyunk_már(A) IF A > 0 THEN PRINT "Nem, még nem" RETURN END IF PRINT "IGEN! Dolgok, amiker érkezéskor akartál megtenni" END SUB REM egyszer GOSUB ott_vagyunk_már(1) REM aztán mégegyszer GOSUB ott_vagyunk_már(0)`

A függvények roppant hasonlók, de ott mindenképp kell a `RETURN` és a `RETURN` utasításnak kell hogy legyen egy paramétere, méghozzá pont olyan típusú, mint amit a függvény neve jelez. A függvényeket a programodból simán a nevükkel hívhatod, zárójelben a paramétereikkel (a zárójel mindenképp kötelező, akkor is, ha nincs paramétere). Például:

    1
    2
    3
    4
    5

`FUNCTION sztringesfüggvényem$() RETURN "egy sztring" END FUNCTION LET a$ = sztringesfüggvényem$()`

## Print utasítás

    PRINT kifejezés [;|,] [kifejezés [;|,] [kifejezés [;|,]]] ...

Kiír egy vagy több kifejezést a képernyőre. Ha a kifejezések `;` kettősponttal vannak elválasztva, akkor szorosan egymásután. Ha `,` vesszővel, akkor oszlopokra tagoltan. A számok elé mindenképp kitesz egy szóközt, és ha a lista egy kifejezéssel zárul (azaz nem `;` és nem `,` az utasítás vége), akkor egy újsor karaktert is kiír a végére.

## Input utasítás

    INPUT "kérdés" [;|,] változó

Kiírja a kérdést, majd bekér egy értéket a felhasználótól, és letárolja azt a megadott változóban. Ha a kérdés és a változó `,` vesszővel van elválasztva, akkor a kérdés után egy `?` kérdőjelet is kitesz.

FIGYELEM

Az ECMA-55 specifiákció több változót is megenged, de a MEG-4 BASIC csak egyet fogad el.

## Peek és Poke

Ezekkel a parancsokkal direktben elérhető a MEG-4 memóriája, így az MMIO terület is.

Beolvasás

    változó = PEEK(cím)

Beolvassa a megadott címen lévő bájtot, lebegőpontos számmá alakítja, és elhelyezi a megadott változóban.

Például, hogy lekérdezzük, a billentyűzetsor üres-e:

    1

`IF PEEK($1A) <> PEEK($1B) THEN`
Kíírás

    POKE cím, kifejezés

Kiszámítja a kifjezés értékét, bájttá alakítja, majd azt a bájtértéket kiírja a megadott memóriacímre.

Például, hogy átállítsuk a palettát az 1-es színkód esetén:

    1
    2
    3
    4
    5
    6
    7
    8

`REM piros összetevő POKE $84, 10 REM zöld összetevő POKE $85, 10 REM kék összetevő POKE $86, 10 REM alfa (átlátszóság) POKE $87, 255`

## Elérhető függvények

Néhány MEG-4 API hívás rendszerváltozóként érhető el, `RND` (rnd), `TIME` (time), `NOW%` (now), és `INKEY$` (getc).

Néhány másik parancsként, `INPUT` (gets + val), `PRINT` (printf), `PEEK` (inb), `POKE` (outb).

Hogy megfeleljen az ECMA-55 szabványnak, két további függvény át lett nevezve: `SQR` (sqrt) és `ATN%` (atan). Ezeken kívül minden más pontosan úgy használható, ahogy ebben a dokumentációban szerepelnek, kivéve, hogy a visszatérési értékük típusának megfelelő utótagot kaptak (például az str sztringet ad vissza, ezért `STR$` lett belőle).

Fontos, hogy az ECMA-55 a trigonometrikus függvényeknél radiánt vár alapból (és egy `OPTION` paranccsal lehet fokokra váltani), de a MEG-4 API mindig fokokat használ, 0-tól 359-ig, ahol a 0 a felfele irány és 90 a jobbra. Ezért van az, hogy az `ATN%` egy egészszám típus utótagot kap például, mivel fokokat ad vissza egészszámban.

Alap esetben az olyan funkciókat, melyeknek nincs visszatérési értékük, a `GOSUB` kulcsszóval kell meghívni, azonban a MEG-4 API egy különleges eset, mert azoknál ez a kulcsszó elhagyható, és az API egy-az-egyben hívható.

ElőzőKövetkező

# Assembly

Ha ezt a nyelvet választod, akkor kezd a programodat az `#!asm` sorral.

## Példa program

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

`#!asm .data /* globális változók */ számláló: di 123 szám: df 3.1415 cím: di 0x0048C sztring: db "valami" tömb: di 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 fmt: db "a számláló %d, balshift %d\n" .code /* Induláskor lefuttatandó dolgok */ setup: /* lokális változó (igazából nem, csak helyet foglalunk a veremben) */ sp -4 ret /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ loop: /* MEG-4 stílusú kimenet */ pshci KEY_LSHIFT scall getkey sp 4 pushi ci számláló ldi pushi pshci fmt scall printf sp 12 ret`

## Leírás

Ez igazából nem egy programozási nyelv. Amikor valamelyik beépített nyelvet lefordítod, akkor a fordító olyan bájtkódot generál, amit aztán a CPU végrehajt. Az Assembly ezeknek a bájtkódoknak az egy-az-egybeni, ember számára is olvasható, szöveges mnemonik átirata. Két szekciója van, adat és kód, mindkettő cimkék és utasítások tetszőleges sorozatából áll. Az utasítás egy mnemonik opcionális paraméterrel.

Játszhatsz és kísérletezhetsz ezzel, ha bátornak érzed magad.

## Literálok

Pontosan ugyanazok, mint a MEG-4 C literáljai.

## Változók

Assemblyben nincs olyan, hogy változó. Helyette a `.data` kulcsszó indítja az adat szekciót, amibe csak adatokat pakolsz a `db` (bájt), `dw` (word, szó), `di` (integer, egészszám), `df` (float, lebegőpontos szám) utasítások paramétereként. Ebbe az adatfolyamba az utasítások elé rakhatsz címkéket, amik az adott adat címét fogják jelenteni. A betöltéshez a kód szekcióban, előbb be kell tölteni az akkumulátor regiszterbe egy ilyen címkét a `ci` utasítással, majd pedig kiadni a `ldb` (load, bájt betöltése), `ldw` (szó betöltése), `ldi` (egészszám betöltése) vagy `ldf` (lebegőpontos szám betöltése) utasítás valamelyikét. Ha az `ldb` vagy `ldw` betöltő utasításoknak nem-nulla paramétert adunk, akkor előjelesen 32 bitre kiegészítik az értéket.

## Vezérlésirányítás

Minden, ami a `.code` kulcsszó után kerül, kód lesz. Nincs vezérlésirányítás, minden utasítás sorjában, egymás után kerül végrehajtásra; kézzel kell átállítanod a PC (program counter, programszámláló) regisztert, hogy befolyásold ezt. Ehhez a `jmp` (jump, ugrás), `jz` (jump if zero, ugrás ha nulla), `jnz` (jump if not zero, ugrás ha nem nulla) vagy az `sw` (switch, esetválasztás) utasításokat használhatod.

## Függvények

Nincs olyan, hogy függvénydeklaráció. Csak megadsz egy címkét, hogy megjelöld a kód adott pontját. Hívásnál lerakod a paramétereket a verembe fordított sorrendben a `pushi` és `pushf` utasításokkal, majd a `call` mnemoniknak paraméterül ezt a címkét adod. A függvényen belül a paraméterek címét az `adr` (address, cím) utasítással lehet lekérni, aminek a paramétere a függvényparaméter sorszáma szorozva néggyel. Például `adr 0` az első függvényparaméter címét rakja az akkumulátor regiszterbe, az `adr 4` a másodikét. Visszatérni egy függvényből a `ret` utasítással lehet. A visszatérési érték az akkumulátor regiszterben adódik át, amit beállíthatsz direktben a `ci` (constant integer, egészszám konstans) és `cf` (constant float, lebegőpontos konstans) utasításokkal, illetve indirektben a `popi`, `popf`, `ldb`, `ldw`, `ldi` és `ldf` utasításokkal. Hívás után mindig a hívó fél felelőssége a paraméterek eltávolítása a veremből az `sp`+paraméterek száma szorozva néggyel utasítással.

## Elérhető függvények

Minden MEG-4 API függvény a rendelkezésedre áll; pontosan azokkal a nevekkel, ahogy ebben a leírásban szerepelnek.

Lerakod a paramétereket a verembe fordított sorrendben, majd az `scall` (system call, rendszerhívás) mnemoniknak az egyik MEG-4 API funkció nevét adod paraméterül. Hívás után mindig a hívó fél felelőssége a paraméterek eltávolítása a veremből.

## Mnemonikok

Mielőtt belemennénk a részletekbe, muszáj pár szót ejteni a MEG-4 CPU specifikációjáról.

A MEG-4 CPU egy 32 bites, kicsi elöl (little endian) CPU. Minden érték a memóriában úgy van tárolva, hogy az alacsonyabb helyiérték van az alacsonyabb címen. Képes műveleteket végezni 8 bites, 16 bites és 32 bites egészszámokkal (integer, előjeles és előjel nélküli is), valamint 32 bites lebegőpontos számokkal.

A memóriamodellje sík, ami azt jelenti, hogy minden adat elérhető egy egyszerű offszettel. Nincs lapozás se virtuális címfordítás, se szegmentálás, kivéve, hogy az adat- és kódszegmens hivatkozás implicit (azaz nem kell előtagot kiírni, a szegmensre hivatkozás automatikus).

Biztonsági okokból a kódszegmens és az adatszegmens el van különítve, akárcsak a hívásverem és az adatverem. Veremtúlcsordulásos támadás és egyéb buffertúlcsordulásos kód injektálás egyszerűen nem lehetséges ezen a CPU-n, ami különösen biztonságossá és hülyebiztossá teszi (továbbá a kódszeparálás nélkül lehetetlen lenne harmadik fél bájtkódját integrálni, lásd Lua). E tekintetben inkább Harvard architektúrájú, viszont minden másban inkább Neumann architektúrájú.

A CPU a következő regiszterekkel rendelkezik:

- AC: akkumulátor regiszter, egészszám értékkel
- AF: akkumulátor regiszter, lebegőpontos értékkel
- FLG: a processzor jelzőbitjei (setup lefutott, B/K-ra illetve időzítőre várakozik, futtatás megszakítva)
- TMR: az időzítő regiszter aktuális értéke
- DP: adatmutató (data pointer), a felhasznált globális változó memória tetejére mutat
- BP: bázismutató (base pointer), ez jelzi, hol van a függvényveremkeret teteje
- SP: veremmutató (stack pointer), ez mutatja a verem alját
- CP: hívásveremmutató (callstack pointer), a hívásverem tetejére mutat
- PC: programszámláló (program counter), ez az éppen aktuálisan végrehajtott utasításra mutat

Az adatszegmens bájt alapú, azaz a DP, BP és az SP regiszterek 8 bites egységekre mutatnak. Az adatszegmensre a `db` (8 bit), `dw` (16 bit), `di` (32 bit) és `df` (32 bit float, lebegőpontos) menmonikokkal lehet adatokat elhelyezni. Ezeknek egy vagy akár több vesszővel elválaszott paraméterük is lehet, továbbá a `db` esetén sztring literál és karakter literál is használható.

A kódszegmens felbontása 32 bit, azaz ez a legkissebb címezhető egység. Emiatt a PC ilyen 32 bites egységekre mutat és nem bájtokra. A kódszegmensre a következő mnemonikokkal lehet utasításokat elhelyezni:

Mnemonik | Paraméter | Leírás
--- | --- | ---
`debug` |  | Meghívja a beépített debuggolót (MEG-4 PRO alatt nop)
`ret` |  | Visszatérés `call` hívásból (return), kivesz a hívásveremből
`scall` | MEG-4 API funckció | Rendszerhívás (system call)
`call` | cím/kódcimke | Beteszi a pozíciót a hívásverembe, majd meghívja a függvényt
`jmp` | cím/kódcimke | Ugrás a megadott címre
`jz` | cím/kódcimke | Ugrás a megadott címre, ha az akkumulátor nulla
`jnz` | cím/kódcimke | Ugrás a megadott címre, ha az akkumulátor nem nulla
`js` | cím/kódcimke | A veremből kivett értéket előjeligazítja, és ugrik, ha negatív vagy nulla
`jns` | cím/kódcimke | A veremből kivett értéket előjeligazítja, és ugrik, ha pozitív
`sw` | szám,cím,cím0,cím1... | Esetválasztás (switch, lásd alább)
`ci` | szám/adat cimke | Egészszámot helyez az akkumulátorba
`cf` | szám | Lebegőpontos számot helyez az akkumulátorba
`bnd` | szám | Ellenőrzi, hogy az akkumulátor tartalma 0 és szám közötti-e
`lea` | szám | A DP + szám címet tölti az akkumulátorba
`adr` | szám | A BP + szám címet tölti az akkumulátorba
`sp` | szám | Hozzáadja a számot az SP regiszterhez
`pshci` | szám/adat cimke | Egészszám konstanst tol az adatverembe
`pshcf` | szám | Lebegőpontos konstanst tol az adatverembe
`pushi` |  | Az egészszám akkumulátor értékét az adatverembe tolja
`pushf` |  | Az lebegőpontos akkumulátor értékét az adatverembe tolja
`popi` |  | Kiveszi az adatverem legfelső elemét az egészszám akkumulátorba
`popf` |  | Kiveszi az adatverem legfelső elemét a lebegőpontos akkumulátorba
`cnvi` |  | Az adatverem legfelső elemét egészszámmá konvertálja
`cnvf` |  | Az adatverem legfelső elemét lebegőpontos számmá konvertálja
`ldb` | 0/1 | Az akkumulátor által mutatott adatcímről egy bájtot tölt be (előjelesre egészít, ha nem-nulla a paraméter)
`ldw` | 0/1 | Az akkumulátor által mutatott adatcímről egy szót tölt be (előjelesre egészít, ha nem-nulla a paraméter)
`ldi` |  | Az akkumulátor által mutatott adatcímről egy egészszámot tölt be
`ldf` |  | Az akkumulátor által mutatott adatcímről egy lebegőpontost tölt be
`stb` |  | Kiveszi a címet a veremből, és egy bájtot rak oda az akkumulátorból
`stw` |  | Kiveszi a címet a veremből, és egy szót rak oda az akkumulátorból
`sti` |  | Kiveszi a címet a veremből, és egy egészszámot rak oda az akkumulátorból
`stf` |  | Kiveszi a címet a veremből, és egy lebegőpontost rak oda az akkumulátorból
`incb` | szám | Kiveszi a címet a veremből, és számmal növeli a bájtot a címen
`incw` | szám | Kiveszi a címet a veremből, és számmal növeli a szót a címen
`inci` | szám | Kiveszi a címet a veremből, és számmal növeli az egészszámot a címen
`decb` | szám | Kiveszi a címet a veremből, és számmal csökkenti a bájtot a címen
`decw` | szám | Kiveszi a címet a veremből, és számmal csökkenti a szót a címen
`deci` | szám | Kiveszi a címet a veremből, és számmal csökkenti az egészszámot a címen
`not` |  | Logikai NEM művelet végzése az akkumulátoron
`neg` |  | Bitenkénti NEM művelet végzése az akkumulátoron (negálás)
`or` |  | A veremből kivett értékkel bitenkénti VAGY végzése az akkumulátoron
`xor` |  | A veremből kivett értékkel KIZÁRÓ VAGY végzése az akkumulátoron
`and` |  | A veremből kivett értékkel bitenkénti ÉS végzése az akkumulátoron
`shl` |  | A veremből kivett értéket eltolja akkumlátornyi bittel balra, az eredmény az akkumulátorba kerül
`shr` |  | A veremből kivett értéket eltolja akkumlátornyi bittel jobbra, az eredmény az akkumulátorba kerül
`eq` |  | Beállítja az akkumulátort ha veremből kivett érték egyezik az akkumulátorral
`ne` |  | Beállítja az akkumulátort ha veremből kivett érték nem egyezik az akkumulátorral
`lts` |  | Beállítja az akkumulátort ha veremből kivett érték előjelesen kissebb
`gts` |  | Beállítja az akkumulátort ha veremből kivett érték előjelesen nagyobb
`les` |  | Beállítja az akkumulátort ha veremből kivett érték előjelesen kissebb vagy egyenlő
`ges` |  | Beállítja az akkumulátort ha veremből kivett érték előjelesen nagyobb vagy egyenlő
`ltu` |  | Beállítja az akkumulátort ha veremből kivett érték előjel nélkül kissebb
`gtu` |  | Beállítja az akkumulátort ha veremből kivett érték előjel nélkül nagyobb
`leu` |  | Beállítja az akkumulátort ha veremből kivett érték előjel nélkül kissebb vagy egyenlő
`geu` |  | Beállítja az akkumulátort ha veremből kivett érték előjel nélkül nagyobb vagy egyenlő
`ltf` |  | Beállítja az akkumulátort ha veremből kivett érték lebegőpontosan kissebb
`gtf` |  | Beállítja az akkumulátort ha veremből kivett érték lebegőpontosan nagyobb
`lef` |  | Beállítja az akkumulátort ha veremből kivett érték lebegőpontosan kissebb vagy egyenlő
`gef` |  | Beállítja az akkumulátort ha veremből kivett érték lebegőpontosan nagyobb vagy egyenlő
`addi` |  | Kivesz a veremből és hozzáadja az akkumulátort, egészszámként
`subi` |  | Kivesz a veremből és kivonja belőle az akkumulátort, egészszámként
`muli` |  | Kivesz a veremből és megszorozza az akkumulátorral, egészszámként
`divi` |  | Kivesz a veremből és elosztja az akkumulátorral, egészszámként
`modi` |  | Kivesz a veremből, elosztja és a maradék az akkumulátorba kerül, egészszámként
`powi` |  | Kivesz a veremből és az akkumulátoradik hatványra emeli, egészszámként
`addf` |  | Kivesz a veremből és hozzáadja az akkumulátort, lebegőpontosként
`subf` |  | Kivesz a veremből és kivonja belőle az akkumulátort, lebegőpontosként
`mulf` |  | Kivesz a veremből és megszorozza az akkumulátorral, lebegőpontosként
`divf` |  | Kivesz a veremből és elosztja az akkumulátorral, lebegőpontosként
`modf` |  | Kivesz a veremből, elosztja és a tizedes az akkumulátorba kerül, lebegőpontosként
`powf` |  | Kivesz a veremből és az akkumulátoradik hatványra emeli, lebegőpontosként

Az `sw` mnemonik változó számú (de legalább három) paraméterrel rendelkezik. Az első paramétere egy szám, a második egy kódcimke, és a többi is mind kódcimke. Az akkumulátorból kivonja a megadott számot, majd ellenőrzi, hogy az eredmény pozitív-e és kissebb, mint a megadott cimkék száma. Ha nem, akkor a második paraméterként megadott, első cimkére ugrik. Ha igen, akkor pedig a harmadik paramétertől (második cimkétől) kezdve az akkumulátoradik cimkét veszi, és oda ugrik.

Szóval dióhéjban

    sw (érték), (cimke ahová egyébként ugrik),
      (cimke ahová ugrik ha az akkumulátor egyenlő értékkel),
      (cimke ahová ugrik ha az akkumulátor egyenlő érték + 1-el),
      (cimke ahová ugrik ha az akkumulátor egyenlő érték + 2-vel),
      (cimke ahová ugrik ha az akkumulátor egyenlő érték + 3-al),
      ...
      (cimke ahová ugrik ha az akkumulátor egyenlő érték + N-el)

Összesen 256 érték címkéje lehet minden `sw` mnemoniknak.

ElőzőKövetkező

# Lua

Ha ezt a nyelvet választod, akkor kezd a programodat a `#!lua` sorral.

## Példa program

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

`#!lua -- globális változók szamlalo = 123 szam = 3.1415 cim = 0x0048C sztring = "valami" tomb = {} -- Induláskor lefuttatandó dolgok function setup() -- lokális változók lokalisvagyok = 234 end -- Minden képkockánál lefuttatandó dolgok, 60 FPS function loop() -- Lua stílusú print print("Épp", "futok") -- MEG-4 stílusú kimenet printf("a számláló %d, balshift %d\n", szamlalo, getkey(KEY_LSHIFT)) end`

## További információk

A többi nyelvvel ellentétben ez nem szerves része a MEG-4-nek, hanem egy külsős szoftver. Emiatt nincs (és nem is lehet) tökéletesen integrálva (például nincs debuggolója és a hibaüzenetek sincsenek lefordítva). Maga a futtató a többi nyelvhez képest iszonyat lassú, de működik, használható.

A beágyazott verzió a Lua 5.4.7, több módosítással. A biztonság érdekében a nyelvből kikerült a konkurencia, valamint a dinamikus modulkezelés, fájlelérés, csővezetékek, parancsfuttatás. A `coroutine`, `io` és `os` függvénycsomagok és a függvényeik nincsenek (de a nyelv eszköztára és a baselib összes többi része továbbra is elérhető). A hiányzó táblák helyett azonban bekerült a MEG-4 API, ami ugyanúgy használható, mint a többi nyelvnél (pár apró, lényegtelen eltéréssel a jobb integráció kedvéért).

Amennyiben érdekel ez a nyelv, magyarul itt találsz róla bővebb információt, illetve a hivatalos Programming in Lua útmutató (angolul).

## API Eltérések

- memsave egyformán elfogad MEG-4 memória címet (integer) vagy Lua táblát integer számokkal (ami egy bájttömb akar lenni).
- memload híváskor mindenképp egy érvényes MEG-4 memória címet vár, de aztán Lua táblát ad vissza. Ha nem speciális MMIO területre akarsz betölteni, akkor `MEM_USER`-t (0x30000-et) adj meg, és csak használd az adatokat a visszaadott Lua táblában.
- memcpy paramétere lehet két MEG-4 memória cím, ahogy megszokott, de az egyik lehet Lua tábla is (de csak az egyik, mindkettő nem). Ezzel a funkcióval lehet adatokat másolni a MEG-4 memória és a Lua között (de az inb és az outb is működik).
- remap csak Lua táblát fogad el (amiben 256 integer számnak kell lennie).
- maze utolsó két paramétere (`numnpc` és `npc`) helyett lehet használni egy darab Lua táblát (amiben minden elem egy újabb Lua tábla).
- printf, sprintf és trace esetén nem a MEG-4 szabályait követi a formázó sztring, hanem a Lua-ét (habár e kettő majdnem teljesen ugyanaz).

ElőzőKövetkező

# Memóriatérkép

## Általános

Minden érték kicsi elöl (little endian), azaz a kissebb helyiértékű bájt van az alacsonyabb címen.

Cím | Méret | Leírás
--- | --- | ---
00000 | 1 | MEG-4 förmver verzió major (fő verzió)
00001 | 1 | MEG-4 förmver verzió minor (alverzió)
00002 | 1 | MEG-4 förmver verzió bugfix (hibajavító verzió)
00003 | 1 | performancia számláló, eltöltetlen idő 1/1000 másodpercekben
00004 | 4 | tikkszámláló, bekapcsolás óta eltelt idő 1/1000 másodpercekben
00008 | 8 | UTC unix időbélyeg
00010 | 2 | kiválaszott lokál, nyelvkód

A performancia számláló azt mutatja, a legutóbbi képkocka generálásakor mennyi idő maradt kihasználatlanul. Ha ez nulla vagy negatív, akkor az azt jelzi, mennyivel lépte túl a loop() függvényed a rendelkezésre álló időkeretet.

## Mutató

Cím | Méret | Leírás
--- | --- | ---
00012 | 2 | mutató (egér) gombok állapota (lásd getbtn és getclk)
00014 | 2 | mutató szprájt index
00016 | 2 | mutató X koordináta
00018 | 2 | mutató Y koordináta

A mutató egérgombjai a következők:

Define | Bitmaszk | Leírás
--- | --- | ---
`BTN_L` | 1 | Bal egérgomb (left)
`BTN_M` | 2 | Középső egérgomb (middle)
`BTN_R` | 4 | Jobb egérgomb (right)
`SCR_U` | 8 | Szkrollozás fel (up)
`SCR_D` | 16 | Szkrollozás le (down)
`SCR_L` | 32 | Szkrollozás balra (left)
`SCR_R` | 64 | Szkrollozás jobbra (right)

A mutató szprájt felső bitjei adják meg a kurzor eltolását: bit 13-15 Y eltolás, bit 10-12 X eltolás, bit 0-9 szprájt. Van néhány beépített, előre definiált kurzor:

Define | Érték | Leírás
--- | --- | ---
`PTR_NORM` | 03fb | Normál (nyíl) mutató
`PTR_TEXT` | 03fc | Szöveg mutató
`PTR_HAND` | 0bfd | Hivatkozás mutató
`PTR_ERR` | 93fe | Hiba történt mutató
`PTR_NONE` | ffff | Elrejti a mutatót

## Billentyűzet

Cím | Méret | Leírás
--- | --- | ---
0001A | 1 | billentyűsor farok
0001B | 1 | billentyűsor fej
0001C | 64 | billentyűsor, 16 elem, egyenként 4 bájt (lásd popkey)
0005C | 18 | lenyomott billentyű állapotok, szkenkódonként (lásd getkey)

A billentyűsorból kivett gombok UTF-8-ban vannak ábrázolva. Néhány érvénytelen UTF-8 sorozat speciális (nem-megjeleníthető) gombnak felel meg, például:

Gombkód | Leírás
--- | ---
`\x8` | A 8-as karakter, `←Backspace` gomb
`\x9` | A 9-es karakter, `Tab` gomb
`\n` | A 10-es karakter, `⏎Enter` gomb
`\x1b` | A 27-es karakter, `Esc` gomb
`Del` | A `Del` (törlés előre) gomb
`Up` | A kurzornyíl `▴` gomb
`Down` | A kurzornyíl `▾` gomb
`Left` | A kurzornyíl `◂` gomb
`Rght` | A kurzornyíl `▸` gomb
`Cut` | Kivág gomb (vagy `Ctrl`+`X`)
`Cpy` | Másol gomb (vagy `Ctrl`+`C`)
`Pst` | Beilleszt gomb (vagy `Ctrl`+`V`)

A szkenkódok a következők:

Szkenkód | Cím | Bitmaszk | Define
--- | --- | --- | ---
0 | 0005C | 1 | `KEY_CHEAT`
1 | 0005C | 2 | `KEY_F1`
2 | 0005C | 4 | `KEY_F2`
3 | 0005C | 8 | `KEY_F3`
4 | 0005C | 16 | `KEY_F4`
5 | 0005C | 32 | `KEY_F5`
6 | 0005C | 64 | `KEY_F6`
7 | 0005C | 128 | `KEY_F7`
8 | 0005D | 1 | `KEY_F8`
9 | 0005D | 2 | `KEY_F9`
10 | 0005D | 4 | `KEY_F10`
11 | 0005D | 8 | `KEY_F11`
12 | 0005D | 16 | `KEY_F12`
13 | 0005D | 32 | `KEY_PRSCR`
14 | 0005D | 64 | `KEY_SCRLOCK`
15 | 0005D | 128 | `KEY_PAUSE`
16 | 0005E | 1 | `KEY_BACKQUOTE`
17 | 0005E | 2 | `KEY_1`
18 | 0005E | 4 | `KEY_2`
19 | 0005E | 8 | `KEY_3`
20 | 0005E | 16 | `KEY_4`
21 | 0005E | 32 | `KEY_5`
22 | 0005E | 64 | `KEY_6`
23 | 0005E | 128 | `KEY_7`
24 | 0005F | 1 | `KEY_8`
25 | 0005F | 2 | `KEY_9`
26 | 0005F | 4 | `KEY_0`
27 | 0005F | 8 | `KEY_MINUS`
28 | 0005F | 16 | `KEY_EQUAL`
29 | 0005F | 32 | `KEY_BACKSPACE`
30 | 0005F | 64 | `KEY_TAB`
31 | 0005F | 128 | `KEY_Q`
32 | 00060 | 1 | `KEY_W`
33 | 00060 | 2 | `KEY_E`
34 | 00060 | 4 | `KEY_R`
35 | 00060 | 8 | `KEY_T`
36 | 00060 | 16 | `KEY_Y`
37 | 00060 | 32 | `KEY_U`
38 | 00060 | 64 | `KEY_I`
39 | 00060 | 128 | `KEY_O`
40 | 00061 | 1 | `KEY_P`
41 | 00061 | 2 | `KEY_LBRACKET`
42 | 00061 | 4 | `KEY_RBRACKET`
43 | 00061 | 8 | `KEY_ENTER`
44 | 00061 | 16 | `KEY_CAPSLOCK`
45 | 00061 | 32 | `KEY_A`
46 | 00061 | 64 | `KEY_S`
47 | 00061 | 128 | `KEY_D`
48 | 00062 | 1 | `KEY_F`
49 | 00062 | 2 | `KEY_G`
50 | 00062 | 4 | `KEY_H`
51 | 00062 | 8 | `KEY_J`
52 | 00062 | 16 | `KEY_K`
53 | 00062 | 32 | `KEY_L`
54 | 00062 | 64 | `KEY_SEMICOLON`
55 | 00062 | 128 | `KEY_APOSTROPHE`
56 | 00063 | 1 | `KEY_BACKSLASH`
57 | 00063 | 2 | `KEY_LSHIFT`
58 | 00063 | 4 | `KEY_LESS`
59 | 00063 | 8 | `KEY_Z`
60 | 00063 | 16 | `KEY_X`
61 | 00063 | 32 | `KEY_C`
62 | 00063 | 64 | `KEY_V`
63 | 00063 | 128 | `KEY_B`
64 | 00064 | 1 | `KEY_N`
65 | 00064 | 2 | `KEY_M`
66 | 00064 | 4 | `KEY_COMMA`
67 | 00064 | 8 | `KEY_PERIOD`
68 | 00064 | 16 | `KEY_SLASH`
69 | 00064 | 32 | `KEY_RSHIFT`
70 | 00064 | 64 | `KEY_LCTRL`
71 | 00064 | 128 | `KEY_LSUPER`
72 | 00065 | 1 | `KEY_LALT`
73 | 00065 | 2 | `KEY_SPACE`
74 | 00065 | 4 | `KEY_RALT`
75 | 00065 | 8 | `KEY_RSUPER`
76 | 00065 | 16 | `KEY_MENU`
77 | 00065 | 32 | `KEY_RCTRL`
78 | 00065 | 64 | `KEY_INS`
79 | 00065 | 128 | `KEY_HOME`
80 | 00066 | 1 | `KEY_PGUP`
81 | 00066 | 2 | `KEY_DEL`
82 | 00066 | 4 | `KEY_END`
83 | 00066 | 8 | `KEY_PGDN`
84 | 00066 | 16 | `KEY_UP`
85 | 00066 | 32 | `KEY_LEFT`
86 | 00066 | 64 | `KEY_DOWN`
87 | 00066 | 128 | `KEY_RIGHT`
88 | 00067 | 1 | `KEY_NUMLOCK`
89 | 00067 | 2 | `KEY_KP_DIV`
90 | 00067 | 4 | `KEY_KP_MUL`
91 | 00067 | 8 | `KEY_KP_SUB`
92 | 00067 | 16 | `KEY_KP_7`
93 | 00067 | 32 | `KEY_KP_8`
94 | 00067 | 64 | `KEY_KP_9`
95 | 00067 | 128 | `KEY_KP_ADD`
96 | 00068 | 1 | `KEY_KP_4`
97 | 00068 | 2 | `KEY_KP_5`
98 | 00068 | 4 | `KEY_KP_6`
99 | 00068 | 8 | `KEY_KP_1`
100 | 00068 | 16 | `KEY_KP_2`
101 | 00068 | 32 | `KEY_KP_3`
102 | 00068 | 64 | `KEY_KP_ENTER`
103 | 00068 | 128 | `KEY_KP_0`
104 | 00069 | 1 | `KEY_KP_DEC`
105 | 00069 | 2 | `KEY_INT1`
106 | 00069 | 4 | `KEY_INT2`
107 | 00069 | 8 | `KEY_INT3`
108 | 00069 | 16 | `KEY_INT4`
109 | 00069 | 32 | `KEY_INT5`
110 | 00069 | 64 | `KEY_INT6`
111 | 00069 | 128 | `KEY_INT7`
112 | 0006A | 1 | `KEY_INT8`
113 | 0006A | 2 | `KEY_LNG1`
114 | 0006A | 4 | `KEY_LNG2`
115 | 0006A | 8 | `KEY_LNG3`
116 | 0006A | 16 | `KEY_LNG4`
117 | 0006A | 32 | `KEY_LNG5`
118 | 0006A | 64 | `KEY_LNG6`
119 | 0006A | 128 | `KEY_LNG7`
120 | 0006B | 1 | `KEY_LNG8`
121 | 0006B | 2 | `KEY_APP`
122 | 0006B | 4 | `KEY_POWER`
123 | 0006B | 8 | `KEY_KP_EQUAL`
124 | 0006B | 16 | `KEY_EXEC`
125 | 0006B | 32 | `KEY_HELP`
126 | 0006B | 64 | `KEY_SELECT`
127 | 0006B | 128 | `KEY_STOP`
128 | 0006C | 1 | `KEY_AGAIN`
129 | 0006C | 2 | `KEY_UNDO`
130 | 0006C | 4 | `KEY_CUT`
131 | 0006C | 8 | `KEY_COPY`
132 | 0006C | 16 | `KEY_PASTE`
133 | 0006C | 32 | `KEY_FIND`
134 | 0006C | 64 | `KEY_MUTE`
135 | 0006C | 128 | `KEY_VOLUP`
136 | 0006D | 1 | `KEY_VOLDN`

## Játékpad

Cím | Méret | Leírás
--- | --- | ---
0006E | 2 | játékpad joystick határérték (alapból 8000)
00070 | 8 | elsődleges játékpad - billentyűzet szkenkód leképezések
00078 | 4 | 4 játékpad gombjainak lenyomott állapota (lásd getpad)

A játékpad gombok a következők:

Define | Bitmaszk | Leírás
--- | --- | ---
`BTN_L` | 1 | A `◁` gomb vagy joystick balra
`BTN_U` | 2 | A `△` gomb vagy joystick felfele
`BTN_R` | 4 | A `▷` gomb vagy joystick jobbra
`BTN_D` | 8 | A `▽` gomb vagy joystick lefele
`BTN_A` | 16 | Az `Ⓐ` gomb
`BTN_B` | 32 | A `Ⓑ` gomb
`BTN_X` | 64 | A `Ⓧ` gomb
`BTN_Y` | 128 | A `Ⓨ` gomb

A `△△▽▽◁▷◁▷ⒷⒶ` sorozat a `KEY_CHEAT` "gombot" jelzi lenyomottnak.

## Grafikus Feldolgozó Egység

Cím | Méret | Leírás
--- | --- | ---
0007E | 1 | UNICODE kódpont felső bájtja a glifablakhoz
0007F | 1 | szprájtbank választó a térképhez
00080 | 1024 | paletta, 256 szín, egyenként 4 bájt, RGBA
00480 | 2 | x0, vágás X kezdete pixelben (minden rajzoló funkció esetén)
00482 | 2 | x1, vágás X vége pixelben
00484 | 2 | y0, vágás Y kezdete pixelben
00486 | 2 | y1, vágás Y vége pixelben
00488 | 2 | megjelenített vram X offszetje pixelben vagy 0xffff
0048A | 2 | megjelenített vram Y offszetje pixelben vagy 0xffff
0048C | 1 | teknős farok lent állapot (lásd up, down)
0048D | 1 | teknős farok színe, paletta index 0-tól 255-ig (lásd color)
0048E | 2 | teknős irány fokokban, 0-tól 359-ig (lásd left, right)
00490 | 2 | teknős X koordináta pixelben (lásd move)
00492 | 2 | teknős Y koordináta pixelben
00494 | 2 | útvesztő haladási sebesség 1/128-ad csempében (lásd maze)
00496 | 2 | útvesztő forgási sebesség fokokban (1-től 90-ig)
00498 | 1 | konzol betűszíne, paletta index 0-tól 255-ig (lásd printf)
00499 | 1 | konzol háttérszíne, paletta index 0-tól 255-ig
0049A | 2 | konzol X koordináta pixelben
0049C | 2 | konzol Y koordináta pixelben
0049E | 2 | kamera X koordináta 3D-s térben (lásd tri3d, tritx, mesh)
004A0 | 2 | kamera Y koordináta
004A2 | 2 | kamera Z koordináta
004A4 | 2 | kamera iránya, dőlésszög (0 fel, 90 előre)
004A6 | 2 | kamera iránya, forgásszög (0 balra, 90 előre)
004A8 | 1 | kamera látószög (45 alapból, negatív ortografikus projekció)
004AA | 2 | fényforrás pozíció X koordináta (lásd tri3d, tritx, mesh)
004AC | 2 | fényforrás pozíció Y koordináta
004AE | 2 | fényforrás pozíció Z koordináta
00600 | 64000 | térkép, 320 x 200 szprájt index (lásd map és maze)
10000 | 65536 | szprájtok, 256 x 256 paletta index, 1024 8 x 8 pixel (lásd spr)
28000 | 32768 | csúszóablak 4096 betűglifhez (lásd 0007E, width és text)

## Digitális Szignálfeldolgozó Processzor

Cím | Méret | Leírás
--- | --- | ---
0007C | 1 | hullámminta bank választó (1-től 31-ig)
0007D | 1 | zenesáv bank választó (0-tól 7-ig)
004BA | 1 | aktuális tempó (soronkénti tikkszám, csak olvasható)
004BB | 1 | aktuális sáv, amit épp játszik (csak olvasható)
004BC | 2 | aktuális sor, amit épp játszik (csak olvasható)
004BE | 2 | aktuális sáv sorainak száma (csak olvasható)
004C0 | 64 | 16 csatorna státusz regisztere, egyenként 4 bájt (csak olvasható)
00500 | 256 | 64 hangeffekt, egyenként 4 bájt
20000 | 16384 | ablak a hullámmintára (lásd 0007C)
24000 | 16384 | ablak a zenesáv mintákra (lásd 0007D)

Az összes DSP státusz regiszter csak olvasható, és a csatornák regiszterei a következők:

Cím | Méret | Leírás
--- | --- | ---
0 | 2 | aktuális pozíció az épp lejátszott hullámmintában
2 | 1 | aktuális hullámminta (1-től 31-ig, 0 ha a csatorna nem szól)
3 | 1 | aktuális hangerő (0 ha a csatorna ki van kapcsolva)

Az első 4 csatorna a zenéé, a többi a hangeffekteké.

A hullámminták esetén a 0-ás index nincs tárolva, mivel azt jelenti, "használd a korábbi mintát", ezért ez nem használható a választóban. Az összes többi hullámminta formátuma:

Cím | Méret | Leírás
--- | --- | ---
0 | 2 | minták száma
2 | 2 | ismétlés kezdete
4 | 2 | ismétlés hossza
6 | 1 | finomhangolás, -8-tól 7-ig
7 | 1 | hangerő, 0-tól 64-ig
8 | 16376 | előjeles 8-bites mono minták

A hangeffektek és a zenei sávok formátuma ugyanaz, csak annyi a különbség, hogy a zenéknél 4 hangjegy van soronként, minden csatornához egy-egy és 1024 sor van összesen; míg a hangeffekteknél csak egy hangjegy van és 64 sor.

Cím | Méret | Leírás
--- | --- | ---
0 | 1 | hangjegy, lásd `NOTE_x` defineok, 0-tól 96-ig
1 | 1 | hullámminta index, 0-tól 31-ig
2 | 1 | effekt típusa, 0-tól 255-ig (lásd hangjegyeffektek)
3 | 1 | effekt paraméter

A hangjegy sorszáma a következő: a 0 azt jelenti, nincs beállítva. A többi pedig 8 oktávonként 12 érték, azaz az 1-es a C-0, 12-es a B-0 (a legmélyebb oktávon), 13-as a C-1 (egy oktávval magasabb), a 14-es pedig a C#1 (cisz, fél hanggal magasabb). A D hang a 4. oktávon tehát 1 + 4*12 + 2 = 51. A B-7 a 96-os, a legmagasabb hang a legmagasabb oktávon. De vannak define-ok hozzájuk, például a C-1 a `NOTE_C_1` és a C#1 az `NOTE_Cs1`, ha nem akarsz számolni, akkor használhatod ezeket is a programodban.

## Hangjegyeffektek

Az egyszerűség kedvéért a MEG-4 ugyanazokat az effektkódokat használja, mint az Amiga MOD fájlok (így ugyanazt látod a beépített zeneszerkesztőben mint egy külsős trackerben), de nem támogatja az összeset. Mint korábban említettük, ezek a kódok három hexa számból állnak, az első a típus `t`, az utolsó kettő pedig a paraméter, `xy` (vagy `xx`). Az `E1`-től `ED`-ig mind a típus bájtban van tárolva, annak ellenére, hogy úgy látszik, egy tetrádja a paraméterbe lóg, pedig nem is.

Effekt | Kód | Leírás
--- | --- | ---
... | 000 | Nincs effekt
Arp | 0xy | Arpeggio, játszd le a hangot, hang+x, hang+y félhangot is
Po/ | 1xx | Portamento fel, periódus csúsztatása x-el felfelé
Po\ | 2xx | Portamento le, periódus csúsztatása x-el lefelé
Ptn | 3xx | Tone portamento, periódus csúsztatása x-re
Vib | 4xy | Vibrato, y félhanggal oszcillálja a magasságot x freken
Ctv | 5xy | Tone portamento folyt. + hangerőcsúsztatás x fel vagy y le
Cvv | 6xy | Vibrato folyt. + hangerőcsúsztatás x fel vagy y le
Trm | 7xy | Tremolo, y amplitudóval oszcillálja a hangerőt x freken
Ofs | 9xx | Hanghullám minta kezdjen x * 256 pozíción
Vls | Axy | Hangerőcsúsztatás x fel vagy y le
Jmp | Bxx | Pozícióugrás, a x * 64 -dik sorra
Vol | Cxx | Hangerő beállítása x-re (0 és 64 közötti)
Fp/ | E1x | Finom portamento fel, periódus növelése x-el
Fp\ | E2x | Finom portamento le, periódus csökkentése x-el
Svw | E4x | Vibrato hullámtípusa, 0 szinusz, 1 fűrész, 2 négyzet, 3 zaj
Ftn | E5x | Finomhangolás, tunningolás beállítása x-re (-8-tól 7-ig)
Stw | E7x | Tremolo hullámtípusa, 0 szinusz, 1 fűrész, 2 négyzet, 3 zaj
Rtg | E9x | Hang újrázás, a hullám újrakezdése x tikkenként
Fv/ | EAx | Finom hangerő csúsztatás felfelé, x-el
Fv\ | EBx | Finom hangerő csúsztatás lefelé, x-el
Cut | ECx | Hang elvágása x tikknél
Dly | EDx | Hang késleltetése x tikkel
Tpr | Fxx | Soronkénti tikkszám beállítása x-re (alapból 6)

## Felhasználói memória

A 00000-tól 2FFFF-ig terjedő memóriacímek az MMIO-é, minden más fölötte (a 30000 címtől avagy `MEM_USER`-tól kezdve) szabadon hasznosítható felhasználói memória.

Cím | Méret | Leírás
--- | --- | ---
30000 | 4 | (csak BASIC) a DATA címe
30004 | 4 | (csak BASIC) aktulális READ számláló
30008 | 4 | (csak BASIC) maximum READ számláló, DATA elemszáma

Ezt követi a globális változók blokkja, amiket a programodban deklaráltál, azt pedig a konstansok, mint például a sztring literálok. A BASIC nyelv esetén ezután jönnek a tényleges DATA rekordok.

Az inicializált adatok feletti memóriacímeket dinamikusan allokálhatod és felszabadíthatod a programodból a malloc és free hívásokkal.

Végezetül pedig a verem, a memória legtetején (a C0000-ás címtől avagy `MEM_LIMIT`-től kezdődően), ami lefele növekszik. A programod lokális változói (amiket függvényeken belül deklaráltál) ide kerülnek. A verem mérete folyton változik, attól függően, hogy épp melyik függvény hív melyik másik függvényt a programodban.

Amennyiben a dinamikusan allokált memória teteje és a verem alja összeérne, akkor a MEG-4 egy "Nincs elég memória" hibaüzenetet dob.

## Formázó sztring

Néhány függvény, a printf, sprintf és a trace formázó sztringet használ, amiben speciális karakterek lehetnek, amik a paraméterekre hivatkoznak és előírják, hogyan kell azokat megjeleníteni. Ezek a következők:

Kód | Leírás
--- | ---
`%%` | A `%` karakter maga
`%d` | A soronkövetkező paramétert decimális számként írja ki
`%u` | A soronkövetkező paramétert pozitív számként írja ki
`%x` | A soronkövetkező paramétert hexadecimális számként írja ki
`%o` | A soronkövetkező paramétert oktális számként írja ki
`%b` | A soronkövetkező paramétert bináris számként írja ki
`%f` | A soronkövetkező paramétert lebegőpontos számként írja ki
`%s` | A soronkövetkező paramétert sztringként kell kiírni
`%c` | A soronkövetkező paramétert UTF-8 karakterként kell kiírni
`%p` | A soronkövetkező paramétert címként írja ki (pointer)
`\t` | Tab, igazítsd vízszintesen a pozíciót kiírás előtt
`\n` | Kezd új sorban a kiírást

Megadható kitöltés a `%` és a kód közötti méret megadásával. Ha ez `0`-val kezdődik, akkor nullával tölt ki, egyébként szóközzel. Például a `%4d` jobbra fogja igazítani az értéket szóközökkel, míg a `%04x` nullákkal teszi ezt. Az `f` elfogad pontot és egy számot utána, ami a tizedesjegyek számát adja meg (egészen 8-ig), például `%.6f`.

## 3D-s Tér

MEG-4 alatt a 3 dimenziós tér a jobbkéz szabály szerint van értelmezve: +X van jobbra, +Y felfelé, és a +Z pedig a néző felé.

      +Y
       |
       |__ +X
      /
    +Z

Minden pont a -32767 és +32767 közé esik. Hogy ez a 3D-s világ hogyan képeződik le a 2D-s képernyődre, az azon múlik, hogy hogyan állítottad be a kamerát (lásd Grafikus Feldolgozó Egység 0049E-as cím). Természetesen meg kell mondanod az X, Y és Z koordináták megadásával, hol van a kamera a világban. Aztán meg kell azt is adni, merre néz, a dőlésszöggel és a fordulási szöggel. Végezetül meg kell adni a lencse típusát a látószöggel (field of view, FOV). Ez utóbbi általában 30 (nagyon szűk) és 180 fok (mint a halak vagy madarak) közé esik. A MEG-4 127 fokig kezeli ezt, de van egy trükk. A pozitív FOV értékek perspektivikusan lesznek leképezve (minnél távolabbi egy tárgy, annál kissebb), de negatív értéket is elfogad, ami viszont ortografikus leképezést jelent (nem számít a távolság, a tárgy mindig ugyanakkora). A perspektívát az FPS játékok használják, míg az ortografikus leképezést általában a stratégiai játékok részesítik előnyben.

Több háromszög együtt (teljes 3D-s modell) hatékonyan jeleníthető meg a mesh funkcióval. Mivel a modellek valószínűleg lokális koordinátákban vannak megadva, ezért ez minden modellt egymásra rajzol az origó körül. Ha több modellt is szeretnél megjeleníteni a világban, ezért azokat először transzformálni kell (el kell helyezni) a világ koordinátáira a trns hívásával, és a transzformált vertex halmazt kell a mesh-nek megadni (a forgatás és az áthelyezés nem változtatja meg a háromszögeket, csak a koordinátáikat).

## Kód Szerkesztő gyorsbillentyűk

A szokásos billentyűzet kombinációkon túl a forráskód szerkesztéskor elérhető még:

Billentyű | Leírás
--- | ---
`Ctrl`+`F` | Sztring keresése
`Ctrl`+`G` | Következő keresése
`Ctrl`+`H` | Keresés és csere (a kijelöltben, vagy ha az nincs, akkor az egész forrásban)
`Ctrl`+`J` | Megadott sorra ugrás
`Ctrl`+`D` | Funkció definíciójához ugrás
`Ctrl`+`N` | Könyvjelzők listája
`Ctrl`+`B` | Könyvjelző ki/bekapcsolása az aktuális soron
`Ctrl`+`▴` | Előző könyvjelzőhöz ugrás
`Ctrl`+`▾` | Következő könyvjelzőhöz ugrás
`Ctrl`+`◂` | Ugrás az előző szó elejére
`Ctrl`+`▸` | Ugrás a következő szó végére
`Ctrl`+`,` | Behúzás csökkentése a kijelölt területen
`Ctrl`+`.` | Behúzás növelése a kijelölt területen
`Home` | Kurzor mozgatása a sor elejére
`End` | Kurzor mozgatása a sor végége
`PgUp` | Kurzor mozgatása 42 sorral (egy oldallal) feljebb
`PgDown` | Kurzor mozgatása 42 sorral (egy oldallal) lejjebb
`F1` | Ha a kurzor egy API paraméterlistáján áll, akkor az a funkció súgójára visz

A platform billentyűzetkiosztásától függetlenül, minden programozáshoz szükséges karakter (és még pár) mindig elérhető:

Bal `Alt` +
`` `(` `)` `{` `}` `〈` `〉` `!` `^` `_` `-` `=`
`⇥` `` `` `€` `₹` `~` `¥` `` `` `°` `"` `[` `]`
`↨` `&` `$` `@` `¦` `` `#` `` `` `£` `;` `'` `\`
`⇮` `:` `?` `` `元` `%` `+` `✶` `,` `.` `/`

Lásd még a menüben a további alternatív beviteli módokat és azok gyorsbillentyűit.

ElőzőKövetkező

# Konzol

## putc

    1

`void putc(uint32_t chr)`

Leírás
  Kiír egy karaktert a képernyőre.
Paraméterek

  Paraméter | Leírás
  --- | ---
  chr | UTF-8 karakter

## printf

    1

`void printf(str_t fmt, ...)`

Leírás
  Kiír egy szöveget a képernyőre.
Paraméterek

  Paraméter | Leírás
  --- | ---
  fmt | megjelenítendő formázó sztring
  ... | opcionális paraméterek

## getc

    1

`uint32_t getc(void)`

Leírás
  Beolvas egy karaktert a konzolról, blokkolódik, ha nincs mit.
Visszatérési érték
  Egy UTF-8 karakter, amit a felhasználó leütött.
Lásd még
  popkey

## gets

    1

`str_t gets(void)`

Leírás
  Bekér egy újsor karakterrel lezárt szöveget a felhasználótól (az újsor karaktert nem adja vissza).
Visszatérési érték
  A beolvasott bájtok egy sztringben.

## trace

    1

`void trace(str_t fmt, ...)`

Leírás
  A futás jelzése a kimenetre való írással. Csak akkor működik, ha a `meg4` a `-v` kapcsolóval lett indítva.
Paraméterek

  Paraméter | Leírás
  --- | ---
  fmt | formázó sztring
  ... | opcionális paraméterek

## delay

    1

`void delay(uint16_t msec)`

Leírás
  Késlelteti a programod végrehajtását.
Paraméterek

  Paraméter | Leírás
  --- | ---
  msec | késleltetés ezredmásodpercekben

## exit

    1

`void exit(void)`

Leírás
  Kilép a programból.

ElőzőKövetkező

# Audió

## sfx

    1

`void sfx(uint8_t sfx, uint8_t channel, uint8_t volume)`

Leírás
  Lejátszik egy hangeffektet.
Paraméterek

  Paraméter | Leírás
  --- | ---
  sfx | a hangeffekt indexe, 0-tól 63-ig
  channel | használni kívánt csatorna, 0-tól 11-ig
  volume | hangerő, 0-tól 255-ig, 0 kikapcsolja a csatornát

## music

    1

`void music(uint8_t track, uint16_t row, uint8_t volume)`

Leírás
  Lejátszik egy zenesávot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  track | a zenesáv indexe, 0-tól 7-ig
  row | amelyik sortól kezdve kell lejátszani, 0-tól 1023-ig (max sávhossz)
  volume | hangerő, 0-tól 255-ig, 0 kikapcsolja a zenét

ElőzőKövetkező

# GPIO

## gpio_rev

    1

`uint32_t gpio_rev(void)`

Leírás
  Lekérdezi a GPIO board revíziós számát. 0-át ad vissza, ha a platformon nincs GPIO.
Visszatérési érték
  Board revíziós szám, vagy 0 ha nem támogatott.

## gpio_get

    1

`int gpio_get(uint8_t pin)`

Leírás
  Kiolvassa egy GPIO tüske értékét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  pin | fizikai tüske száma, 1-től 40-ig

Visszatérési érték
  1-el tér vissza, ha a tüske magas, 0-ával ha alacsony, -1 ha hiba történt (a GPIO tüske nem támogatott).
Lásd még
  gpio_set

## gpio_set

    1

`int gpio_set(uint8_t pin, int value)`

Leírás
  Beállítja egy GPIO tüske értékét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  pin | fizikai tüske száma, 1-től 40-ig
  value | 1 magasra kapcsolja a tüskét, 0 alacsonyra.

Visszatérési érték
  0-val tér vissza, ha sikeres volt, -1-el hiba esetén (a GPIO tüske nem támogatott).
Lásd még
  gpio_get

ElőzőKövetkező

# Grafika

## cls

    1

`void cls(uint8_t palidx)`

Leírás
  Törli a képernyőt és alaphelyzetbe állítja a megjelenítő ablakát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig

Lásd még
  pget, pset

## cget

    1

`uint32_t cget(uint16_t x, uint16_t y)`

Leírás
  Kiolvassa a megadott koordinátán lévő pixelt, és RGBA színt ad vissza.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben

Visszatérési érték
  Egy csomagolt színkód, RGBA csatornákkal (piros a legalacsonyabb bájtban).
Lásd még
  cls, pget, pset

## pget

    1

`uint8_t pget(uint16_t x, uint16_t y)`

Leírás
  Kiolvassa a megadott koordinátán lévő pixelt, és paletta indexet ad vissza.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben

Visszatérési érték
  Szín paletta indexe, 0-tól 255-ig.
Lásd még
  cls, pset, cget

## pset

    1

`void pset(uint8_t palidx, uint16_t x, uint16_t y)`

Leírás
  Kirak egy pixelt a megadott koordinátára.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x | X koordináta pixelben
  y | Y koordináta pixelben

Lásd még
  cls, pget

## width

    1

`uint16_t width(int8_t type, str_t str)`

Leírás
  Visszaadja a megjelenítendő szöveg szélességét pixelekben.
Paraméterek

  Paraméter | Leírás
  --- | ---
  type | betűtípus, -4-től 4-ig
  str | megmérendő sztring

Visszatérési érték
  A szöveg megjelenítéshez szükséges pixelek száma.
Lásd még
  text

## text

    1

`void text(uint8_t palidx, int16_t x, int16_t y, int8_t type, uint8_t shidx, uint8_t sha, str_t str)`

Leírás
  Szöveget ír ki a képernyőre.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x | X koordináta pixelben
  y | Y koordináta pixelben
  type | betűtípus, -4-től -1-ig monospace, 1-től 4-ig proporcionális
  shidx | árnyék színe, paletta index 0-tól 255-ig
  sha | árnyék átlátszósága, 0-tól (teljesen átlátszó) 255-ig (semennyire)
  str | megjelenítendő sztring

Lásd még
  width

## line

    1

`void line(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)`

Leírás
  Húz egy anti-aliasolt vonalat.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | induló X koordináta pixelekben
  y0 | induló Y koordináta pixelekben
  x1 | vége X koordináta pixelekben
  y1 | vége Y koordináta pixelekben

Lásd még
  qbez, cbez

## qbez

    1
    2

`void qbez(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t cx, int16_t cy)`

Leírás
  Négyzetes (quadratic) Bezier ív húzása.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | induló X koordináta pixelekben
  y0 | induló Y koordináta pixelekben
  x1 | vége X koordináta pixelekben
  y1 | vége Y koordináta pixelekben
  cx | kontrollpont X koordináta pixelekben
  cy | kontrollpont Y koordináta pixelekben

Lásd még
  line, cbez

## cbez

    1
    2

`void cbez(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t cx0, int16_t cy0, int16_t cx1, int16_t cy1)`

Leírás
  Köbös (cubic) Bezier ív húzása.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | induló X koordináta pixelekben
  y0 | induló Y koordináta pixelekben
  x1 | vége X koordináta pixelekben
  y1 | vége Y koordináta pixelekben
  cx0 | első kontrollpont X koordinátája pixelekben
  cy0 | első kontrollpont Y koordinátája pixelekben
  cx1 | második kontrollpont X koordinátája pixelekben
  cy1 | második kontrollpont Y koordinátája pixelekben

Lásd még
  line, qbez

## tri

    1

`void tri(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)`

Leírás
  Kirajzol egy háromszöget.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | első csúcs X koordináta pixelekben
  y0 | első csúcs Y koordináta pixelekben
  x1 | második csúcs X koordináta pixelekben
  y1 | második csúcs Y koordináta pixelekben
  x2 | harmadik csúcs X koordináta pixelekben
  y2 | harmadik csúcs Y koordináta pixelekben

Lásd még
  ftri, tri2d, tri3d, tritx, mesh, trns

## ftri

    1

`void ftri(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)`

Leírás
  Kirajzol egy kitöltött háromszöget.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | első csúcs X koordináta pixelekben
  y0 | első csúcs Y koordináta pixelekben
  x1 | második csúcs X koordináta pixelekben
  y1 | második csúcs Y koordináta pixelekben
  x2 | harmadik csúcs X koordináta pixelekben
  y2 | harmadik csúcs Y koordináta pixelekben

Lásd még
  tri, tri2d, tri3d, tritx, mesh, trns

## tri2d

    1
    2
    3

`void tri2d(uint8_t pi0, int16_t x0, int16_t y0, uint8_t pi1, int16_t x1, int16_t y1, uint8_t pi2, int16_t x2, int16_t y2)`

Leírás
  Kirajzol egy kitöltött háromszöget színátmenetekkel.
Paraméterek

  Paraméter | Leírás
  --- | ---
  pi0 | első csúcs színe, paletta index 0-tól 255-ig
  x0 | első csúcs X koordináta pixelekben
  y0 | első csúcs Y koordináta pixelekben
  pi1 | második csúcs színe, paletta index 0-tól 255-ig
  x1 | második csúcs X koordináta pixelekben
  y1 | második csúcs Y koordináta pixelekben
  pi2 | harmadik csúcs színe, paletta index 0-tól 255-ig
  x2 | harmadik csúcs X koordináta pixelekben
  y2 | harmadik csúcs Y koordináta pixelekben

Lásd még
  tri, ftri, tri3d, tritx, mesh, trns

## tri3d

    1
    2
    3

`void tri3d(uint8_t pi0, int16_t x0, int16_t y0, int16_t z0, uint8_t pi1, int16_t x1, int16_t y1, int16_t z1, uint8_t pi2, int16_t x2, int16_t y2, int16_t z2)`

Leírás
  Kirajzol egy háromszöget színátmenetekkel 3D-s térben.
Paraméterek

  Paraméter | Leírás
  --- | ---
  pi0 | első csúcs színe, paletta index 0-tól 255-ig
  x0 | első csúcs X koordináta a térben
  y0 | első csúcs Y koordináta a térben
  z0 | első csúcs Z koordináta a térben
  pi1 | második csúcs színe, paletta index 0-tól 255-ig
  x1 | második csúcs X koordináta a térben
  y1 | második csúcs Y koordináta a térben
  z1 | második csúcs Z koordináta a térben
  pi2 | harmadik csúcs színe, paletta index 0-tól 255-ig
  x2 | harmadik csúcs X koordináta a térben
  y2 | harmadik csúcs Y koordináta a térben
  z2 | harmadik csúcs Z koordináta a térben

Lásd még
  tri, ftri, tri2d, tritx, mesh, trns

## tritx

    1
    2
    3

`void tritx(uint8_t u0, uint8_t v0, int16_t x0, int16_t y0, int16_t z0, uint8_t u1, uint8_t v1, int16_t x1, int16_t y1, int16_t z1, uint8_t u2, uint8_t v2, int16_t x2, int16_t y2, int16_t z2)`

Leírás
  Kirajzol egy textúrázott háromszöget 3D-s térben.
Paraméterek

  Paraméter | Leírás
  --- | ---
  u0 | első csúcs textúra X koordináta, 0-tól 255-ig
  v0 | első csúcs textúra Y koordináta, 0-tól 255-ig
  x0 | első csúcs X koordináta a térben
  y0 | első csúcs Y koordináta a térben
  z0 | első csúcs Z koordináta a térben
  u0 | második csúcs textúra X koordináta, 0-tól 255-ig
  v0 | második csúcs textúra Y koordináta, 0-tól 255-ig
  x1 | második csúcs X koordináta a térben
  y1 | második csúcs Y koordináta a térben
  z1 | második csúcs Z koordináta a térben
  u0 | harmadik csúcs textúra X koordináta, 0-tól 255-ig
  v0 | harmadik csúcs textúra Y koordináta, 0-tól 255-ig
  x2 | harmadik csúcs X koordináta a térben
  y2 | harmadik csúcs Y koordináta a térben
  z2 | harmadik csúcs Z koordináta a térben

Lásd még
  tri, ftri, tri2d, tri3d, mesh, trns

## mesh

    1

`void mesh(addr_t verts, addr_t uvs, uint16_t numtri, addr_t tris)`

Leírás
  Kirajzol egy modellt a 3D-s térben háromszögekből, indexált pontok és textúra koordináták (vagy paletta) használatával.
Paraméterek

  Paraméter | Leírás
  --- | ---
  verts | vertex pontok tömbjének címe, egyenként 3 x 2 bájt, X, Y, Z
  uvs | UV pontok tömbjének címe (ha 0, akkor palettát használ), egyenként 2 x 1 bájt, textúra X, Y
  numtri | háromszögek száma
  tris | háromszögek, indexeket tartalmazó tömb címe, egyenként 6 x 1 bájt, vi1, ui1/pi1, vi2, ui2/pi2, vi3, ui3/pi3

Lásd még
  tri, ftri, tri2d, tri3d, tritx, trns

## rect

    1

`void rect(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)`

Leírás
  Kirajzol egy téglalapot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | bal felső sarok X koordináta pixelekben
  y0 | bal felső sarok Y koordináta pixelekben
  x1 | jobb alsó sarok X koordináta pixelekben
  y1 | jobb alsó sarok Y koordináta pixelekben

Lásd még
  frect

## frect

    1

`void frect(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)`

Leírás
  Kirajzol egy kitöltött téglalapot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | bal felső sarok X koordináta pixelekben
  y0 | bal felső sarok Y koordináta pixelekben
  x1 | jobb alsó sarok X koordináta pixelekben
  y1 | jobb alsó sarok Y koordináta pixelekben

Lásd még
  rect

## circ

    1

`void circ(uint8_t palidx, int16_t x, int16_t y, uint16_t r)`

Leírás
  Kirajzol egy kört.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x | középpont X koordináta pixelekben
  y | középpont Y koordináta pixelekben
  r | sugár pixelekben

Lásd még
  fcirc, ellip, fellip

## fcirc

    1

`void fcirc(uint8_t palidx, int16_t x, int16_t y, uint16_t r)`

Leírás
  Kirajzol egy kitöltött kört.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x | középpont X koordináta pixelekben
  y | középpont Y koordináta pixelekben
  r | sugár pixelekben

Lásd még
  circ, ellip, fellip

## ellip

    1

`void ellip(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)`

Leírás
  Kirajzol egy ellipszist.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | bal felső sarok X koordináta pixelekben
  y0 | bal felső sarok Y koordináta pixelekben
  x1 | jobb alsó sarok X koordináta pixelekben
  y1 | jobb alsó sarok Y koordináta pixelekben

Lásd még
  circ, fcirc, fellip

## fellip

    1

`void fellip(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)`

Leírás
  Kirajzol egy kitöltött ellipszist.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig
  x0 | bal felső sarok X koordináta pixelekben
  y0 | bal felső sarok Y koordináta pixelekben
  x1 | jobb alsó sarok X koordináta pixelekben
  y1 | jobb alsó sarok Y koordináta pixelekben

Lásd még
  circ, fcirc, ellip

## move

    1

`void move(int16_t x, int16_t y, uint16_t deg)`

Leírás
  Elhelyezi a teknőst a képernyőn vagy az útvesztőben.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben (vagy 1/128-ad csempében maze esetén)
  y | Y koordináta pixelben
  deg | irány fokokban, 0-tól 359-ig, 0 fok felfele van, 90 fok jobbra

Lásd még
  left, right, up, down, color, forw, back

## left

    1

`void left(uint16_t deg)`

Leírás
  Balra forgatja a teknőst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  deg | változás fokokban, 0-tól 359-ig

Lásd még
  move, right, up, down, color, forw, back

## right

    1

`void right(uint16_t deg)`

Leírás
  Jobbra forgatja a teknőst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  deg | változás fokokban, 0-tól 359-ig

Lásd még
  move, left, up, down, color, forw, back

## up

    1

`void up(void)`

Leírás
  Felemeli a teknős farkát. Ezután a teknős úgy mozog, hogy nem húz vonalat.
Lásd még
  move, left, right, down, color, forw, back

## down

    1

`void down(void)`

Leírás
  Leteszi a teknős farkát. Ezután amikor a teknős mozog, vonalat húz (lásd color).
Lásd még
  move, left, right, up, color, forw, back

## color

    1

`void color(uint8_t palidx)`

Leírás
  Beállítja a teknős farkának színét, amikor a teknős mozog, ilyen színű vonalat húz maga után.
Paraméterek

  Paraméter | Leírás
  --- | ---
  palidx | szín, paletta index 0-tól 255-ig

Lásd még
  move, left, right, up, down, forw, back

## forw

    1

`void forw(uint16_t cnt)`

Leírás
  Előre mozgatja a teknőst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  cnt | mennyit, pixelekben (vagy 1/128-ad csempében maze esetén)

Lásd még
  move, left, right, up, down, color, back

## back

    1

`void back(uint16_t cnt)`

Leírás
  Hátra mozgatja a teknőst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  cnt | mennyit, pixelekben (vagy 1/128-ad csempében maze esetén)

Lásd még
  move, left, right, up, down, color, forw

## spr

    1

`void spr(int16_t x, int16_t y, uint16_t sprite, uint8_t sw, uint8_t sh, int8_t scale, uint8_t type)`

Leírás
  Megjelenít egy, vagy akár több, egymásmelletti szprájtot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben
  sprite | szprájt index, 0-tól 1023-ig
  sw | vízszintes szprájtok száma
  sh | függőleges szprájtok száma
  scale | nagyítás, -3-tól 4-ig
  type | típus, 0=normális, 1=forg. 90, 2=forg. 180, 3=forg. 270, 4=függőleges tükrözés, 6=tükr.+90, 5=vízszintes tükr., 7=tükr.+270

Lásd még
  dlg, stext

## dlg

    1
    2
    3
    4

`void dlg(int16_t x, int16_t y, uint16_t w, uint16_t h, int8_t scale, uint16_t tl, uint16_t tm, uint16_t tr, uint16_t ml, uint16_t bg, uint16_t mr, uint16_t bl, uint16_t bm, uint16_t br)`

Leírás
  Megjelenít egy dialógusablakot szprájtok használatával.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben
  w | dialógusablak szélessége pixelekben
  h | dialógusablak magassága pixelekben
  scale | nagyítás, -3-tól 4-ig
  tl | bal felső sarok szprájt id
  tm | középső felső szprájt id
  tr | jobb felső sarok szprájt id
  ml | középső bal oldal szprájt id
  bg | háttér szprájt id
  mr | középső jobb oldal szprájt id
  bl | bal alsó sarok szprájt id
  bm | középső alsó szprájt id
  br | jobb alsó sarok szprájt id

Lásd még
  spr, stext

## stext

    1

`void stext(int16_t x, int16_t y, uint16_t fs, uint16_t fu, uint8_t sw, uint8_t sh, int8_t scale, str_t str)`

Leírás
  Szöveg megjelenítése a képernyőn szprájtok használatával.
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben
  fs | az első megjelenítendő szprájt indexe
  fu | az első UNICODE (legkissebb lehetséges karakter) a sztringben
  sw | vízszintes szprájtok száma
  sh | függőleges szprájtok száma
  scale | nagyítás, -3-tól 4-ig
  str | nullával lezárt UTF-8 sztring

Lásd még
  spr, dlg

## remap

    1

`void remap(addr_t replace)`

Leírás
  Lecseréli a csempéket a térképen. Használható arra, hogy meganimáljuk a térképet.
Paraméterek

  Paraméter | Leírás
  --- | ---
  replace | egy 256 elemű, szprájt idkat tartalmazó tömb

Lásd még
  mget, mset, map, maze

## mget

    1

`uint16_t mget(uint16_t mx, uint16_t my)`

Leírás
  Visszaadja a térkép egy csempéjét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  mx | X térképkoordináta csempékben
  my | Y térképkoordináta csempékben

Visszatérési érték
  A megadott koordinátán lévő szprájt indexe.
Lásd még
  remap, mset, map, maze

## mset

    1

`void mset(uint16_t mx, uint16_t my, uint16_t sprite)`

Leírás
  Beállítja a térkép egy csempéjét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  mx | X térképkoordináta csempékben
  my | Y térképkoordináta csempékben
  sprite | szprájt index, 0-tól 1023-ig

Lásd még
  remap, mget, map, maze

## map

    1

`void map(int16_t x, int16_t y, uint16_t mx, uint16_t my, uint16_t mw, uint16_t mh, int8_t scale)`

Leírás
  Kirajzolja a térképet (vagy egy részét).
Paraméterek

  Paraméter | Leírás
  --- | ---
  x | X koordináta pixelben
  y | Y koordináta pixelben
  mx | X térképkoordináta csempékben
  my | Y térképkoordináta csempékben
  mw | vízszintes csempék száma
  mh | függőleges csempék száma
  scale | nagyítás, -3-tól 4-ig

Lásd még
  remap, mget, mset, maze

## maze

    1
    2

`void maze(uint16_t mx, uint16_t my, uint16_t mw, uint16_t mh, uint8_t scale, uint16_t sky, uint16_t grd, uint16_t door, uint16_t wall, uint16_t obj, uint8_t numnpc, addr_t npc)`

Leírás
  A teknőc pozícióját használva 3D-s útvesztőként jeleníti meg a térképet.
Paraméterek

  Paraméter | Leírás
  --- | ---
  mx | X térképkoordináta csempékben
  my | Y térképkoordináta csempékben
  mw | vízszintes csempék száma
  mh | függőleges csempék száma
  scale | csempénkénti szprájtszám kettő hatványban, 0-tól 3-ig
  sky | ég csempe index
  grd | föld csempe index
  door | első ajtó csempe indexe
  wall | első fal csempe indexe
  obj | első tárgy csempe indexe
  numnpc | NJK rekordok száma
  npc | uint32_t tömb, numnpc darab x,y,csempe index hármas

Lásd még
  remap, mget, mset, map

ElőzőKövetkező

# Bemenet

## getpad

    1

`int getpad(int pad, int btn)`

Leírás
  Visszaadja az egyik játékpad egy gombjának állapotát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  pad | játékpad index, 0-tól 3-ig
  btn | az egyik játékpad gomb, `BTN_`

Visszatérési érték
  Nulla ha nincs lenyomva, nem nulla ha le van nyomva.
Lásd még
  prspad, relpad, getbtn, getclk, getkey

## prspad

    1

`int prspad(int pad, int btn)`

Leírás
  Igaz értékkel tér vissza, ha a legutóbbi hívás óta le lett nyomva a játékpad gombja (press).
Paraméterek

  Paraméter | Leírás
  --- | ---
  pad | játékpad index, 0-tól 3-ig
  btn | az egyik játékpad gomb, `BTN_`

Visszatérési érték
  Nulla ha nem lett lenyomva, nem nulla ha le lett nyomva.
Lásd még
  relpad, getpad, getbtn, getclk, getkey

## relpad

    1

`int relpad(int pad, int btn)`

Leírás
  Igaz értékkel tér vissza, ha a legutóbbi hívás óta fel lett engedve a játékpad gombja (release).
Paraméterek

  Paraméter | Leírás
  --- | ---
  pad | játékpad index, 0-tól 3-ig
  btn | az egyik játékpad gomb, `BTN_`

Visszatérési érték
  Nulla ha nem lett felengedve, nem nulla ha fel lett engedve.
Lásd még
  prspad, getpad, getbtn, getclk, getkey

## getbtn

    1

`int getbtn(int btn)`

Leírás
  Visszaadja az egyik egérgomb állapotát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  btn | az egyik mutató gomb, `BTN_` vagy `SCR_`

Visszatérési érték
  Nulla ha nincs lenyomva, nem nulla ha le van nyomva.
Lásd még
  prspad, relpad, getpad, getclk, getkey

## getclk

    1

`int getclk(int btn)`

Leírás
  Visszaadja az egérgomb kattintást (click).
Paraméterek

  Paraméter | Leírás
  --- | ---
  btn | az egyik mutató gomb, `BTN_`

Visszatérési érték
  Nulla ha nem kattintottak vele, nem nulla ha volt kattinttás.
Lásd még
  prspad, relpad, getpad, getbtn, getkey

## getkey

    1

`int getkey(int sc)`

Leírás
  Visszaadja az egyik billentyű állapotát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  sc | szkenkód, 1-től 144-ig, lásd billentyűzet

Visszatérési érték
  Nulla ha nincs lenyomva, nem nulla ha le van nyomva.
Lásd még
  prspad, relpad, getpad, getbtn, getclk

## popkey

    1

`uint32_t popkey(void)`

Leírás
  Visszaadja a következő UTF-8 gombot a billentyűsorból. Lásd billentyűzet.
Visszatérési érték
  A gomb UTF-8 reprezentációja, vagy 0 ha a sor üres volt.
Lásd még
  pendkey, lenkey, speckey

## pendkey

    1

`int pendkey(void)`

Leírás
  Igaz értékkel tér vissza, ha legalább egy billentyű várakozik a sorban (de benthagyja a sorban, nem veszi ki).
Visszatérési érték
  1 ha van kiolvasatlan billentyű a sorban, egyébként 0 ha a sor üres.
Lásd még
  popkey, lenkey, speckey

## lenkey

    1

`int lenkey(uint32_t key)`

Leírás
  Visszaadja egy UTF-8 gomb hosszát bájtokban.
Paraméterek

  Paraméter | Leírás
  --- | ---
  key | a gomb, ahogy a billentyűsorból kijött

Visszatérési érték
  UTF-8 reprezentáció hossza bájtokban.
Lásd még
  popkey, pendkey, speckey

## speckey

    1

`int speckey(uint32_t key)`

Leírás
  Igaz értékkel tér vissza, ha a gomb speciális.
Paraméterek

  Paraméter | Leírás
  --- | ---
  key | a gomb, ahogy a billentyűsorból kijött

Visszatérési érték
  1 ha a gomb speciális, és 0 ha megjeleníthető.
Lásd még
  popkey, pendkey, lenkey

ElőzőKövetkező

# Matematika

## rand

    1

`uint32_t rand(void)`

Leírás
  Véletlenszám. A `%` modulo használatával méretezhető, például `1 + rand() % 6` 1 és 6 között ad vissza értéket, mint a dobókocka.
Visszatérési érték
  Egy véletlen szám 0 és 232-1 (4294967295) között.
Lásd még
  rnd

## rnd

    1

`float rnd(void)`

Leírás
  Véletlenszám. Ugyanaz, mint a rand, csak lebegőpontos számot ad vissza.
Visszatérési érték
  Egy véletlen szám 0.0 és 1.0 között.
Lásd még
  rand

## float

    1

`float float(int val)`

Leírás
  Egy egészszám lebegőpontos alakját adja vissza.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Lebegőpontos szám.
Lásd még
  int

## int

    1

`int int(float val)`

Leírás
  Egy lebegőpontos szám egészszám alakos változatát adja vissza.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Egészszám.
Lásd még
  float

## floor

    1

`float floor(float val)`

Leírás
  Visszaadja a legnagyobb olyan egész lebegőpontos számot, ami még kissebb a megadottnál.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  A szám lefele kerekítve.
Lásd még
  ceil

## ceil

    1

`float ceil(float val)`

Leírás
  Visszaadja a legkissebb olyan egész lebegőpontos számot, ami már nagyobb a megadottnál.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  A szám felfele kerekítve.
Lásd még
  floor

## sgn

    1

`float sgn(float val)`

Leírás
  Visszaadja a szám előjelét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Vagy 1.0 vagy -1.0.
Lásd még
  abs

## abs

    1

`float abs(float val)`

Leírás
  Visszaadja a lebegőpontos szám abszolút értékét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Vagy az érték, vagy -érték, mindig pozitív.
Lásd még
  sgn

## exp

    1

`float exp(float val)`

Leírás
  Visszaadja az érték exponenciálisát, azaz a természetes alapú logaritmus értékedik hatványát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Az eval értéke.
Lásd még
  log, pow

## log

    1

`float log(float val)`

Leírás
  Visszaadja az érték természetes alapú logaritmusát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  A val természetes alapú logaritmusa.
Lásd még
  exp

## pow

    1

`float pow(float val, float exp)`

Leírás
  Visszaadja egy szám hatványát. Ez nagyon lassú, próbáld elkerülni a használatát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték
  exp | kitevő

Visszatérési érték
  A valexp értéke.
Lásd még
  exp, sqrt, rsqrt

## sqrt

    1

`float sqrt(float val)`

Leírás
  Visszaadja egy szám négyzetgyökét. Ez nagyon lassú, próbáld elkerülni a használatát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Az érték négyzetgyöke.
Lásd még
  pow, rsqrt

## rsqrt

    1

`float rsqrt(float val)`

Leírás
  Visszaadja egy szám négyzetgyökének reciprokát (1/sqrt(val)). John Carmack féle gyors metódust használ.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték

Visszatérési érték
  Az érték négyzetgyökének reciproka.
Lásd még
  pow, sqrt

## clamp

    1

`float clamp(float val, float minv, float maxv)`

Leírás
  Lecsípi (klimpeli) a megadott értéket két határérték közé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték
  minv | minimum érték
  maxv | maximum érték

Visszatérési érték
  Klimpelt érték.
Lásd még
  clampv2, clampv3, clampv4

## lerp

    1

`float lerp(float a, float b, float t)`

Leírás
  Lineárisan interpolál két érték között.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | első lebegőpontos érték
  b | második lebegőpontos érték
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  lerpv2, lerpv3, lerpv4, lerpq, slerpq

## pi

    1

`float pi(void)`

Leírás
  Visszaadja a π értékét lebegőpontos számként.
Visszatérési érték
  A 3.14159265358979323846 érték.

## cos

    1

`float cos(uint16_t deg)`

Leírás
  Visszaadja a koszinuszt.
Paraméterek

  Paraméter | Leírás
  --- | ---
  deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra

Visszatérési érték
  A fok koszinusza, -1.0 és 1.0 közötti érték.
Lásd még
  sin, tan, acos, asin, atan, atan2

## sin

    1

`float sin(uint16_t deg)`

Leírás
  Visszaadja a szinuszt.
Paraméterek

  Paraméter | Leírás
  --- | ---
  deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra

Visszatérési érték
  A fok szinusza, -1.0 és 1.0 közötti érték.
Lásd még
  cos, tan, acos, asin, atan, atan2

## tan

    1

`float tan(uint16_t deg)`

Leírás
  Visszaadja a tangenst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra

Visszatérési érték
  A fok tangense, -1.0 és 1.0 közötti érték.
Lásd még
  cos, sin, acos, asin, atan, atan2

## acos

    1

`uint16_t acos(float val)`

Leírás
  Visszaadja az arkuszkoszinuszt.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték, -1.0 és 1.0 között

Visszatérési érték
  Arkuszkoszinusz fokokban, 0-tól 359-ig, 0 felfele, 90 jobbra.
Lásd még
  cos, sin, tan, asin, atan, atan2

## asin

    1

`uint16_t asin(float val)`

Leírás
  Visszaadja az arkuszszinuszt.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték, -1.0 és 1.0 között

Visszatérési érték
  Arkuszszinusz fokokban, 0-tól 359-ig, 0 felfele, 90 jobbra.
Lásd még
  cos, sin, tan, acos, atan, atan2

## atan

    1

`uint16_t atan(float val)`

Leírás
  Visszaadja az arkusztangenst.
Paraméterek

  Paraméter | Leírás
  --- | ---
  val | érték, -1.0 és 1.0 között

Visszatérési érték
  Arkusztangens fokokban, 0-tól 359-ig, 0 felfele, 90 jobbra.
Lásd még
  cos, sin, tan, acos, asin, atan2

## atan2

    1

`uint16_t atan2(float y, float x)`

Leírás
  Visszaadja y/x arkusztangensét, figyelembe véve az y és x előjelét a kvadráns meghatározásánál.
Paraméterek

  Paraméter | Leírás
  --- | ---
  y | Y koordináta
  x | X koordináta

Visszatérési érték
  Arkusztangens fokokban, 0-tól 359-ig, 0 felfele, 90 jobbra.
Lásd még
  cos, sin, tan, acos, asin

## dotv2

    1

`float dotv2(addr_t a, addr_t b)`

Leírás
  Kiszámolja a kételemű vektorok skaláris szorzatát (dot product).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | két float címe
  b | két float címe

Visszatérési érték
  A vektorok skaláris szorzata.
Lásd még
  lenv2, scalev2, negv2, addv2, subv2, mulv2, divv2, clampv2, lerpv2, normv2

## lenv2

    1

`float lenv2(addr_t a)`

Leírás
  Kiszámítja a kételemű vektor hosszát. Ez nagyon lassú, próbáld elkerülni a használatát (lásd normv2).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | két float címe

Visszatérési érték
  A vektor hossza.
Lásd még
  dotv2, scalev2, negv2, addv2, subv2, mulv2, divv2, clampv2, lerpv2, normv2

## scalev2

    1

`void scalev2(addr_t a, float s)`

Leírás
  Atméretezi a kételemű vektort (skálázás, skalárral szorzás).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | két float címe
  s | skálázó érték

Lásd még
  dotv2, lenv2, negv2, addv2, subv2, mulv2, divv2, clampv2, lerpv2, normv2

## negv2

    1

`void negv2(addr_t a)`

Leírás
  Negálja a kételemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | két float címe

Lásd még
  dotv2, lenv2, scalev2, addv2, subv2, mulv2, divv2, clampv2, lerpv2, normv2

## addv2

    1

`void addv2(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összead két kételemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  a | két float címe
  b | két float címe

Lásd még
  dotv2, lenv2, scalev2, negv2, subv2, mulv2, divv2, clampv2, lerpv2, normv2

## subv2

    1

`void subv2(addr_t dst, addr_t a, addr_t b)`

Leírás
  Kivon két kételemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  a | két float címe
  b | két float címe

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, mulv2, divv2, clampv2, lerpv2, normv2

## mulv2

    1

`void mulv2(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két kételemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  a | két float címe
  b | két float címe

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, subv2, divv2, clampv2, lerpv2, normv2

## divv2

    1

`void divv2(addr_t dst, addr_t a, addr_t b)`

Leírás
  Eloszt két kételemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  a | két float címe
  b | két float címe

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, subv2, mulv2, clampv2, lerpv2, normv2

## clampv2

    1

`void clampv2(addr_t dst, addr_t v, addr_t minv, addr_t maxv)`

Leírás
  Lecsípi (klimpeli) a megadott kételemű vektort két határérték közé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  v | két float címe, bemeneti érték
  minv | két float címe, minimum
  maxv | két float címe, maximum

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, subv2, mulv2, divv2, lerpv2, normv2

## lerpv2

    1

`void lerpv2(addr_t dst, addr_t a, addr_t b, float t)`

Leírás
  Lineárisan interpolál két kételemű vektor között.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | két float címe (kimenet)
  a | két float címe
  b | két float címe
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, subv2, mulv2, divv2, clampv2, normv2

## normv2

    1

`void normv2(addr_t a)`

Leírás
  Normalizálja a kételemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | két float címe

Lásd még
  dotv2, lenv2, scalev2, negv2, addv2, subv2, mulv2, divv2, clampv2, lerpv2

## dotv3

    1

`float dotv3(addr_t a, addr_t b)`

Leírás
  Kiszámolja a háromelemű vektorok skaláris szorzatát (dot product).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | három float címe
  b | három float címe

Visszatérési érték
  A vektorok skaláris szorzata.
Lásd még
  lenv3, scalev3, negv3, addv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## lenv3

    1

`float lenv3(addr_t a)`

Leírás
  Kiszámítja a háromelemű vektor hosszát. Ez nagyon lassú, próbáld elkerülni a használatát (lásd normv3).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | három float címe

Visszatérési érték
  A vektor hossza.
Lásd még
  dotv3, scalev3, negv3, addv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## scalev3

    1

`void scalev3(addr_t a, float s)`

Leírás
  Atméretezi a háromelemű vektort (skálázás, skalárral szorzás).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | három float címe
  s | skálázó érték

Lásd még
  dotv3, lenv3, negv3, addv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## negv3

    1

`void negv3(addr_t a)`

Leírás
  Negálja a háromelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | három float címe

Lásd még
  dotv3, lenv3, scalev3, addv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## addv3

    1

`void addv3(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összead két háromelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## subv3

    1

`void subv3(addr_t dst, addr_t a, addr_t b)`

Leírás
  Kivon két háromelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, mulv3, divv3, crossv3, clampv3, lerpv3, normv3

## mulv3

    1

`void mulv3(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két háromelemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, divv3, crossv3, clampv3, lerpv3, normv3

## divv3

    1

`void divv3(addr_t dst, addr_t a, addr_t b)`

Leírás
  Eloszt két háromelemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, mulv3, crossv3, clampv3, lerpv3, normv3

## crossv3

    1

`void crossv3(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két háromelemű vektort (cross product, keresztszorzat, vektoriális szorzat).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, mulv3, divv3, clampv3, lerpv3, normv3

## clampv3

    1

`void clampv3(addr_t dst, addr_t v, addr_t minv, addr_t maxv)`

Leírás
  Lecsípi (klimpeli) a megadott háromelemű vektort két határérték közé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  v | három float címe, bemeneti érték
  minv | három float címe, minimum
  maxv | három float címe, maximum

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, mulv3, divv3, crossv3, lerpv3, normv3

## lerpv3

    1

`void lerpv3(addr_t dst, addr_t a, addr_t b, float t)`

Leírás
  Lineárisan interpolál két háromelemű vektor között.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  a | három float címe
  b | három float címe
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, mulv3, divv3, crossv3, clampv3, normv3

## normv3

    1

`void normv3(addr_t a)`

Leírás
  Normalizálja a háromelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | három float címe

Lásd még
  dotv3, lenv3, scalev3, negv3, addv3, subv3, mulv3, divv3, crossv3, clampv3, lerpv3

## dotv4

    1

`float dotv4(addr_t a, addr_t b)`

Leírás
  Kiszámolja a négyelemű vektorok skaláris szorzatát (dot product).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe
  b | négy float címe

Visszatérési érték
  A vektorok skaláris szorzata.
Lásd még
  lenv4, scalev4, negv4, addv4, subv4, mulv4, divv4, clampv4, lerpv4, normv4

## lenv4

    1

`float lenv4(addr_t a)`

Leírás
  Kiszámítja a négyelemű vektor hosszát. Ez nagyon lassú, próbáld elkerülni a használatát (lásd normv4).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Visszatérési érték
  A vektor hossza.
Lásd még
  dotv4, scalev4, negv4, addv4, subv4, mulv4, divv4, clampv4, lerpv4, normv4

## scalev4

    1

`void scalev4(addr_t a, float s)`

Leírás
  Atméretezi a négyelemű vektort (skálázás, skalárral szorzás).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe
  s | skálázó érték

Lásd még
  dotv4, lenv4, negv4, addv4, subv4, mulv4, divv4, clampv4, lerpv4, normv4

## negv4

    1

`void negv4(addr_t a)`

Leírás
  Negálja a négyelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Lásd még
  dotv4, lenv4, scalev4, addv4, subv4, mulv4, divv4, clampv4, lerpv4, normv4

## addv4

    1

`void addv4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összead két négyelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  dotv4, lenv4, scalev4, negv4, subv4, mulv4, divv4, clampv4, lerpv4, normv4

## subv4

    1

`void subv4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Kivon két négyelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, mulv4, divv4, clampv4, lerpv4, normv4

## mulv4

    1

`void mulv4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két négyelemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, subv4, divv4, clampv4, lerpv4, normv4

## divv4

    1

`void divv4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Eloszt két négyelemű vektort (lineáris kombináció).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, subv4, mulv4, clampv4, lerpv4, normv4

## clampv4

    1

`void clampv4(addr_t dst, addr_t v, addr_t minv, addr_t maxv)`

Leírás
  Lecsípi (klimpeli) a megadott négyelemű vektort két határérték közé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  v | négy float címe, bemeneti érték
  minv | négy float címe, minimum
  maxv | négy float címe, maximum

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, subv4, mulv4, divv4, lerpv4, normv4

## lerpv4

    1

`void lerpv4(addr_t dst, addr_t a, addr_t b, float t)`

Leírás
  Lineárisan interpolál két négyelemű vektor között.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, subv4, mulv4, divv4, clampv4, normv4

## normv4

    1

`void normv4(addr_t a)`

Leírás
  Normalizálja a négyelemű vektort.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Lásd még
  dotv4, lenv4, scalev4, negv4, addv4, subv4, mulv4, divv4, clampv4, lerpv4

## idq

    1

`void idq(addr_t a)`

Leírás
  Betölti az identitás kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Lásd még
  eulerq, dotq, lenq, scaleq, negq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## eulerq

    1

`void eulerq(addr_t dst, uint16_t pitch, uint16_t yaw, uint16_t roll)`

Leírás
  Betölt egy Euler-szögekkel megadott kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  pitch | dőlésszög, X tengely körüli forgatás fokokban, 0-tól 359-ig
  yaw | forgásszög, Y tengely körüli forgatás fokokban, 0-tól 359-ig
  roll | pörgésszög, Z tengely körüli forgatás fokokban, 0-tól 359-ig

Lásd még
  idq, dotq, lenq, scaleq, negq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## dotq

    1

`float dotq(addr_t a, addr_t b)`

Leírás
  Kiszámolja a kvaternió skaláris szorzatát (dot product).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe
  b | négy float címe

Visszatérési érték
  A kvaternió skaláris szorzata.
Lásd még
  idq, eulerq, lenq, scaleq, negq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## lenq

    1

`float lenq(addr_t a)`

Leírás
  Kiszámítja a kvaternió hosszát. Ez nagyon lassú, próbáld elkerülni a használatát (lásd normq).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Visszatérési érték
  A kvaternió hossza.
Lásd még
  idq, eulerq, dotq, scaleq, negq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## scaleq

    1

`void scaleq(addr_t a, float s)`

Leírás
  Atméretezi a kvaterniót (skálázás, skalárral szorzás).
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe
  s | skálázó érték

Lásd még
  idq, eulerq, dotq, lenq, negq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## negq

    1

`void negq(addr_t a)`

Leírás
  Negálja a kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, addq, subq, mulq, rotq, lerpq, slerpq, normq

## addq

    1

`void addq(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összead két kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, subq, mulq, rotq, lerpq, slerpq, normq

## subq

    1

`void subq(addr_t dst, addr_t a, addr_t b)`

Leírás
  Kivon két kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, mulq, rotq, lerpq, slerpq, normq

## mulq

    1

`void mulq(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két kvaterniót (vektoriális szorzat).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, subq, rotq, lerpq, slerpq, normq

## rotq

    1

`void rotq(addr_t dst, addr_t q, addr_t v)`

Leírás
  Összeszoroz egy kvaterniót egy háromelemű forgatási vektorral.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  q | négy float címe
  v | három float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, subq, mulq, lerpq, slerpq, normq

## lerpq

    1

`void lerpq(addr_t dst, addr_t a, addr_t b, float t)`

Leírás
  Lineárisan interpolál két kvaternió között.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, subq, mulq, rotq, slerpq, normq

## slerpq

    1

`void slerpq(addr_t dst, addr_t a, addr_t b, float t)`

Leírás
  Gömbfelületen interpolál két kvaternió között (spherical).
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  a | négy float címe
  b | négy float címe
  t | interpoláció értéke 0.0 és 1.0 között

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, subq, mulq, rotq, lerpq, normq

## normq

    1

`void normq(addr_t a)`

Leírás
  Normalizálja a kvaterniót.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | négy float címe

Lásd még
  idq, eulerq, dotq, lenq, scaleq, negq, addq, subq, mulq, rotq, lerpq, slerpq

## idm4

    1

`void idm4(addr_t a)`

Leírás
  Betölti a 4 x 4-es identitás mátrixot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | 16 float címe

Lásd még
  trsm4, detm4, addm4, subm4, mulm4, mulm4v3, mulm4v4, invm4, trpm4

## trsm4

    1

`void trsm4(addr_t dst, addr_t t, addr_t r, addr_t s)`

Leírás
  Létrehoz egy 4 x 4-es transzformációs mátrixot eltolás, forgatás és nagyítás adatokból.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe, a kimeneti mátrix
  t | három float címe, az eltolás vektor (translation)
  r | négy float címe, a forgatási kvaternió (rotation)
  s | három float címe, a nagyítási vektor (scaling)

Lásd még
  idm4, detm4, addm4, subm4, mulm4, mulm4v3, mulm4v4, invm4, trpm4

## detm4

    1

`float detm4(addr_t a)`

Leírás
  Visszaadja a mátrix determinánsát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  a | 16 float címe

Visszatérési érték
  A mátrix determinánsa.
Lásd még
  idm4, trsm4, addm4, subm4, mulm4, mulm4v3, mulm4v4, invm4, trpm4

## addm4

    1

`void addm4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összead két mátrixot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe (kimenet)
  a | 16 float címe
  b | 16 float címe

Lásd még
  idm4, trsm4, detm4, subm4, mulm4, mulm4v3, mulm4v4, invm4, trpm4

## subm4

    1

`void subm4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Kivon két mátrixot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe (kimenet)
  a | 16 float címe
  b | 16 float címe

Lásd még
  idm4, trsm4, detm4, addm4, mulm4, mulm4v3, mulm4v4, invm4, trpm4

## mulm4

    1

`void mulm4(addr_t dst, addr_t a, addr_t b)`

Leírás
  Összeszoroz két mátrixot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe (kimenet)
  a | 16 float címe
  b | 16 float címe

Lásd még
  idm4, trsm4, detm4, addm4, subm4, mulm4v3, mulm4v4, invm4, trpm4

## mulm4v3

    1

`void mulm4v3(addr_t dst, addr_t m, addr_t v)`

Leírás
  Összeszoroz egy háromelemű vektort egy mátrixszal.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | három float címe (kimenet)
  m | 16 float címe
  v | három float címe

Lásd még
  idm4, trsm4, detm4, addm4, subm4, mulm4, mulm4v4, invm4, trpm4

## mulm4v4

    1

`void mulm4v4(addr_t dst, addr_t m, addr_t v)`

Leírás
  Összeszoroz egy négyelemű vektort egy mátrixszal.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | négy float címe (kimenet)
  m | 16 float címe
  v | négy float címe

Lásd még
  idm4, trsm4, detm4, addm4, subm4, mulm4, mulm4v3, invm4, trpm4

## invm4

    1

`void invm4(addr_t dst, addr_t a)`

Leírás
  Kiszámítja a mátrix inverzét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe (kimenet)
  a | 16 float címe

Lásd még
  idm4, trsm4, detm4, addm4, subm4, mulm4, mulm4v3, mulm4v4, trpm4

## trpm4

    1

`void trpm4(addr_t dst, addr_t a)`

Leírás
  Transzponálja a mátrixot.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | 16 float címe (kimenet)
  a | 16 float címe

Lásd még
  idm4, trsm4, detm4, addm4, subm4, mulm4, mulm4v3, mulm4v4, invm4

## trns

    1
    2
    3
    4

`void trns(addr_t dst, addr_t src, uint8_t num, int16_t x, int16_t y, int16_t z, uint16_t pitch, uint16_t yaw, uint16_t roll, float scale)`

Leírás
  Transzformálja a vertex halmazt, azaz elhelyezi a 3D-s modellt a 3D-s térben.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél vertex pontok tömbjének címe, egyenként 3 x 2 bájt, X, Y, Z
  src | forrás vertex pontok tömbjének címe, egyenként 3 x 2 bájt, X, Y, Z
  num | vertex koordinátahármasok száma a tömbben
  x | világ X koordináta, -32767-tól 32767-ig
  y | világ Y koordináta, -32767-tól 32767-ig
  z | világ Z koordináta, -32767-tól 32767-ig
  pitch | dőlésszög, X tengely körüli forgatás fokokban, 0-tól 359-ig
  yaw | forgásszög, Y tengely körüli forgatás fokokban, 0-tól 359-ig
  roll | pörgésszög, Z tengely körüli forgatás fokokban, 0-tól 359-ig
  scale | átméretezés, használj 1.0-t az eredeti méret megtartásához

Lásd még
  mesh

ElőzőKövetkező

# Memória

## inb

    1

`uint8_t inb(addr_t src)`

Leírás
  Beolvas egy bájtot a memóriából.
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | cím, 0x00000-tól 0xBFFFF-ig

Visszatérési érték
  Visszaadja az értéket az adott címről.

## inw

    1

`uint16_t inw(addr_t src)`

Leírás
  Beolvas egy szót (word, 2 bájt) a memóriából.
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | cím, 0x00000-tól 0xBFFFE-ig

Visszatérési érték
  Visszaadja az értéket az adott címről.

## ini

    1

`uint32_t ini(addr_t src)`

Leírás
  Beolvas egy egészszámot (integer, 4 bájt) a memóriából.
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | cím, 0x00000-tól 0xBFFFC-ig

Visszatérési érték
  Visszaadja az értéket az adott címről.

## outb

    1

`void outb(addr_t dst, uint8_t value)`

Leírás
  Kiír egy bájtot a memóriába.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cím, 0x00000-tól 0xBFFFF-ig
  value | beállítandó érték, 0-tól 255-ig

## outw

    1

`void outw(addr_t dst, uint16_t value)`

Leírás
  Kiír egy szót (word, 2 bájt) a memóriába.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cím, 0x00000-tól 0xBFFFE-ig
  value | beállítandó érték, 0-tól 65536-ig

## outi

    1

`void outi(addr_t dst, uint32_t value)`

Leírás
  Kiír egy egészszámot (integer, 4 bájt) a memóriába.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cím, 0x00000-tól 0xBFFFC-ig
  value | beállítandó érték, 0-tól 4294967295-ig

## memsave

    1

`int memsave(uint8_t overlay, addr_t src, uint32_t size)`

Leírás
  Elmenti a megadott memória tartalmát egy átfedőbe.
Paraméterek

  Paraméter | Leírás
  --- | ---
  overlay | cél átfedő indexe, 0-tól 255-ig
  src | elmentendő memória címe, 0x00000-tól 0xBFFFF-ig
  size | elmentendő bájtok száma

Visszatérési érték
  1-et ad vissza ha sikerült, 0-át hiba esetén.
Lásd még
  memload

## memload

    1

`int memload(addr_t dst, uint8_t overlay, uint32_t maxsize)`

Leírás
  Betölti egy átfedő tartalmát a memória megadott címére.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél memória terület címe, 0x00000-tól 0xBFFFF-ig
  overlay | betöltendő átfedő indexe, 0-tól 255-ig
  maxsize | betöltendő bájtok maximális száma

Visszatérési érték
  Visszaadja, hogy hány bájtot töltött végül be (ami lehet kevesebb, mint a maxsize).
Lásd még
  memsave

## memcpy

    1

`void memcpy(addr_t dst, addr_t src, uint32_t len)`

Leírás
  Memóriaterületek másolása.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél címe, 0x00000-tól 0xBFFFF-ig
  src | forrás címe, 0x00000-tól 0xBFFFF-ig
  len | átmásolandó bájtok száma

## memset

    1

`void memset(addr_t dst, uint8_t value, uint32_t len)`

Leírás
  Memóriaterület feltöltése adott bájttal.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél címe, 0x00000-tól 0xBFFFF-ig
  value | beállítandó érték, 0-tól 255-ig
  len | beállítandó bájtok száma

## memcmp

    1

`int memcmp(addr_t addr0, addr_t addr1, uint32_t len)`

Leírás
  Két memóriaterület összehasonlítása.
Paraméterek

  Paraméter | Leírás
  --- | ---
  addr0 | első cím, 0x00000-tól 0xBFFFF-ig
  addr1 | második cím, 0x00000-tól 0xBFFFF-ig
  len | összehasonlítandó bájtok száma

Visszatérési érték
  Visszaadja a különbséget, azaz 0-át, ha a két terület tartalma megegyezik.

## deflate

    1

`int deflate(addr_t dst, addr_t src, uint32_t len)`

Leírás
  Betömörít (összezsugorít) egy adatbuffert RFC1950 deflate (zlib) használatával.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél címe, 0x30000-tól 0xBFFFF-ig
  src | forrás címe, 0x30000-tól 0xBFFFF-ig
  len | tömörítendő bájtok száma

Visszatérési érték
  0 vagy negatív hiba esetén, egyébként a betömörített bájtok száma és a betömörített adat a dst-ben.
Lásd még
  inflate

## inflate

    1

`int inflate(addr_t dst, addr_t src, uint32_t len)`

Leírás
  Kitömörít (felfúj) egy RFC1950 deflate (zlib) tömörített buffert.
Paraméterek

  Paraméter | Leírás
  --- | ---
  dst | cél címe, 0x30000-tól 0xBFFFF-ig
  src | forrás címe, 0x30000-tól 0xBFFFF-ig
  len | betömörített bájtok száma

Visszatérési érték
  0 vagy negatív hiba esetén, egyébként a kitömörített bájtok száma és a kitömörített adat a dst-ben.
Lásd még
  deflate

## time

    1

`float time(void)`

Leírás
  Visszaadja a bekapcsolás óta eltelt tikkek számát.
Visszatérési érték
  A bekapcsolás óta eltelt idő ezredmásodpercekben.
Lásd még
  now

## now

    1

`uint32_t now(void)`

Leírás
  Visszaadja a UNIX időbélyeget. A 0000C címen lévő bájttal ellenőrizheted, hogy túlcsordult-e.
Visszatérési érték
  A greenwichi középidő szerinti 1970. január 1.-e éjfél óta eltelt másodpercek száma.
Lásd még
  time

## atoi

    1

`int atoi(str_t src)`

Leírás
  Egy ASCII decimális számot alakít át egészszámmá.
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | sztring címe, 0x00000-tól 0xBFFFF-ig

Visszatérési érték
  A sztringbeli szám egészszám megfelelője.
Lásd még
  itoa, str, val

## itoa

    1

`str_t itoa(int value)`

Leírás
  Egy egésszámot alakít ASCII decimális karaktersorozattá, sztringé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  value | az érték, -2147483648-tól 2147483647-ig

Visszatérési érték
  A szám sztringbe kiírt változata.
Lásd még
  atoi, str, val

## val

    1

`float val(str_t src)`

Leírás
  Egy ASCII decimális számot alakít át lebegőpontos számmá.
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | sztring címe, 0x00000-tól 0xBFFFF-ig

Visszatérési érték
  A sztringbeli szám lebegőpontos szám megfelelője.
Lásd még
  itoa, atoi, str

## str

    1

`str_t str(float value)`

Leírás
  Egy lebegőpontos számot alakít ASCII decimális karaktersorozattá, sztringé.
Paraméterek

  Paraméter | Leírás
  --- | ---
  value | a szám

Visszatérési érték
  A szám sztringbe kiírt változata.
Lásd még
  atoi, itoa, val

## sprintf

    1

`str_t sprintf(str_t fmt, ...)`

Leírás
  Kigenerál egy nullával lezárt, UTF-8 sztringet a megadott formázás és paraméterek alapján.
Paraméterek

  Paraméter | Leírás
  --- | ---
  fmt | formázó sztring
  ... | opcionális paraméterek

Visszatérési érték
  A megformázott sztring.

## strlen

    1

`int strlen(str_t src)`

Leírás
  Visszaadja, mennyi bájtból áll a sztring (a lezáró nulla nélkül).
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | sztring címe, 0x00000-tól 0xBFFFF-ig

Visszatérési érték
  A sztringben lévő bájtok száma.
Lásd még
  mblen

## mblen

    1

`int mblen(str_t src)`

Leírás
  Visszaadja, mennyi UTF-8 multibájt karakterből áll a sztring (a lezáró nulla nélkül).
Paraméterek

  Paraméter | Leírás
  --- | ---
  src | sztring címe, 0x00000-tól 0xBFFFF-ig

Visszatérési érték
  A sztringben lévő karakterek száma.
Lásd még
  strlen

## malloc

    1

`addr_t malloc(uint32_t size)`

Leírás
  Dinamikusan lefoglalja a memória egy részét.
Paraméterek

  Paraméter | Leírás
  --- | ---
  size | lefoglalandó bájtok száma

Visszatérési érték
  Az újonnan allokált buffer címe, vagy NULL hiba esetén.
Lásd még
  realloc, free

## realloc

    1

`addr_t realloc(addr_t addr, uint32_t size)`

Leírás
  Átméretez egy korábban lefoglalt buffert.
Paraméterek

  Paraméter | Leírás
  --- | ---
  addr | az allokált buffer címe
  size | bájtok száma, amire átméretez

Visszatérési érték
  Az újonnan allokált buffer címe, vagy NULL hiba esetén.
Lásd még
  malloc, free

## free

    1

`int free(addr_t addr)`

Leírás
  Felszabadítja a dinamikusan lefoglalt memóriát.
Paraméterek

  Paraméter | Leírás
  --- | ---
  addr | az allokált buffer címe

Visszatérési érték
  1 siker esetén, 0 ha hiba történt.
Lásd még
  malloc, realloc

ElőzőKövetkező

# Pattogó labda

Ebben a példában egy olyan programot fogunk készíteni, ami egy labdát pattogtat a képernyőn.

## Labda megjelenítése

Először is indítsuk el a `meg4` programot, és hozzuk be a Szprájt szerkesztőt (üsd le az `F3`-at). Válasszuk ki az első szprájtot szerkesztésre jobbra, és rajzoljuk meg a labdát a bal oldali szerkesztőben.

A labda megrajzolása

Most menjünk a Kód szerkesztőbe (üsd le az `F2`-őt). Elsőre a programunk egy üres váz lesz.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ }`

Jelenítsük meg az újonnan rajzolt szprájtunkat! Ezt az spr hívással tehetjük meg. Menjünk a `setup()` függvény törzsébe, kezdjük el beírni, és alul a státuszsorban megjelennek a paraméterei.

Láthatjuk, hogy az első két paraméter az `x, y`, a képernyő koordináta, ahová ki akarjuk rakni a szprájtot (ha nem lenne egyértelmű a paraméter nevéből, hogy mit takar, akkor az `F1` leütésével bejön a súgó részletes leírással, majd ott `Esc`-et ütve visszakerülsz ide a kódszerkesztésre). A képernyő 320 pixel széles és 200 pixel magas, ezért ha középre akarjuk elhelyezni, adjunk meg a `160, 100` értékeket. A következő paraméter a `sprite`. Mivel a legelső, nulladik szprájtra rajzoltunk, ezért ez `0`. Az ezt követő paraméterek az `sw` (szprájt szélesség) és `sh` (szprájt magasság). Mivel a labdánk csupán egyetlen szprájtba belefér, azért írjunk `1, 1`-et. Ezt követi a `scale` (átméretezés), de nem szeretnénk felnagyítani, így ide is írjunk csak `1`-et. Végül az utolsó paraméter a `type` (megjelenés típusa), amivel transzformálhatjuk a szprájtot. Mivel ezt sem szeretnénk, azért adjunk csak meg `0`-át.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ spr(160, 100, 0, 1, 1, 1, 0); } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ }`

Próbáljuk meg lefuttatni ezt a programot a `Ctrl`+`R` leütésével, és lássuk mi történik. Ha valamilyen hibát vétettél a begépeléskor, akkor alul a státuszsorban egy hibaüzenet fog megjelenni, és a kurzor a hibát kiváltó részre fog ugrani.

Ha minden rendben volt, akkor a szerkesztőképernyő el fog tűnni, és helyette egy fekete képernyő, közepén a labdával fog megjelenni. Azonban a labdánk nem teljesen középre került, mivel elfelejtettük kivonni a szprájt méretének felét a koordinátákból (egy szprájtot jelenítünk meg itt (sw = 1 és sh = 1), szóval 8 x 8 pixelt, aminek a fele 4). Üssük le az `F2`-őt, hogy visszatérjünk a szerkesztőbe, és javítsuk ki.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ spr(156, 96, 0, 1, 1, 1, 0); } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ }`

Futtassuk le újra! A labdánk megjelenik a jó helyen, de a korábbi helyén is ottmaradt! Ez azért van, mert nem töröltük le a képernyőt. Ezt a cls (clear screen) paranccsal tehetjük meg, ezért ezt írjuk be a szprájtmegjelenítés elé.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ cls(0); spr(156, 96, 0, 1, 1, 1, 0); } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ }`

Most már minden rendben, pontosan a képernyő közepén megjelenik a labda.

## Labda mozgatása

Van egy kis probléma a kódunkkal. A labdát a `setup()` függvényben jelenítjük meg, de ez csak egyszer fut le, amikor a programunk elindul. Ahhoz, hogy mozogni lássuk a labdát, újra és újra ki kell rajzolnunk, mindig más pozícióra. Hogy ezt elérjük, tegyük át a labdánk megjelenítését a `loop()` függvénybe. Ez minden egyes alkalommal lefut, amikor a képernyő frissül.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(156, 96, 0, 1, 1, 1, 0);}`

Ha most leütjük a `Ctrl`+`R`-t, akkor a labda pontosan ugyanúgy fog megjelenni, mint eddig. Amit nem látunk, az az, hogy most nemcsak egyszer, hanem újra és újra kirajzolódik.

Mozgassuk meg a labdát! Most mindig ugyanott jelenik meg, mivel konstans koordinátákat használtunk. Javítsunk ezen úgy, hogy bevezetünk két változót, amik a labda épp aktuális pozícióját fogják tárolni a képernyőn.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

`#!c int x, y; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(156, 96, 0, 1, 1, 1, 0); }`

Cseréljük le a koordinátákat a kirajzolásnál ezekre a változókra, és adjunk nekik induló értéket a program indulásakor.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

`#!c int x, y; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96;} void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); }`

Ha most lefuttatjuk a programunkat, akkor még mindig nem fogunk semmi változást látni. Azonban annak köszönhetően, hogy most már változókat használunk, futás közben tudjuk változtatni a pozíciót.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

`#!c int x, y; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); x = x + 1; y = y + 1;}`

Futtasuk le így, és látni fogjuk a labdát mozogni!

## Labda pattogás

Még nem vagyunk készen, mert a labdánk nagyon gyorsan eltűnik a képernyőről. Ez azért van, mert folyton növeljük a koordinátáit, és nem fordítjuk meg az irányát, amikor a képernyő szélére ér.

Akárcsak a koordináták esetében először, most is konstanst használunk, és szeretnénk az irányt dinamikusan változtatni. A megoldás most is ugyanaz, lecseréljük a konstansokat két új változóra.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

`#!c int x, y, dx, dy; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); x = x + dx; y = y + dy; }`

Nagyszerű! Mint korábban említettük, a képernyő 320 pixel széles, és 200 pixel magas. Ez azt jelenti, hogy a lehetséges `x` értékek 0 és 319 között vannak, `y` esetén pedig 0 és 199 között. Azonban nem akarjuk, hogy a labdánk eltűnjön a képernyőről, így ebből ki kell vonni a szprájt méretét (8 x 8 pixel). Így végül azt kapjuk, hogy az `x` 0 és 311 közötti, az `y` pedig 0 és 191 közötti. Amikor a labdánk pozíciója eléri ezeket az értékeket, akkor meg fell fordítanunk az irányát, hogy mindig a képernyőn belül maradjon.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

`#!c int x, y, dx, dy; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || y == 191) dy = -dy;}`

Futtasuk le ezt a prgoramot a `Ctrl`+`R`-el. Gratulálunk, van egy mozgó labdád, ami megpattan a képernyő szélein!

## Ütő hozzáadása

Az a játék, amit nem tudunk befolyásolni, nem túl izgalmas. Ezért hozzáadunk egy ütőt, amit a játékos irányíthat.

Menjünk a Szprájt szerkesztőbe (üsd le az `F3`-at), és rajzoljuk meg az ütőt. Ez most három szprájt széles lesz. Megrajzolhatod egyenként, vagy akár kijelölhetsz több szprájtot is jobbra, és együtt szerkesztheted őket.

Az ütő megrajzolása

Hasonlóan a labdához, ezt is az spr paranccsal fogjuk megjeleníteni. Azt azonban már tudjuk, hogy szükségünk lesz egy változóra, ami a pozícióját tárolja, így adjuk hozzá egyből ezt is.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

`#!c int x, y, dx, dy, px; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); spr(px, 191, 1, 3, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || y == 191) dy = -dy; }`

Az `x` paraméter helyére kerül a `px` változó, az `y` koordináta konstans `191`, mivel függőlegesen nem fogjuk mozgatni az ütőt, csak vízszintesen. Mivel az ütőt az egyes szprájtra rajzoltuk, ezért a `sprite` paraméter most `1`, és mivel három szprájt széles, ezért az `sw` pedig `3`, de továbbra is csak egy szprájt magas, tehát az `sh` az `1`.

Eddig jó, de hogy fogja tudni mozgatni a játékos az ütőt az egérrel? Hát úgy, hogy az egér koordinátáját adjuk a `px` változónak. Ha megnézed a memóriatérképet, akkor a mutató fejezetben azt látod, hogy az egér X koordintája 2 bájton, a `00016`-os címen található. Hogy ezt lekérdezzük, az inw függvényt fogjuk használni (word, azaz szó, mivel két bájtra van szükségünk). De arra is figyelnünk kell, hogy az ütő a képernyőn maradjon, ezért csak azokat a koordinátákat engedjük, amik kissebbek, mint a képernyő szélessége mínusz az ütő szélessége (ami három szprájtnyi, tehát 24 pixeles). Még egy dolog, a memóriatérképen minden cím tizenhatos számrendszerben van megadva, így a `0x` előtagot kell használnunk, hogy jelezzük a fordítóprogramnak, egy hexadecimális szám következik.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

`#!c int x, y, dx, dy, px; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); px = inw(0x16); if(px > 296) px = 296; spr(px, 191, 1, 3, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || y == 191) dy = -dy; }`

Futtassuk le a programot! Megjelenik az ütő, és mozgatni is tudjuk az egérrel. Azonban akad egy kis bökkenő, a labdát nem érdekli, hogy hol van az ütő. Írjuk át a programot, hogy a képernyő alja helyett csak akkor pattanjon a labda, ha épp az ütőre esik. A labda magassága 8 pixel, ezért ennyivel feljebb kell az ellenőrzést elvégezni.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

`#!c int x, y, dx, dy, px; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); px = inw(0x16); if(px > 296) px = 296; spr(px, 191, 1, 3, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || (y == 183 && x >= px && x <= px + 24)) dy = -dy; }`

Ez azt jelenti, hogy az `y` koordináta nulla, vagy `183` és ugyanakkor az `x` pedig `px` és `px + 24` közötti (ahol a `px` az ütő pozíciója).

## Játék vége

Most, hogy átírtuk az alsó pattanást, szükségünk van egy újabb ellenőrzésre, hogy a labda alul kiment-e a képernyőről. Ez ugye a játék végét fogja jelenteni.

Először is ne felejtsük el, hogy a `loop()` továbbra is többször lefut, ezért hogy a labda ne mozogjon tovább, a `dx` és `dy` változókat nullára állítjuk. Másodszor, meg akarunk jeleníteni egy vége a játéknak üzenetet.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

`#!c int x, y, dx, dy, px; str_t msg = "VÉGE A JÁTÉKNAK!"; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); px = inw(0x16); if(px > 296) px = 296; spr(px, 191, 1, 3, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || (y == 183 && x >= px && x <= px + 24)) dy = -dy; if(y > 199) { dx = dy = 0; text(184, (320 - width(2, msg)) / 2, 90, 2, 112, 128, msg); }}`

Szöveget a text funkcióval lehet kiírni a képernyőre. Alul a gyorssúgó mutatja, milyen paraméterei vannak. A legelső a `palidx`, ami egy paletta index, a szöveg színe. Üssük le az `F3` gombot, és palettán kattintsunk a kívánt színre. Alul meg fog jelenni a sorszáma tizenhatos számrendszerben, illetve zárójelben tízesben.

Én egy piros színt választottam, aminek a sorszáma `B8`, azaz `184` tízes számrendszerben. Menjünk vissza a kódszerkesztőbe az `F2` leütésével, és írjuk be a szín sorszámát. A következő két paraméter az `x` és az `y`, a képernyő pozíció. Megtehettük volna, hogy megszámoljuk, mennyi pixel a szöveg, de lusták vagyunk, ezért inkább a width funkcióval kiszámoltatjuk. Ezt kivonva a képernyő szélességéből és elosztva kettővel pont középen fog megjelenni a szöveg. Mivel ahhoz is listák vagyunk, hogy kétszer írjuk be a szöveget, ezért azt egy `msg` nevű sztring változóba raktuk. Így `msg`-ként hivatkozunk rá egyszer, amikor a méretét lekérjük, és akkor is, amikor a kiírásnak megadjuk, mit kell kiírni. A koordináták után jön a `type`, ami a betűtípus, illetve pontosabban itt most a mérete. Mivel nagy betűkkel szeretnénk kiírni, ezért `2` lett megadva, dupla méret. Ezt követi az `shidx`, ami megint egy szín sorszám, az árnyék színe. Ide egy sötétebb pirosat választottam. Az árnyéknál fontos azonban az is, hogy mennyire átlátszó, ezt az `sha` paraméterben adhatjuk meg, ami egy alfa csatorna érték 0-tól (teljesen átlátszó) 255-ig (semennyire sem). Ide a `128`-at választottam, ami félúton van a két érték között, tehát félig átlátszó. Végezetül pedig `str`-ben kell megadni, hogy melyik szöveget szeretnénk kiíratni, ezt ugye az `msg` változóban tároljuk.

## Újrakezdés

Végezetül pedig, ha a játékos kattint egyet, akkor újra akarjuk indítani a játékot.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

`#!c int x, y, dx, dy, px; str_t msg = "VÉGE A JÁTÉKNAK!"; void setup() { /* Induláskor lefuttatandó dolgok */ x = 156; y = 96; dx = dy = 1; } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(x, y, 0, 1, 1, 1, 0); px = inw(0x16); if(px > 296) px = 296; spr(px, 191, 1, 3, 1, 1, 0); x = x + dx; y = y + dy; if(x == 0 || x == 311) dx = -dx; if(y == 0 || (y == 183 && x >= px && x <= px + 24)) dy = -dy; if(y > 199) { dx = dy = 0; text(184, (320 - width(2, msg)) / 2, 90, 2, 112, 128, msg); if(getclk(BTN_L)) setup(); } }`

Hogy megtudjuk, kattintott-e a felhasználó, arra a getclk (get click) funkciót használjuk, egy `BTN_L` (button left) paraméterrel, azaz kattintottak-e a bal egérgombbal. A pattogó labda játékunk alapértékeit a `setup()` függvényben állítottuk be, ami nagyon kapóra jön, mivel ha itt most újra meghívjuk a `setup()`-ot, akkor a játék egyszerűen visszaáll az alaphelyzetébe.

ElőzőKövetkező

# Sétáló

Ebben a példában egy sétáló karaktert fogunk megjeleníteni szprájtokkal. Ez az alapja a legtöbb kaland és kósza-típusú játéknak.

## Szprájtlap beszerzése

Meg is rajzolhattuk volna magunk, de az egyszerűség kedvéért letöltöttem egy szabadon felhasználható lapot az internetről. Ez három animációs fázist tartalmaz minden sorban, és mind a négy irányhoz van egy-egy sor. Rengeteg ilyen szprájtlapot találsz a neten, mivel ez a népszerű RPG Maker szprájtlap elrendezése.

FIGYELEM

Mindig ellenőrizd az internetről letöltött kellékek licenszfeltételeit. Ne használd a kelléket, ha nem vagy teljesen biztos a felhasználás feltételeiben.

Indítsd el a `meg4`-et, és húzd rá az ablakára a letöltött PNG képet az importáláshoz.

A beimportált szprájtlap

Amint látható, egy karakterszprájt 4 x 4 szprájtból áll. Jelenítsük meg! Üsd le az `F2`-őt, hogy behozd a kód szerkesztőt.

## Karakter megjelenítése

A szokásos vázzal indítunk. Az előző példából tudjuk, hogy le kell törölni a képernyőt és a szprájtot az spr hívással, a `loop()` funkcióban kell megjelenítenünk, mivel az animálás folyamatos újrarajzolást igényel.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ cls(0); spr(144, 84, 0, 4, 4, 0, 0);}`

A képernyő közepe 160, 100-nál van, de a karakterünk 4 x 4 szprájtból áll (32 x 32 pixeles), így ennek a felét le kell vonni. Ezt követő 0 a `sprite`, ami az első szprájtot jelenti, 4, 4-el folytatva, mivel összesen ennyi szprájtot akarunk kirakni. Az utolsó két paraméter 0, 0, mivel nem akarunk sem nagyítani, sem transzformációt használni, pont úgy akarjuk a szprájtokat megjeleníteni, ahogy azok a szprájt szerkesztőben látszanak.

## Irányváltoztatás

Tegyük lehetővé, hogy megváltoztatható legyen, merre néz a karakter. Ehhez a getpad hívást fogjuk használni, ami visszaadja a játékpad állapotát. Mivel az elsődleges játékpad a billentyűzetre is le van képezve, ezért ez a kurzornyilakkal is működni fog. Hogy letároljuk az épp aktuális irányt, ehhez szükségünk lesz egy változóra, ami kiválasztja, hogy melyik szprájtot is kell megjelenítenünk.

A szprájt sorszám kiderítése

Leütheted az `F3`-at és a szprájtválasztóban a karakter bal felső szprájtjára kattintva kiírja az adott irányhoz tartozó szprájt sorszámát. Ezt a sorszámot az `irány` változóban fogjuk tárolni, és ezt a változót használjuk a `sprite` paraméter helyén.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

`#!c int irány; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Felhasználói bemenet */ if(getpad(0, BTN_D)) { irány = 0; } else if(getpad(0, BTN_L)) { irány = 128; } else if(getpad(0, BTN_R)) { irány = 256; } else if(getpad(0, BTN_U)) { irány = 384; } /* Karakter megjelenítése */ cls(0); spr(144, 84, irány, 4, 4, 0, 0); }`

Próbáljuk ki! Látni fogjuk, hogy a kurzornyilak lenyomására irányt vált a karakterünk.

## Animálás hozzáadása

A karakterünk még nem sétál. Javítsuk ki! Azt szeretnénk, hogy a gomb (vagy kurzornyíl) lenyomásakor a karakter sétáljon, és megálljon, amikor felengedjük azt. Ehhez szükségünk lesz egy változóra, ami tárolja, hogy épp van-e lenyomva gomb.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

`#!c int irány, lenyomva; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Felhasználói bemenet */ lenyomva = 0; if(getpad(0, BTN_D)) { irány = 0; lenyomva = 1; } else if(getpad(0, BTN_L)) { irány = 128; lenyomva = 1; } else if(getpad(0, BTN_R)) { irány = 256; lenyomva = 1; } else if(getpad(0, BTN_U)) { irány = 384; lenyomva = 1; } /* Karakter megjelenítése */ cls(0); spr(144, 84, irány, 4, 4, 0, 0); }`

Először is, töröljük a `lenyomva` változót. Aztán minden if blokkban beállítjuk 1-re. Ennek hatására ha lenyomjuk valamelyik gombot, akkor a változó értéke 1 lesz, de amint felengedjük azt a gombot, akkor egyből visszaáll 0-ra.

Kelleni fog mégegy változó, ami pedig azt mondja meg, melyik képkockát kell épp kirajzolni. Használhatnánk valami vicces képletet is, de egyszerűbb egy tömbben letárolni, hogy melyik képkockához melyik szprájt tartozik az adott sorban. Szóval a sor adja meg az irányt, az oszlop pedig az animációs fázist. E kettőt összeadva kapjuk meg a végleges képkockát.

Még egy valami, csak három szprájtunk van, viszont négy képkockára van szükségünk, mivel a középső szprájtot kétszer is meg kell jelenítenünk, hogy rendes oda-vissza lábmozgás animációt kapjunk. Tehát az adott sorban vesszük a középső képkockát, az utolsót, megint a középsőt, majd az elsőt.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

`#!c int irány, lenyomva, képkocka; int anim[4] = { 4, 8, 4, 0 }; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Felhasználói bemenet */ lenyomva = 0; if(getpad(0, BTN_D)) { irány = 0; lenyomva = 1; } else if(getpad(0, BTN_L)) { irány = 128; lenyomva = 1; } else if(getpad(0, BTN_R)) { irány = 256; lenyomva = 1; } else if(getpad(0, BTN_U)) { irány = 384; lenyomva = 1; } /* Karakter megjelenítése */ képkocka = lenyomva ? (képkocka + 1) & 3 : 0; cls(0); spr(144, 84, irány + anim[képkocka], 4, 4, 0, 0); }`

Ezután kiszámoljuk, melyik képkockára van szükségünk, de csak akkor, ha van gomb lenyomva. Ha nincs, akkor konstans 0-át használunk, ami az első képkockát jelenti. Egyébként megnöveljük a `képkocka` változó értékét, hogy következő képkockát vegyük, és logikai ÉS-t használunk a túlcsordulás elkerülésére. Amikor a `képkocka` értéke 4 lesz (ami 0b100) és ezt ÉS-eljük 3-al (0b011), akkor az eredmény 0 lesz, azaz a képkocka számláló körbefordul. Használhattunk volna "modulo képkockák száma" kifejezést is, de ez gyorsabb. Végül az így kapott képkockának megfelelő szprájt azonosító eltolást (amit az `anim` tömbben tárolunk), hozzáadjuk az `irány` változóhoz, hogy megkapjuk, ténylegesen melyik szprájtot is kell kirajzolni.

Próbáljuk ki, üsd le a `Ctrl`+`R`-t! Remekül működik, azonban az animáció túl gyors. Ez azért van, mert minden frissítésnél növeljük a `képkocka` változót, tehát másodpercenként 60-szor. Hogy ezt elkerüljük, az MMIO-ból kell kiolvasni a tikkeket és a képkockát a frissítéstől függetlenül kell meghatározni. A tikkszámláló azonban ezredmásodperces, így le kell osztanunk. Ha 100-al osztanánk, akkor másodpercenként 10 képkockát kapnánk. Ehelyett 7 bittel jobbra eltolást fogunk használni, ami 128-al való osztásnak felel meg. Először is, üsd le az `F1`-et és kattints az Általános-ra. Láthatjuk, hogy a tikkszámláló címe a 0x4, és 4 bájt hosszú (ezért az ini hívást kell használnunk). Menjünk vissza a kódra, és a képkockaszámítást cseréljük le erre.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

`#!c int irány, lenyomva, képkocka; int anim[4] = { 4, 8, 4, 0 }; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Felhasználói bemenet */ lenyomva = 0; if(getpad(0, BTN_D)) { irány = 0; lenyomva = 1; } else if(getpad(0, BTN_L)) { irány = 128; lenyomva = 1; } else if(getpad(0, BTN_R)) { irány = 256; lenyomva = 1; } else if(getpad(0, BTN_U)) { irány = 384; lenyomva = 1; } /* Karakter megjelenítése */ képkocka = lenyomva ? (ini(0x4) >> 7) & 3 : 0; cls(0); spr(144, 84, irány + anim[képkocka], 4, 4, 0, 0); }`

És készen vagyunk! Van egy szépen sétáló karakter animációnk, amit mi irányíthatunk a játékban. Mozgathatod magát a karaktert is a képernyőn, ha változókra cseréled az x, y paramétereket, de az ilyen játékoknál sokkal elterjedtebb, hogy inkább a térképet mozgatják a karakter talpa alatt az ellenkező irányba.

ElőzőKövetkező

# Ágyú

Ebben a példában egy ágyút fognunk csinálni. Minden benne van, ami az Asteroids játék alapját képezi.

## Ágyúcső kirajzolása

A szokásos vázzal indítunk. Az előző példából tudjuk, hogy le kell törölnünk a képernyőt, aztán egy line hívással egy egyszerű vonal ágyút rajzolunk.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

`#!c void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Kirajzolás */ cls(0); line(23, 160, 100, 160, 100 - 10);}`

A képernyő közepe 160, 100-nál van, innen egy 10 pixeles csövet húzunk felfelé azáltal, hogy a vége Y koordinátából kivonunk 10-et. Továbbá a csőhöz szürkés színt használunk (23).

## Ágyúcső forgatása

Hogy a játékos ezt forgatni tudja, szükségünk lesz egy változóra, ami az aktuális szöget tárolja, hogy merre mutat a cső.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

`#!c int szog; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Kirajzolás */ cls(0); line(23, 160, 100, 160, 100 - 10); }`

Lekérdezzük, hogy a játékos leütötte-e a jobbra vagy balra nyilakat és ennek megfelelően változtatjuk a szöget. De még nem vagyunk készen, mert a szöget vágni is kell, méghozzá úgy, hogyha eléri az alsó értéket, akkor a legnagyobb legyen, míg ha a felső értéket, akkor meg a legkissebb. Ennek eredményeként egy szépen körbe-körbe forgatható ágyúcsövet kapunk.

Namost hogy az ágyúcsövet ebben a szögben tudjuk kirajzolni, ahhoz tudnunk kell, hogy egy adott szög mit jelent pixelekben az X és Y tengelyen. Talán rémlik iskolás matekóráról, hogy a szinusz és koszinusz függvények pontosan ezt adják meg. Persze egységet adnak, azért ahhoz, hogy 10 pixel hosszú legyen a cső, az eredményt fel kell még szorozni 10-el. Fontos, hogy a sin és a cos függvény is lebegőpontos értéket (nem `1` hanem `1.0`) ad vissza.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

`#!c int szog; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Kirajzolás */ cls(0); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Üssük le a `Ctrl`+`R`-t és látni fogjuk, hogy az ágyúcső szépen forgatható.

## Lövedék hozzáadása

Ahogy azt a labda pattogás példából tudjuk, ahhoz, hogy a képernyőn egy mozgó objektumunk legyen, kell két változó, ami a koordinátáit tárolja, valamint még további kettő, ami meg azt, hogy mennyit kell elmozdulnia. A labdával ellentétben, ami csak átlósan mozgott, itt most mindenféle tetszőleges szöget akarunk használni, ezért a szép folyamatos mozgáshoz törtpixeleket kell tárolni, tehát lebegőpontos változókra lesz szükségünk (ezért nem `int` hanem `float`).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

`#!c float x, y, dx, dy;int szog; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Lövedék mozgatása */ x += dx; y += dy; if(x < 0 || x >= 320 || y < 0 || y >= 200) dx = dy = 0.0; /* Kirajzolás */ cls(0); pset(8, x, y); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Pont ahogy a legelső példában is csináltuk, a fő `loop()` függvényben hozzáadjuk a delta értékeket a koordinátákhoz. Továbbá ellenőrizzük, hogy a lövedék elérte-e valamelyik képernyőszélet, és ha igen, akkor alaphelyzetbe állítjuk, hogy megakadályozzuk a lövedék további mozgását. Magának a lövedéknek a megjelenítésére pedig kiteszünk egy sárga (8) pixelt a pset függvénnyel.

## Ágyú elsütése

Már csak egy dolog maradt hátra, hogy a játékos lőni is tudjon ezzel az ágyúval.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35

`#!c float x, y, dx, dy; int szog; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Ágyú elsütése */ if(getkey(KEY_SPACE)) { dx = cos(szog); dy = sin(szog); x = 160 + dx * 9; y = 100 + dy * 9; } /* Lövedék mozgatása */ x += dx; y += dy; if(x < 0 || x >= 320 || y < 0 || y >= 200) dx = dy = 0.0; /* Kirajzolás */ cls(0); pset(8, x, y); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Amikor a játékos leüti a `Szóköz` billentyűt, asszerint állítjuk be a dx és dy értékét, hogy a cső aktuális elfordulása mennyi pixelt is jelent az X és Y tengelyen. Ezen kívül a lövedék koordinátáját a cső végéhez állítjuk be. A delta értékeket csak 9-el szorozzuk meg itt, mivel mindjárt a következő dolog, amit tenni fogunk az az, hogy a léptetés miatt hozzáadjuk a delta értékeket a koordinátákhoz, ezért ez így pont olyan, mintha 10-el szoroztunk volna.

Próbáljuk ki! Működik, de van egy kis bökkenő. Ha a játékos lenyomva tartja a `Szóköz`-t, akkor semmi sem történik! Ez amiatt van, mert ilyenkor a getkey állandóan igaz lesz, ezért folyamatosan beállítjuk az x, y, dx, dy változókat, így aztán hiába léptetjük. Javítsuk ki! Kelleni fog egy változó, amiben azt tároljuk, hogy el lett-e már sütve az ágyú.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39

`#!c float x, y, dx, dy; int szog, elsutve; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Ágyú elsütése */ if(getkey(KEY_SPACE)) { if(!elsutve) { elsutve = 1; dx = cos(szog); dy = sin(szog); x = 160 + dx * 9; y = 100 + dy * 9; } } else elsutve = 0; /* Lövedék mozgatása */ x += dx; y += dy; if(x < 0 || x >= 320 || y < 0 || y >= 200) dx = dy = 0.0; /* Kirajzolás */ cls(0); pset(8, x, y); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Tehát amikor `Szóköz` le van nyomva, akkor azt is ellenőrizzük, hogy nincs az `elsutve` változó beállítva, és na nincs, akkor beállítjuk a többi változóval egyetemben. Így most csak egyszer állítjuk be a változókat. De nem akarjuk, hogy így is maradjon az `elsutve`, ezért amikor a `Szóköz` nincs nyomva, akkor lenullázuk, hogy legközelebb is elsüthessük az ágyút. És ennyi lenne.

TIPP

Egy blokkot raktunk akköré a sorok köré, amik beállítják a változókat. Nem kell ilyenkor egy csomó szóközt becsépelnünk, hogy beljebb toljuk az utasításokat. Elég csak kijelölni a sorokat, és a `Ctrl`+`.` leütésével mindet egyszerre beljebb húzza a szerkesztő.

## Több lövedék

A kódunknak még mindig van egy szépséghibája. Ha akkor sütjük el az ágyút, amikor már van egy lövedék kilőve, akkor az eltűnik. Ez azért van, mert jelenleg csak egyetlen lövedéket tudunk kezelni, mert csak egy x, y, dx, dy négyesünk van. A több lövedékhez át kell alakítanunk ezeket tömbökké, amik több értéket is képesek tárolni, egy-egy négyest minden lövedékhez.

Elsőre csak csináljunk egy elemű tömböket. Amikor deklarálunk, akkor elemszámot kell megadni a fordítónak, de amikor hivatkozunk rájuk, akkor az indexük nullától indul, ezért egy N elemű tömb esetén 0 és N - 1 közötti lehet az index.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

`#!c #define N 1 float x[N], y[N], dx[N], dy[N]; int szog, elsutve; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Ágyú elsütése */ if(getkey(KEY_SPACE)) { if(!elsutve) { elsutve = 1; dx[0] = cos(szog); dy[0] = sin(szog); x[0] = 160 + dx[0] * 9; y[0] = 100 + dy[0] * 9; } } else elsutve = 0; /* Lövedék mozgatása */ x[0] += dx[0]; y[0] += dy[0]; if(x[0] < 0 || x[0] >= 320 || y[0] < 0 || y[0] >= 200) dx[0] = dy[0] = 0.0; /* Kirajzolás */ cls(0); pset(8, x[0], y[0]); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Próbáljuk ki! Ha nem rontottuk el, akkor pontosan ugyanúgy fog futni, mint ezidáig.

Hogy továbblépjünk, be kell hoznunk a ciklusokat, amik végigmennek az elemeken. Első nekifutásra alakítsuk át a léptetést és a kirajzolást.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

`#!c #define N 1 float x[N], y[N], dx[N], dy[N]; int szog, elsutve; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { int i; /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Ágyú elsütése */ if(getkey(KEY_SPACE)) { if(!elsutve) { elsutve = 1; dx[0] = cos(szog); dy[0] = sin(szog); x[0] = 160 + dx[0] * 9; y[0] = 100 + dy[0] * 9; } } else elsutve = 0; /* Lövedékek mozgatása */ for(i = 0; i < N; i++) { x[i] += dx[i]; y[i] += dy[i]; if(x[i] < 0 || x[i] >= 320 || y[i] < 0 || y[i] >= 200) dx[i] = dy[i] = 0.0; } /* Kirajzolás */ cls(0); for(i = 0; i < N; i++) pset(8, x[i], y[i]); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Amint látható, nem változtattunk sokat, csak a kifejezések köré raktunk egy ciklust, a konstans `0` indexet meg lecseréltük az `i` ciklusváltozóra. Ezáltal minden egyes ciklus ismétlődésnél a ciklusmag pontosan egy lövedéket fog léptetni. Hasonlóan jártunk el a kirajzolásnál is, ott is egy lövedéket rajzolunk ki minden iterációban.

De lőnünk is kell tudni az ágyúval. Ez kicsit trükkösebb, mert itt keresnünk kell egy változó négyest, ami nincs használatban. És ha találtunk, akkor meg kell állnunk, mert egyszerre csak egy lövedék változóit akarjuk állítani.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

`#!c #define N 1 float x[N], y[N], dx[N], dy[N]; int szog, elsutve; void setup() { /* Induláskor lefuttatandó dolgok */ } void loop() { int i; /* Minden képkockánál lefuttatandó dolgok, 60 FPS */ /* Gombok lekezelése */ if(getkey(KEY_LEFT)) szog--; if(getkey(KEY_RIGHT)) szog++; if(szog < 0) szog = 359; if(szog > 359) szog = 0; /* Ágyú elsütése */ if(getkey(KEY_SPACE)) { if(!elsutve) { elsutve = 1; for(i = 0; i < N; i++) if(dx[i] == 0.0 && dy[i] == 0.0) { dx[i] = cos(szog); dy[i] = sin(szog); x[i] = 160 + dx[i] * 9; y[i] = 100 + dy[i] * 9; break; } } } else elsutve = 0; /* Lövedékek mozgatása */ for(i = 0; i < N; i++) { x[i] += dx[i]; y[i] += dy[i]; if(x[i] < 0 || x[i] >= 320 || y[i] < 0 || y[i] >= 200) dx[i] = dy[i] = 0.0; } /* Kirajzolás */ cls(0); for(i = 0; i < N; i++) pset(8, x[i], y[i]); line(23, 160, 100, 160 + cos(szog)*10, 100 + sin(szog)*10); }`

Ez a ciklus egy feltételes blokkot tartalmaz, ami azt nézi, hogy az adott lövedék elmozdulása nulla-e. Amennyiben igen, úgy találtunk egy szabad lövedék változó négyest `i`-nél, amit használhatunk. Elvégezzük a korábbi beállításokat ezen az `i`-edik négyesen, aztán a `break` kulcsszóval megszakítjuk a ciklus további futását.

Futtassuk le! Még mindig semmi változás, pontosan ugyanúgy működik, mint eddig. De hogy rávilágítsunk, miért is dolgoztunk a tömbösítéssel ilyen keményen, változtassunk meg csak egyetlen egy dolgot:

    1

`#define N 100`

És láss csodát!

Ha lecseréljük az ágyú fix 160-as és 100-as koordinátáit újabb x, y és dx, dy változókra, akkor képesek leszünk mozgatni, és máris van egy Asteroids űrhajónk!

ElőzőKövetkező

# Hangeffekt

Ebben az oktatóanyagban előkészítünk és beimportálunk egy hangeffektet. Ehhez az Audacity programot fogjuk használni, de bármelyik másik hullámszerkesztő is megfelel a célra.

## Hullám betöltése

Először is, töltsük be a hanghullám fájlt az Audacity-be.

Hanghullám megnyitása Audacity-ben

Egyből látjuk, hogy két hullám is van, ami azt jelenti, hogy a mintánk sztereó. A MEG-4 csak mono mintákat kezel, ezért válasszuk a `Tracks` > `Mix` > `Mix Stereo Down to Mono` menüpontot a konvertáláshoz. Ha eleve csak egy hullámod van, akkor ez a lépés kihagyható.

## Hangmagasság és hangerő

Mivel a MEG-4 magától hangolja a mintákat, ezért az importált mintának egy adott hangmagasságúnak kell lennie. Valamiért a hangmagasságérzékelés bugos az Audacity-ben, ezért kézzel kell elvégezni. Üsd le a `Ctrl`+`A`-t a teljes hullám kijelöléséhez, majd menj az `Analyze` > `Plot Spectrum...` menüpontra.

Spektrumanalízis

Mozgasd az egeredet a legnagyobb csúcs fölé, és az aktuális hangmagasság alul meg fog jelenni (a példánkban ez `C3`). Ha a hangjegy nem `C4`, akkor válaszd az `Effect` > `Pitch and Tempo` > `Change Pitch...` menüpontot.

Hangmagasság állítása

A "from" mezőbe írd azt a hangjegyet amit a spektrumanalízisnél láttál, a "to" mezőt pedig állítsd a C-4 hangra, majd kattints az "Apply" gombra.

Hangerő állítása

A következő a hangerő normalizálása. Menj az `Effect` > `Volume and Compression` > `Amplify...` menüpontra. A felugró ablakban kattints az "Apply" gombra (minden beállítást helyesen detektál, nem kell állítani semmit).

## Minták száma

A MEG-4 nem kezel több, mint 16376 mintát egy hullámban. Ha eleve ennél kevesebb mintából áll a hullámod, akkor ez a lépés kihagyható.

A hullámminta képe alatt láthatod a kijelölést századmásodpercekben, kattints itt az "s"-re, és váltsd át "samples"-re.

Mértékegység megváltoztatása

A példánkban ez több, mint a megengedett maximum. A minták száma úgy számítódik, hogy a mintavételezési ráta értéket megszorozzuk a hullámunk időtartamával. Szóval hogy csökkentsük a mintaszámot, vagy csökkentjük a rátát, vagy lecsapunk a hullámunk végéből. Ebben az oktatóanyagban mindkettőt megtesszük.

Kijelöltem mindent mondjuk úgy 1.0 után, majd a `Del` leütésével töröltem. Ez működik, viszont a hullám vége hirtelen vágódik el és csúnya hangja lesz. Hogy ezt kiigazítsuk, jelöljünk ki a hullám végéből egy valamekkora darabot, majd válasszuk az `Effect` > `Fading` > `Fade Out` menüpontot. Ennek hatására a hullám vége szépen elhalkul.

Hullám levágása és a vég elhalkítása

A hullámunk még mindig túl hosszú (44380 minta), de többet már nem lehet levágni belőle annélkül, hogy elrontanánk. Itt jön képbe a mintavételezési ráta. Az Audacity korábbi verzióiban ez kényelmesen alul az eszköztáron látszott, mint "Project Rate (Hz)". De többé már nem, az újabb Audacity-nél ez sokkal macerásabb lett. Először is kattintsunk az `Audio Setup` gombra az eszköztáron, majd válasszuk ki a `Audio Settings...`-et. A felugró ablakban keressük meg a "Quality" / "Project Sample Rate" sort, és mellette állítsuk az opciólistát "Other..."-re, hogy a tényleges mező szerkeszthetővé váljon.

FIGYELEM

Bizonyosodj meg róla, hogy jó számot adsz meg! Az Audacity nem képes visszavonni ezt a lépést, ezért nem próbálkozhatsz újra!

Ide egy olyan számot kell beírni, ami 16376 osztva a hullámunk időtartamával (1.01 másodperc a példánkban), majd kattintsunk az "OK"-ra.

Mintaszám csökkentése

Jelöljünk ki az egész hullámmintát (`Ctrl`+`A` leütésével), és alul a kijelölés végénél az kell látnunk, hogy az kevesebb, mint 16376.

## Elmentés és beimportálás

Végezetül, mentsd el a módosított hullámmintát, válaszd a `File` > `Export` > `Export as WAV` menüpontot. Győzödj meg róla, hogy a kódolás (Encoding) "Unsigned 8-bit PCM"-re van állítva. Fájlnévnek `dspXX.wav`-t adj meg, ahol az `XX` egy hexa szám, `01` és `1F` között, az a MEG-4 hullámhely, ahová be szeretnéd importálni (használhatsz más nevet is, ekkor a legelső szabad helyre fog betöltődni).

A beimportált hullámminta

Amint megvan a fájl, egyszerűen csak húzd rá a MEG-4 ablakára és kész is.

ElőzőKövetkező

# Kalandjáték

Az advcomp fordítóval lehet AdvGame JSON forrásfájlokat MEG-4 Kalandjátékokká konvertálni. Ezek klasszikus szöveges játékok (hívják őket Interaktív Fikciónak is), ahol a játékos mondatokat gépel be a játékban történő haladáshoz. Ezeket a mondatokat aztán igére és főnev(ek)re bontja, amikre keres. Ha talál szkriptet az aktuális ige és főnév kombinációhoz, akkor azt lefuttatja.

MEGJEGYZÉS

Az `advcomp` fordító képes kattintós felületű kalandjátékokat is fordítani pontosan ugyanazokból a JSON fájlokból. Habár a MEG-4 be tudja tölteni ezeket is, de közben sima szöveges kalandjátékká konvertálja őket, a point'n'click játékmód csak az `advgame` programmal elérhető.

Korlátok:

- igék: 32 különböző akció, egyenként 15 bájt, 8 szinonímával (max. 1536 bájt összesen)
- főnevek: 255 különböző tárgy, egyenként 15 bájt (max. 1536 bájt összesen)
- üzenetek: 32 különböző sztring szobánként, egyenként 255 bájt (max. 2048 bájt nyelvenként)
- szkriptek: 1 globális, 63 közös minden szobában, és 63 különböző szobánként
- utasítások: 21 mnemonik 8 kondícióval, elágazásmentes kivitelezés, 61 utasítás szkriptenként
- képek: alapból 1 szobánként, de használható egyéni implementáció
- szobák: 254 összesen, melyek 6 különböző irányban összeköthetőek

## Játék állapot

A kalandjáték aktuális állapota egy 256 elemű bájttömben tárolódik. A legelső bájt az aktuális szoba száma, az utolsó 32 bájt a leltárnak van fenntartva, a többi szabadon felhasználható. Ezek lehetnek jelzőbitek, számlálók, bármi. A szkriptek ezen a 256 bájtnyi memórián végeznek műveleteket és ez az állapot elmenthető és visszatölthető játékmentésként.

## Felső szint

A forrásfájl legfelső szintjén lennie kell egy `"AdvGame"` JSON struktúrának, ami egyben a fájl azonosítója is. A mezői:

- `sprites`: sztring, 256 x 256 pixeles PNG szprájtlap elérési útja, a felső 32 sora üres
- `music`: sztringtömb, Amiga MOD (.mod) vagy MIDI (.mid) zenefájlok elérési útjai (8 elemű)
- `sounds`: sztringtömb, RIFF WAVE (.wav) formátumú fájlok elérési útjai (31 elemű)
- `setup`: számtömb, a játék induló állapota (256 elemű, mind 0 és 255 közötti, az első szám az induló szoba)
- `status`: számtömb, melyik játékállapotokat írja ki a státusz (2 elemig, többért lásd `custom`)
- `vars`: sztringtömb, a állapot indexek aliaszai, ún. "változók" (csak a JSON-ben használt)
- `rooms`: sztringtömb, a szobaszámok aliaszai (csak a JSON-ben használt)
- `verbs`: sztringtömb, a `verb1`, `verb2`, `verb3` stb. aliaszai (csak a JSON-ben használt)
- `nouns`: sztringtömb, a főnevek aliaszai (csak a JSON-ben használt)
- `colors`: 5 elemű számtömb, intró háttér- és betű-, szoba háttér- és betű-, valamint promptszín
- `pos`: szám, szöveg pozíciója pixelekben a képernyő tetejétől számítva
- `custom`: sztringtömb, plusz kusztom C kód a felhasználói felület megjelenítésére (első az intróé, a második a szobák kódja)
- `logic`: sztringtömb, általános játék logika szkript, ami mindig minden parancs előtt lefut
- `config0`: struktúra, fő játékkonfiguráció
- `config1`: struktúra, alternatív játékkonfiguráció (többnyelvűség támogatás)
- szám/"rooms" aliasz: struktúra, szobadefiníciók.

Alapesetben feltételezi, hogy a szprájtlap ketté van vágva: a felső 128 sor szobánként cserélődik, az alsó 128 sor állandó (felhasználói felület elemei, ikonok stb. ez utóbbiak töltődnek be a `sprites`-ról). Ha a textpos be van állítva, akkor az intrónál és a szobáknál is textpos (de legfeljebb 96) sor a szprájtlap 32. sorától kezdődően megjelenik a szöveg fölött a képernyőn. A kusztom felület C kóddal pedig akármilyen és akármennyi szprájt kirakható e helyett.

## Konfiguráció

Van egy fő- és egy alternatív konfiguráció a többnyelvűség támogatásához. A mezőik:

- `lang`: sztring, kétbetűs nyelvkkód
- `text`: sztring, intró szövege (429 bájtig)
- `answers`: 4 elemű sztringtömb, üzenetek (egyenként 63 bájtig): ismeretlen parancs, nem lehet arra menni, nem használható, játék elmentve.
- `save`: sztringtömb, játékmentés igéi (15 bájtig, 8 szinoníma)
- `load`: sztringtömb, játékbetöltés igéi
- `list`: sztringtömb, leltárlistázás igéi
- `north`: sztringtömb, északra navigálás igéi
- `west`: sztringtömb, nyugatra navigálás igéi
- `east`: sztringtömb, keletre navigálás igéi
- `south`: sztringtömb, délre navigálás igéi
- `up`: sztringtömb, emeletre navigálás igéi
- `down`: sztringtömb, alagsorba navigálás igéi
- `verb1`: sztringtömb, 1-es akció igéi (a kulcs lehet valamenyik "verbs" aliasz is)
- `verb2`: sztringtömb, 2-es akció igéi
- `verb3`: sztringtömb, 3-as akció igéi
- `verb32`: sztringtömb, 32-es akció igéi
- `nouns`: sztringtömb, tárgyak főnevei (255 sztringig)

A parszolás során a három UNICODE karakternél rövidebb szavaknak teljes egészében, egyébként csak a szó elején kell egyeznie. Emiatt ha például a `verb1`-nek `[ "kinyit" ]`, a `nouns`-nak meg `[ "lád" ]` van megadva, akkor fel fogja ismerni azt is, ha a játékos `kinyit láda` vagy `kinyitom a ládát` parancsot gépeli be.

## Szobák

A szobák sorszáma 1 és 254 közötti lehet (a 0-ás szoba az intró illetve reset valamint nem járható irány navigációs parancsoknál, a 255-ös meg a mentett játékállás helye). Egy szoba struktúra mezői:

- `image`: sztring, egy PNG elérési útja, legfeljebb 256 x 96 pixeles
- `text0`: sztringtömb, a `config0`-hoz tartozó szövegek (32 sztringig, egyenként 255 bájt)
- `text1`: sztringtömb, a `config1`-hez tartozó szövegek
- `north`: szám / sztring / sztringtömb, északi irány szkript
- `west`: szám / sztring / sztringtömb, nyugati irány szkript
- `east`: szám / sztring / sztringtömb, keleti irány szkript
- `south`: szám / sztring / sztringtömb, déli irány szkript
- `up`: szám / sztring / sztringtömb, felfele irány szkript
- `down`: szám / sztring / sztringtömb, lefele irány szkript
- `logic`: szám / sztring / sztringtömb, a szobába lépéskor automatikusan lefutó szkript
- `verbX`: szám / sztring / sztringtömb, önálló igés szkriptek (X értéke 1 és 32 közötti, vagy "verbs" aliasz)
- `verbX Y`: szám / sztring / sztringtömb, egy főnévvel rendelkező szkriptek (Y értéke 1 és 255 közötti, vagy "nouns" aliasz)
- `verbX Y Z`: szám / sztring / sztringtömb, két főnévvel rendelkező szkriptek (Y, Z értéke 1 és 255 közötti, vagy "nouns" aliasz)

A szövegek 255 bájtosak lehetnek, és minden szobának saját 32 szövege lehet, melyeket a `say` / `sayv` / `sayc` utasításokkal lehet kiiratni.

Az 1-es számú szoba szkriptjei speciálisak abból a szempontból, hogy minden más szobában is elérhetőek. Emiatt ide érdemes egy "Vége a játéknak" szobát rakni, aminek a logikája csak egy `jmp 0`-ás resetet tartalmaz, így nincs benne további parancsbekérés.

## Szkriptek

Bármelyik navigációs vagy igés parancs utánni JSON érték lehet egy nem nulla szám, ami egy szobaszám:

    "north": 12,

Vagy lehet sztring, ami egy "rooms" aliasz:

    "north": "padlás",

De ha egy sztringtömb, akkor az egy utasításokat tartalmazó szkript:

    "north": [ "jmp 12" ],

Ezek befolyásolják a játék állapotát, szöveget jelenítenek meg, stb. Az utasítások paraméterei számok, de a megfelelő helyeken "rooms", "vars", stb. aliaszok használhatók.

A rendelkezésre álló utasítások:

- `end`: szkript vége
- `and`: az utótagja a következő utasítás feltételéhez adódik logikai ÉS kapcsolattal
- `or`: az utótagja a következő utasítás feltételéhez adódik logikai VAGY kapcsolattal
- `bgm X`: háttérzene lejátszása (X értéke 0 és 7 közötti)
- `sfx X`: hangeffekt lejátszása (X értéke 0 és 63 közötti)
- `jmp X`: X szobába lép (X értéke 0 és 254 közötti)
- `jmpv (X)`: mint a `jmp`, de a szobát az X változóból veszi
- `call X`: meghívja az 1-es szoba X szkriptjét (X értéke 1 és 64 közötti)
- `callv (X)`: mint a `call`, de a szkript számát az X változóból veszi
- `give X`: hozzáadja az X főnevet a leltárhoz (X értéke 1 és 254 közötti)
- `take X`: kiveszi az X főnevet a leltárból
- `say X`: az X szöveg megjelenítése (X értéke 1 és 32 közötti)
- `sayv (X) Y`: az X változó értéke + Y szöveg megjelenítése
- `sayc X Y`: vagy az X (hamis), vagy az Y (igaz) szöveg megjelenítése kondíciótól függően
- `add (X) Y`: az X változó növelése Y-al (X és Y értéke 1 és 255 közötti)
- `addv (X) (Y)`: az X változó növelése Y változó értékével
- `sub (X) Y`: az X változó csökkentése Y-al (X és Y értéke 1 és 255 közötti)
- `subv (X) (Y)`: az X változó csökkentése Y változó értékével
- `set (X) Y`: az X változó értékét Y-ra állítja (Y értéke 0 és 255 közötti)
- `rnd (X) Y`: mint a `set`, de egy 0 és Y közötti véletlenszámot rak X-be
- `mov (X) (Y)`: az Y változó értékét X változóba másolja

Ezek az utasítások mind elláthatók a következő utótagok egyikével:

- nincs utótag: feltétel nélkül végrehajtódik
- `if (V) = N`: csak ha a V változó értéke N
- `if (V) != N`: csak ha a V változó értéke nem N
- `if (V) <= N`: csak ha a V változó értéke kissebb vagy egyenlő, mint N
- `if (V) < N`: csak ha a V változó értéke kissebb, mint N
- `if (V) > N`: csak ha a V változó értéke nagyobb, mint N
- `has N`: csak ha az N főnév a leltárban van
- `not N`: csak ha az N főnév nincs a leltárban

Különleges eset, ha a `(V)` 250 vagy nagyobb, ilyenkor az adott navigációs irányt használja: 250 (vagy `north`, észak), 251 (vagy `west`, nyugat), 252 (vagy `east`, kelet), 253 (vagy `south`, dél), 254 (vagy `up`, fel), 255 (vagy `down`, le). Ha például azt a feltételt szeretnénk, hogy északra járható-e a szoba, az `if north != 0`. Ezek az állapotindexek a leltár bitmaszkját tárolják, amit a `has` illetve `not` feltételekkel kell elérni, így nincs ütközés.

A 0-ás szobára ugrás vár egy billentyűleütésre, majd újraindítja a játékot és a 0-ás helyett a megadott induló szobára ugrik (ez csak kifejezetten `jmp` utasításnak adható meg, mert a 0 szám nem használható, mint cél szobaszám).

Alapesetben egy szobaösszeköttetéshez szobaszámot (vagy "rooms" aliaszt) adunk meg, de ez feltétel nélkül átengedi a játékost az egyik szobából a másikba. Például ha van egy "kulcs felvéve" jelző a 7-es állapotban, és a 11-es szobában pedig van egy ajtó az északi irányban a 12-es szoba felé, és azt akarjuk, hogy csak akkor legyen járható, ha a játékos rendelkezik a kulccsal, akkor szkriptelt navigációra van szükség.

    "11": {
      "text0": [ "Az ajtó zárva." ],
      "north": [ "jmp 12 if (7) = 1", "say 1" ]
    }

Ilyenkor a `north` mezőben szám helyett egy sztringtömben a `jmp 12 if (7) = 1` utasítást adjuk meg. Ez csak abban az esetben ugrik a 12-es szobába, ha a 7-es állapot értéke 1, egyébként marad a 11-esben. Ilyenkor mondhatjuk azt is, hogy "Az ajtó zárva" a `say 1` utasítással (ha korábban a 12-es szobára ugrottunk, akkor ez már nem hajtódik végre). A szobaszám helyett használható "rooms" aliasz, az állapot index (változó) helyén pedig "vars" aliasz, például `jmp padlás if kulcs = 1`. Bonyolultabb összefüggés is megadható az `and` / `or` utasításokkal, amennyiben a befolyásolandó utasítás elé tesszük őket. Például hogy csak éjjel lehessen átmenni, és csak ha lámpája is van a játékosnak, az `[ "and if éjjel = 1", "and has lámpa", "jmp padlás if kulcs = 1" ]`.

Egy másik példa, ami véletlenszerűen ugrik a 100 és 109 közötti szoba valamelyikére:

    [ "rnd (1) 10",   /* 0 és 9 közötti véletlenszám az 1-es állapotba */
      "add (1) 100",  /* hozzáadunk 100-at így az most 100 és 109 közötti */
      "jmpv (1)" ]    /* az állapotban tárolt szobaszámra ugrás */

A kiírás is jöhet változóból, például ha a halál okát a 9-es állapotban tároljuk, ami 0 és 2 közötti, akkor:

    "text0": [
      "Meghaltál, ennek oka:",  /* 1-es szöveg */
      "megfulladtál",           /* 2-es szöveg */
      "éhenhaltál",             /* 3-as szöveg */
      "bedarált a hegyirém"     /* 4-es szöveg */
    ],
    "logic": [ "say 1", "sayv (9) 2" ]

Itt a `say` előbb kiírja az 1-es szöveget, majd a `sayv` veszi a 9-es állapot értékét, hozzáad 2-őt, és az annyadik szöveget írja ki a 2-es és 4-es közötti szövegek közül.

Ugyancsak hasznos a feltételes szövegkiírás, ami a kondíciótól függően vagy egy hamis, vagy egy igaz szöveget ír ki. Például:

    "text0": [
      "Nincs nálad kulcs.",     /* 1-es szöveg */
      "Kinyitottad a ládát."    /* 2-es szöveg */
    ],
    "nyit láda": [ "sayc 1 2 has kulcs", "set (10) 1 has kulcs" ]

Amennyiben a játékosnál nincs kulcs, úgy a `sayc` az 1-es, ha van, akkor meg a 2-es szöveget írja ki. Aztán beállítunk egy "láda nyitva" jelzőt a `set`-el, de csak akkor, ha volt kulcs a játékosnál. (Hogy a parancs így megadható legyen, ahhoz kell egy `nyit` "verbs" aliasz és egy `láda` "nouns" aliasz is. Mégegyszer, az aliaszok csak a JSON-ben használatosak és függetlenek a lefordítható szavaktól, amit a játékosok a játék közben gépelnek be.)

## Minta játékok

Minta MEG-4 Kalandjátékok a meg4_advgame repóban találhatók.

ElőzőKövetkező

# MEG-4 Licensz

A MEG-4 Fantasy Konzol Szabad és Nyílt Forráskódú szoftver, ami GPLv3+ (vagy tetszés szerint ennek bármelyik újabb verziója) alatt kerül terjesztésre.

     Ez a program szabad szoftver; terjeszthető illetve módosítható a Free Software
     Fundation által kiadott GNU General Public License dokumentumban leírtak;
     akár a licensz 3-as, akár (tetszőleges) későbbi változata szerint.

     Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz, de minden
     egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy BÁRMELY CÉLÚ ALKALMAZHATÓSÁGRA
     való garanciát is beleértve. További részleteket a GNU General Public License
     tartalmaz.

     A felhasználónak a programmal együtt meg kell kapnia a GNU General Public
     License egy példányát; ha mégsem kapta meg, akkor írjon erre a címre:
     Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

A MEG-4 PRO Fantasy Konzol zárt kereskedelmi licenszű. A GPL-es változat funkcionalitásán túl képes a programodat önálló Web, Windows és Linux alkalmazásként exportálni.

ElőzőKövetkező

# Hivatkozások

A MEG-4 megalkotásához felhasznált anyagok

- pocketmod
- stb_image
- Bresenham
- raycasting
- TinyGL
- Lua
- DawnBringer32
- ZIP formátum
- PNG formátum
- TGA formátum
- TMX formátum
- BDF formátum
- MOD formátum
- MIDI formátum
- PICO-8 formátum
- TIC-80 formátum

Előző