Ü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.
Ha nem akarsz semmit sem telepíteni, akkor csak látogasd meg a weboldalt, ahol egy böngésződbe ágyazott emulátor fut.
Menj a repóba és töltsd le az operációs rendszerednek megfelelő binárist.
Egy egy hordozható futtatható, semmilyen hagyományos telepítési eljárást nem igényel.
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
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 FlopiEgyé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.
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] [-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. |
-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. |
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.
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ű).
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.
A benne lévő fájlok:
Sima szöveges fájl, a MEG-4 Förmver verziójával és a programod nevével.
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.
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.
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.
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.
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ő, és abból is csak egy csatorna használt (64 hangjegy összesen).
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.
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.
Á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.
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.
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).
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.
A kényelmed érdekében számos gyorsbillentyűvel és beviteli metódussal szolgál.
Billentyűkombináció | Leírás |
---|---|
GUI | Vagy Super, néha logó van rajta. UNICODE kódpont beviteli mód. |
AltGr | A szóköztől jobbra lévő Alt billentyű, Kompozit beviteli mód. |
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+K | Katakana beviteli mód. |
Alt+J | Hiragana beviteli mód. |
Alt+A | Ha nem lenne a billentyűzeten ilyen gomb, & (ampersand). |
Alt+H | Ha nem lenne a billentyűzeten ilyen gomb, # (hashmark). |
Alt+S | Ha nem lenne a billentyűzeten ilyen gomb, $ (dollar). |
Alt+L | Ha nem lenne a billentyűzeten ilyen gomb, £ (pound). |
Alt+E | Ha nem lenne a billentyűzeten ilyen gomb, € (euro). |
Alt+R | Ha nem lenne a billentyűzeten ilyen gomb, ₹ (rupee). |
Alt+Y | Ha nem lenne a billentyűzeten ilyen gomb, ¥ (yen). |
Alt+N | Ha nem lenne a billentyűzeten ilyen gomb, 元 (yuan). |
Alt+B | Ha nem lenne a billentyűzeten ilyen gomb, ₿ (bitcoin). |
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. |
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ó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ó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 aktív marad bevitel után is, üss Esc gombot a normál beviteli módhoz való visszatéréshez.
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.
MEGJEGYZÉS
Ez a funkció adattáblákkal került implementálásra, újabb kombinációk vagy akár újabb írásrendszerek könnyedén, bármikor hozzáadhatók a src/inp.c fájlhoz programozói ismeretek nélkül is.
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.
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.
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).
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.
Itt az egész felület egy nagy forráskód szerkesztő felület. Alul látható a státuszsor, 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).
Kód Szerkesztő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.
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.
A normál billentyűkön és beviteli módokon túl (lásd billentyűzet), a kódszerkesztéskor még ezek is elérhetők:
Billentyűkombináció | 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. |
Home | Kurzor mozgatása a sor elejére. |
End | Kurzor mozgatása a sor végége. |
Page Up | Kurzor mozgatása 42 sorral (egy oldallal) feljebb. |
Page Down | Kurzor mozgatása 42 sorral (egy oldallal) lejjebb. |
F1 | Ha a kurzor egy API paraméterlistáján áll, akkor az API funkció súgójára visz. |
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.
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.
A szerkesztőnek három fő mezője van, kettő felül, egy pedig alul.
Szprájt SzerkesztőBalra fent van a szerkesztő mező. Itt tudod módosítani a szprájtot. A elhelyezi a kijelölt pixelt a szprájton, míg a törli őket.
Jobbra mellette látható a szprájtválasztó. 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.
Alul helyezkedik el a pixel paletta. 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, 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.
A szerkesztőmező alatt található az eszköztár a gombokkal. 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.
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.
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.
Felül a nagy részen láthatod és szerkesztheted a térképet. 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őket 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).
A térképszerkesztő mező alatt található az eszköztár, ugyanaz, mint a szprájt szerkesztő képernyőn, ugyanazokkal a funkciókkal és ugyanazokkal a gyorsgombokkal (csak itt 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 térképválasztó. Ez utóbbi a térkép szprájtbankját választja (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).
A gomboktól jobbra helyezkedik el a szprájtválasztó paletta, 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.
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.
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.
Ennek az oldalnak az elrendezése hasonló, mint a szprájt szerkesztő. Balra található a glifszerkesztési terület, jobbra pedig a glifválasztó. (A glif egy adott betű, azaz UNICODE kódpont megjelenített alakja).
Betű SzerkesztőElég egyszerű, balklikk beállítja a kinézetet (előtér), a pedig törli (háttér).
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.
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.
A hangszoró ikonra kattinva (vagy F6) szerkeszthetők a hangeffektek.
A hangeffekteket a programodból az sfx paranccsal tudod megszólaltatni.
Balra található a hanghullám szerkesztő és az eszköztára, jobbra a hangeffekt választó, alattuk pedig a hangeffekt szerkesztő.
HangeffektekJobbra látható a hangeffektek listája, 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.
Alul a zongora, 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.
Alapból a hanghullám 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áraAmikor 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.
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.
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ávokBalra az első oszlopban lehet kiválasztani, melyik zenei sávot szeretnénk szerkeszteni.
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, de ez a blokk csak akkor kel életre, ha folyamatban van a lejátszás.
Mellette négy hasonló oszlop található, mindegyikben hangjegyek. 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. |
A csatornák alatt látható a hangjegyszerkesztő, néhány gombbal balra és egy nagy zongorával jobbra.
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 memóriatérképné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ű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.
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.
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.
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.
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 jobbraBalra 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.
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).
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őkAz oldal tetején látható a memóriaátfedő kiválasztó, minden egyes átfedő méretével. 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.
A tábla alatt láthatod az átfedő adatait hexdump formájában (csak akkor, ha nem üres átfedő van épp kiválasztva).
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.
A menüsorban fent, 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.
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
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 (vagy a Tab billentyűvel) váltogathatsz kód- és adatnézet között.
DebuggolóBalra láthatod a hívásvermet. 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.
Balra látható a programod globális változóinak listája, az épp aktuális értékeikkel.
Jobbra van a verem, 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.
Függetlenül attól, hogy melyik nézet az aktív, a CPU regiszterei mindig látszanak alul. 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.
Ha ezt a nyelvet választod, akkor kezd a programodat a #!c sorral.
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));
}
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.
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 };
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"
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ö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];
FIGYELEM
A tömbökkel ellentétben a mutató feloldásakor nincs méretellenőrzés!
Precedenciájuk szerint csökkenő sorrendben:
Aritmetikai
* / % + -
Relációs
!= == <= >= < >
Logikai
! && ||
Bitenkénti
~ & | << >>
Léptető
++ --
1
2
a = 0; b = ++a * 3; /* a == 1, b == 3 */
a = 0; b = a++ * 3; /* a == 1, b == 0 */
Feltételes
?:
Értékadás
= *= /= %= += -= ~= &= |= <<= >>=
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.
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);
}
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();
}
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ó.
Ha ezt a nyelvet választod, akkor kezd a programodat a #!bas sorral.
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
GOSUB printf("a számláló %d, balshift %d\n", számláló%, getkey%(KEY_LSHIFT))
END SUB
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.
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).
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ö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.
Precedenciájuk szerint csökkenő sorrendben:
Aritmetikai
^ * / MOD + -
Relációs
<> = <= >= < >
Logikai
NOT AND OR
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.
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
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 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 "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.
Ezekkel a parancsokkal direktben elérhető a MEG-4 memóriája, így az MMIO terület is.
Beolvasásvá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
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
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.
Ha ezt a nyelvet választod, akkor kezd a programodat az #!asm sorral.
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
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.
Pontosan ugyanazok, mint a MEG-4 C literáljai.
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 num-nulla paramétert adunk, akkor előjelesen 32 bitre kiegészítik az értéket.
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.
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.
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.
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:
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.
Ha ezt a nyelvet választod, akkor kezd a programodat a #!lua sorral.
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
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ó Lua 5.4.6, 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ő). Bekerült ezek helyett a MEG-4 API, ami pár apró, lényegtelen eltéréssel a jobb integráció kedvéért ugyanúgy használható, mint a többi nyelvnél.
Amennyiben érdekel ez a nyelv, magyarul itt találsz róla bővebb információt, illetve a hivatalos Programming in Lua útmutató (angolul).
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.
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 |
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 |
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.
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) |
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 |
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.
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) |
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.
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.
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).
1
void putc(uint32_t chr)
Paraméter | Leírás |
---|---|
chr | UTF-8 karakter |
1
void printf(str_t fmt, ...)
Paraméter | Leírás |
---|---|
fmt | megjelenítendő formázó sztring |
... | opcionális paraméterek |
1
uint32_t getc(void)
1
str_t gets(void)
1
void trace(str_t fmt, ...)
Paraméter | Leírás |
---|---|
fmt | formázó sztring |
... | opcionális paraméterek |
1
void delay(uint16_t msec)
Paraméter | Leírás |
---|---|
msec | késleltetés ezredmásodpercekben |
1
void exit(void)
1
void sfx(uint8_t sfx, uint8_t channel, uint8_t volume)
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 |
1
void music(uint8_t track, uint16_t row, uint8_t volume)
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 |
1
uint32_t gpio_rev(void)
1
int gpio_get(uint8_t pin)
Paraméter | Leírás |
---|---|
pin | fizikai tüske száma, 1-től 40-ig |
1
int gpio_set(uint8_t pin, int value)
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. |
1
void cls(uint8_t palidx)
Paraméter | Leírás |
---|---|
palidx | szín, paletta index 0-tól 255-ig |
1
uint32_t cget(uint16_t x, uint16_t y)
Paraméter | Leírás |
---|---|
x | X koordináta pixelben |
y | Y koordináta pixelben |
1
uint8_t pget(uint16_t x, uint16_t y)
Paraméter | Leírás |
---|---|
x | X koordináta pixelben |
y | Y koordináta pixelben |
1
void pset(uint8_t palidx, uint16_t x, uint16_t y)
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 |
1
uint16_t width(int8_t type, str_t str)
Paraméter | Leírás |
---|---|
type | betűtípus, -4-től 4-ig |
str | megmérendő sztring |
1
void text(uint8_t palidx, int16_t x, int16_t y, int8_t type, uint8_t shidx, uint8_t sha, str_t str)
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 |
1
void line(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
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 |
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)
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 |
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)
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 |
1
void tri(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
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 |
1
void ftri(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
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 |
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)
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 |
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)
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 |
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)
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 |
1
void mesh(addr_t verts, addr_t uvs, uint16_t numtri, addr_t tris)
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 |
1
void rect(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
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 |
1
void frect(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
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 |
1
void circ(uint8_t palidx, int16_t x, int16_t y, uint16_t r)
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 |
1
void fcirc(uint8_t palidx, int16_t x, int16_t y, uint16_t r)
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 |
1
void ellip(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
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 |
1
void fellip(uint8_t palidx, int16_t x0, int16_t y0, int16_t x1, int16_t y1)
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 |
1
void move(int16_t x, int16_t y, uint16_t deg)
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 |
1
void left(uint16_t deg)
Paraméter | Leírás |
---|---|
deg | változás fokokban, 0-tól 359-ig |
1
void right(uint16_t deg)
Paraméter | Leírás |
---|---|
deg | változás fokokban, 0-tól 359-ig |
1
void up(void)
1
void down(void)
1
void color(uint8_t palidx)
Paraméter | Leírás |
---|---|
palidx | szín, paletta index 0-tól 255-ig |
1
void forw(uint16_t cnt)
Paraméter | Leírás |
---|---|
cnt | mennyit, pixelekben (vagy 1/128-ad csempében maze esetén) |
1
void back(uint16_t cnt)
Paraméter | Leírás |
---|---|
cnt | mennyit, pixelekben (vagy 1/128-ad csempében maze esetén) |
1
void spr(int16_t x, int16_t y, uint16_t sprite, uint8_t sw, uint8_t sh, int8_t scale, uint8_t type)
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 |
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)
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 |
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)
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 |
1
void remap(addr_t replace)
Paraméter | Leírás |
---|---|
replace | egy 256 elemű, szprájt idkat tartalmazó tömb |
1
uint16_t mget(uint16_t mx, uint16_t my)
Paraméter | Leírás |
---|---|
mx | X térképkoordináta csempékben |
my | Y térképkoordináta csempékben |
1
void mset(uint16_t mx, uint16_t my, uint16_t sprite)
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 |
1
void map(int16_t x, int16_t y, uint16_t mx, uint16_t my, uint16_t mw, uint16_t mh, int8_t scale)
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 |
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)
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 |
1
int getpad(int pad, int btn)
Paraméter | Leírás |
---|---|
pad | játékpad index, 0-tól 3-ig |
btn | az egyik játékpad gomb, BTN_ |
1
int prspad(int pad, int btn)
Paraméter | Leírás |
---|---|
pad | játékpad index, 0-tól 3-ig |
btn | az egyik játékpad gomb, BTN_ |
1
int relpad(int pad, int btn)
Paraméter | Leírás |
---|---|
pad | játékpad index, 0-tól 3-ig |
btn | az egyik játékpad gomb, BTN_ |
1
int getbtn(int btn)
Paraméter | Leírás |
---|---|
btn | az egyik mutató gomb, BTN_ vagy SCR_ |
1
int getclk(int btn)
Paraméter | Leírás |
---|---|
btn | az egyik mutató gomb, BTN_ |
1
int getkey(int sc)
Paraméter | Leírás |
---|---|
sc | szkenkód, 1-től 144-ig, lásd billentyűzet |
1
uint32_t popkey(void)
1
int pendkey(void)
1
int lenkey(uint32_t key)
Paraméter | Leírás |
---|---|
key | a gomb, ahogy a billentyűsorból kijött |
1
int speckey(uint32_t key)
Paraméter | Leírás |
---|---|
key | a gomb, ahogy a billentyűsorból kijött |
1
uint32_t rand(void)
1
float rnd(void)
1
float float(int val)
Paraméter | Leírás |
---|---|
val | érték |
1
int int(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float floor(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float ceil(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float sgn(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float abs(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float exp(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float log(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float pow(float val, float exp)
Paraméter | Leírás |
---|---|
val | érték |
exp | kitevő |
1
float sqrt(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float rsqrt(float val)
Paraméter | Leírás |
---|---|
val | érték |
1
float clamp(float val, float minv, float maxv)
Paraméter | Leírás |
---|---|
val | érték |
minv | minimum érték |
maxv | maximum érték |
1
float lerp(float a, float b, float t)
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 |
1
float pi(void)
1
float cos(uint16_t deg)
Paraméter | Leírás |
---|---|
deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra |
1
float sin(uint16_t deg)
Paraméter | Leírás |
---|---|
deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra |
1
float tan(uint16_t deg)
Paraméter | Leírás |
---|---|
deg | fok, 0-tól 359-ig, 0 felfele, 90 jobbra |
1
uint16_t acos(float val)
Paraméter | Leírás |
---|---|
val | érték, -1.0 és 1.0 között |
1
uint16_t asin(float val)
Paraméter | Leírás |
---|---|
val | érték, -1.0 és 1.0 között |
1
uint16_t atan(float val)
Paraméter | Leírás |
---|---|
val | érték, -1.0 és 1.0 között |
1
uint16_t atan2(float y, float x)
Paraméter | Leírás |
---|---|
y | Y koordináta |
x | X koordináta |
1
float dotv2(addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
a | két float címe |
b | két float címe |
1
float lenv2(addr_t a)
Paraméter | Leírás |
---|---|
a | két float címe |
1
void scalev2(addr_t a, float s)
Paraméter | Leírás |
---|---|
a | két float címe |
b | skálázó érték |
1
void negv2(addr_t a)
Paraméter | Leírás |
---|---|
a | két float címe |
1
void addv2(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | két float címe (kimenet) |
a | két float címe |
b | két float címe |
1
void subv2(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | két float címe (kimenet) |
a | két float címe |
b | két float címe |
1
void mulv2(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | két float címe (kimenet) |
a | két float címe |
b | két float címe |
1
void divv2(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | két float címe (kimenet) |
a | két float címe |
b | két float címe |
1
void clampv2(addr_t dst, addr_t v, addr_t minv, addr_t maxv)
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 |
1
void lerpv2(addr_t dst, addr_t a, addr_t b, float t)
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 |
1
void normv2(addr_t a)
Paraméter | Leírás |
---|---|
a | két float címe |
1
float dotv3(addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
a | három float címe |
b | három float címe |
1
float lenv3(addr_t a)
Paraméter | Leírás |
---|---|
a | három float címe |
1
void scalev3(addr_t a, float s)
Paraméter | Leírás |
---|---|
a | három float címe |
b | skálázó érték |
1
void negv3(addr_t a)
Paraméter | Leírás |
---|---|
a | három float címe |
1
void addv3(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
a | három float címe |
b | három float címe |
1
void subv3(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
a | három float címe |
b | három float címe |
1
void mulv3(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
a | három float címe |
b | három float címe |
1
void divv3(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
a | három float címe |
b | három float címe |
1
void crossv3(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
a | három float címe |
b | három float címe |
1
void clampv3(addr_t dst, addr_t v, addr_t minv, addr_t maxv)
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 |
1
void lerpv3(addr_t dst, addr_t a, addr_t b, float t)
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 |
1
void normv3(addr_t a)
Paraméter | Leírás |
---|---|
a | három float címe |
1
float dotv4(addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
a | négy float címe |
b | négy float címe |
1
float lenv4(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void scalev4(addr_t a, float s)
Paraméter | Leírás |
---|---|
a | négy float címe |
b | skálázó érték |
1
void negv4(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void addv4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void subv4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void mulv4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void divv4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void clampv4(addr_t dst, addr_t v, addr_t minv, addr_t maxv)
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 |
1
void lerpv4(addr_t dst, addr_t a, addr_t b, float t)
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 |
1
void normv4(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void idq(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void eulerq(addr_t dst, uint16_t pitch, uint16_t yaw, uint16_t roll)
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 |
1
float dotq(addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
a | négy float címe |
b | négy float címe |
1
float lenq(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void scaleq(addr_t a, float s)
Paraméter | Leírás |
---|---|
a | négy float címe |
b | skálázó érték |
1
void negq(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void addq(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void subq(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void mulq(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
a | négy float címe |
b | négy float címe |
1
void rotq(addr_t dst, addr_t q, addr_t v)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
q | négy float címe |
v | három float címe |
1
void lerpq(addr_t dst, addr_t a, addr_t b, float t)
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 |
1
void slerpq(addr_t dst, addr_t a, addr_t b, float t)
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 |
1
void normq(addr_t a)
Paraméter | Leírás |
---|---|
a | négy float címe |
1
void idm4(addr_t a)
Paraméter | Leírás |
---|---|
a | 16 float címe |
1
void trsm4(addr_t dst, addr_t t, addr_t r, addr_t s)
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) |
1
float detm4(addr_t a)
Paraméter | Leírás |
---|---|
a | 16 float címe |
1
void addm4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | 16 float címe (kimenet) |
a | 16 float címe |
b | 16 float címe |
1
void subm4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | 16 float címe (kimenet) |
a | 16 float címe |
b | 16 float címe |
1
void mulm4(addr_t dst, addr_t a, addr_t b)
Paraméter | Leírás |
---|---|
dst | 16 float címe (kimenet) |
a | 16 float címe |
b | 16 float címe |
1
void mulm4v3(addr_t dst, addr_t m, addr_t v)
Paraméter | Leírás |
---|---|
dst | három float címe (kimenet) |
m | 16 float címe |
v | három float címe |
1
void mulm4v4(addr_t dst, addr_t m, addr_t v)
Paraméter | Leírás |
---|---|
dst | négy float címe (kimenet) |
m | 16 float címe |
v | négy float címe |
1
void invm4(addr_t dst, addr_t a)
Paraméter | Leírás |
---|---|
dst | 16 float címe (kimenet) |
a | 16 float címe |
1
void trpm4(addr_t dst, addr_t a)
Paraméter | Leírás |
---|---|
dst | 16 float címe (kimenet) |
a | 16 float címe |
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)
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 |
1
uint8_t inb(addr_t src)
Paraméter | Leírás |
---|---|
src | cím, 0x00000-tól 0xBFFFF-ig |
1
uint16_t inw(addr_t src)
Paraméter | Leírás |
---|---|
src | cím, 0x00000-tól 0xBFFFE-ig |
1
uint32_t ini(addr_t src)
Paraméter | Leírás |
---|---|
src | cím, 0x00000-tól 0xBFFFC-ig |
1
void outb(addr_t dst, uint8_t value)
Paraméter | Leírás |
---|---|
dst | cím, 0x00000-tól 0xBFFFF-ig |
value | beállítandó érték, 0-tól 255-ig |
1
void outw(addr_t dst, uint16_t value)
Paraméter | Leírás |
---|---|
dst | cím, 0x00000-tól 0xBFFFE-ig |
value | beállítandó érték, 0-tól 65536-ig |
1
void outi(addr_t dst, uint32_t value)
Paraméter | Leírás |
---|---|
dst | cím, 0x00000-tól 0xBFFFC-ig |
value | beállítandó érték, 0-tól 4294967295-ig |
1
int memsave(uint8_t overlay, addr_t src, uint32_t size)
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 |
1
int memload(addr_t dst, uint8_t overlay, uint32_t maxsize)
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 |
1
void memcpy(addr_t dst, addr_t src, uint32_t len)
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 |
1
void memset(addr_t dst, uint8_t value, uint32_t len)
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 |
1
int memcmp(addr_t addr0, addr_t addr1, uint32_t len)
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 |
1
int deflate(addr_t dst, addr_t src, uint32_t len)
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 |
1
int inflate(addr_t dst, addr_t src, uint32_t len)
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 |
1
float time(void)
1
uint32_t now(void)
1
int atoi(str_t src)
Paraméter | Leírás |
---|---|
src | sztring címe, 0x00000-tól 0xBFFFF-ig |
1
str_t itoa(int value)
Paraméter | Leírás |
---|---|
value | az érték, -2147483648-tól 2147483647-ig |
1
float val(str_t src)
Paraméter | Leírás |
---|---|
src | sztring címe, 0x00000-tól 0xBFFFF-ig |
1
str_t str(float value)
Paraméter | Leírás |
---|---|
value | a szám |
1
str_t sprintf(str_t fmt, ...)
Paraméter | Leírás |
---|---|
fmt | formázó sztring |
... | opcionális paraméterek |
1
int strlen(str_t src)
Paraméter | Leírás |
---|---|
src | sztring címe, 0x00000-tól 0xBFFFF-ig |
1
int mblen(str_t src)
Paraméter | Leírás |
---|---|
src | sztring címe, 0x00000-tól 0xBFFFF-ig |
1
addr_t malloc(uint32_t size)
Paraméter | Leírás |
---|---|
size | lefoglalandó bájtok száma |
1
addr_t realloc(addr_t addr, uint32_t size)
Paraméter | Leírás |
---|---|
addr | az allokált buffer címe |
size | bájtok száma, amire átméretez |
1
int free(addr_t addr)
Paraméter | Leírás |
---|---|
addr | az allokált buffer címe |
Ebben a példában egy olyan programot fogunk készíteni, ami egy labdát pattogtat a képernyőn.
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ásaMost 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.
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!
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!
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ásaHasonló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;
}
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. Az y koordináta konstans, mivel függőlegesen nem fogjuk mozgatni az ütőt, csak vízszintesen.
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 az x paraméternek. 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 használjuk, 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, 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).
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.
Ilyenkor három dolgot is szeretnénk. 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. 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();
}}
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.
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érgommbal. 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.
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.
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.
A letöltött képet nem fogod tudni egy-az-egyben beimportálni. Előbb a kép dimenzióját 256 x 256 pixelesre kell állítani. Ne használd az átméretezést, helyette a GIMP-ben válaszd az Image > Canvas size... menüpontot, majd a felugró ablakban a szélesség magassághoz írd be a 256-ot. Így a szprájtlap mérete marad az, ami volt, csak ki lesz egészítve átlátszó pixelekkel. Indítsd el a meg4-et, és húzd rá az ablakára ezt a 256 x 256 pixeles képet az importáláshoz.
A beimportált szprájtlapAmint 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.
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.
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.
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);
}
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.
Próbáljuk ki! Látni fogjuk, hogy a kurzornyilak lenyomására irányt vált a karakterünk.
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. 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. Mivel a karakterünk 4 x 4 szprájtból áll, ezért eleve fel is szorozhatjuk ezeket a szprájt azonosító eltolásokat a tömbben. Még egy valami, csak három szprájtunk van, viszont négy képkockára van szükségünk, így 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.
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);
}
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.
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.
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.
Először is, töltsük be a hanghullám fájlt az Audacity-be.
Hanghullám megnyitása Audacity-benEgybő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ó.
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ízisMozgasd 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ásaA "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ásaA 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).
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ásaA 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ásaA 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éseJelö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.
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ámmintaAmint megvan a fájl, egyszerűen csak húzd rá a MEG-4 ablakára és kész is.
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 megalkotásához felhasznált anyagok