Az NES (Nintendo Entertainment System) egy 1980-as években megjelent 8-bites konzol, amelyből kb. 62 milliót darabot adtak el világszerte. Ez a program a konzol alapvető egységeit emulálja, és megjeleníti. Bár nem törekszik a legpontosabb emulációra, mégis elég pontos ahhoz, hogy többek közt lehessen rajta futtatni az erre a konzolra legtöbbet eladott játékot: Super Mario Bros.
- A repository rekurzívan klónozzuk, vagy klónozás után futtassuk a
git submodule update --init --recursiveparancsot. - Futtassuk a
lib/gl3wmappában futtassuk agl3w_gen.pyszkriptet - Premake5 segítségével a projekt gyökerében futtassuk Linux esetén
premake5 gmake-t, Windows esetén pedigpremake5 vs2022. - Ha Linuxot használunk, akkor töltsük le a
gtk-t. Pl. Ubuntun:sudo apt install libgtk-3-dev - Linux esetén a projekt gyökerében futtassuk a
makeparancsot. Windows esetén nyissuk meg az létrehozott.slnfájlt, és ott fordítsuk.
- NES.h fájlt includeoljuk be a projektbe.
- Példányosítsuk az NES struktúrát (
NES* nes = CreateNES();) - A következő függvényekkel tudunk kazettát belehelyezni, és újraindítani a konzolt:
SetCartNES(NES* nes, char* path),ResetNES(NES* nes),RemoveCartNES(NES* nes). ARemoveCartNES-t hívjuk meg mindenSetCartNESelőtt. - Futtassunk egy főciklust az emulátor bezárásig:
4.1 Töltsük fel anes->controller8 gomb értékeit
4.2 Hozzunk létre egy 256x240 RGB24uint8_tbuffert és állítsuk be aznes->ppu->displayértéket annak címére.
4.3 Hívjuk meg aTickNES-t egy képkocka futtatásához.
4.4 Az adott képkocka kirajzolandó képe megjelenik aznes->ppu->display-ben. - Bezáráskor hívjuk meg a
RemoveCartNES, majd aDestroyNESfüggvényeket.
Ez a fájl tartalmazza a program belépési pontját (main), és felelős az ablakkezelésért, a felhasználói bemenet feldolgozásáért, a grafikus felület (GUI) megjelenítéséért és a fő emulációs ciklus időzítéséért. A projekt SDL2-t használ az ablakkezeléshez és bemenethez, valamint OpenGL 3.0-t és cimgui-t a grafikus felülethez, továbbá Native File Dialog-ot egy fájl megnyitásakor.
Fontosabb konstansok:
WINDOW_SIZE: A skálázási tényező. A natív NES felbontás (256x240) kétszerese kerül megjelenítésre (2 érték esetén).
FPS: Képkocka per másodperc (60 FPS).
int main(int argc, char* argv[])A program:
- SDL2, OpenGL, ImGui inicializálás
- Ablak létrehozása: Létrehoz egy SDL ablakot "NES emulátor" címmel, középre igazítva. A méret az NES natív felbontás és a
WINDOW_SIZEszorzata. - Betűtípus: Betölti a Segoe UI betűtípust a
segoeui.hfájlból. - Emulátor inicializálás
- Meghívja a
CreateNES()függvényt az emulátor magjának példányosításához.
- Meghívja a
- Létrehoz egy
SDL_Texture-t (SDL_TEXTUREACCESS_STREAMINGflaggel), amelyre a PPU egyből rajzol aTickNES->TickPPUsorán. - Főciklus
- A while blokk lefut minden képkockában, ameddig a felhasználó ki nem lép.
- Leállítás
- Eltávolítja a kazettát és megsemmisíti a NES példányt (
DestroyNES). - Leállítja az ImGui-t, törli a textúrákat, ablakokat, kontextusokat és kilép az SDL-ből.
- Eltávolítja a kazettát és megsemmisíti a NES példányt (
A főciklus:
- A
SDL_PollEventhívással dolgozza fel az operációs rendszer eseményeit (pl. ablak bezárása), valamint továbbítja azokat az ImGui-nak. - Az SDL leolvassa a billyentűzetet és beállítja az
nes->controllermezőket. - Zárolja a megjelenítési textúrát (
SDL_LockTexture), és a nyers pixel buffert közvetlenül átadja anes->ppu->displaymutatónak. Így a PPU közvetlenül az SDL textúrába rajzol. - Futtatás: Meghívja a
TickNESfüggvényt, amely lefuttat egy teljes képkockányi emulációt. - Feloldja a textúrát, érvényesítve a PPU által írt adatokat.
- Kezeli az ImGui rajzolást.
- Kirajzolja a NES képernyőt tartalmazó textúrát a háttérbe (
SDL_RenderCopy). - Rárajzolja az ImGui felületet (
ImGui_ImplOpenGL3_RenderDrawData). - Kiszámítja az eltelt időt, és ha a feldolgozás gyorsabb volt, mint a célzott képkocka idő (MSPF, 60 FPS esetén kb. 16ms), akkor a maradék időt várakozással tölti (
SDL_Delay).
