# ๐ŸŽฎ ESP32-S3 GameBoy Emulator **Hochoptimierter GameBoy/GameBoy Color Emulator fรผr Waveshare ESP32-S3-Touch-LCD-2** --- ## ๐Ÿ“‹ Projekt-รœbersicht Dieses Projekt ist ein vollstรคndig funktionsfรคhiger GameBoy Emulator, der auf dem **Waveshare ESP32-S3-Touch-LCD-2** Board lรคuft. Es nutzt den **Peanut-GB** Emulator-Core und erreicht **90-111 FPS** bei vielen Spielen - schneller als der Original GameBoy (59.73 FPS)! ### โœจ Fertige Features - โœ… **GameBoy Emulation** (Peanut-GB Core) - โœ… **ST7789 Display** (2.0", 320x240, 80 MHz SPI) - โœ… **Perfekter 4-Kanal Audio** (I2S MAX98357A, 32768 Hz) - โœ… **SD Card ROM Loading** (FAT32, .gb Dateien) - โœ… **PSRAM Optimization** (8MB Octal Mode, Double-Buffering) - โœ… **Dynamisches Display-Scaling** (1.0x bis 1.67x konfigurierbar) - โœ… **90-111 FPS Performance** (besser als Original!) ### ๐Ÿšง Geplante Features - โณ **8 GameBoy Buttons** (GPIO 8-14, 21 - Hardware fertig, Software TODO) - โณ **NFC ROM-Auswahl** (PN532 I2C - Hardware fertig, Software TODO) - โณ **Potentiometer Controls** (Volume & Brightness - Hardware fertig, Software TODO) - โณ **Link Cable 2-Player** (GPIO 2, 15, 17 - Hardware fertig, Software TODO) --- ## ๐Ÿ—๏ธ Programmablauf & Architektur ### Systemarchitektur ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ESP32-S3 Dual Core โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ CORE 1 โ”‚ CORE 0 โ”‚ โ”‚ (Emulation Task) โ”‚ (Display Task) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ GameBoy Emulator โ”‚ โ”‚ โ”‚ Display Rendering โ”‚ โ”‚ โ”‚ โ”‚ (Peanut-GB) โ”‚ โ”‚ โ”‚ (ST7789 SPI) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ - CPU Emulation โ”‚ โ”‚ โ”‚ - Byte Swapping โ”‚ โ”‚ โ”‚ โ”‚ - PPU Rendering โ”‚ โ”‚ โ”‚ - SPI Transfer โ”‚ โ”‚ โ”‚ โ”‚ - APU Audio โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”ค - Compact Buffer โ”‚ โ”‚ โ”‚ โ”‚ - Memory Map โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ–ฒ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Render Buffer โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ–บโ”‚ Display Buffer โ”‚ โ”‚ โ”‚ โ”‚ (PSRAM 150KB) โ”‚ Swap โ”‚ โ”‚ (PSRAM 150KB) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ Audio Task โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ (I2S Output) โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ I2S Audio โ”‚ โ”‚ SPI Display โ”‚ โ”‚ (MAX98357A) โ”‚ โ”‚ (ST7789) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Programmablauf beim Start ``` 1. app_main() startet โ”‚ โ”œโ”€โ–บ ST7789 Display initialisieren (80 MHz SPI) โ”‚ โ””โ”€โ–บ Backlight auf 80% setzen โ”‚ โ”œโ”€โ–บ SD-Karte mounten (FAT32) โ”‚ โ””โ”€โ–บ ROM laden: /tetris.gb โ”‚ โ”œโ”€โ–บ PSRAM prรผfen (8MB Octal Mode) โ”‚ โ”œโ”€โ–บ Render Buffer allokieren (150 KB) โ”‚ โ””โ”€โ–บ Display Buffer allokieren (150 KB) โ”‚ โ”œโ”€โ–บ I2S Audio initialisieren (32768 Hz, 16-bit) โ”‚ โ””โ”€โ–บ Audio Task starten (Core 1, Priority 5) โ”‚ โ”œโ”€โ–บ Peanut-GB Emulator initialisieren โ”‚ โ”œโ”€โ–บ ROM laden โ”‚ โ”œโ”€โ–บ Callbacks registrieren: โ”‚ โ”‚ โ”œโ”€โ–บ gb_lcd_draw_line() - Zeile rendern โ”‚ โ”‚ โ””โ”€โ–บ audio_callback() - Audio-Sample โ”‚ โ””โ”€โ–บ GameBoy-Palette setzen (DMG Grรผn) โ”‚ โ”œโ”€โ–บ Display Task erstellen (Core 0, Priority 10) โ”‚ โ””โ”€โ–บ Wartet auf frame_ready_sem โ”‚ โ””โ”€โ–บ Emulation Loop starten (Main Loop) โ”‚ โ””โ”€โ–บ Fรผr immer: โ”œโ”€โ–บ gb_run_frame() - Emuliert 1 Frame โ”‚ โ”œโ”€โ–บ CPU lรคuft (70224 Takte) โ”‚ โ”œโ”€โ–บ PPU rendert Zeilen โ†’ gb_lcd_draw_line() โ”‚ โ””โ”€โ–บ APU erzeugt Audio โ†’ audio_callback() โ”‚ โ”œโ”€โ–บ Buffer Swap (Render โ†” Display) โ”‚ โ””โ”€โ–บ frame_ready_sem freigeben โ”‚ โ”œโ”€โ–บ Auf frame_done_sem warten โ”‚ โ””โ”€โ–บ Display Task hat gerendert โ”‚ โ””โ”€โ–บ FPS berechnen & ausgeben (alle 60 Frames) ``` ### Double-Buffering Synchronisation ``` EMULATION TASK (Core 1) DISPLAY TASK (Core 0) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”Œโ”€ Frame N rendern โ”Œโ”€ Wartet auf Semaphore โ”‚ in Render Buffer โ”‚ (frame_ready_sem) โ”‚ โ”‚ โ”‚ gb_run_frame() โ”‚ โ”‚ โ””โ”€โ–บ Zeilen in โ”‚ โ”‚ render_buffer โ”‚ โ”‚ schreiben โ”‚ โ”‚ โ”‚ โ””โ”€ Frame fertig โ”‚ โ”‚ Buffer Swap: โ”‚ render_buffer โ†” โ”‚ display_buffer โ”‚ โ”‚ frame_ready_sem โ”‚ freigeben โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ””โ”€ Semaphore empfangen! Warte auf โ”Œโ”€ Display buffer kopieren frame_done_sem โ”‚ zu compact_buffer โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ (nur GameBoy-Region) โ”‚ โ”œโ”€ SPI Transfer โ”‚ st7789_draw_buffer_ โ”‚ preswapped() โ”‚ โ””โ”€ Fertig! frame_done_sem freigeben frame_done_sem empfangen โ—„โ”€โ”€โ”€โ”€ โ”Œโ”€ Nรคchstes Frame โ”Œโ”€ Wartet wieder... โ”‚ rendern โ”‚ ``` --- ## ๐Ÿงฉ Component-Beschreibung ### 1. Peanut-GB Component **Pfad:** `components/peanut-gb/` **Funktion:** Kern des GameBoy-Emulators. Header-only Bibliothek fรผr GameBoy CPU/PPU/APU Emulation. **Wichtige Funktionen:** - `gb_init()` - Initialisiert den Emulator - `gb_run_frame()` - Emuliert 1 GameBoy Frame (70224 CPU-Takte = 16.7ms) - `gb_lcd_draw_line()` - Callback fรผr jede gerenderte Bildschirmzeile **Optimierung:** Kompiliert mit `-O3` Flag fรผr maximale Performance ### 2. ST7789 Display Driver Component **Pfad:** `components/st7789/` **Funktion:** Treiber fรผr ST7789 TFT-Display (320ร—240 Pixel, RGB565 Farbformat) **Wichtige Funktionen:** - `st7789_init()` - Display initialisieren (80 MHz SPI) - `st7789_draw_buffer_preswapped()` - Optimierter Transfer (vorher RGBโ†’BGR gewandelt) - `st7789_set_backlight()` - Hintergrundbeleuchtung steuern (0-100%) **Besonderheit:** - Chunked SPI Transfer (max 32KB pro Transfer wegen DMA-Limit) - Byte-Swapping wird im Emulator gemacht (RGBโ†’BGR), nicht im Treiber ### 3. Link Cable Component **Pfad:** `components/link_cable/` **Status:** Hardware fertig, Software TODO **Funktion:** 2-Player Multiplayer รผber GPIO (serieller Transfer) **Geplante Nutzung:** - Pokemon-Tausch - Tetris 2-Player - Andere Multiplayer-Games ### 4. NFC Manager Component **Pfad:** `components/nfc_manager/` **Status:** Hardware fertig (PN532 auf I2C), Software TODO **Funktion:** ROM-Auswahl per NFC-Tag scannen **Geplante Funktionsweise:** 1. NFC-Tag scannen 2. UID auslesen 3. In `nfc_roms.json` nachschlagen 4. Entsprechende ROM laden ### 5. Potentiometer Manager Component **Pfad:** `components/potentiometer_manager/` **Status:** Hardware fertig (ADC GPIO 3, 4), Software TODO **Funktion:** Analoge Steuerung fรผr Volume und Brightness **Geplante Nutzung:** - Poti 1 (GPIO 3): Lautstรคrke (0-100%) - Poti 2 (GPIO 4): Helligkeit (10-100%) ### 6. Minizip Component **Pfad:** `components/minizip/` **Funktion:** ZIP-Dekompression fรผr .zip ROM-Dateien **Status:** Eingebunden, aber aktuell nicht genutzt (ROMs sind .gb, nicht gezippt) ### 7. Zlib Component **Pfad:** `components/zlib/` **Funktion:** Compression-Bibliothek (fรผr Minizip und Save-States) **Status:** Eingebunden als Dependency fรผr Minizip --- ## ๐Ÿ”ง Wichtige Code-Bereiche in main.c ### 1. GameBoy Palette ```c // Zeilen 417-422: DMG Grรผn-Palette static const uint16_t gb_palette[4] = { 0xFFFF, // WeiรŸ (Hintergrund) 0xAD55, // Hellgrรผn 0x52AA, // Mittelgrรผn 0x0000 // Schwarz (Vordergrund) }; ``` **Erklรคrung:** GameBoy hat 4 Graustufen (2-bit), hier als RGB565-Werte definiert. ### 2. Audio Callback ```c // Zeilen 424-461: Audio-Sample Callback void audio_callback(struct gb_s *gb, uint16_t left, uint16_t right) ``` **Funktion:** Wird von Peanut-GB fรผr jedes Audio-Sample aufgerufen (32768 Hz). **Ablauf:** 1. Samples in Ring-Buffer schreiben 2. Bei Buffer voll: I2S schreiben 3. APU-Register auslesen fรผr Kanal-Status ### 3. Display Zeilen-Rendering ```c // Zeilen 463-530: LCD Zeilen-Callback static void gb_lcd_draw_line(...) ``` **Funktion:** Wird 144ร— pro Frame aufgerufen (eine Zeile pro Aufruf) **Scaling-Algorithmus:** 1. Vertikales Scaling: `y_base = (line * GB_RENDER_HEIGHT) / 144` 2. Horizontales Scaling: Jedes Pixel wird dynamisch auf 1-2 Output-Pixel gemapped 3. Byte-Swapping: RGB565 โ†’ BGR565 (fรผr ST7789) 4. Pixel-Width-Berechnung verhindert Lรผcken im Bild **Beispiel bei Scale 1.6:** - GameBoy Zeile 0 โ†’ Display Y = 0 - GameBoy Zeile 10 โ†’ Display Y = 16 (10 * 1.6 = 16) - Einige Zeilen werden dupliziert fรผr gleichmรครŸige Skalierung ### 4. Display Task ```c // Zeilen 610-653: Display Rendering Task static void display_task(void *arg) ``` **Funktion:** Lรคuft auf Core 0, rendert fertigen Frame zum Display **Optimierung - Compact Buffer:** 1. Nur GameBoy-Region kopieren (nicht schwarze Rรคnder) 2. Von 320ร—240 Buffer โ†’ 256ร—230 kompakter Buffer 3. 33% weniger SPI-Transfer! 4. Geschwindigkeit steigt von 20ms auf 16ms pro Frame ### 5. Main Loop ```c // Zeilen 702-786: Hauptschleife void app_main(void) ``` **Ablauf:** 1. Display init 2. SD-Card mount 3. PSRAM check & Buffer alloc 4. Audio init & Task start 5. Emulator init 6. Display Task start 7. Unendliche Emulations-Loop --- ## ๐ŸŽฏ Performance-Optimierungen ### 1. PSRAM Double-Buffering **Problem:** SPI-Transfer (10ms) blockiert Emulation **Lรถsung:** 2 Buffer in PSRAM, parallel arbeiten **Ergebnis:** - Core 0: Display rendering (10ms) - Core 1: Emulation (10ms) - Parallel = 50% schneller! ### 2. Display Scaling **Problem:** Fullscreen (320ร—240) zu langsam (20ms) **Lรถsung:** Kleinere Auflรถsung mit schwarzen Rรคndern **Ergebnis:** - Scale 1.0: 160ร—144 = 83 FPS (sehr klein) - Scale 1.5: 240ร—216 = 90-100 FPS (gut) - Scale 1.6: 256ร—230 = 60-90 FPS (beste Balance) - Scale 1.67: 267ร—240 = 55-70 FPS (volle Hรถhe) ### 3. Compact Buffer **Problem:** 320ร—240 Buffer mit vielen schwarzen Pixeln **Lรถsung:** Nur GameBoy-Region transferieren **Ergebnis:** - Vorher: 153.600 Bytes SPI-Transfer - Nachher: 117.760 Bytes (23% weniger!) - Speedup: 3-4ms pro Frame ### 4. Compiler Optimierung **Problem:** Emulator zu langsam (45ms pro Frame) **Lรถsung:** `-O3` Compiler-Flag fรผr Peanut-GB **Ergebnis:** - -O2: 22-25ms - -O3: 16-19ms - **40% schneller!** ### 5. SPI Clock Speed **Problem:** Display-Transfer Bottleneck **Lรถsung:** 80 MHz SPI (Maximum fรผr ST7789) **Ergebnis:** - 40 MHz: 28ms pro Frame - 80 MHz: 16ms pro Frame - **Fast doppelt so schnell!** --- ## ๐Ÿ“Š Performance-Tabelle | Game | Scale | FPS | Frame Time | Audio | |---------------|-------|----------|------------|-------| | Tetris | 1.5 | 60-70 | 14-16ms | โœ… | | DuckTales | 1.5 | 90-111 | 9-11ms | โœ… | | Pokemon | 1.6 | 55-65 | 15-18ms | โœ… | | Super Mario | 1.6 | 60-75 | 13-16ms | โœ… | | Original GB | - | **59.73**| **16.7ms** | โœ… | **Fazit:** Bei vielen Spielen schneller als Original GameBoy! --- ## ๐Ÿš€ Schnellstart - Build & Flash ### Voraussetzungen - **ESP-IDF v4.4** installiert - **Python 3.10** (pyenv empfohlen) - **Git** ### Build ```bash # ESP-IDF Environment laden source ~/esp-idf/export.sh # Projekt bauen cd /home/duffy/Arduino/gameboy/gnuboy idf.py build ``` ### Flash ```bash # Flashen idf.py -p /dev/ttyUSB0 flash # Mit Monitor idf.py -p /dev/ttyUSB0 flash monitor ``` --- ## ๐Ÿ› ๏ธ Hardware ### Hauptkomponenten | Component | Model | Notes | |----------------|---------------------------------|------------------------| | **MCU Board** | Waveshare ESP32-S3-Touch-LCD-2 | 16MB Flash, 8MB PSRAM | | **Display** | ST7789 2.0" | 320ร—240, integriert | | **Audio** | MAX98357A | I2S Amplifier | | **Storage** | MicroSD Card | FAT32, via SPI | ### Pin-Belegung > **Siehe `main/include/hardware_config.h` fรผr alle Pin-Definitionen!** **Display (ST7789 SPI):** - MOSI: GPIO 38, SCLK: GPIO 39, CS: GPIO 45 - DC: GPIO 42, BCKL: GPIO 1 **Audio (I2S):** - BCLK: GPIO 48, LRC: GPIO 47, DIN: GPIO 16 **Buttons (TODO):** - UP: 8, DOWN: 9, LEFT: 10, RIGHT: 11 - A: 12, B: 13, START: 14, SELECT: 21 **NFC (I2C, TODO):** - SCL: GPIO 6, SDA: GPIO 5 (shared mit Touch) **Link Cable (TODO):** - SCLK: GPIO 15, SOUT: GPIO 2, SIN: GPIO 17 **Potentiometer (ADC, TODO):** - Volume: GPIO 3, Brightness: GPIO 4 --- ## ๐Ÿ“ฆ Projekt-Struktur ``` gnuboy/ โ”œโ”€โ”€ CMakeLists.txt # Root CMake โ”œโ”€โ”€ sdkconfig # ESP-IDF Konfiguration โ”œโ”€โ”€ README.md # Diese Datei โ”‚ โ”œโ”€โ”€ main/ โ”‚ โ”œโ”€โ”€ CMakeLists.txt โ”‚ โ”œโ”€โ”€ main.c # Hauptprogramm (ausfรผhrlich kommentiert) โ”‚ โ””โ”€โ”€ include/ โ”‚ โ””โ”€โ”€ hardware_config.h # Pin-Definitionen & Scaling โ”‚ โ””โ”€โ”€ components/ โ”œโ”€โ”€ peanut-gb/ # GameBoy Emulator Core (-O3) โ”œโ”€โ”€ st7789/ # Display Driver (80 MHz SPI) โ”œโ”€โ”€ minizip/ # ZIP Support โ”œโ”€โ”€ zlib/ # Compression โ”œโ”€โ”€ link_cable/ # 2-Player (TODO) โ”œโ”€โ”€ nfc_manager/ # NFC ROM Selection (TODO) โ””โ”€โ”€ potentiometer_manager/ # Volume/Brightness (TODO) ``` --- ## ๐Ÿ”ง Konfiguration ### Display Scaling รคndern In `main/include/hardware_config.h`: ```c // Zeile 54: Scaling-Faktor anpassen #define GB_SCALE_FACTOR 1.6 // ร„ndern auf 1.4, 1.5, 1.67, etc. ``` **Empfohlene Werte:** - `1.4` - Klein, sehr schnell (>100 FPS) - `1.5` - Gut, schnell (90-100 FPS) - `1.6` - Beste Balance (60-90 FPS) โญ - `1.67` - Volle Hรถhe (55-70 FPS) ### Fullscreen aktivieren ```c // Zeile 41: Scaling deaktivieren #define GB_PIXEL_PERFECT_SCALING 0 // Fullscreen 320ร—240 ``` **Warnung:** Fullscreen ist langsamer (~50 FPS bei vielen Spielen) --- ## ๐Ÿ› Troubleshooting ### Build Fehler? ```bash # Clean & Rebuild idf.py fullclean idf.py build ``` ### PSRAM nicht erkannt? ```bash # Prรผfen im Monitor idf.py monitor # Sollte zeigen: "PSRAM: 8191 KB total" ``` Falls nicht: ```bash idf.py menuconfig # โ†’ Component config โ†’ ESP32S3-Specific # โ†’ [*] Support for external, SPI-connected RAM # โ†’ Mode: Octal Mode PSRAM # โ†’ Speed: 80MHz ``` ### Zu langsam? 1. Display Scaling reduzieren (`GB_SCALE_FACTOR 1.4`) 2. Compiler-Optimierung prรผfen (sollte `-O3` sein) 3. SPI-Speed prรผfen (sollte 80 MHz sein) ### Audio knackt? - Normal bei sehr langsamen Spielen (<40 FPS) - Bei >50 FPS sollte Audio perfekt sein --- ## ๐Ÿ“ Lizenz - **Peanut-GB:** MIT License - **Projekt-spezifischer Code:** MIT - **Components:** Siehe jeweilige LICENSE-Dateien --- ## ๐Ÿ™ Credits - **Peanut-GB:** Delta (Header-only GameBoy Emulator) - **Waveshare:** Hardware Board ESP32-S3-Touch-LCD-2 - **Espressif:** ESP-IDF Framework - **Duffy:** Dieses LEGO GameBoy Projekt! ๐ŸŽฎ --- ## ๐ŸŽฏ Roadmap **Nรคchste Schritte:** 1. โœ… Emulator lรคuft perfekt (90-111 FPS!) 2. โœ… Audio funktioniert (4 Kanรคle) 3. โœ… Display-Scaling optimiert 4. โณ Button-Input implementieren 5. โณ ROM-Menรผ auf SD-Card 6. โณ NFC ROM-Auswahl 7. โณ Potentiometer Volume/Brightness 8. โณ Link Cable 2-Player 9. โณ Save-States --- **Viel SpaรŸ beim Zocken! ๐ŸŽฎ๐Ÿ”Š** *Erstellt mit Liebe zum Detail โค๏ธ*