KITAQ ENTWICKLUNGSSYSTEM
BENUTZERHANDBUCH 2026.09

KITAQ SERIES • REFERENZAUSGABE

KITAQGB-BIBLIOTHEK

Werkzeuge zur Spieleentwicklung

Von der ersten Codezeile zur Ausführung, Beobachtung und erneuten Prüfung.
Quellenstand: 14. September 2026 · Englische Referenzausgabe: 14. September 2026

Bibliotheken mit dem nativen Compiler verwenden

lib/ enthält C-Header und C-Quellen, die in das Konsolen-ROM übersetzt werden. PC-Compiler und Hilfswerkzeuge sind in Rust geschrieben; Spielquellen, Zielbibliotheken und ihre APIs bleiben C. Die mitgelieferten SOURCE_MANIFEST.json und LIBRARY_MERGE.json dokumentieren die Auswahl der Bibliotheksquellen.

kitaqgb · Nativer Rust-Compiler und Hilfswerkzeuge · GitHub Actions

Native Builds und Ausführungsprüfungen waren unter Windows, Linux, macOS ARM und macOS Intel erfolgreich. KITAQGB bestand pro Umgebung 48 Tests und 395 Werkzeugprüfungen, KITAQFC 55 und 401. Rust 1.85 wurde ebenfalls getestet. PUBLIC_DISTRIBUTION.json enthält die Hashwerte der installierten Programme und die Herkunft der Prüfergebnisse. Die öffentlichen GitHub-Actions-Workflows bauen und testen diese Quellen unabhängig.

Gespeicherte Referenzausgaben prüfen ROM-Bytes, Diagnosen und Werkzeugformate. Frühere C#-Emulatorprüfungen bleiben historische Nachweise mit ihren ursprünglichen Quellfingerabdrücken. Sie belegen nicht automatisch sämtliche Rust-APIs, echte Hardware oder einen vollständigen Spielstart über das FDS-BIOS. Das nicht verfügbare ursprüngliche PNG-Skript wurde nach seiner Spezifikation neu implementiert; Bytegleichheit mit ihm kann nicht bestätigt werden.

KITAQGB · SHA-256 · KITAQFC · SHA-256

Lokale Bibliothek: Änderungen und Prüfung vom 2026-10-03

Die Quellen aus C:/kitaqgb_project/lib wurden mit der öffentlichen Revision 2de7f4b verglichen. Zeitstempel allein bestimmen nicht die neuere Version. Die lokale Fassung enthält Ergänzungen; die öffentliche enthält andere Ergänzungen und Korrekturen. Dieser Abschnitt beschreibt die gesicherten lokalen Quellen getrennt von bisherigen Nachweisen der öffentlichen API.

physics2d.c behält die Kontakt-API bei und ergänzt zwischengespeicherte Kontakt- und Geschwindigkeitsbegrenzung unter KQ2D_CACHE_SURFACE. Reservieren Sie dabei ROM-Bank 13. Bei KQ2D_EXTERNAL_SCALE_Q8, KQ2D_EXTERNAL_REST_COMPONENT oder KQ2D_EXTERNAL_SURFACE muss der Aufrufer die jeweilige Implementierung liefern. Die folgenden 8.872 Fälle prüfen den Standardpfad ohne diese Definitionen.

KQ3D_BODY_SPHERE=0x04 wählt Kugel–Quader-Kontakte. Der Kugelradius ist half_x. kq3d_overlap_sphere_aabb(sphere, box) schließt Berührung ein und liefert bei NULL-Zeigern oder nichtpositivem Radius 0. Einen speziellen Kugel–Kugel-Löser gibt es nicht. Differenzen, Produkte und Quadratsummen müssen in ihren 16-Bit-Bereichen bleiben.

Ein aktiver body mit KQ3D_BODY_KINEMATIC=0x02 aktualisiert in kq3d_step X/Y-Geschwindigkeit und Position auch bei inverser Masse 0. Z-Position und Z-Geschwindigkeit bleiben unverändert. Kontakte verschieben einen body mit inverser Masse 0 nicht. kq3d_integrate_body überspringt weiterhin statische bodies. break_speed und KQ3D_BODY_BROKEN lösen keine automatische Zerstörung aus.

Lokales bank_switch schreibt kq_bank_current und Adresse 0x2000. Anders als der öffentliche __bankswitch-Pfad aktualisiert es die Bankverfolgung des Compilers nicht. Wechseln Sie aus der festen Bank; verwenden Sie __bankswitch, wenn auch der Wiederherstellungszustand gepflegt werden muss.

Lokales cgb_bg_color/cgb_obj_color und die RGB-Hüllen für einzelne Farben aktivieren die automatische Indexerhöhung nicht. Die CGB-Ausführung bestätigt: Das untere Byte von 0x1234 wird durch 0x12 überschrieben. Verwenden Sie die öffentliche Korrektur oder eine colors-Array-API. Auf DMG erfolgt kein Schreibzugriff.

Lokales metasprite_draw erhöht den Belegungszähler erst nach vollständigem Abschluss auf first_id+count. Bei vorzeitiger Rückkehr an der Grenze von 40 Sprites bleibt er unverändert. Bei first_id=39 und count=2 war der Rückgabewert 1, Platz 39 aktiv und der Zähler 0. Die öffentliche Version aktualisiert ihn für jeden bearbeiteten Platz.

Die lokale Version bietet vram_get_queue_used und vram_get_queue_free, jedoch nicht das öffentliche vram_get_queue_capacity. Die Kapazität ist VRAM_QUEUE_MAX, standardmäßig 32. Nach einem Auftrag waren used=1 und free=31.

wire3d_dmg.h deklariert DrawRect2D nur für das Profil mit 96 Zeilen. DrawBoxEdges2D ist in beiden Profilen deklariert, DrawIndexedEdges nur bei 120 Zeilen. Wählen Sie eine zum Profil passende Quelle. Die Darstellung dieser Funktionen wurde diesmal nicht erneut geprüft. In den gesicherten lib-Quellen wurde keine Implementierung von DrawRect2D oder DrawBoxEdges2D gefunden. Es sind nur Deklarationen; für Aufrufe ist eine eigene Implementierung nötig.

Lokales audio_vblank enthält weder die öffentlichen AudioVBlank_QueueReset/QueueRefill/QueuePlay-APIs noch audio_vblank_queue.inc. Auch ZX0 gibt es nur öffentlich. Diese Ergänzungen zählen nicht zu den nachgewiesenen lokalen Funktionen.

kq3d_overlap_sphere_aabb
u8 kq3d_overlap_sphere_aabb(const KQBody3D* sphere, const KQBody3D* box);

KQ3D_BODY_SPHERE=0x04 wählt Kugel–Quader-Kontakte. Der Kugelradius ist half_x. kq3d_overlap_sphere_aabb(sphere, box) schließt Berührung ein und liefert bei NULL-Zeigern oder nichtpositivem Radius 0. Einen speziellen Kugel–Kugel-Löser gibt es nicht. Differenzen, Produkte und Quadratsummen müssen in ihren 16-Bit-Bereichen bleiben.

physics3d.c / physics3d.h

Ausgeführte Prüfungen

2D-Standardpfad: 8.872 erfolgreiche Fälle über die KOKURA-C-API mit automatischer Hardwarewahl. Geprüft wurden Geschwindigkeitsbegrenzung, Kontakte, vorzeichenbehaftete Q8-Multiplikation und Kontaktzeit. Dies war keine getrennte Prüfung mit expliziter DMG/CGB-Wahl.

Physikgrenzen: 19 Fälle jeweils auf DMG und CGB, alle 38 Läufe erfolgreich. Getrennte 3D-Erweiterungs- und Sprite/VRAM/Paletten-Reproduktionen entsprachen in beiden Modi den Erwartungen. Palette und Sprites reproduzieren Fehler; sie bestätigen keine korrekte Funktion.

Dies sind Emulatorprüfungen von ROMs des C#-Compilers. Sie belegen weder Rust-Gleichwertigkeit, reale Hardware, Audio, Darstellung noch die Korrektheit aller APIs. Vorhandene Bilder und Prüfungen bleiben historische Ergebnisse, gebunden an die Quellfingerabdrücke ihrer Aufzeichnungen.

Quellfingerabdrücke, Eingaben, erwartete und gemessene Werte sowie Wiederholungsschritte · evidence.tar.gz · verify_rom_cases.py · verify_surface.py

1. Die Bibliothek verwenden

Die Bibliothek besteht aus wiederverwendbaren C-Quelldateien, die auf den __-Intrinsics von KITAQGB aufbauen. Sie umfasst Bildschirmsteuerung, Physik, 3D-Darstellung und Kommunikation.

c
#include "input.h"
// 起動時に一度
input_init();
// ゲームの1フレームに一度
input_update();
if (input_pressed(BTN_A)) { /* 決定処理 */ }
powershell
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\gb_input.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input.gb --profile=dev

Jeder API-Eintrag enthält Deklaration, Header, Implementierung und ein Anwendungsbeispiel. Die Aufruffragmente zeigen die Argumentübergabe; das aufrufende Programm muss die benötigten Puffer und Objekte bereitstellen. Im Abschnitt mit vollständigen Programmen finden Sie direkt zu ROMs kompilierbare Beispiele.

2. Ein Spielbild vorbereiten

system_init initialisiert die Bildverwaltung. system_wait_vblank wartet auf VBlank und erhöht den Software-Bildzähler. Auf dem GB ruft diese Wartefunktion den VBlank-Callback kooperativ auf. Das Registrieren eines Callbacks richtet keinen Hardware-Interrupt-Handler ein.

  1. Aktualisieren Sie den Eingabezustand einmal.
  2. Berechnen Sie Bewegung, Kollisionen und Spielzustand.
  3. Bereiten Sie Zeichenbefehle und OAM-Daten vor.
  4. Übertragen Sie die Änderungen während VBlank.
  5. Lassen Sie die Musik entsprechend dem gewählten Treiber weiterlaufen.

Wenn Sie mehrere wartende Funktionen wie vram_flush und sprite_flush_oam kombinieren, kann eine einzige Spielaktualisierung zwei Bildwechsel abwarten. Haben Sie bereits selbst gewartet, kann die entsprechende _now-Funktion geeignet sein. Dabei müssen Sie deren Anforderungen an den Zugriffszeitpunkt selbst sicherstellen.

3. Eingaben und Tastenwiederholung

input_down(mask) prüft gehaltene Tasten, input_pressed(mask) neu gedrückte Tasten und input_released(mask) gerade losgelassene Tasten. input_repeat(mask) liefert die für Menüs übliche Tastenwiederholung. Diese Zustände ändern sich bei input_update(). Mehrere Aktualisierungen innerhalb desselben Spielbildes können ein gerade erkanntes Drücken wieder überschreiben.

TastenMasken
Rechts, Links, Oben, Unten0x01 / 0x02 / 0x04 / 0x08
A, B, SELECT, START0x10 / 0x20 / 0x40 / 0x80

gb_input.c zählt das Drücken von A. Prüfen Sie zunächst, dass das Gedrückthalten den Zähler nicht fortlaufend erhöht. Ersetzen Sie anschließend input_pressed durch input_down, um den Unterschied zu sehen.

4. Hintergrund, Text und VRAM

vram_queue_bg_tile stellt eine Kachel in die Warteschlange, vram_queue_bg_rect ein Rechteck und vram_queue_bg_block die Übertragung eines Arrays. Prüfen Sie die Rückgabewerte und vram_get_overflowed(), um einen Überlauf zu erkennen. Behält ein Auftrag einen Quellzeiger, müssen die Quelldaten bis zum Ende der Übertragung unverändert bleiben. Der Speicher muss gültig und seine Bank zugänglich sein.

text.c und menu.c implementieren die in rpg.h deklarierten Funktionen für Text, Auswahlmenüs und Fenster. Stimmen Sie die Zuordnung von Zeichen zu Kacheln auf die Schrift ab, die Sie ins VRAM laden. Diese Zuordnung entspricht nicht automatisch der des Handbuchhelfers m_text.

5. Sprites und Animation

Beginnen Sie mit sprite_init, sprite_alloc, sprite_set_tile und sprite_set_pos. Der GB unterstützt insgesamt 40 Sprites und höchstens 10 pro Bildschirmzeile. Achten Sie deshalb auch darauf, wie viele Sprites sich auf gleicher Höhe befinden. sprite_warn_scanline_overflow und sprite_max_scanline_count helfen bei der Prüfung.

MetaSpritePart beschreibt die relative Anordnung von OBJ-Teilen. SpriteAnim beschreibt die Kacheln einer Animation und deren Wechselintervalle. Die von metasprite_draw gezeichneten Teile müssen zu den reservierten OBJ-Plätzen passen. Das A in gb_sprite.c zeigt, wie eine Zeichenkachel als Sprite verwendet wird.

6. Farbe, Scrollen, Rastereffekte und Kamera

Die RGB-Argumente von cgb_bg_rgb und cgb_obj_rgb liegen zwischen 0 und 31, nicht zwischen 0 und 255. CGB_RGB15 fasst diese Komponenten in einem 16-Bit-Wert zusammen. Die übergeordneten CGB-Palettenfunktionen sind so ausgelegt, dass sie auf dem DMG keine Wirkung haben.

Scroll_SetBg positioniert den Hintergrund und Scroll_SetWindow das Fenster. Das Kameramodul berechnet aus Weltkoordinaten einen sichtbaren Ausschnitt. Unterscheiden Sie dabei zwischen den Festkommaeinheiten der Kamera und ganzzahligen Bildschirmpixeln.

raster.c erstellt Scrolltabellen für Bildstreifen und horizontale Verzerrungen pro Zeile. Die Operationen von Scroll_SplitCommit verwenden die VBlank- und STAT-Vektoren. Musik- und Scrollroutinen dürfen denselben Vektor nicht unabhängig voneinander belegen. Führen Sie ihre Aufrufe bei Bedarf in einem gemeinsamen Interrupt-Handler zusammen.

7. Musik und Soundeffekte

Kompilieren Sie zuerst audio_hwregs_gb.c, danach audio.c und zuletzt den Spielquelltext. Definiert das Spiel die Register NR10–NR52 bereits, dürfen Sie diese Definitionen nicht doppelt einbinden. Nach Audio_Init wird Audio_Update üblicherweise einmal pro Bild aufgerufen.

Audio_PlayMusic(bank,song) gibt die Musikbank ausdrücklich an. Audio_PlaySFXBanked spielt einen Effekt aus einer anderen Bank ab. Prioritäten entscheiden darüber, welcher Effekt einen gemeinsam genutzten Hardwarekanal erhält. Der GB besitzt vier Hardware-Soundkanäle: CH1, CH2, CH3 und CH4.

Die Musikstream-Befehle AUDIO_CMD_NOTE, AUDIO_CMD_SET_INST und AUDIO_CMD_STOP_CHANNEL verwenden dieselben Kanal-IDs wie die normale API: 0=CH1, 1=CH2, 2=CH3, 3=CH4. CH1 erzeugt Pulse mit Sweep, CH2 Pulse, CH3 Wellenformen und CH4 Rauschen. Der Header definiert AUDIO_NOTE_MAX=67.

Der einfache CH1-Effektstrom liest pro Bild ein Paar aus Note und Lautstärke und endet bei Note 0. CH3 verwendet ein anderes Format und eine andere Endmarkierung. Ein Beispiel finden Sie in gb_sound.c. Überblendungen schreiten bei Audio_Update fort; ohne weitere Aktualisierungen bleibt auch die Überblendung stehen.

8. Musik im VBlank-Interrupt

audio_vblank.c verwendet ein eigenes Wiedergabeformat. Zeitgesteuerte Datensätze bestehen aus fünf Bytes: delay, ch1_note, ch2_note, ch3_note, ch4_noise_param. Der Treiber liest direkt adressierbare Musikdaten oder verarbeitet eine WRAM-Warteschlange. Initialisieren Sie den Warteschlangenmodus mit AudioVBlank_QueueReset, übergeben Sie vollständige Fünf-Byte-Datensätze mit AudioVBlank_QueueRefill und starten Sie mit AudioVBlank_QueuePlay. Nur ein einziger Produzent im Vordergrund darf die Warteschlange nachfüllen. LOOP wird nur in direkten Streams erkannt, IMMEDIATE nur im Warteschlangenmodus. Normale audio.c-Streams können nicht unverändert übergeben werden.

powershell
# この方式を採用したROMに対してのみ行います。
.\kitaqgb\scripts\patch_gb_vblank_irq.ps1 .\out\game.gb .\out\game.map

Der Patch setzt den VBlank-Vektor bei 0x0040 und aktualisiert die Prüfsumme. Wenden Sie ihn nur auf eine für diesen Treiber vorbereitete ROM an. Prüfen Sie mögliche Konflikte mit eigenen VBlank-ISRs und geteiltem Scrollen. Eine erfolgreiche Kompilierung belegt noch keine hörbare Wiedergabe. Nehmen Sie den Ton mit KOKURA auf und prüfen Sie, ob das Musikstück tatsächlich fortschreitet.

9. Festkomma, Physik und 3D

Bei der Q8.8-Arithmetik aus fixed.h steht 256 für 1,0 und 128 für 0,5. gb_fixed.c zeigt fix_from_int, fix_mul und fix_to_int. Legen Sie die Wertebereiche vor der Implementierung fest, um Überläufe zu vermeiden.

physics2d verarbeitet Rechtecke, physics2d_circle Kreise und physics3d achsenparallele 3D-Quader (AABBs). Initialisieren Sie die vom Aufrufer bereitgestellten Welt- und Körperarrays, setzen Sie Geschwindigkeit oder Schwerkraft und führen Sie dann einen Simulationsschritt aus. Verwenden Sie einheitliche Einheiten für Positionen und Geschwindigkeiten pro Schritt; die Bibliothek rechnet nicht automatisch in Pixel um. Das Kreisbeispiel verwendet Position 40 und Geschwindigkeit 2. Eine inverse Masse von null kennzeichnet einen statischen Körper. Beachten Sie die in den Headern angegebenen Bereiche für Koeffizienten und Zwischenrechnungen. Besonders wichtig ist die Funktion kq2d_body_apply_friction: Sie wandelt ihren Koeffizienten in ein vorzeichenbehaftetes Byte um. Werte von 128 bis 255 werden dadurch negativ und sind keine gewöhnlichen vorzeichenlosen Q8-Dämpfungsfaktoren. gb_circle.c enthält ein vollständiges Beispiel für einen Simulationsschritt.

wire3d_dmg ist eine Bibliothek für monochrome Drahtgittergrafik auf dem Game Boy. Kompilieren Sie wire3d_dmg_96.c für 128 × 96 oder wire3d_dmg.c für 128 × 120 und verwenden Sie die Funktionen Wire3DDMG_*. wire3d und dmg3d bieten alternative Einstiegspunkte für die Profile mit 96 beziehungsweise 120 Zeilen. Kompilieren Sie pro Programm nur einen Einstiegspunkt. wire3d_cgb ist der Renderer für die Farbdarstellung. Reservieren Sie die RAM-, VRAM- und Bildschirmbereiche für jeden Renderer ausdrücklich. Die beiden monochromen Renderer verwerfen Kanten, die den zulässigen Tiefenbereich überschreiten, anstatt sie an dessen Grenzen abzuschneiden. Ihre Verdeckungsprüfung verwendet umschließende Rechtecke von Flächen und fünf Prüfpunkte je Linie. Sie ist daher eine Näherung und kein Tiefentest für jedes Pixel. Der CGB-Pfad nutzt doppelte Taktrate und DMA und benötigt --cgb=cgb_only.

Wire3DDMG_BeginFrame (WIRE3D_DMG_HEIGHT=96) leert den Zeichenpuffer. Wire3DDMG_BeginFrame (WIRE3D_DMG_HEIGHT=120) setzt lediglich den Verdeckungszustand zurück: DMG3D überträgt die vorgemerkten Bytes und löscht sie dabei. Bei der Übertragung geänderter Kacheln werden auch die Kacheln des vorherigen Bildes berücksichtigt, damit alte Pixel verschwinden. Die zusätzliche Übertragung nutzt einen Teil des Hauptpuffers gemeinsam; sie besitzt keinen unabhängigen Puffer. Passen Sie deshalb die Reihenfolge der Aufrufe an den verwendeten Renderer an.

Verwenden Sie für CGB-Linien die Farben 1, 2 und 3. Der normale Modus mit 128 × 96 kombiniert die Farbbits: Überlagern sich Farbe 1 und Farbe 2, entsteht Farbe 3. Farbe 0 löscht keine Linie. Löschen Sie stattdessen das Bild oder verwenden Sie die dafür vorgesehenen Löschfunktionen. Im normalen Modus erfassen Wire3DCGB_DrawLine2D und die Modelldarstellung nicht den Bereich für eine Teilübertragung. Verwenden Sie Wire3DCGB_DrawLineClipped2D, wenn beim Linienzeichnen auch dieser Bereich erfasst werden soll. Mit Wire3DCGB_InvalidateFrameHistory nehmen Sie den gesamten Zeichenbereich in die nächste Teilübertragung auf.

Der Modus mit 160 × 144 reserviert höchstens 127 Kacheln pro Bild. Kann der schnelle Linienzeichner keine weitere Kachel reservieren oder trifft er auf eine Koordinate außerhalb des Bildschirms, liefert Wire3DCGB_GetFullScreenOverflow() einen Wert ungleich null. Weitere Pixelschreibzugriffe unterbleiben bis zur Initialisierung des nächsten Bildes. Halten Sie die Eckpunkte innerhalb des gewählten Zeichenbereichs. Der rechte Sicherheitsrand der Dreiecksmaske reicht im Modus 128 × 96 höchstens bis X=127, im Vollbildmodus bis X=159. Beachten Sie die bei den APIs beschriebene WRAM-Bankzuordnung, insbesondere bei Vollbild- und FastMap-Funktionen.

10. Szenen, Objektpools und Geschossmuster

scene verwaltet Zustände wie Titel, Spiel und Pause; entity bietet einen Objektpool fester Kapazität; chain stellt die Nachführung gegliederter Körper und einen Positionsverlauf bereit. Verwenden Sie ChainBody, um eine gegliederte Schlange oder ein Seil zu bewegen. Prüfen Sie vor der Verwendung des von entity_get gelieferten Pointers auf Fehlerwerte der Reservierung wie 0xFF.

danmaku bietet Geschosspools mit Festkommaarithmetik, gerichtetes und fächerförmiges Erzeugen von Geschossen sowie Treffer- und Streiferkennung. Sein CGB-Pfad setzt Geschosse in den Hintergrund ein und umgeht damit die übliche OBJ-Anzahlbegrenzung. Rechenzeit pro Bild und Bandbreite für Hintergrundübertragungen bleiben jedoch begrenzt. Messen Sie die Verarbeitungszeit, statt allein eine hohe Geschosszahl anzustreben.

11. Rollenspiele, Adventures, Strategiespiele und Speichern

rpg.h bündelt Deklarationen für Zufallszahlen, Flags, Aufgaben, Kompression, Text, Menüs, Skripte, Karten, Spielstände und Wegsuche. Die Implementierungen verteilen sich auf Dateien wie rng.c, flags.c, rle.c und text.c. Wählen Sie anhand der API-Referenz die benötigten Implementierungsdateien aus.

Ein fester Wert für rng_seed erzeugt eine wiederholbare Folge für Tests. Prüfen Sie bei jeder Bereichsfunktion, ob die obere Grenze eingeschlossen ist. flag_get und flag_set arbeiten mit Bitmengen. save.c greift nach dem MBC5-Schema auf SRAM zu. Die im ROM-Header angegebene RAM-Kapazität muss zum Speicherbereich des Spiels passen.

Trennen Sie die Brett-, Zuglisten- und Rücknahmefunktionen aus slg.h sowie die Wegsuche aus slg_path.c von Ihren eigenen Spielregeln und Bewertungsfunktionen. Breite, Höhe und Arbeitsarrays müssen sowohl die Bibliotheksgrenzen als auch die Anforderungen der einzelnen Argumente einhalten.

12. Kommunikation

link.c stellt serielle Byteübertragungen bereit. link_packet.c ergänzt bei Bedarf eine Paketschicht. Binden Sie link_hwregs_gb.c zuerst ein. Polling- und Interrupt-Modus benötigen unterschiedliche Aufrufe. Im Interrupt-Modus muss das Spiel den Vektor 0x0058 mit der passenden Routine verbinden.

Die logischen Link4_*-Operationen und die Operationen für den physischen Nintendo-DMG-07-Adapter unter LinkDmg07_* sind getrennte Systeme. DMG-07 arbeitet mit einem externen Takt: Rufen Sie LinkDmg07_Poll häufig und LinkDmg07_TickFrame einmal pro Bild auf. Nur einmal pro Bild zu pollen kann zeitlich unzureichend sein. Prüfen Sie mit den KOKURA-Aufträgen für pair/dmg07 das Verbinden, den Start, das Trennen und das erneute Verbinden jeweils gesondert.

13. Banken, Ressourcen und Fehlersuche

BankPtr verbindet eine Banknummer mit einem Zeiger. far_data_read liest Ressourcen aus einer anderen Bank ins RAM. Das Ressourcenmodul ordnet IDs den entsprechenden Beschreibungen zu. Für Gültigkeitsdauer, Bankzugriff und Größen bleibt das Spiel verantwortlich.

debug_trace_u8 und debug_trace_u16 protokollieren Werte im RAM; debug_assert_fail speichert einen Diagnosecode. Diese Funktionen geben keinen printf-Text auf einer PC-Konsole aus. Untersuchen Sie die Einträge über die Speicheransicht des Emulators. gb_debug.c protokolliert HP=42.

vram_get_queue_capacity() liefert die Gesamtzahl der Befehlsplätze, standardmäßig 32. vram_get_queue_free() liefert die Zahl der freien Plätze, vram_get_queue_used() die Zahl der belegten Plätze. Jeder vorgemerkte Auftrag benötigt unabhängig von seiner Übertragungsgröße genau einen Platz. Diese Abfragen beschreiben die Übertragungswarteschlange, nicht den ungenutzten Teil des Hardware-VRAMs.

Vollständige Beispielprogramme

Enthalten sind alle Programme, die gemeinsamen Header, die bereitgestellte ascii.c und die daraus konvertierten Ressourcen. Namen mit m_ am Anfang bezeichnen Hilfsfunktionen für diese Handbücher. Lesen Sie jeden Build-Befehl zusammen mit dem erwarteten Ergebnis und dem Prüfprotokoll. Führen Sie die Befehle im übergeordneten Ordner der nebeneinanderliegenden Repositories aus.

Skript zur Stapelkompilierung / Ergebnisse und Bildschirmaufnahmen

Den mitgelieferten Zeichensatz anzeigen gb_font.c

Zweck: Zeigt, welche Buchstaben, Ziffern und Satzzeichen die mitgelieferte eigens erstellte Schrift enthält und wie sie gezeichnet werden.

Funktionsweise: m_init bereitet Anzeige und Schrift vor. m_text zeichnet jede Zeile; m_put zeichnet das doppelte Anführungszeichen mit Zeichencode 34.

Bedienung und erwartetes Ergebnis: Prüfen Sie, ob 26 Großbuchstaben, 26 Kleinbuchstaben, 10 Ziffern und 30 Satzzeichen erscheinen und alle Zeichen gut lesbar sind. Es ist keine Eingabe erforderlich.

Den mitgelieferten Zeichensatz anzeigen: Prüfen Sie, ob 26 Großbuchstaben, 26 Kleinbuchstaben, 10 Ziffern und 30 Satzzeichen erscheinen und alle Zeichen gut lesbar sind. Es ist keine Eingabe erforderlich.
Anzeigebeispiel: Prüfen Sie, ob 26 Großbuchstaben, 26 Kleinbuchstaben, 10 Ziffern und 30 Satzzeichen erscheinen und alle Zeichen gut lesbar sind. Es ist keine Eingabe erforderlich.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_font.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_font.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Display the letters, digits and punctuation from the supplied ascii.c font.
// Expected: Uppercase, lowercase, numbers and all 30 supplied punctuation glyphs
#include "gb_common.h"


// Lay out every supplied character category, yielding between rows. The final
// m_put uses character code 34 to display the double quote separately.
void main() {
    m_init();
    m_text(2,3,"FONT");
    m_text(2,5,"ABCDEFGHIJKLMNOP"); m_wait();
    m_text(2,6,"QRSTUVWXYZ"); m_wait();
    m_text(2,8,"0123456789"); m_wait();
    m_text(2,10,"abcdefghijklmnop"); m_wait();
    m_text(2,11,"qrstuvwxyz"); m_wait();
    m_text(2,13,"!#$%&'()*+,-./"); m_wait();
    m_text(2,14,":;<=>?@[]^_`{}~"); m_wait();
    m_put(16,13,34); m_wait();
    while (1) { m_wait();  }
}
Die erste Textausgabe gb_hello.c

Zweck: Zeigt den grundlegenden Ablauf zum Starten einer ROM und zum Zeichnen von Text und einer Zahl im Hintergrund.

Funktionsweise: Nach m_init zeichnet m_text die Begrüßung und m_number formatiert 42. Die abschließende Schleife wartet auf Frames und lässt das Bild sichtbar.

Bedienung und erwartetes Ergebnis: Der Bildschirm zeigt HELLO WORLD und 042. Die führende Null entsteht durch die Dezimaldarstellung mit drei Stellen.

Die erste Textausgabe: Der Bildschirm zeigt HELLO WORLD und 042. Die führende Null entsteht durch die Dezimaldarstellung mit drei Stellen.
Anzeigebeispiel: Der Bildschirm zeigt HELLO WORLD und 042. Die führende Null entsteht durch die Dezimaldarstellung mit drei Stellen.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_hello.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_hello.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Display a first message on screen.
// Expected: HELLO WORLD and 042
#include "gb_common.h"


// Initialize the display/font, write HELLO WORLD and a three-digit 042,
// then wait for frames so the result remains visible.
void main() {
    m_init();
    m_text(2,3,"HELLO");
    m_text(2,5,"HELLO WORLD");
    m_number(42);
    while (1) { m_wait();  }
}
Mit breiterem Zwischentyp rechnen gb_arithmetic.c

Zweck: Zeigt, wie ein Zwischenergebnis gespeichert wird, das nicht in acht Bit passt.

Funktionsweise: (u16)200 + 100 ergibt 300. Das Programm teilt das Ergebnis durch 10 und wandelt es anschließend zur Anzeige in u8 um. Beachten Sie, dass die Typverbreiterung vor der Addition erfolgt.

Bedienung und erwartetes Ergebnis: 030 steht für das berechnete Ergebnis 30.

Mit breiterem Zwischentyp rechnen: 030 steht für das berechnete Ergebnis 30.
Anzeigebeispiel: 030 steht für das berechnete Ergebnis 30.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_arithmetic.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_arithmetic.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Variables, arithmetic and type conversion.
// Expected: 030
#include "gb_common.h"


// Widen before adding 200 + 100, divide the 16-bit sum, and display 30.
// The cast demonstrates avoiding an 8-bit intermediate result.
void main() {
    m_init();
    m_text(2,3,"ARITHMETIC");
    u16 sum;
    sum = (u16)200 + 100;
    m_number((u8)(sum / 10));
    while (1) { m_wait();  }
}
Verzweigungen und Schleifen gb_control.c

Zweck: Erprobt for, continue, while, do/while und switch in einer kleinen Berechnung.

Funktionsweise: Die Summe von 0 bis 7 ohne 3 ergibt 25. Die while-Schleife erhöht auf 30, do/while auf 32, und switch wählt case 32, um 42 zuzuweisen.

Bedienung und erwartetes Ergebnis: 042 ist das Endergebnis dieser Schleifen und Verzweigungen.

Verzweigungen und Schleifen: 042 ist das Endergebnis dieser Schleifen und Verzweigungen.
Anzeigebeispiel: 042 ist das Endergebnis dieser Schleifen und Verzweigungen.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_control.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_control.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Conditional branches and loops.
// Expected: 042
#include "gb_common.h"


// Exercise loop control and a final branch, then display the selected value 42.
void main() {
    m_init();
    m_text(2,3,"CONTROL");
    u8 i; u8 sum; sum=0;
    for (i=0;i<8;i++) { if (i==3) continue; sum=(u8)(sum+i); }
    while (sum<30) { sum++; }
    do { sum++; } while (sum<32);
    switch (sum) { case 32: sum=42; break; default: sum=0; break; }
    m_number(sum);
    while (1) { m_wait();  }
}
Funktionen, Arrays, Strukturen und Zeiger gb_aggregate.c

Zweck: Zeigt, wie Werte gruppiert und über Funktionen und Zeiger angesprochen werden.

Funktionsweise: Das Programm kopiert einen Point mit (10,20) und schreibt dann über einen Zeiger 1 bis 4 in ein Array. Es addiert das Funktionsergebnis 30, die Arraywerte 1, 2 und 4 sowie die Konstante 5.

Bedienung und erwartetes Ergebnis: Die Summe wird als 042 angezeigt. Verfolgen Sie die Strukturkopie, die Schreibzugriffe auf ptr[i] und den Rückgabewert der Funktion.

Funktionen, Arrays, Strukturen und Zeiger: Die Summe wird als 042 angezeigt. Verfolgen Sie die Strukturkopie, die Schreibzugriffe auf ptr[i] und den Rückgabewert der Funktion.
Anzeigebeispiel: Die Summe wird als 042 angezeigt. Verfolgen Sie die Strukturkopie, die Schreibzugriffe auf ptr[i] und den Rückgabewert der Funktion.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_aggregate.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_aggregate.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Functions, arrays, structures and pointers.
// Expected: 042
#include "gb_common.h"

typedef struct { u8 x; u8 y; } Point;
// Add two byte values and explicitly narrow the returned result to u8.
u8 add(u8 a,u8 b) { return (u8)(a+b); }
// Copy a structure, fill an array through a pointer, and combine selected values
// through add() to produce 42. Keep the final screen visible in the idle loop.
void main() {
    m_init();
    m_text(2,3,"AGGREGATE");
    Point a; Point b; u8 i; u8 data[4]; u8* ptr;
    a.x=10; a.y=20; b=a; ptr=data;
    for(i=0;i<4;i++) ptr[i]=(u8)(i+1);
    m_number((u8)(add(b.x,b.y)+ptr[0]+ptr[1]+ptr[3]+5));
    while (1) { m_wait();  }
}
Bitflags und Pufferkopie gb_bits_memory.c

Zweck: Packt Flags in ein Byte und kopiert einen Puffer in einen getrennten Speicherbereich.

Funktionsweise: __memset löscht vier Bytes. Das Programm setzt Bit 3, invertiert Bit 1 und kopiert anschließend alle vier Bytes mit __memcpy.

Bedienung und erwartetes Ergebnis: Das erste Zielbyte wird als 010 angezeigt; Bit 3 trägt 8 und Bit 1 trägt 2 bei.

Bitflags und Pufferkopie: Das erste Zielbyte wird als 010 angezeigt; Bit 3 trägt 8 und Bit 1 trägt 2 bei.
Anzeigebeispiel: Das erste Zielbyte wird als 010 angezeigt; Bit 3 trägt 8 und Bit 1 trägt 2 bei.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe  kitaq-docs/samples/gb_bits_memory.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_bits_memory.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Bit operations and memory copying.
// Expected: 010
#include "gb_common.h"
void __memset(void* dst,u8 value,u16 len);
void __memcpy(void* dst,const void* src,u16 len);
void __bit_set(u8* base,u16 bit);
void __bit_toggle(u8* base,u16 bit);

// Clear the source bytes, set bits 3 and 1, copy the buffer, and display 8 + 2 = 10.
void main() {
    m_init();
    m_text(2,3,"BITS MEMORY");
    u8 data[4]; u8 copy[4];
    __memset(data,0,4); __bit_set(data,3); __bit_toggle(data,1);
    __memcpy(copy,data,4); m_number(copy[0]);
    while (1) { m_wait();  }
}
Neue Tastendrücke zählen gb_input.c

Zweck: Unterscheidet einen neuen Tastendruck von einer weiterhin gedrückten Taste.

Funktionsweise: In jedem Frame wird input_update aufgerufen. Der Zähler steigt nur, wenn input_pressed(BTN_A) wahr ist.

Bedienung und erwartetes Ergebnis: Der Anfangswert ist 000. Drücken Sie A, um 001 zu erhalten; Gedrückthalten erhöht den Zähler nicht weiter. Loslassen und erneut drücken ergibt 002. Der Bytezähler springt nach 255 auf 000 zurück.

Neue Tastendrücke zählen: Der Anfangswert ist 000. Drücken Sie A, um 001 zu erhalten; Gedrückthalten erhöht den Zähler nicht weiter. Loslassen und erneut drücken ergibt 002. Der Bytezähler springt nach 255 auf 000 zurück.
Anzeigebeispiel: Der Anfangswert ist 000. Drücken Sie A, um 001 zu erhalten; Gedrückthalten erhöht den Zähler nicht weiter. Loslassen und erneut drücken ergibt 002. Der Bytezähler springt nach 255 auf 000 zurück.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/input.c kitaq-docs/samples/gb_input.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_input.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Distinguish a new button press from a held button.
// Expected: 000 initially; A increments once per press
#include "gb_common.h"
#include "input.h"
u8 manual_count;
// Sample buttons once per frame and increment only on a new A press.
// Holding A does not repeatedly increment; the byte-sized counter wraps after 255.
void main() {
    m_init();
    m_text(2,3,"INPUT");
    input_init();
    m_number(0);
    while (1) { m_wait(); input_update(); if(input_pressed(BTN_A)) { manual_count++; m_number(manual_count); } }
}
Q8.8-Festkommawerte multiplizieren gb_fixed.c

Zweck: Zeigt die Umwandlung von Ganzzahlen in Q8.8, die Multiplikation und die Rückwandlung in eine Ganzzahl.

Funktionsweise: fix_from_int wandelt 3 und 4 in Q8.8 um. fix_mul multipliziert sie, und fix_to_int wandelt das Produkt wieder in eine Ganzzahl um.

Bedienung und erwartetes Ergebnis: 012 bedeutet 3 × 4 = 12. Es ist die umgewandelte Ganzzahl, nicht der intern mit 256 skalierte Wert.

Q8.8-Festkommawerte multiplizieren: 012 bedeutet 3 × 4 = 12. Es ist die umgewandelte Ganzzahl, nicht der intern mit 256 skalierte Wert.
Anzeigebeispiel: 012 bedeutet 3 × 4 = 12. Es ist die umgewandelte Ganzzahl, nicht der intern mit 256 skalierte Wert.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/fixed.c kitaq-docs/samples/gb_fixed.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_fixed.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Calculate with signed Q8.8 fixed-point values.
// Expected: 012
#include "gb_common.h"
#include "fixed.h"

// Convert 3 and 4 to Q8.8, multiply them, convert the result back to an
// integer, and display 12.
void main() {
    m_init();
    m_text(2,3,"FIXED");
    fix8 a; fix8 b; a=fix_from_int(3); b=fix_from_int(4);
    m_number((u8)fix_to_int(fix_mul(a,b)));
    while (1) { m_wait();  }
}
Aus einem festen Objektpool zuweisen gb_entity.c

Zweck: Erzeugt ein Objekt aus einer festen Menge von Speicherplätzen, ohne dynamische Speicherzuweisung.

Funktionsweise: entity_init setzt den Pool zurück. entity_create erzeugt Typ 1 bei (20,30); das Programm prüft auf die Fehler-ID 0xFF, bevor es vx auf 2 setzt.

Bedienung und erwartetes Ergebnis: 001 ist die Anzahl aktiver Objekte, keine ID oder Koordinate. Das Beispiel aktualisiert und zeichnet das Objekt nicht; daher erscheint keine bewegte Figur.

Aus einem festen Objektpool zuweisen: 001 ist die Anzahl aktiver Objekte, keine ID oder Koordinate. Das Beispiel aktualisiert und zeichnet das Objekt nicht; daher erscheint keine bewegte Figur.
Anzeigebeispiel: 001 ist die Anzahl aktiver Objekte, keine ID oder Koordinate. Das Beispiel aktualisiert und zeichnet das Objekt nicht; daher erscheint keine bewegte Figur.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/entity.c kitaq-docs/samples/gb_entity.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_entity.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Allocate an entity from a fixed-capacity object pool.
// Expected: 001
#include "gb_common.h"
#include "entity.h"

// Create one entity and check the 0xFF allocation-failure sentinel before
// accessing its velocity. Display the pool occupancy, not the entity ID.
void main() {
    m_init();
    m_text(2,3,"ENTITY");
    u8 id; entity_init(); id=entity_create(1,20,30);
    if(id!=0xFF) entity_get(id)->vx=2; m_number(entity_count_active());
    while (1) { m_wait();  }
}
Einen Diagnosewert im RAM aufzeichnen gb_debug.c

Zweck: Speichert einen benannten Spielwert getrennt von der Bildschirmanzeige in einem Diagnosepuffer.

Funktionsweise: Das Programm initialisiert die Diagnose, setzt die Framekennung auf 1 und zeichnet den Wert 42 unter dem Namen HP auf.

Bedienung und erwartetes Ergebnis: 001 ist die Anzahl der Trace-Einträge. HP=42 liegt im Diagnosepuffer; der Bildschirm allein zeigt oder bestätigt diesen Inhalt nicht.

Einen Diagnosewert im RAM aufzeichnen: 001 ist die Anzahl der Trace-Einträge. HP=42 liegt im Diagnosepuffer; der Bildschirm allein zeigt oder bestätigt diesen Inhalt nicht.
Anzeigebeispiel: 001 ist die Anzahl der Trace-Einträge. HP=42 liegt im Diagnosepuffer; der Bildschirm allein zeigt oder bestätigt diesen Inhalt nicht.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/debug.c kitaq-docs/samples/gb_debug.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_debug.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Record diagnostic values in the debug trace.
// Expected: 001; trace log contains HP=42
#include "gb_common.h"
#include "debug.h"

// Record HP = 42 with frame tag 1 and display the number of trace entries.
// The trace buffer contains the value; the screen displays the count, not HP.
void main() {
    m_init();
    m_text(2,3,"DEBUG");
    debug_init(); debug_set_frame(1); debug_trace_u8("HP",42);
    m_number(debug_get_trace_count());
    while (1) { m_wait();  }
}
Einen Positionsverlauf speichern gb_chain.c

Zweck: Zeigt, wie ein Positionsverlauf in einem Ringpuffer gespeichert wird.

Funktionsweise: chain_init bindet ein Array mit Platz für vier Punkte ein. Anschließend zeichnet chain_push_head (20,30) auf.

Bedienung und erwartetes Ergebnis: 042 ist eine feste Abschlussmarkierung, keine Koordinate oder Anzahl. Prüfen Sie trail und points für den gespeicherten Verlauf. Dieses Programm zeichnet keinen nachfolgenden Körper.

Einen Positionsverlauf speichern: 042 ist eine feste Abschlussmarkierung, keine Koordinate oder Anzahl. Prüfen Sie trail und points für den gespeicherten Verlauf. Dieses Programm zeichnet keinen nachfolgenden Körper.
Anzeigebeispiel: 042 ist eine feste Abschlussmarkierung, keine Koordinate oder Anzahl. Prüfen Sie trail und points für den gespeicherten Verlauf. Dieses Programm zeichnet keinen nachfolgenden Körper.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/chain.c kitaq-docs/samples/gb_chain.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_chain.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Store a position history in a ring buffer.
// Expected: 042; history contains (20,30)
#include "gb_common.h"
#include "chain.h"
Chain trail; ChainPoint points[4];
// Attach four history slots and record one point. The displayed 42 is a fixed
// completion marker; inspect the chain to verify the stored (20,30) point.
void main() {
    m_init();
    m_text(2,3,"CHAIN");
    chain_init(&trail,points,4); chain_push_head(&trail,20,30);
    m_number(42);
    while (1) { m_wait();  }
}
Den Framezähler der Bibliothek lesen gb_system.c

Zweck: Zeigt, wie Wartezeiten in Frames den Framezähler der Bibliothek beeinflussen.

Funktionsweise: Nach system_init ruft das Programm system_wait_vblank zweimal auf und zeigt system_get_frame8 an.

Bedienung und erwartetes Ergebnis: Das Ergebnis ist 002. Die Warteschleife verwendet die Handbuch-Hilfsfunktion m_wait; der angezeigte Wert steigt daher nicht weiter.

Den Framezähler der Bibliothek lesen: Das Ergebnis ist 002. Die Warteschleife verwendet die Handbuch-Hilfsfunktion m_wait; der angezeigte Wert steigt daher nicht weiter.
Anzeigebeispiel: Das Ergebnis ist 002. Die Warteschleife verwendet die Handbuch-Hilfsfunktion m_wait; der angezeigte Wert steigt daher nicht weiter.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/system.c kitaq-docs/samples/gb_system.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_system.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Count completed frame waits.
// Expected: 002
#include "gb_common.h"
#include "system.h"

// Reset the library frame count, perform two counted waits, and display 2.
// Subsequent m_wait calls leave that library counter unchanged.
void main() {
    m_init();
    m_text(2,3,"SYSTEM");
    system_init(); system_wait_vblank(); system_wait_vblank();
    m_number(system_get_frame8());
    while (1) { m_wait();  }
}
Die aktuelle Szenen-ID wählen gb_scene.c

Zweck: Zeigt, wie eine ID zur Unterscheidung von Szenen wie Titelbildschirm und Spiel gewählt wird.

Funktionsweise: Das Programm registriert zwei mit null initialisierte SceneDef-Einträge und wählt mit scene_change die ID 1.

Bedienung und erwartetes Ergebnis: 001 ist die aktuelle von scene_get_current gelieferte ID. In diesem Beispiel sind weder Szenen-Callbacks noch Übergangszeichnungen registriert.

Die aktuelle Szenen-ID wählen: 001 ist die aktuelle von scene_get_current gelieferte ID. In diesem Beispiel sind weder Szenen-Callbacks noch Übergangszeichnungen registriert.
Anzeigebeispiel: 001 ist die aktuelle von scene_get_current gelieferte ID. In diesem Beispiel sind weder Szenen-Callbacks noch Übergangszeichnungen registriert.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scene.c kitaq-docs/samples/gb_scene.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_scene.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Switch the current scene ID.
// Expected: 001; no callbacks registered
#include "gb_common.h"
#include "scene.h"
SceneDef manual_scenes[2];
// Register two zero-initialized scene entries, select ID 1 and display it.
// No callbacks are registered in this example.
void main() {
    m_init();
    m_text(2,3,"SCENE");
    scene_init(manual_scenes,2); scene_change(1);
    m_number(scene_get_current());
    while (1) { m_wait();  }
}
Weltkoordinaten in Bildschirmkoordinaten umwandeln gb_camera.c

Zweck: Zieht die Kameraposition ab, um die Bildschirmposition eines Weltpunkts zu bestimmen.

Funktionsweise: Camera_Set erhält den Q8.8-Wert 2560, also X=10 Pixel. Anschließend wandelt Camera_WorldToScreenX die Weltkoordinate X=52 um.

Bedienung und erwartetes Ergebnis: 052 minus 010 ergibt die angezeigte 042. Dies ist eine Koordinatenberechnung; der Hintergrund wird nicht gescrollt.

Weltkoordinaten in Bildschirmkoordinaten umwandeln: 052 minus 010 ergibt die angezeigte 042. Dies ist eine Koordinatenberechnung; der Hintergrund wird nicht gescrollt.
Anzeigebeispiel: 052 minus 010 ergibt die angezeigte 042. Dies ist eine Koordinatenberechnung; der Hintergrund wird nicht gescrollt.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scroll.c kitaqgb/lib/camera.c kitaq-docs/samples/gb_camera.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_camera.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Convert world coordinates to screen coordinates.
// Expected: 042: world x=52 minus camera x=10
#include "gb_common.h"
#include "camera.h"
Camera8_8 cam;
// Set the camera X coordinate to 10 pixels in Q8.8 (10 * 256), then subtract
// it from world X = 52 to display screen X = 42.
void main() {
    m_init();
    m_text(2,3,"CAMERA");
    Camera_Init(&cam); Camera_Set(&cam,2560,0);
    m_number((u8)Camera_WorldToScreenX(&cam,52));
    while (1) { m_wait();  }
}
RLE-Daten in den RAM entpacken gb_rle.c

Zweck: Erprobt eine kompakte Darstellung wiederholter Bytes als Anzahl und Wert.

Funktionsweise: Die gepackten Bytes {3,42,0} bedeuten drei Kopien von 42, gefolgt von einer Nullanzahl als Endmarke. rle_decode schreibt in einen drei Byte großen Zielpuffer.

Bedienung und erwartetes Ergebnis: Das letzte Byte, out[2], wird als 042 angezeigt. Alle drei entpackten Bytes sollen den Wert 42 enthalten.

RLE-Daten in den RAM entpacken: Das letzte Byte, out[2], wird als 042 angezeigt. Alle drei entpackten Bytes sollen den Wert 42 enthalten.
Anzeigebeispiel: Das letzte Byte, out[2], wird als 042 angezeigt. Alle drei entpackten Bytes sollen den Wert 42 enthalten.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/rle.c kitaq-docs/samples/gb_rle.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_rle.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Decode run-length encoded data.
// Expected: 042; three bytes each equal to 42
#include "gb_common.h"
#include "rpg.h"
__prg_rom u8 packed[] = {3,42,0};
// Decode count/value pair (3,42), terminated by a zero count, into a
// three-byte buffer and display the final decoded byte.
void main() {
    m_init();
    m_text(2,3,"RLE");
    u8 out[3]; rle_decode(out,packed); m_number(out[2]);
    while (1) { m_wait();  }
}
Ein Brettfeld lesen und schreiben gb_board.c

Zweck: Zeigt, wie Rasterkoordinaten eines Brettspiels auf Speicherpositionen abgebildet werden.

Funktionsweise: Ein 16-Byte-Array speichert ein 4×4-Brett. Das Programm löscht es, schreibt 42 in Zelle (2,1) und liest dieselbe Zelle wieder.

Bedienung und erwartetes Ergebnis: 042 ist der zurückgelesene Wert. Das Programm zeichnet das 4×4-Brett selbst nicht.

Ein Brettfeld lesen und schreiben: 042 ist der zurückgelesene Wert. Das Programm zeichnet das 4×4-Brett selbst nicht.
Anzeigebeispiel: 042 ist der zurückgelesene Wert. Das Programm zeichnet das 4×4-Brett selbst nicht.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/slg_board.c kitaq-docs/samples/gb_board.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_board.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Read and write cells in a game board.
// Expected: 042
#include "gb_common.h"
#include "slg.h"
SLGBoard board; u8 cells[16];
// Create a cleared 4-by-4 board in caller-owned storage, write 42 at (2,1),
// and display the value read back from the same cell.
void main() {
    m_init();
    m_text(2,3,"BOARD");
    slg_board_init(&board,4,4,cells); slg_board_clear(&board,0);
    slg_board_set(&board,2,1,42); m_number(slg_board_get(&board,2,1));
    while (1) { m_wait();  }
}
Eine Box um einen Physikschritt bewegen gb_physics.c

Zweck: Initialisiert eine Welt und einen rechteckigen Körper und aktualisiert dann die Position anhand der Geschwindigkeit.

Funktionsweise: Der Körper startet bei (40,40) mit Geschwindigkeit (2,0) und Schwerkraft null. Das Programm ruft kq2d_step einmal auf.

Bedienung und erwartetes Ergebnis: 042 ist die resultierende X-Koordinate, hier in ganzen Pixeln. Es werden weder eine Boxform noch eine fortlaufende Animation gezeichnet.

Eine Box um einen Physikschritt bewegen: 042 ist die resultierende X-Koordinate, hier in ganzen Pixeln. Es werden weder eine Boxform noch eine fortlaufende Animation gezeichnet.
Anzeigebeispiel: 042 ist die resultierende X-Koordinate, hier in ganzen Pixeln. Es werden weder eine Boxform noch eine fortlaufende Animation gezeichnet.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/fixed.c kitaqgb/lib/physics2d.c kitaq-docs/samples/gb_physics.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_physics.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Advance a rectangular body through one physics step.
// Expected: 042: integer pixel coordinates
#include "gb_common.h"
#include "physics2d.h"
KQWorld2D world; KQBody2D boxes[1];
// Create one box at X = 40, set horizontal velocity 2 and zero gravity,
// then display its X coordinate after a single physics step.
void main() {
    m_init();
    m_text(2,3,"PHYSICS");
    kq2d_world_init(&world,boxes,1);
    kq2d_body_init(&boxes[0],40,40,4,4);
    kq2d_body_set_velocity(&boxes[0],2,0);
    world.gravity_x=0; world.gravity_y=0;
    kq2d_step(&world); m_number((u8)boxes[0].x);
    while (1) { m_wait();  }
}
ROM-Daten mit einem Bankargument lesen gb_bank.c

Zweck: Erklärt die Argumente zum Kopieren von ROM-Daten in den RAM.

Funktionsweise: far_data_read kopiert die beiden Bytes 7 und 42 mit Bankargument 0 und Länge 2 nach copied.

Bedienung und erwartetes Ergebnis: Das zweite Zielbyte wird als 042 angezeigt. Dieses Beispiel liest aus fest eingeblendetem ROM; es zeigt keine Übertragung zwischen verschiedenen umschaltbaren Banken.

ROM-Daten mit einem Bankargument lesen: Das zweite Zielbyte wird als 042 angezeigt. Dieses Beispiel liest aus fest eingeblendetem ROM; es zeigt keine Übertragung zwischen verschiedenen umschaltbaren Banken.
Anzeigebeispiel: Das zweite Zielbyte wird als 042 angezeigt. Dieses Beispiel liest aus fest eingeblendetem ROM; es zeigt keine Übertragung zwischen verschiedenen umschaltbaren Banken.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/bank.c kitaq-docs/samples/gb_bank.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_bank.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Read data using an explicit ROM bank.
// Expected: 042; explicit bank argument 0
#include "gb_common.h"
#include "bank.h"
__prg_rom u8 values[] = {7,42}; u8 copied[2];
// Copy two ROM bytes using bank argument zero and display the second byte.
// This introduces the API; it does not test switching between distinct payload banks.
void main() {
    m_init();
    m_text(2,3,"BANK");
    far_data_read(0,values,copied,2); m_number(copied[1]);
    while (1) { m_wait();  }
}
Daten anhand der Asset-ID laden gb_asset.c

Zweck: Registriert Position und Länge eines Assets und ruft anschließend seine Bytes anhand der ID ab.

Funktionsweise: Asset 0 hat Typ RAW, Bank 0, einen Zeiger auf {7,42} und Länge 2. asset_load_raw kopiert es in einen Zwei-Byte-RAM-Puffer.

Bedienung und erwartetes Ergebnis: Das zweite Byte wird als 042 angezeigt. Das Beispiel demonstriert das Auffinden und Kopieren von Assets, keine Bilddarstellung.

Daten anhand der Asset-ID laden: Das zweite Byte wird als 042 angezeigt. Das Beispiel demonstriert das Auffinden und Kopieren von Assets, keine Bilddarstellung.
Anzeigebeispiel: Das zweite Byte wird als 042 angezeigt. Das Beispiel demonstriert das Auffinden und Kopieren von Assets, keine Bilddarstellung.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/asset.c kitaq-docs/samples/gb_asset.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_asset.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Load asset bytes into RAM by asset ID.
// Expected: 042
#include "gb_common.h"
#include "asset.h"
AssetDesc table[1]; __prg_rom u8 values[] = {7,42}; u8 copied[2];
// Register a two-byte raw asset, copy it into RAM and display its second byte.
// This example uses bank zero and a destination sized for the complete payload.
void main() {
    m_init();
    m_text(2,3,"ASSET");
    table[0].type=ASSET_TYPE_RAW; table[0].bank=0;
    table[0].ptr=values; table[0].len=2;
    asset_set_table(0,table,1); asset_load_raw(0,copied,2);
    m_number(copied[1]);
    while (1) { m_wait();  }
}
Ein Geschoss zuweisen gb_danmaku.c

Zweck: Initialisiert den Geschosspool und prüft seine Belegung nach dem Erzeugen eines Geschosses.

Funktionsweise: Nach danmaku_reset ruft das Programm danmaku_spawn(40,40,16,0) auf und zeigt dm_count an.

Bedienung und erwartetes Ergebnis: 001 ist die Anzahl zugewiesener Geschosse. Es gibt hier weder eine Geschoss-Aktualisierungsschleife noch eine Hintergrundkomposition; bewegte Geschosse werden nicht gezeichnet.

Ein Geschoss zuweisen: 001 ist die Anzahl zugewiesener Geschosse. Es gibt hier weder eine Geschoss-Aktualisierungsschleife noch eine Hintergrundkomposition; bewegte Geschosse werden nicht gezeichnet.
Anzeigebeispiel: 001 ist die Anzahl zugewiesener Geschosse. Es gibt hier weder eine Geschoss-Aktualisierungsschleife noch eine Hintergrundkomposition; bewegte Geschosse werden nicht gezeichnet.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/danmaku.c kitaq-docs/samples/gb_danmaku.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_danmaku.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Allocate a bullet and inspect the pool count.
// Expected: 001; numeric pool example, no bullet BG compositor
#include "gb_common.h"
#include "danmaku.h"

// Reset the bullet pool, spawn one bullet and display the active count.
// This numeric example does not install the background bullet compositor.
void main() {
    m_init();
    m_text(2,3,"DANMAKU");
    danmaku_reset(); danmaku_spawn(40,40,16,0);
    m_number(dm_count);
    while (1) { m_wait();  }
}
Eine CGB-Hintergrundpalette einstellen gb_cgb_palette.c

Zweck: Wählt Hintergrund- und Textfarben anhand der RGB-Komponenten des Game Boy Color.

Funktionsweise: Das Programm schaltet das LCD im VBlank aus, setzt Farbe 0 der Palette 0 auf Weiß (31,31,31) und Farbe 3 auf Violett (12,0,22) und aktiviert dann die Anzeige.

Bedienung und erwartetes Ergebnis: Führen Sie das Programm im CGB-Modus aus, um violetten Text und 042 auf weißem Hintergrund zu sehen. Die monochrome DMG-Ausgabe kann diese Farben nicht darstellen.

Eine CGB-Hintergrundpalette einstellen: Führen Sie das Programm im CGB-Modus aus, um violetten Text und 042 auf weißem Hintergrund zu sehen. Die monochrome DMG-Ausgabe kann diese Farben nicht darstellen.
Anzeigebeispiel: Führen Sie das Programm im CGB-Modus aus, um violetten Text und 042 auf weißem Hintergrund zu sehen. Die monochrome DMG-Ausgabe kann diese Farben nicht darstellen.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/cgb_palette.c kitaq-docs/samples/gb_cgb_palette.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_cgb_palette.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb
c
// Set Game Boy Color palette entries.
// Expected: 042 in purple on white; CGB mode
#include "gb_common.h"
#include "cgb_palette.h"

// Set palette-zero background colors to white and purple, then display 42.
// Run the ROM in CGB mode to observe the color result.
void main() {
    m_init();
    m_text(2,3,"CGB PALETTE");
    // Disable the LCD during VBlank so both palette bytes remain accessible.
    m_wait(); M_LCDC = 0;
    cgb_bg_rgb(0,0,31,31,31); cgb_bg_rgb(0,3,12,0,22);
    M_LCDC = 0x91;
    m_number(42);
    while (1) { m_wait();  }
}
Den Hintergrund horizontal scrollen gb_scroll.c

Zweck: Verschiebt die Ansicht, ohne den Hintergrundinhalt neu zu zeichnen.

Funktionsweise: Jeder Frame erhöht phase und übergibt den Wert an Scroll_SetBg. Die Acht-Bit-Position springt nach 255 auf null zurück.

Bedienung und erwartetes Ergebnis: Das Wort SCROLL bewegt sich nach links. Beobachten Sie seine Position über die Zeit; eine einzelne Aufnahme kann die Bewegung nicht zeigen.

Den Hintergrund horizontal scrollen: Das Wort SCROLL bewegt sich nach links. Beobachten Sie seine Position über die Zeit; eine einzelne Aufnahme kann die Bewegung nicht zeigen.
Anzeigebeispiel: Das Wort SCROLL bewegt sich nach links. Beobachten Sie seine Position über die Zeit; eine einzelne Aufnahme kann die Bewegung nicht zeigen.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scroll.c kitaq-docs/samples/gb_scroll.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_scroll.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Scroll the background horizontally.
// Expected: title moves left as SCX increases
#include "gb_common.h"
#include "scroll.h"
u8 phase;
// Advance an 8-bit horizontal scroll position once per frame, wrapping naturally
// after 255. Background motion demonstrates the changing scroll register.
void main() {
    m_init();
    m_text(2,3,"SCROLL");
    Scroll_SetBg(0,0);
    while (1) { m_wait(); phase++; Scroll_SetBg(phase,0); }
}
Eine Tile-Aktualisierung einreihen gb_vram_queue.c

Zweck: Trennt eine Zeichenanforderung von der VRAM-Übertragung, die sie umsetzt.

Funktionsweise: vram_queue_bg_tile reiht Tile 52 für Tile-Koordinate (3,8) ein, und vram_flush überträgt es. In der mitgelieferten Schrift ist Tile 52 die Ziffer 4.

Bedienung und erwartetes Ergebnis: Achten Sie auf eine einzelne 4 bei Hintergrund-Tile-Koordinate (3,8). Dies ist eine Tile-Aktualisierung, kein Zahlenzähler.

Eine Tile-Aktualisierung einreihen: Achten Sie auf eine einzelne 4 bei Hintergrund-Tile-Koordinate (3,8). Dies ist eine Tile-Aktualisierung, kein Zahlenzähler.
Anzeigebeispiel: Achten Sie auf eine einzelne 4 bei Hintergrund-Tile-Koordinate (3,8). Dies ist eine Tile-Aktualisierung, kein Zahlenzähler.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/vram.c kitaq-docs/samples/gb_vram_queue.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_vram_queue.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Queue a VRAM update and flush it at VBlank.
// Expected: 4 at (3,8)
#include "gb_common.h"
#include "vram.h"

// Queue font tile 52 (the digit 4) at tile coordinate (3,8), then wait for
// VBlank and execute the queued transfer.
void main() {
    m_init();
    m_text(2,3,"VRAM QUEUE");
    vram_init();
    vram_queue_bg_tile(3,8,52); vram_flush();
    while (1) { m_wait();  }
}
Ein Sprite per OAM-DMA anzeigen gb_sprite.c

Zweck: Weist ein Sprite zu und zeigt es unabhängig vom Hintergrund an.

Funktionsweise: Der neu initialisierte Pool liefert Platz 0. Das Programm wählt Tile 65, setzt Position (70,80), aktiviert die OBJ-Anzeige und überträgt das Schatten-OAM in jedem Frame.

Bedienung und erwartetes Ergebnis: An der angegebenen Sprite-Position erscheint ein unbewegtes A. Prüfen Sie im Spiel vor Verwendung der zurückgegebenen ID, ob die Zuweisung fehlgeschlagen ist.

Ein Sprite per OAM-DMA anzeigen: An der angegebenen Spriteposition erscheint ein unbewegliches A. Prüfen Sie im Spiel, ob die Zuweisung fehlgeschlagen ist, bevor Sie die zurückgegebene ID verwenden.
Anzeigebeispiel: An der angegebenen Sprite-Position erscheint ein unbewegtes A. Prüfen Sie im Spiel vor Verwendung der zurückgegebenen ID, ob die Zuweisung fehlgeschlagen ist.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/sprite.c kitaq-docs/samples/gb_sprite.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_sprite.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Display a sprite through the OAM DMA path.
// Expected: letter A at sprite position
#include "gb_common.h"
#include "sprite.h"

// Allocate the first sprite, choose font tile 65 (A), set its position and
// enable sprite display. Flush shadow OAM after each frame wait.
void main() {
    m_init();
    m_text(2,3,"SPRITE");
    // The freshly reset pool guarantees slot zero for this first allocation.
    // In a running game, check the allocation-failure sentinel before using the returned ID.
    sprite_init(); sprite_set_tile(sprite_alloc(),65);
    sprite_set_pos(0,70,80); M_LCDC=(u8)(M_LCDC|2);
    while (1) { m_wait(); sprite_flush_oam_now(); }
}
Einen reproduzierbaren Zufallswert erzeugen gb_rng.c

Zweck: Verwendet einen Startwert, um eine Pseudozufallsfolge zu reproduzieren.

Funktionsweise: rng_seed(1234) initialisiert den Generator; danach wird rng_range(10) einmal aufgerufen. Die Obergrenze 10 ist ausgeschlossen.

Bedienung und erwartetes Ergebnis: Der Bildschirm zeigt einen Wert von 000 bis 009. Ein Neustart desselben Programms mit demselben Startwert erzeugt ihn erneut; er ändert sich nicht in jedem Frame.

Einen reproduzierbaren Zufallswert erzeugen: Der Bildschirm zeigt einen Wert von 000 bis 009. Ein Neustart desselben Programms mit demselben Startwert erzeugt ihn erneut; er ändert sich nicht in jedem Frame.
Anzeigebeispiel: Der Bildschirm zeigt einen Wert von 000 bis 009. Ein Neustart desselben Programms mit demselben Startwert erzeugt ihn erneut; er ändert sich nicht in jedem Frame.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/rng.c kitaq-docs/samples/gb_rng.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_rng.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Generate a repeatable pseudorandom value from a seed.
// Expected: value 000 through 009; same seed repeats
#include "gb_common.h"
#include "rpg.h"

// Seed the generator with 1234 and display one value in [0,10).
// Restarting with the same seed reproduces the sequence.
void main() {
    m_init();
    m_text(2,3,"RNG");
    rng_seed(1234); m_number(rng_range(10));
    while (1) { m_wait();  }
}
Ein Spielzustandsflag speichern gb_flags.c

Zweck: Stellt einen booleschen Zustand, etwa den Abschluss eines Ereignisses, durch eine Flagnummer dar.

Funktionsweise: Das Programm löscht Flag 12, setzt es und liest es mit flag_get zurück.

Bedienung und erwartetes Ergebnis: 001 bedeutet, dass Flag 12 wahr ist. Das Beispiel arbeitet mit RAM-Flags und erhält sie nicht über Aus- und Einschalten hinweg.

Ein Spielzustandsflag speichern: 001 bedeutet, dass Flag 12 wahr ist. Das Beispiel arbeitet mit RAM-Flags und erhält sie nicht über Aus- und Einschalten hinweg.
Anzeigebeispiel: 001 bedeutet, dass Flag 12 wahr ist. Das Beispiel arbeitet mit RAM-Flags und erhält sie nicht über Aus- und Einschalten hinweg.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/flags.c kitaq-docs/samples/gb_flags.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_flags.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Read and write RAM-backed game-state flags.
// Expected: 001
#include "gb_common.h"
#include "rpg.h"

// Clear and set flag 12, then display its Boolean value. This does not write
// a save file or demonstrate persistence across power cycles.
void main() {
    m_init();
    m_text(2,3,"FLAGS");
    flag_clear(12); flag_set(12); m_number(flag_get(12));
    while (1) { m_wait();  }
}
Einen Kreis um einen Physikschritt bewegen gb_circle.c

Zweck: Richtet einen kreisförmigen Körper ein und aktualisiert seine Position anhand der Geschwindigkeit.

Funktionsweise: Der aktive Kreis hat Radius 4, Position (40,40) und Geschwindigkeit (2,0). Die Schwerkraft ist null und linear_damping_q8 ist 255; kq2dc_step wird einmal ausgeführt.

Bedienung und erwartetes Ergebnis: 042 ist die resultierende ganzzahlige X-Koordinate. Das Beispiel zeichnet weder einen Kreisumriss noch eine Kollisionsanimation.

Einen Kreis um einen Physikschritt bewegen: 042 ist die resultierende ganzzahlige X-Koordinate. Das Beispiel zeichnet weder einen Kreisumriss noch eine Kollisionsanimation.
Anzeigebeispiel: 042 ist die resultierende ganzzahlige X-Koordinate. Das Beispiel zeichnet weder einen Kreisumriss noch eine Kollisionsanimation.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/physics2d_circle.c kitaq-docs/samples/gb_circle.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_circle.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Advance a circular body through one physics step.
// Expected: 042 after one step; this example uses integer pixels
#include "gb_common.h"
#include "physics2d_circle.h"
KQCircleBody2D balls[1]; KQCircleWorld2D world;
// Activate one circle at X = 40 with horizontal velocity 2 and zero gravity.
// Advance one step and display its resulting integer-pixel X coordinate.
void main() {
    m_init();
    m_text(2,3,"CIRCLE");
    kq2dc_world_init(&world,balls,1);
    balls[0].active=1; balls[0].x=40; balls[0].y=40;
    balls[0].radius=4; balls[0].inv_mass_q8=256;
    balls[0].vx=2; balls[0].vy=0;
    world.gravity_x=0; world.gravity_y=0; world.linear_damping_q8=255;
    kq2dc_step(&world); m_number((u8)balls[0].x);
    while (1) { m_wait();  }
}
Einen Soundeffekt in jedem Frame verarbeiten gb_sound.c

Zweck: Startet einen Soundeffekt-Datenstrom und lässt ihn durch regelmäßige Frameaktualisierungen fortschreiten.

Funktionsweise: Nach Audio_Init startet Audio_PlaySFX tone auf Kanal-ID 1. Die Hauptschleife ruft Audio_Update einmal pro Frame auf.

Bedienung und erwartetes Ergebnis: Ein kurzer Pulseffekt erklingt, während 042 sichtbar bleibt. Die Zahl ist eine feste Markierung, weder Lautstärke noch Wiedergabeposition. Beurteilen Sie den Klang über die Audioausgabe oder eine Aufnahme.

Einen Soundeffekt in jedem Frame verarbeiten: Ein kurzer Pulseffekt erklingt, während 042 sichtbar bleibt. Die Zahl ist eine feste Markierung, weder Lautstärke noch Wiedergabeposition. Beurteilen Sie den Klang über die Audioausgabe oder eine Aufnahme.
Anzeigebeispiel: Ein kurzer Pulseffekt erklingt, während 042 sichtbar bleibt. Die Zahl ist eine feste Markierung, weder Lautstärke noch Wiedergabeposition. Beurteilen Sie den Klang über die Audioausgabe oder eine Aufnahme.

Quelltext herunterladen / Prüfstatus

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/audio_hwregs_gb.c kitaqgb/lib/audio.c kitaq-docs/samples/gb_sound.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_sound.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Play a Game Boy pulse-channel sound effect.
// Expected: 042 and a short pulse tone
#include "gb_common.h"
#include "audio.h"
__prg_rom u8 tone[] = { 24,0xF0,24,0xE0,24,0xC0,24,0xA0,24,0x80,24,0x60,0 };
// Start a pulse-channel effect and service Audio_Update once per frame
// so the effect stream advances while 42 remains on screen.
void main() {
    m_init();
    m_text(2,3,"SOUND");
    Audio_Init(); Audio_PlaySFX(tone,1); m_number(42);
    while (1) { m_wait(); Audio_Update(); }
}

API-Referenz der Bibliothek

554 Einträge. Öffnen Sie einen Eintrag, um Syntax, Argumente, Quellhinweise und ein Anwendungsbeispiel zu sehen. Aufruffragmente benötigen zusätzliche Initialisierung und sind keine eigenständigen ROMs. Die Beispiele zeigen, wie vorbereitete Werte an die API übergeben werden; sie belegen keine Prüfung am Gerät.

zx0

Decodiert ZX0-kompatible Assets in RAM oder VRAM. Bereiten Sie Assets am PC mit kitaqgb-zx0.exe vor und decodieren Sie zur Laufzeit nur benötigte Daten. --format=auto vergleicht unkomprimierte, RLE- und ZX0-Nutzdaten und wählt die kleinsten; bei Gleichstand gilt die Reihenfolge unkomprimiert, RLE, ZX0. Der gesamte Container einschließlich Neun-Byte-Header darf 65535 Bytes nicht überschreiten. Teilen Sie Assets passend zu tatsächlichen CPU-Bänken und RAM auf.

Einar Saukas entwickelte das ZX0-Format und den ursprünglichen Kompressionsalgorithmus. Der hier bereitgestellte Kompressor und Dekompressor sind unabhängige KITAQ-Implementierungen, Copyright DAISUKE OBA, veröffentlicht unter der MIT-Lizenz.

Führen Sie diese Hostbefehle im Stammverzeichnis des Repositorys aus. Bauen Sie das Werkzeug mit tools/zx0/build.ps1.

.\kitaqgb-zx0.exe tiles.bin tiles.zx0
.\kitaqgb-zx0.exe tiles.bin tiles.h --header=tiles
.\kitaqgb-zx0.exe map.bin map.kqa --format=auto
.\kitaqgb-zx0.exe tiles.zx0 restored.bin --decompress
zx0_decompress

Decodiert einen ZX0-v2-Strom in einen begrenzten RAM-Bereich. Übereinstimmungen verweisen auf zuvor decodierte Bytes; das Ziel muss daher les- und beschreibbar sein. Geeignet für Tilemaps oder Leveltabellen, die die CPU vor ihrer Verwendung verarbeitet.

Syntax

c
u16 zx0_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);

Parameter

dst

Beginn des beschreibbaren Ziel-RAM; darf nicht null sein. Geben Sie die Kapazität in Bytes an, nicht in Arrayelementen.

capacity

Anzahl beschreibbarer Zielbytes. Ein gewöhnlicher ZX0-Strom benötigt mindestens ein Byte. Ein leeres unkomprimiertes KQA1-Asset kann mit Kapazität null erfolgreich sein.

src

Beginn der über die aktuelle Bankeinblendung lesbaren komprimierten Daten. Darf nicht null sein.

packed_size

Byteanzahl der vollständigen Eingabe. Ein ZX0-Strom enthält seine Endmarkierung und keine nachfolgenden Bytes. Ein KQA1-Container enthält seinen Neun-Byte-Header. Maximum: 65535 Bytes.

Rückgabewert

Liefert bei Erfolg die Anzahl decodierter Bytes, bei Fehler null. Prüfen Sie stets auch zx0_error.

Bedingungen und Grenzen

Binden Sie zx0.h ein und kompilieren Sie lib/zx0.c. Diese Routinen teilen sich Arbeitsspeicher und sind aus Interrupts nicht reentrant. Ein- und Ausgabe dürfen weder überlappen noch im CPU-Adressraum umbrechen oder aktuell eingeblendete Bankfenster überschreiten. Die Bibliothek schaltet keine Asset-Bänke um.

Jeder Aufruf aktualisiert zx0_error: 0 Erfolg, 1 ungültiges Argument, 2 abgeschnittene Eingabe, 3 fehlerhafter Datenstrom, 4 zu wenig Ausgabespeicher, 5 aktive Anzeige. Ein Fehler kann Teilausgabe hinterlassen; verwenden Sie diese nicht. Bei mehreren ungültigen Bedingungen bestimmt die zuerst erkannte den Code.

Akzeptiert vorwärtsgerichtete ZX0-v2-Ströme. ZX0 v1, Rückwärtsströme und externe Wörterbücher gehören nicht zu dieser Schnittstelle. Kennen Sie die decodierte Größe des am Host erzeugten Assets und stellen Sie ausreichend Speicher bereit.

ZX0-Format — Einar Saukas

Anwendungsbeispiel

c
count=zx0_decompress(decoded_map,16,packed_map,packed_map_SIZE);
    if(count!=16||zx0_error!=ZX0_OK)failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

zx0_decompress: DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
zx0_decompress: CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/zx0.h:15

Deklarationshinweise im Original
Return decoded bytes, or zero on error (possibly after partial writes).
Source and output must not overlap or cross their current CPU bank windows.
Capacity and packed_size are byte counts. No prefix/backward/v1 streams.

kitaqgb/lib/zx0.c:52

c
u16 zx0_decompress(void* dst,u16 capacity,const void* src,u16 packed_size) {
    u8 phase; u8 low; u8* out; u8* match;
    u16 count; u16 distance; u16 used; u16 upper;
    zx0_error=ZX0_OK;
    if(!kq_zx_arguments(dst,capacity,src,packed_size)) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
    kq_zx_input=(const u8*)src; kq_zx_left=packed_size;
    kq_zx_mask=0; kq_zx_borrowed=0;
    out=(u8*)dst; used=0; distance=1; phase=0;
    // Phase 0 is literal, 1 reuses the last distance, 2 carries a new distance.
    while(1) {
        if(phase==2) {
            upper=kq_zx_number(1);
            if(zx0_error) return 0;
            if(upper==256) {
                if(kq_zx_left!=0) { zx0_error=ZX0_BAD_STREAM; return 0; }
                return used;
            }
            if(upper>255) { zx0_error=ZX0_BAD_STREAM; return 0; }
            low=kq_zx_byte();
            distance=(u16)((upper<<7)-(low>>1));
            kq_zx_borrowed=1; kq_zx_borrow_value=(u8)(low&1);
            count=kq_zx_number(0);
            if(count==65535) { zx0_error=ZX0_BAD_STREAM; return 0; }
            count++;
        } else count=kq_zx_number(0);
        if(zx0_error) return 0;
        if(count>capacity-used) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
        if(phase==0) {
            if(count>kq_zx_left) { zx0_error=ZX0_TRUNCATED; return 0; }
            kq_zx_left-=count; used+=count;
            while(count!=0) { *out++=*kq_zx_input++; count--; }
            phase=kq_zx_bit()?2:1;
        } else {
            if(distance>used) { zx0_error=ZX0_BAD_STREAM; return 0; }
            match=out-distance; used+=count;
            // Forward byte copying deliberately supports overlapping matches.
            while(count!=0) { *out++=*match++; count--; }
            phase=kq_zx_bit()?2:0;
        }
        if(zx0_error) return 0;
    }
}
asset_decompress

Liest Codec und Größen aus einem mit --format=auto erzeugten KQA1-Header und kopiert dann rohe Bytes oder decodiert RLE/ZX0 ins RAM. Der Aufrufer benötigt keine separate Verzweigung je Codec.

Syntax

c
u16 asset_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);

Parameter

dst

Beginn des beschreibbaren Ziel-RAM; darf nicht null sein. Geben Sie die Kapazität in Bytes an, nicht in Arrayelementen.

capacity

Anzahl beschreibbarer Zielbytes. Ein gewöhnlicher ZX0-Strom benötigt mindestens ein Byte. Ein leeres unkomprimiertes KQA1-Asset kann mit Kapazität null erfolgreich sein.

src

Beginn der über die aktuelle Bankeinblendung lesbaren komprimierten Daten. Darf nicht null sein.

packed_size

Byteanzahl der vollständigen Eingabe. Ein ZX0-Strom enthält seine Endmarkierung und keine nachfolgenden Bytes. Ein KQA1-Container enthält seinen Neun-Byte-Header. Maximum: 65535 Bytes.

Rückgabewert

Liefert bei Erfolg die Anzahl decodierter Bytes, bei Fehler null. Prüfen Sie stets auch zx0_error.

Bedingungen und Grenzen

Binden Sie zx0.h ein und kompilieren Sie lib/zx0.c. Diese Routinen teilen sich Arbeitsspeicher und sind aus Interrupts nicht reentrant. Ein- und Ausgabe dürfen weder überlappen noch im CPU-Adressraum umbrechen oder aktuell eingeblendete Bankfenster überschreiten. Die Bibliothek schaltet keine Asset-Bänke um.

Jeder Aufruf aktualisiert zx0_error: 0 Erfolg, 1 ungültiges Argument, 2 abgeschnittene Eingabe, 3 fehlerhafter Datenstrom, 4 zu wenig Ausgabespeicher, 5 aktive Anzeige. Ein Fehler kann Teilausgabe hinterlassen; verwenden Sie diese nicht. Bei mehreren ungültigen Bedingungen bestimmt die zuerst erkannte den Code.

KQA1 ist der KITAQ-Asset-Container: Vier-Byte-Kennung, Ein-Byte-Codec (0 unkomprimiert, 1 RLE, 2 ZX0), decodierte Größe u16, Nutzdatengröße u16, danach Nutzdaten. Die u16-Felder sind Little-Endian. RLE wiederholt Anzahl/Wert-Paare mit Anzahlen 1..255 und einem Abschluss mit Anzahl null. Ein leeres unkomprimiertes Asset ist mit Rückgabewert null und Fehler null erfolgreich.

ZX0-Format — Einar Saukas

Anwendungsbeispiel

c
count=asset_decompress(decoded_auto,16,packed_auto,packed_auto_SIZE);
    if(count!=16||zx0_error!=ZX0_OK)failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

asset_decompress: DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
asset_decompress: CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/zx0.h:18

Deklarationshinweise im Original
Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto.
Empty raw assets return zero with zx0_error==ZX0_OK.

kitaqgb/lib/zx0.c:95

c
u16 asset_decompress(void* dst,u16 capacity,const void* src,u16 packed_size) {
    const u8* in; u8* out; u16 raw; u16 packed; u16 used;
    u8 codec; u8 count; u8 value;
    zx0_error=ZX0_OK;
    if(packed_size<9||!kq_zx_arguments(dst,capacity,src,packed_size)) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
    in=(const u8*)src; out=(u8*)dst;
    if(in[0]!=75||in[1]!=81||in[2]!=65||in[3]!=49) { zx0_error=ZX0_BAD_STREAM; return 0; }
    codec=in[4]; raw=(u16)((u16)in[5]|((u16)in[6]<<8));
    packed=(u16)((u16)in[7]|((u16)in[8]<<8));
    if(packed!=packed_size-9||codec>2) { zx0_error=ZX0_BAD_STREAM; return 0; }
    if(raw>capacity) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
    in+=9;
    if(codec==2) {
        used=zx0_decompress(dst,raw,in,packed);
        if(zx0_error==0&&used!=raw) zx0_error=ZX0_BAD_STREAM;
        return zx0_error?0:used;
    }
    if(codec==0) {
        if(raw!=packed) { zx0_error=ZX0_BAD_STREAM; return 0; }
        used=raw; while(raw!=0) { *out++=*in++; raw--; } return used;
    }
    used=0;
    while(packed!=0) {
        count=*in++; packed--;
        if(count==0) {
            if(packed!=0||used!=raw) { zx0_error=ZX0_BAD_STREAM; return 0; }
            return used;
        }
        if(packed==0) { zx0_error=ZX0_TRUNCATED; return 0; }
        value=*in++; packed--;
        if((u16)count>raw-used) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
        used+=count; while(count!=0) { *out++=value; count--; }
    }
    zx0_error=ZX0_TRUNCATED; return 0;
}
zx0_decompress_vram

Decodiert bei angehaltenem LCD ZX0-Tilepixel oder Kartendaten direkt in die gewählte VRAM-Bank. VRAM selbst liefert den Verlauf für Rückverweise; ein RAM-Zwischenpuffer ist daher unnötig.

Syntax

c
u16 zx0_decompress_vram(u16 vram_addr, const void* src, u16 packed_size);

Parameter

vram_addr

VRAM-Startadresse, 0x8000..0x9FFF. Die Ausgabe wird durch das VRAM-Ende bei 0xA000 begrenzt. Wählen Sie auf CGB vor dem Aufruf VBK.

src

Beginn der über die aktuelle Bankeinblendung lesbaren komprimierten Daten. Darf nicht null sein.

packed_size

Byteanzahl der vollständigen Eingabe. Ein ZX0-Strom enthält seine Endmarkierung und keine nachfolgenden Bytes. Ein KQA1-Container enthält seinen Neun-Byte-Header. Maximum: 65535 Bytes.

Rückgabewert

Liefert bei Erfolg die Anzahl decodierter Bytes, bei Fehler null. Prüfen Sie stets auch zx0_error.

Bedingungen und Grenzen

Binden Sie zx0.h ein und kompilieren Sie lib/zx0.c. Diese Routinen teilen sich Arbeitsspeicher und sind aus Interrupts nicht reentrant. Ein- und Ausgabe dürfen weder überlappen noch im CPU-Adressraum umbrechen oder aktuell eingeblendete Bankfenster überschreiten. Die Bibliothek schaltet keine Asset-Bänke um.

Jeder Aufruf aktualisiert zx0_error: 0 Erfolg, 1 ungültiges Argument, 2 abgeschnittene Eingabe, 3 fehlerhafter Datenstrom, 4 zu wenig Ausgabespeicher, 5 aktive Anzeige. Ein Fehler kann Teilausgabe hinterlassen; verwenden Sie diese nicht. Bei mehreren ungültigen Bedingungen bestimmt die zuerst erkannte den Code.

Akzeptiert vorwärtsgerichtete ZX0-v2-Ströme. ZX0 v1, Rückwärtsströme und externe Wörterbücher gehören nicht zu dieser Schnittstelle. Kennen Sie die decodierte Größe des am Host erzeugten Assets und stellen Sie ausreichend Speicher bereit.

Liefert Fehler 5 bei aktiviertem LCD; VBlank allein genügt nicht. Anzeige-, VBK- und Interrupt-Einstellungen bleiben unverändert. Der Aufrufer stoppt und startet das LCD.

ZX0-Format — Einar Saukas

Anwendungsbeispiel

c
count=zx0_decompress_vram(0x8800,packed_tiles,packed_tiles_SIZE);
    if(count!=48||zx0_error!=ZX0_OK)failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

zx0_decompress_vram: DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
DMG — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
zx0_decompress_vram: CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.
CGB — Die Zeile RAM MAP wiederholt Quadrat-, Rauten- und Schachbrett-Tiles. AUTO RLE MAP bildet aus sechzehn Quadraten einen waagerechten Balken. VRAM TILES wiederholt dieselben drei Tiles nach Decodierung ihrer Pixel ins VRAM. Auf CGB und FC ist das Quadrat weiß, die Raute rot und das Schachbrett blau; DMG verwendet Graustufen. CHECKS OK bestätigt die erwarteten decodierten Größen ohne Fehler bei allen drei Aufrufen.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/zx0.h:21

Deklarationshinweise im Original
Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off.
Preserve LCDC, VBK and interrupt state. Output must fit before $A000.

kitaqgb/lib/zx0.c:132

c
u16 zx0_decompress_vram(u16 vram_addr,const void* src,u16 packed_size) {
    zx0_error=ZX0_OK;
    if(vram_addr<0x8000||vram_addr>=0xA000) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
    if(kq_zx_lcdc&0x80) { zx0_error=ZX0_DISPLAY_ACTIVE; return 0; }
    return zx0_decompress((void*)vram_addr,(u16)(0xA000-vram_addr),src,packed_size);
}

asset.h — Ressourcen-IDs und Datenbeschreibungen

Die Ressourcenbibliothek findet Daten in ROM-Bänken über eine 8-Bit-ID. Binden Sie asset.c ein; auf dem FC zusätzlich bank.c. Ein gepackter AssetDesc belegt 6 Byte: Typ, Banknummer der Nutzdaten, 16-Bit-Adresse und Länge in Byte. Deskriptortabelle und Nutzdaten dürfen in verschiedenen ROM-Bänken liegen.

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Sucht eine RAW- oder TILES-Ressource und überträgt alle desc.len Byte mit __vram_copy. Wählen Sie zuvor die ROM-Bank der Nutzdaten aus: Die GB-Funktion verwendet desc.ptr direkt und schaltet für den Transfer nicht auf desc.bank um.

asset_get

Kopiert einen AssetDesc aus der ROM-Bank der registrierten Tabelle in den bereitgestellten Speicher. Damit werden die Metadaten der Ressource gelesen, nicht ihre Nutzdaten.

Syntax

c
u8 asset_get(u8 asset_id, AssetDesc* out_desc);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

out_desc

Beschreibbarer Speicher für einen 6-Byte-Deskriptor. Ein Nullzeiger wird vor dem Tabellenzugriff zurückgewiesen.

Rückgabewert

1 nach dem Kopieren des Deskriptors; 0 bei Nullzeiger oder ungültiger ID. Bei diesen Fehlern bleibt der Zielspeicher unverändert.

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Anwendungsbeispiel

c
loaded=asset_get(0,&descriptor);
expect(loaded==1,1);
expect(descriptor.type==ASSET_TYPE_TILES && descriptor.bank==2,2);
expect(descriptor.ptr==asset_shapes && descriptor.len==144,3);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest Deskriptor 0 und prüft Typ TILES, Bank 2, Zeiger und Länge 144 Byte. Ungültige IDs und Nullzeiger müssen scheitern; bei einer fehlgeschlagenen Suche bleibt der vorherige Ausgabewert erhalten.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_get: DMG
DMG
asset_get: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:24

Deklarationshinweise im Original
Copy one descriptor from its ROM bank into caller storage. Return zero for a
null destination or an out-of-range ID; table validity is the caller's responsibility.

kitaqgb/lib/asset.c:18

c
u8 asset_get(u8 asset_id, AssetDesc* out_desc)
{
    if (out_desc == 0) return 0;
    if (asset_id >= asset_table_count) return 0;
    __farmemcpy(out_desc, asset_table_bank, asset_table + asset_id, sizeof(AssetDesc));
    return 1;
}
asset_get_bank

Liest die Banknummer der Nutzdaten aus dem Deskriptor. Dies ist nicht die Banknummer der Tabelle. Nach dem Aufruf bleibt diese ROM-Bank auch nicht ausgewählt.

Syntax

c
u8 asset_get_bank(u8 asset_id);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

Rückgabewert

Das 8-Bit-Feld bank oder 0, wenn die Suche scheitert. Bank null kann ebenfalls gültig sein. Nutzen Sie asset_get(), um den Erfolg unabhängig vom Wert zu erkennen.

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Jede Abfrage ruft erneut asset_get auf und kopiert einen Deskriptor. Wenn Bank, Zeiger und Länge gemeinsam benötigt werden, genügt ein Aufruf von asset_get mit anschließendem Lesen der Felder.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Anwendungsbeispiel

c
payload_bank=asset_get_bank(0);
expect(payload_bank==2,17); // Payload bank, not descriptor-table bank 3.
expect(asset_get_bank(4)==0,18); // Failure sentinel; a valid descriptor may also use bank 0.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Erwartet wird ROM-Bank 2 der Nutzdaten, obwohl die Tabelle in Bank 3 liegt. Zusätzlich muss eine ungültige ID null zurückgeben.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_get_bank: DMG
DMG
asset_get_bank: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:32

Deklarationshinweise im Original
Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.

kitaqgb/lib/asset.c:51

c
u8 asset_get_bank(u8 asset_id)
{
    AssetDesc desc;
    if (asset_get(asset_id, &desc) == 0) return 0;
    return desc.bank;
}
asset_get_len

Liest die Länge der Ressource in Byte aus dem Deskriptor. Der Wert ist eine Metadatenangabe. Die Funktion untersucht keine Nutzdaten und rechnet die Länge nicht in Kacheln, Elemente oder Bilder um.

Syntax

c
u16 asset_get_len(u8 asset_id);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

Rückgabewert

Das 16-Bit-Feld len in Byte oder 0 bei erfolgloser Suche. Auch eine leere Ressource hat Länge null. Unterscheiden Sie diese Fälle mit asset_get().

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Jede Abfrage ruft erneut asset_get auf und kopiert einen Deskriptor. Wenn Bank, Zeiger und Länge gemeinsam benötigt werden, genügt ein Aufruf von asset_get mit anschließendem Lesen der Felder.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Anwendungsbeispiel

c
expect(asset_get_len(0)==144,21); // Bytes, not tiles.
expect(asset_get_len(3)==0 && asset_get_len(4)==0,22); // Empty asset and invalid ID both yield zero.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Ressource mit neun Kacheln muss 144 Byte melden, nicht neun Kacheln. Eine leere Ressource und eine ungültige ID müssen beide null liefern.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_get_len: DMG
DMG
asset_get_len: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:37

Deklarationshinweise im Original
Return the descriptor byte length, or zero if its ID cannot be resolved.

kitaqgb/lib/asset.c:68

c
u16 asset_get_len(u8 asset_id)
{
    AssetDesc desc;
    if (asset_get(asset_id, &desc) == 0) return 0;
    return desc.len;
}
asset_get_ptr

Liest die im Deskriptor gespeicherte 16-Bit-Adresse der Nutzdaten. Der zurückgegebene Nahzeiger enthält keine Banknummer. Verwenden Sie ihn zusammen mit asset_get_bank() und einer bankübergreifenden Kopierfunktion, um Daten aus einer anderen ROM-Bank zu lesen.

Syntax

c
const u8* asset_get_ptr(u8 asset_id);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

Rückgabewert

Der gespeicherte const u8* oder ein Nullzeiger bei erfolgloser Suche. Der Nutzdatenzeiger im Deskriptor wird nicht auf null geprüft. Mit asset_get() lässt sich ein Suchfehler eindeutig erkennen.

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Jede Abfrage ruft erneut asset_get auf und kopiert einen Deskriptor. Wenn Bank, Zeiger und Länge gemeinsam benötigt werden, genügt ein Aufruf von asset_get mit anschließendem Lesen der Felder.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Anwendungsbeispiel

c
payload_pointer=asset_get_ptr(0);
expect(payload_pointer==asset_shapes,19);
expect(*asset_bank_marker==0xA1,20); // Getting the pointer leaves bank 1 selected.
// Use payload_bank together with payload_pointer for a far copy; do not dereference it here.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Zeiger muss der nach dem Linken feststehenden ROM-Adresse entsprechen, während ein Marker in Bank 1 weiterhin lesbar ist. Danach werden Zeiger und ROM-Bank 2 an die bankübergreifende Kopie übergeben.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_get_ptr: DMG
DMG
asset_get_ptr: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:35

Deklarationshinweise im Original
Return the stored address without switching banks. Use the descriptor bank
with far-data helpers before dereferencing banked assets; failure returns null.

kitaqgb/lib/asset.c:60

c
const u8* asset_get_ptr(u8 asset_id)
{
    AssetDesc desc;
    if (asset_get(asset_id, &desc) == 0) return 0;
    return desc.ptr;
}
asset_load_raw

Sucht die Ressource und kopiert min(desc.len, max_len) Byte aus ihrer ROM-Bank in beschreibbaren Speicher. Der Typ wird nicht geprüft: Grafik-, Karten- und Musikdaten werden unverändert kopiert, ohne Dekodierung oder Dekomprimierung.

Syntax

c
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

dst

Ziel in beschreibbarem Speicher mit genügend Platz für alle kopierten Byte. Abgesehen von einem Transfer mit Länge null erfolgt keine Prüfung auf Nullzeiger oder ungültige Zieladressen.

max_len

Höchstens zu kopierende Byte, 0–65535. Eine kleinere Grenze kürzt die Kopie; bei null werden keine Nutzdaten kopiert.

Rückgabewert

0, wenn die Suche scheitert, sonst 1 – auch bei gekürzter Kopie, Grenze null oder leerer Ressource. Der Rückgabewert ist keine Byteanzahl und bestätigt nicht, dass die gesamte Ressource in den Puffer passte.

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Der gesamte Quellbereich muss in der vorgesehenen ROM-Zuordnung lesbar und der gesamte Zielbereich beschreibbar sein. Die Kopie schaltet am Fensterende nicht automatisch zur nächsten Bank, behandelt Überlappungen nicht wie memmove und steuert keine sicheren VRAM-Schreibzeitpunkte. Verwenden Sie für VRAM die Grafikübertragungs-APIs.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Anwendungsbeispiel

c
loaded=asset_load_raw(0,buffer,7); // Success with truncation: copy seven of 144 bytes.
expect(loaded==1 && buffer[7]==0x55,7);
for(i=0;i<7;i++) expect(buffer[(__safe_index u8)i]==expected_shape_byte(i),8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Eine Grenze von sieben kopiert nur sieben Byte einer 144-Byte-Ressource und lässt das nächste Byte auf 0x55, meldet aber Erfolg. Außerdem werden vollständige Kopie, Grenze null, leere Ressource und das Kopieren von MAP-Daten geprüft.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_load_raw: DMG
DMG
asset_load_raw: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:27

Deklarationshinweise im Original
Copy at most max_len bytes using the asset's bank. Success means the ID was
valid, even when the payload was truncated to fit the supplied limit.

kitaqgb/lib/asset.c:28

c
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len)
{
    AssetDesc desc;
    u16 len;
    if (asset_get(asset_id, &desc) == 0) return 0;
    len = desc.len;
    if (len > max_len) len = max_len;
    __farmemcpy(dst, desc.bank, desc.ptr, len);
    return 1;
}
asset_load_tiles

Sucht eine RAW- oder TILES-Ressource und überträgt alle desc.len Byte mit __vram_copy. Wählen Sie zuvor die ROM-Bank der Nutzdaten aus: Die GB-Funktion verwendet desc.ptr direkt und schaltet für den Transfer nicht auf desc.bank um.

Syntax

c
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);

Parameter

asset_id

Ressourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID asset_id < count.

vram_dst

Byteadresse im VRAM zwischen $8000 und $9FFF, keine Kachelnummer. Für Kachelmuster sind eine durch 16 teilbare Adresse und eine Länge als Vielfaches von 16 nötig. Die Bibliothek prüft diese Formatregeln nicht.

Rückgabewert

0 bei ungültiger ID oder einem anderen Typ als RAW/TILES; 1 nach einem akzeptierten Transfer, auch bei Länge null. Erfolg bestätigt weder das Kachelformat noch die korrekte Darstellung im VRAM.

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Die Beispiele legen den aufrufenden Code in die feste Bank 0, damit ein Wechsel der Quellbank den laufenden Code nicht ausblendet. Die Übertragungen sind synchron. Unterbrechen Sie sie nicht durch eine weitere bankwechselnde Kopie. Die Hilfsfunktion allein macht nicht die gesamte Anwendung interruptsicher.

Der Transfer schreibt nur Bytes. Er platziert keine Kacheln auf der Karte, weist keine Farben zu und reserviert keinen VRAM. Kachelkarte und Paletten werden separat eingerichtet. Die Beispiele übertragen bei abgeschalteter Darstellung und schalten sie erst nach dem Bildaufbau ein.

Die GB-Hilfsroutine stellt die vom Compiler gemerkte ROM-Bank wieder her. Halten Sie diesen Zustand mit __bankswitch aktuell; direkte Mapper-Schreibzugriffe aktualisieren ihn nicht. Der HRAM-Speicherplatz für die Rückkehrbank wird gemeinsam genutzt. Verschachtelte Übertragungen dürfen ihn nicht überschreiben.

Anwendungsbeispiel

c
__bankswitch(payload_bank); // GB tile upload expects the payload bank already visible.
loaded=asset_load_tiles(0,0x8010); // Nine tiles = 144 bytes, LCD off.
expect(loaded==1,24);
__bankswitch(1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel lädt neun eigene Muster mit je 8×8 Pixeln, insgesamt 144 Byte, und prüft die Ablehnung von MAP und ungültigen IDs. Auf dem FC werden damit sowohl der 128-Byte-Block als auch die verbleibenden 16 Byte geprüft.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_load_tiles: DMG
DMG
asset_load_tiles: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:30

Deklarationshinweise im Original
Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes
the descriptor pointer directly; callers must arrange the correct visible ROM bank.

kitaqgb/lib/asset.c:41

c
u8 asset_load_tiles(u8 asset_id, u16 vram_dst)
{
    AssetDesc desc;
    if (asset_get(asset_id, &desc) == 0) return 0;
    if (desc.type != ASSET_TYPE_TILES && desc.type != ASSET_TYPE_RAW) return 0;
    __vram_copy(vram_dst, desc.ptr, desc.len);
    return 1;
}
asset_set_table

Registriert Banknummer, Adresse und Eintragszahl der einzigen aktiven Deskriptortabelle. Die Funktion speichert nur diese drei Werte. Sie kopiert weder die Tabelle noch Nutzdaten und reserviert keinen Speicher.

Syntax

c
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);

Parameter

bank

8-Bit-Nummer der ROM-Bank mit der Deskriptortabelle, nicht mit den Nutzdaten.

table

Nahzeiger auf count aufeinanderfolgende AssetDesc-Einträge. Solange die Tabelle registriert ist, müssen alle count * 6 Byte in ihrer ROM-Bank lesbar bleiben.

count

Anzahl der Einträge, 0–255. Bei null ist keine ID gültig. Mit asset_set_table(0, 0, 0) lässt sich sicher eine leere Tabelle registrieren.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Registrieren Sie die Tabelle vor der ersten Suche. Die Registrierung ist ein gemeinsamer globaler Zustand und darf nicht gleichzeitig mit einer Suche geändert werden. Geprüft werden IDs und der Ausgabezeiger von asset_get, nicht jedoch Tabelle, Nutzdatenadressen oder Cartridge-Inhalt.

Anwendungsbeispiel

c
asset_set_table(3,asset_descriptors,4); // Four descriptors in bank 3, payloads in bank 2.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel registriert vier Deskriptoren in Bank 3; ihre nicht leeren Nutzdaten liegen in Bank 2. Zusätzlich wird geprüft, dass die Suche in einer leeren Tabelle ohne Lesen von Adresse null scheitert.

Erwartetes Bild: Eine rote Reihe beginnt bei (16,32) und belegt 72×8 Pixel. Dreimal folgen ein 8×8-Dreieck, ein 8×8-Quadrat mit einem Pixel Rand und eine Kachel mit vier gefüllten linken Spalten. Das Dreieck wächst von einem Pixel oben links auf acht Pixel in der untersten Zeile.

Auf dem GB zeigen das blaue Dreieck und der Rahmen bei (16,64) das Ergebnis von __farmemcpy, das grüne Paar bei (16,96) das von __far_memcpy. Jedes Paar belegt 16×8 Pixel. Der CGB nutzt diese Farben, der DMG dieselben Formen in Schwarz auf Weiß.

Erwartet werden FAILED CHECKS 000 und FIRST FAILURE 00. Die Prüfung führt 300 Bilder aus und vergleicht Text, Formmasken und Farben mit den Sollwerten. Dies ist ein Emulatornachweis, kein Test auf physischer Hardware.

asset_set_table: DMG
DMG
asset_set_table: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/asset.h:21

Deklarationshinweise im Original
Retain the descriptor table address, bank and count; the table is not copied.

kitaqgb/lib/asset.c:9

c
void asset_set_table(u8 bank, const AssetDesc* table, u8 count)
{
    asset_table_bank = bank;
    asset_table = table;
    asset_table_count = count;
}

audio.h — Musik, Soundeffekte und Audiosteuerung

Bietet Direktzugriff auf vier Stimmen, bankbasierte Musik/Effekte, Stereorouting, Lautstärkeübergänge und eigene Wellen. Kanal-IDs von Musikstream und direkter API sind CH1=0, CH2=1, CH3=2, CH4=3. CH3 spielt Wellenformen, CH4 erzeugt Rauschen.

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

Audio_CancelMasterVolumeFade

Stoppt weitere Übergangsschritte und erhält die aktuellen Pegel und Register.

Syntax

c
void Audio_CancelMasterVolumeFade();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Anwendungsbeispiel

c
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
    sound_begin("PAN AND VOLUME");
    Audio_SetMasterVolume(7,7);
    Audio_Ch1NoteOn(33,0xC0,2);
    Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
    sound_result[0]=NR51;
    sound_wait(30);
    // Packed low two bits are CH1: 2 means right. Other channels remain centered.
    Audio_SetPanPacked(2);
    sound_result[1]=NR51;
    sound_wait(30);
    Audio_SetPanPacked(0);
    sound_result[2]=NR51;
    Audio_FadeToMasterVolume(1,1,5);
    sound_wait(30);
    sound_result[3]=NR50;
    sound_result[4]=Audio_FadeActive;
    sound_wait(30);
    // Cancel halfway through a rise: retain volume 4 instead of reaching 7.
    Audio_FadeToMasterVolume(7,7,5);
    sound_wait(15);
    Audio_CancelMasterVolumeFade();
    sound_result[5]=NR50;
    sound_wait(30);
    sound_result[6]=NR50;
    // A zero fade interval sets the target immediately. Level zero is not mute.
    Audio_FadeToMasterVolume(0,0,0);
    sound_result[7]=NR50;
    sound_wait(30);
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

A4 wandert nach links, rechts und in die Mitte. Dort sinkt der Pegel von 7 auf 1, steigt dann auf 4 und bleibt so. Pegel 0 ist noch leise hörbar; erst der Kanalstopp erzeugt Stille. Routingänderungen können einen abklingenden Filtertransienten hinterlassen.

Audio_CancelMasterVolumeFade: DMG
DMG
Audio_CancelMasterVolumeFade: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:125

Deklarationshinweise im Original
Cancel further volume steps, retaining the current cached levels and hardware output.

kitaqgb/lib/audio.c:548

c
void Audio_CancelMasterVolumeFade() {
    Audio_FadeTargetLeft = Audio_MasterLeft;
    Audio_FadeTargetRight = Audio_MasterRight;
    Audio_FadeStepFrames = 0;
    Audio_FadeCounter = 0;
    Audio_FadeActive = 0;
}
Audio_Ch1NoteOn

Setzt CH1-Sweep, Tastgrad, Hüllkurve und Tonhöhe und löst den Puls aus.

Syntax

c
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2);

Parameter

note

Tonhöhentabellenindex 0..67. Hinweise zur Bereichsrückführung und zum Oktavunterschied von CH3 stehen in den Anmerkungen.

vol_env

NR12-/NR22-/NR42-Codierung: oberes Halbbyte Anfangslautstärke, Bit 3 steigende Hüllkurve, untere drei Bits Hüllkurvenperiode. 0xC0 hält Lautstärke 12.

duty2

Puls-Tastgrad: 0=12,5 %, 1=25 %, 3=75 %; alle anderen Werte wählen 50 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

note indiziert eine Tonhöhentabelle von 0 bis 67: 0 ist C2, 33 ist A4. Werte über 67 werden auf 67 begrenzt; 60..67 verwenden die Frequenzen von 48..55. Bei gleichem Index klingt CH3 eine Oktave tiefer als ein Pulskanal. Note-on-Funktionen lösen die Hardware direkt aus, ohne Aktivierungs- oder Pauseschalter zu prüfen.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_Ch1NoteOn: DMG
DMG
Audio_Ch1NoteOn: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:151

Deklarationshinweise im Original
Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the
note index; duty values 0, 1 and 3 select their encodings, and all others use 2.

kitaqgb/lib/audio.c:132

c
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2) {
    u16 freq;
    u8 duty_reg;
    u8 hi;

    if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
    freq = GB_FREQ_TABLE[note];

    duty_reg = 128;
    if (duty2 == 0) duty_reg = 0;
    else if (duty2 == 1) duty_reg = 64;
    else if (duty2 == 3) duty_reg = 192;

    NR10 = Audio_Ch1Sweep;
    NR11 = duty_reg;
    NR12 = vol_env;
    NR13 = (u8)(freq & 0xFF);
    hi = (u8)((u16)freq >> 8);
    NR14 = (u8)(hi | 0x80);
}
Audio_Ch2NoteOn

Setzt CH2-Tastgrad, Hüllkurve und Tonhöhe und löst den Puls aus.

Syntax

c
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2);

Parameter

note

Tonhöhentabellenindex 0..67. Hinweise zur Bereichsrückführung und zum Oktavunterschied von CH3 stehen in den Anmerkungen.

vol_env

NR12-/NR22-/NR42-Codierung: oberes Halbbyte Anfangslautstärke, Bit 3 steigende Hüllkurve, untere drei Bits Hüllkurvenperiode. 0xC0 hält Lautstärke 12.

duty2

Puls-Tastgrad: 0=12,5 %, 1=25 %, 3=75 %; alle anderen Werte wählen 50 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

note indiziert eine Tonhöhentabelle von 0 bis 67: 0 ist C2, 33 ist A4. Werte über 67 werden auf 67 begrenzt; 60..67 verwenden die Frequenzen von 48..55. Bei gleichem Index klingt CH3 eine Oktave tiefer als ein Pulskanal. Note-on-Funktionen lösen die Hardware direkt aus, ohne Aktivierungs- oder Pauseschalter zu prüfen.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_Ch2NoteOn: DMG
DMG
Audio_Ch2NoteOn: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:154

Deklarationshinweise im Original
Trigger CH2 with the supplied raw envelope and a clamped note index. Duty
values 0, 1 and 3 select their encodings; all other values use duty 2.

kitaqgb/lib/audio.c:666

c
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2) {
    u16 freq;
    u8 duty_reg;
    u8 hi;

    if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
    freq = GB_FREQ_TABLE[note];

    duty_reg = 128;
    if (duty2 == 0) duty_reg = 0;
    else if (duty2 == 1) duty_reg = 64;
    else if (duty2 == 3) duty_reg = 192;

    NR21 = duty_reg;
    NR22 = vol_env;
    NR23 = (u8)(freq & 0xFF);
    hi = (u8)((u16)freq >> 8);
    NR24 = (u8)(hi | 0x80);
}
Audio_Ch3NoteOn

Triggert die geladene CH3-Welle mit angeforderter Tonhöhe und NR32-Pegel.

Syntax

c
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level);

Parameter

note

Tonhöhentabellenindex 0..67. Hinweise zur Bereichsrückführung und zum Oktavunterschied von CH3 stehen in den Anmerkungen.

level

NR32-Codierung: 0x00=stumm, 0x20=100 %, 0x40=50 %, 0x60=25 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

note indiziert eine Tonhöhentabelle von 0 bis 67: 0 ist C2, 33 ist A4. Werte über 67 werden auf 67 begrenzt; 60..67 verwenden die Frequenzen von 48..55. Bei gleichem Index klingt CH3 eine Oktave tiefer als ein Pulskanal. Note-on-Funktionen lösen die Hardware direkt aus, ohne Aktivierungs- oder Pauseschalter zu prüfen.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_Ch3NoteOn: DMG
DMG
Audio_Ch3NoteOn: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:157

Deklarationshinweise im Original
Clamp the note index, program the raw NR32 output level, and trigger CH3.
Wave RAM must already contain the desired waveform; this does not load one.

kitaqgb/lib/audio.c:115

c
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level) {
    u16 freq;
    u8 hi;

    if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
    freq = GB_FREQ_TABLE[note];

    NR30 = 128;
    NR31 = 0;
    NR32 = level;
    NR33 = (u8)(freq & 255);
    hi = (u8)((u16)freq >> 8);
    NR34 = (u8)(hi | 128);
}
Audio_Ch4NoteOn

Speichert die Rauschparameter, setzt Hüllkurven-/Polynomzählerregister und triggert CH4.

Syntax

c
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env);

Parameter

param

Rohes NR43: Bits 7..4 Taktschiebung, Bit 3 kurzes LFSR, Bits 2..0 Teilercode.

vol_env

NR12-/NR22-/NR42-Codierung: oberes Halbbyte Anfangslautstärke, Bit 3 steigende Hüllkurve, untere drei Bits Hüllkurvenperiode. 0xC0 hält Lautstärke 12.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Automatischer Längenstopp ist nicht aktiviert. Beenden Sie den Ton über die Hüllkurve oder einen ausdrücklichen Stopp.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_Ch4NoteOn: DMG
DMG
Audio_Ch4NoteOn: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:160

Deklarationshinweise im Original
Cache the supplied noise parameter, program the raw envelope and polynomial
registers, then trigger CH4 with the length-enable bit clear.

kitaqgb/lib/audio.c:688

c
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env) {
    Audio_SetCh4Param(param);
    NR41 = 0x20;
    NR42 = vol_env;
    NR43 = Audio_Ch4Param;
    NR44 = 0x80;
}
Audio_FadeToMasterVolume

Bewegt jeden Ausgabepegel im angeforderten Intervall um einen Schritt zum Ziel.

Syntax

c
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames);

Parameter

left

Linker Hauptpegel 0..7; größere Werte werden auf 7 begrenzt. Null ist keine vollständige Stille.

right

Rechter Hauptpegel 0..7; größere Werte werden auf 7 begrenzt.

step_frames

Anzahl Audio_Update-Aufrufe pro Pegelschritt. Null wendet den Zielwert sofort an.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Anwendungsbeispiel

c
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
    sound_begin("PAN AND VOLUME");
    Audio_SetMasterVolume(7,7);
    Audio_Ch1NoteOn(33,0xC0,2);
    Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
    sound_result[0]=NR51;
    sound_wait(30);
    // Packed low two bits are CH1: 2 means right. Other channels remain centered.
    Audio_SetPanPacked(2);
    sound_result[1]=NR51;
    sound_wait(30);
    Audio_SetPanPacked(0);
    sound_result[2]=NR51;
    Audio_FadeToMasterVolume(1,1,5);
    sound_wait(30);
    sound_result[3]=NR50;
    sound_result[4]=Audio_FadeActive;
    sound_wait(30);
    // Cancel halfway through a rise: retain volume 4 instead of reaching 7.
    Audio_FadeToMasterVolume(7,7,5);
    sound_wait(15);
    Audio_CancelMasterVolumeFade();
    sound_result[5]=NR50;
    sound_wait(30);
    sound_result[6]=NR50;
    // A zero fade interval sets the target immediately. Level zero is not mute.
    Audio_FadeToMasterVolume(0,0,0);
    sound_result[7]=NR50;
    sound_wait(30);
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

A4 wandert nach links, rechts und in die Mitte. Dort sinkt der Pegel von 7 auf 1, steigt dann auf 4 und bleibt so. Pegel 0 ist noch leise hörbar; erst der Kanalstopp erzeugt Stille. Routingänderungen können einen abklingenden Filtertransienten hinterlassen.

Audio_FadeToMasterVolume: DMG
DMG
Audio_FadeToMasterVolume: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:123

Deklarationshinweise im Original
Move left/right volume toward clamped targets at the requested Audio_Update
call interval. An interval of zero applies the levels immediately.

kitaqgb/lib/audio.c:528

c
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames) {
    Audio_FadeTargetLeft = Audio_ClampVolume(left);
    Audio_FadeTargetRight = Audio_ClampVolume(right);

    if (step_frames == 0) {
        Audio_SetMasterVolume(Audio_FadeTargetLeft, Audio_FadeTargetRight);
        return;
    }

    Audio_FadeStepFrames = step_frames;
    Audio_FadeCounter = step_frames;
    if (Audio_MasterLeft == Audio_FadeTargetLeft && Audio_MasterRight == Audio_FadeTargetRight) {
        Audio_FadeActive = 0;
        Audio_FadeCounter = 0;
    } else {
        Audio_FadeActive = 1;
    }
}
Audio_Init

Aktiviert die APU, initialisiert Musik-, Effekt-, Pause-, Misch- und Wellenzustand und lässt alle Kanäle stumm.

Syntax

c
void Audio_Init();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_Init: DMG
DMG
Audio_Init: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:76

Deklarationshinweise im Original
Enable the APU and reset software streams, instruments, mix and fade state.
Load the initial triangle wave, then leave every channel silent. Call at startup
before concurrent interrupt-driven audio service can access these shared fields.

kitaqgb/lib/audio.c:864

c
void Audio_Init() {
    NR52 = 0x80;
    NR51 = 0xFF;
    Audio_Pan = 0xFF;
    Audio_EffectPan = AUDIO_PAN_INHERIT;
    Audio_EffectPan3 = AUDIO_PAN_INHERIT;
    Audio_UpdateNR51();

    Audio_SetMasterVolume(AUDIO_VOLUME_MAX, AUDIO_VOLUME_MAX);
    Audio_SilenceAll();

    Audio_PlayingMusic = 0;
    Audio_Paused = 0;
    Audio_MusicEnabled = 1;
    Audio_SfxEnabled = 1;
    Audio_Delay = 0;
    Audio_MusicBank = 0;
    Audio_MusicPointer = 0;
    Audio_MusicLoopPoint = 0;

    Audio_EffectPointer = 0;
    Audio_EffectPriority = 0;
    Audio_EffectBank = 0;
    Audio_EffectPointer3 = 0;
    Audio_EffectPriority3 = 0;
    Audio_EffectBank3 = 0;
    Audio_EffectUsesCh2 = 0;
    Audio_EffectPan = AUDIO_PAN_INHERIT;
    Audio_EffectPan3 = AUDIO_PAN_INHERIT;

    Audio_LastChMask = 0;
    Audio_LastCh1Note = 0;
    Audio_LastCh2Note = 0;
    Audio_LastCh3Note = 0;
    Audio_LastCh4Param = 0;

    Audio_Ch1Duty = 2;
    Audio_Ch2Duty = 2;
    Audio_Ch1Env = 0xF1;
    Audio_Ch2Env = 0xF2;
    Audio_Ch4Env = 0xF1;
    Audio_Ch4Param = 0x00;
    Audio_Ch3Level = AUDIO_CH3_LEVEL_100;
    Audio_Ch3Wave = AUDIO_WAVE_TRIANGLE;
    Audio_Ch1Sweep = 0x00;

    Audio_SetCustomWaveTriangle();
#ifdef AUDIO_EXCLUDE_WAVE_LOAD_API
    Audio_ApplyWaveBytes(Audio_CustomWave);
#else
    Audio_LoadWave(Audio_Ch3Wave);
#endif
    Audio_Ch3Off();
}
Audio_LoadCustomWave

Kopiert sechzehn Bytes in Benutzerwellen-Cache und CH3-Wellen-RAM.

Syntax

c
void __stackcall Audio_LoadCustomWave(const u8 *wave16);

Parameter

wave16

Sechzehn lesbare Bytes; oberes und unteres Halbbyte codieren aufeinanderfolgende Abtastwerte. NULL wird ignoriert.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Nach dem Kopieren darf der Aufrufer die Quelle wiederverwenden. Die Funktion deaktiviert den DAC zum Schreiben; der Aufrufer triggert die Note erneut.

Anwendungsbeispiel

c
// Compare a triangle preset with an original packed 32-sample pulse waveform.
#include "gb_sound_example.h"
__prg_rom u8 custom_wave[16]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0,0,0,0,0};
void main() {
    sound_begin("WAVE PRESET CUSTOM");
    Audio_SetMasterVolume(3,3);
    Audio_LoadWave(AUDIO_WAVE_TRIANGLE);
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // Loading copies all sixteen bytes and enables the DAC without triggering a note.
    Audio_LoadCustomWave(custom_wave);
    sound_result[0]=Audio_CustomWave[0]; sound_result[1]=Audio_CustomWave[8];
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // The cache survives another preset load; select CUSTOM to reuse it.
    Audio_LoadWave(AUDIO_WAVE_SAW);
    Audio_LoadWave(AUDIO_WAVE_CUSTOM);
    sound_result[2]=WAVE0; sound_result[3]=WAVE8;
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Zu hören sind die Dreiecksvorgabe, eine eigene Pulswelle und dieselbe aus dem Cache nachgeladene Pulswelle. Jede dauert 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 220 Hz; nur die erste klingt anders.

Audio_LoadCustomWave: DMG
DMG
Audio_LoadCustomWave: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:138

Deklarationshinweise im Original
Copy 16 packed sample bytes into the persistent custom cache and wave RAM.
A null pointer is ignored; the source is needed only for this call.

kitaqgb/lib/audio.c:614

c
void __stackcall Audio_LoadCustomWave(const u8 *wave16) {
    if (wave16 == 0) return;

    Audio_CustomWave[0] = wave16[0];   Audio_CustomWave[1] = wave16[1];
    Audio_CustomWave[2] = wave16[2];   Audio_CustomWave[3] = wave16[3];
    Audio_CustomWave[4] = wave16[4];   Audio_CustomWave[5] = wave16[5];
    Audio_CustomWave[6] = wave16[6];   Audio_CustomWave[7] = wave16[7];
    Audio_CustomWave[8] = wave16[8];   Audio_CustomWave[9] = wave16[9];
    Audio_CustomWave[10] = wave16[10]; Audio_CustomWave[11] = wave16[11];
    Audio_CustomWave[12] = wave16[12]; Audio_CustomWave[13] = wave16[13];
    Audio_CustomWave[14] = wave16[14]; Audio_CustomWave[15] = wave16[15];

    Audio_ApplyWaveBytes(Audio_CustomWave);
}
Audio_LoadWave

Installiert eine Vorgabe- oder zwischengespeicherte Benutzerwelle im CH3-Wellen-RAM.

Syntax

c
void __stackcall Audio_LoadWave(u8 wave_id);

Parameter

wave_id

AUDIO_WAVE_*-ID 0..7; 7 wählt die zwischengespeicherte eigene Welle. Werte über 7 bewirken nichts.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Laden startet keine Note und ändert Audio_Ch3Wave nicht. Die Dreiecksvorgabe setzt auch den benutzerdefinierten Cache auf Dreieck zurück. Rufen Sie Audio_Ch3NoteOn zum Auslösen auf.

Anwendungsbeispiel

c
// Compare a triangle preset with an original packed 32-sample pulse waveform.
#include "gb_sound_example.h"
__prg_rom u8 custom_wave[16]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0,0,0,0,0};
void main() {
    sound_begin("WAVE PRESET CUSTOM");
    Audio_SetMasterVolume(3,3);
    Audio_LoadWave(AUDIO_WAVE_TRIANGLE);
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // Loading copies all sixteen bytes and enables the DAC without triggering a note.
    Audio_LoadCustomWave(custom_wave);
    sound_result[0]=Audio_CustomWave[0]; sound_result[1]=Audio_CustomWave[8];
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // The cache survives another preset load; select CUSTOM to reuse it.
    Audio_LoadWave(AUDIO_WAVE_SAW);
    Audio_LoadWave(AUDIO_WAVE_CUSTOM);
    sound_result[2]=WAVE0; sound_result[3]=WAVE8;
    Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
    sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Zu hören sind die Dreiecksvorgabe, eine eigene Pulswelle und dieselbe aus dem Cache nachgeladene Pulswelle. Jede dauert 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 220 Hz; nur die erste klingt anders.

Audio_LoadWave: DMG
DMG
Audio_LoadWave: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:135

Deklarationshinweise im Original
Install a named preset or the cached custom wave. Unknown IDs are ignored.
This does not update Audio_Ch3Wave or trigger a new note.

kitaqgb/lib/audio.c:631

c
void __stackcall Audio_LoadWave(u8 wave_id) {
    if (wave_id == AUDIO_WAVE_TRIANGLE) Audio_LoadWave0();
    else if (wave_id == AUDIO_WAVE_SAW) Audio_LoadWave1();
    else if (wave_id == AUDIO_WAVE_VOWEL_A) Audio_LoadWave2();
    else if (wave_id == AUDIO_WAVE_VOWEL_I) Audio_LoadWave3();
    else if (wave_id == AUDIO_WAVE_VOWEL_U) Audio_LoadWave4();
    else if (wave_id == AUDIO_WAVE_VOWEL_E) Audio_LoadWave5();
    else if (wave_id == AUDIO_WAVE_VOWEL_O) Audio_LoadWave6();
    else if (wave_id == AUDIO_WAVE_CUSTOM) Audio_ApplyWaveBytes(Audio_CustomWave);
}
Audio_PlayMusic

Bereitet das Lied in der angegebenen Bank von Anfang an vor und setzt Instrumente, Panorama und delay zurück.

Syntax

c
void __stackcall Audio_PlayMusic(u8 bank, u8 *song);

Parameter

bank

ROM-Bank des Streams; muss seiner Ablage entsprechen.

song

Startadresse des Lieds. Der Treiber leiht das Array aus; es muss während der gesamten Wiedergabe lesbar bleiben.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Das nächste Audio_Update liest die Daten. NULL wird nicht geprüft. Bestehende Effekte bleiben aktiv.

Anwendungsbeispiel

c
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
    AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_LOOP
};
void main() {
    u8 delay;
    sound_begin("MUSIC PAUSE GATE");
    Audio_SetMasterVolume(3,3);
    Audio_PlayMusic(0,song);
    sound_wait(30);
    delay=Audio_Delay;
    Audio_SetPaused(1);
    sound_wait(30);
    sound_result[0]=(u8)(Audio_Delay==delay);
    sound_result[1]=Audio_Paused;
    Audio_SetPaused(0);
    sound_wait(30);
    sound_result[2]=Audio_Paused;
    // Disabling suppresses note writes; the next 30 updates still consume data.
    Audio_SetMusicEnabled(0);
    sound_wait(30);
    sound_result[3]=Audio_Delay;
    sound_result[4]=Audio_MusicEnabled;
    // Explicitly stop the sounding channel while leaving the stream running.
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(30);
    Audio_SetMusicEnabled(1);
    sound_wait(30);
    Audio_StopMusic();
    sound_result[5]=Audio_PlayingMusic;
    sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Es folgen eine Note, Pausenstille, Fortsetzung, eine bei deaktivierter Musik gehaltene Note, ausdrückliche Kanalstille, die nächste Note nach Aktivierung und schließlich Stopp. RAM-Prüfungen zeigen zudem: 30 Pausenupdates erhalten delay, während die bloße Musiksperre es bis 30 fortschreiten lässt.

Audio_PlayMusic: DMG
DMG
Audio_PlayMusic: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:83

Deklarationshinweise im Original
Retain the bank and song pointer, reset legacy instruments/cursors, and arm
playback from the beginning. Supply a valid, persistent song; no bytes are copied
and null is not checked. Existing effect streams remain active.

kitaqgb/lib/audio.c:924

c
void __stackcall Audio_PlayMusic(u8 bank, u8 *song) {
    Audio_PlayingMusic = 0;
    Audio_MusicBank = bank;
    Audio_MusicPointer = song;
    Audio_MusicLoopPoint = song;
    Audio_Delay = 0;
    Audio_LastChMask = 0;

    Audio_Ch1Duty = 2;
    Audio_Ch2Duty = 2;
    Audio_Ch1Env = 0xF1;
    Audio_Ch2Env = 0xF2;
    Audio_Ch4Env = 0xF1;
    Audio_Ch4Param = 0x00;
    Audio_Ch3Level = AUDIO_CH3_LEVEL_100;
    Audio_Ch3Wave = AUDIO_WAVE_TRIANGLE;
    Audio_Ch1Sweep = 0x00;
    Audio_Pan = 0xFF;
    Audio_UpdateNR51();
    Audio_LoadWave(Audio_Ch3Wave);

    Audio_PlayingMusic = 1;
}
Audio_PlaySFX

Erfasst die aktuelle ROM-Bank und fordert einen Effekt mit übernommenem Basispanorama an.

Syntax

c
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority);

Parameter

sfx

Beginn des Effekt-Bytestroms. Hinweise zu Puls- und CH3-Formaten stehen in den Anmerkungen.

priority

Priorität 0..255. Größere Werte gewinnen; gleiche Werte können den aktuellen Effekt ebenfalls ersetzen.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_PlaySFX: DMG
DMG
Audio_PlaySFX: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:93

Deklarationshinweise im Original
Capture the currently mapped ROM bank and start an effect with inherited pan.
Use the explicit-bank API when the pointer belongs to another bank.

kitaqgb/lib/audio.c:1085

c
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority) {
    Audio_PlaySFXBanked(__rom_bank, sfx, priority);
}
Audio_PlaySFXBanked

Bestimmt den Effekttyp in der ausdrücklich angegebenen Quellbank und fordert Wiedergabe mit übernommenem Basispanorama an.

Syntax

c
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority);

Parameter

bank

ROM-Bank des Streams; muss seiner Ablage entsprechen.

sfx

Beginn des Effekt-Bytestroms. Hinweise zu Puls- und CH3-Formaten stehen in den Anmerkungen.

priority

Priorität 0..255. Größere Werte gewinnen; gleiche Werte können den aktuellen Effekt ebenfalls ersetzen.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_PlaySFXBanked: DMG
DMG
Audio_PlaySFXBanked: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:95

Deklarationshinweise im Original
Start a banked effect with the channel's base pan, subject to priority arbitration.

kitaqgb/lib/audio.c:1078

c
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority) {
    Audio_PlaySFXPannedBanked(bank, sfx, priority, AUDIO_PAN_INHERIT);
}
Audio_PlaySFXPanned

Erfasst die aktuelle ROM-Bank und fordert einen Effekt mit eigenem Panorama an.

Syntax

c
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan);

Parameter

sfx

Beginn des Effekt-Bytestroms. Hinweise zu Puls- und CH3-Formaten stehen in den Anmerkungen.

priority

Priorität 0..255. Größere Werte gewinnen; gleiche Werte können den aktuellen Effekt ebenfalls ersetzen.

pan

0=Mitte, 1=links, 2=rechts, 3=stumm. Effekt-APIs übernehmen bei Werten über 3 einschließlich 0xFF das Basispanorama.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_PlaySFXPanned: DMG
DMG
Audio_PlaySFXPanned: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:98

Deklarationshinweise im Original
Capture the currently mapped ROM bank and request an effect with a pan override.
Use the explicit-bank API when the pointer belongs to another bank.

kitaqgb/lib/audio.c:1091

c
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan) {
    Audio_PlaySFXPannedBanked(__rom_bank, sfx, priority, pan);
}
Audio_PlaySFXPannedBanked

Belegt einen Puls- oder CH3-Effektslot mit ausdrücklicher Bank-, Prioritäts- und Panoramaangabe.

Syntax

c
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan);

Parameter

bank

ROM-Bank des Streams; muss seiner Ablage entsprechen.

sfx

Beginn des Effekt-Bytestroms. Hinweise zu Puls- und CH3-Formaten stehen in den Anmerkungen.

priority

Priorität 0..255. Größere Werte gewinnen; gleiche Werte können den aktuellen Effekt ebenfalls ersetzen.

pan

0=Mitte, 1=links, 2=rechts, 3=stumm. Effekt-APIs übernehmen bei Werten über 3 einschließlich 0xFF das Basispanorama.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_PlaySFXPannedBanked: DMG
DMG
Audio_PlaySFXPannedBanked: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:103

Deklarationshinweise im Original
Retain a banked effect stream if its priority equals or exceeds the current
owner's priority, or that slot is empty. A leading CH3 marker selects the wave
slot and is skipped; other streams use the pulse slot. Paused requests are ignored.
Keep stream storage valid until completion; acceptance does not trigger a note.

kitaqgb/lib/audio.c:1041

c
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan) {
    u8 sfx_pan = pan;
    u8 use_ch3 = 0;
    if (sfx_pan > AUDIO_PAN_MUTE) sfx_pan = AUDIO_PAN_INHERIT;

    if (Audio_Paused != 0) return;
    if (sfx != 0) {
        use_ch3 = Audio_SfxStartsOnCh3Banked(bank, sfx);
        if (use_ch3 != 0) {
            if (Audio_EffectPointer3 == 0 || priority >= Audio_EffectPriority3) {
                Audio_EffectPointer3 = sfx + 1;
                Audio_EffectPriority3 = priority;
                Audio_EffectBank3 = bank;
                Audio_EffectPan3 = sfx_pan;
                Audio_UpdateNR51();
            }
            return;
        }
    }
    if (Audio_EffectPointer == 0 || priority >= Audio_EffectPriority) {
#ifdef AUDIO_VBLANK_SFX_AUTO_CH2
        // Choose pulse-channel ownership when accepting the effect, so its later
        // updates and deferred recovery agree on which physical channel was borrowed.
        Audio_EffectUsesCh2 = (u8)(AudioVBlank_MusicPlaying != 0 &&
                                   AudioVBlank_MusicEnabled != 0);
#else
        Audio_EffectUsesCh2 = 0;
#endif
        Audio_EffectPointer = sfx;
        Audio_EffectPriority = priority;
        Audio_EffectBank = bank;
        Audio_EffectPan = sfx_pan;
        Audio_UpdateNR51();
    }
}
Audio_SetCh1Duty

Speichert den Tastgradindex für die nächste CH1-Note.

Syntax

c
void __stackcall Audio_SetCh1Duty(u8 duty);

Parameter

duty

Puls-Tastgradindex; gespeichert werden die unteren zwei Bits. 0=12,5 %, 1=25 %, 2=50 %, 3=75 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Dieser Aufruf allein ändert keine aktiven Audioregister. Übergeben Sie den gespeicherten Wert an Note-on oder verwenden Sie den zugehörigen Stream zum Anwenden.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_SetCh1Duty: DMG
DMG
Audio_SetCh1Duty: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:141

Deklarationshinweise im Original
Cache the low two duty bits for the next CH1 note; do not change the active register.

kitaqgb/lib/audio.c:644

c
void __stackcall Audio_SetCh1Duty(u8 duty) {
    Audio_Ch1Duty = (u8)(duty & 3);
}
Audio_SetCh2Duty

Speichert den Tastgradindex für die nächste CH2-Note.

Syntax

c
void __stackcall Audio_SetCh2Duty(u8 duty);

Parameter

duty

Puls-Tastgradindex; gespeichert werden die unteren zwei Bits. 0=12,5 %, 1=25 %, 2=50 %, 3=75 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Dieser Aufruf allein ändert keine aktiven Audioregister. Übergeben Sie den gespeicherten Wert an Note-on oder verwenden Sie den zugehörigen Stream zum Anwenden.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_SetCh2Duty: DMG
DMG
Audio_SetCh2Duty: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:143

Deklarationshinweise im Original
Cache the low two duty bits for the next CH2 note; do not change the active register.

kitaqgb/lib/audio.c:649

c
void __stackcall Audio_SetCh2Duty(u8 duty) {
    Audio_Ch2Duty = (u8)(duty & 3);
}
Audio_SetCh3Level

Speichert den NR32-Ausgabepegel für die nächste CH3-Note.

Syntax

c
void __stackcall Audio_SetCh3Level(u8 level);

Parameter

level

NR32-Codierung: 0x00=stumm, 0x20=100 %, 0x40=50 %, 0x60=25 %.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Dieser Aufruf allein ändert keine aktiven Audioregister. Übergeben Sie den gespeicherten Wert an Note-on oder verwenden Sie den zugehörigen Stream zum Anwenden.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_SetCh3Level: DMG
DMG
Audio_SetCh3Level: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:145

Deklarationshinweise im Original
Cache the raw NR32 level encoding for the next CH3 note without writing hardware.

kitaqgb/lib/audio.c:654

c
void __stackcall Audio_SetCh3Level(u8 level) {
    Audio_Ch3Level = level;
}
Audio_SetCh4Param

Speichert die NR43-Rauschparameter für die nächste CH4-Note.

Syntax

c
void __stackcall Audio_SetCh4Param(u8 param);

Parameter

param

Rohes NR43: Bits 7..4 Taktschiebung, Bit 3 kurzes LFSR, Bits 2..0 Teilercode.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Dieser Aufruf allein ändert keine aktiven Audioregister. Übergeben Sie den gespeicherten Wert an Note-on oder verwenden Sie den zugehörigen Stream zum Anwenden.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_SetCh4Param: DMG
DMG
Audio_SetCh4Param: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:147

Deklarationshinweise im Original
Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.

kitaqgb/lib/audio.c:659

c
void __stackcall Audio_SetCh4Param(u8 param) {
    Audio_Ch4Param = param;
}
Audio_SetMasterVolume

Begrenzt beide Hauptpegel auf 0..7, schreibt sie sofort und bricht einen aktiven Lautstärkeübergang ab.

Syntax

c
void __stackcall Audio_SetMasterVolume(u8 left, u8 right);

Parameter

left

Linker Hauptpegel 0..7; größere Werte werden auf 7 begrenzt. Null ist keine vollständige Stille.

right

Rechter Hauptpegel 0..7; größere Werte werden auf 7 begrenzt.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Anwendungsbeispiel

c
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
    sound_begin("PAN AND VOLUME");
    Audio_SetMasterVolume(7,7);
    Audio_Ch1NoteOn(33,0xC0,2);
    Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
    sound_result[0]=NR51;
    sound_wait(30);
    // Packed low two bits are CH1: 2 means right. Other channels remain centered.
    Audio_SetPanPacked(2);
    sound_result[1]=NR51;
    sound_wait(30);
    Audio_SetPanPacked(0);
    sound_result[2]=NR51;
    Audio_FadeToMasterVolume(1,1,5);
    sound_wait(30);
    sound_result[3]=NR50;
    sound_result[4]=Audio_FadeActive;
    sound_wait(30);
    // Cancel halfway through a rise: retain volume 4 instead of reaching 7.
    Audio_FadeToMasterVolume(7,7,5);
    sound_wait(15);
    Audio_CancelMasterVolumeFade();
    sound_result[5]=NR50;
    sound_wait(30);
    sound_result[6]=NR50;
    // A zero fade interval sets the target immediately. Level zero is not mute.
    Audio_FadeToMasterVolume(0,0,0);
    sound_result[7]=NR50;
    sound_wait(30);
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

A4 wandert nach links, rechts und in die Mitte. Dort sinkt der Pegel von 7 auf 1, steigt dann auf 4 und bleibt so. Pegel 0 ist noch leise hörbar; erst der Kanalstopp erzeugt Stille. Routingänderungen können einen abklingenden Filtertransienten hinterlassen.

Audio_SetMasterVolume: DMG
DMG
Audio_SetMasterVolume: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:120

Deklarationshinweise im Original
Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.

kitaqgb/lib/audio.c:515

c
void __stackcall Audio_SetMasterVolume(u8 left, u8 right) {
    Audio_MasterLeft = Audio_ClampVolume(left);
    Audio_MasterRight = Audio_ClampVolume(right);
    Audio_FadeTargetLeft = Audio_MasterLeft;
    Audio_FadeTargetRight = Audio_MasterRight;
    Audio_FadeStepFrames = 0;
    Audio_FadeCounter = 0;
    Audio_FadeActive = 0;
    Audio_UpdateNR50();
}
Audio_SetMusicEnabled

Steuert, ob der normale Musikdecoder neue Noten schreibt.

Syntax

c
void __stackcall Audio_SetMusicEnabled(u8 on);

Parameter

on

Null deaktiviert, ungleich null aktiviert. Unterscheiden Sie anhand der Funktionsbeschreibung zwischen Stummschaltung und Sperren der Aktualisierung.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Deaktivieren lässt den Stream und Instrument-/Panoramasteuerungen weiterlaufen. Die aktuelle Note wird nicht stumm. Zum Pausieren verwenden Sie Audio_SetPaused.

Anwendungsbeispiel

c
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
    AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_LOOP
};
void main() {
    u8 delay;
    sound_begin("MUSIC PAUSE GATE");
    Audio_SetMasterVolume(3,3);
    Audio_PlayMusic(0,song);
    sound_wait(30);
    delay=Audio_Delay;
    Audio_SetPaused(1);
    sound_wait(30);
    sound_result[0]=(u8)(Audio_Delay==delay);
    sound_result[1]=Audio_Paused;
    Audio_SetPaused(0);
    sound_wait(30);
    sound_result[2]=Audio_Paused;
    // Disabling suppresses note writes; the next 30 updates still consume data.
    Audio_SetMusicEnabled(0);
    sound_wait(30);
    sound_result[3]=Audio_Delay;
    sound_result[4]=Audio_MusicEnabled;
    // Explicitly stop the sounding channel while leaving the stream running.
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(30);
    Audio_SetMusicEnabled(1);
    sound_wait(30);
    Audio_StopMusic();
    sound_result[5]=Audio_PlayingMusic;
    sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Es folgen eine Note, Pausenstille, Fortsetzung, eine bei deaktivierter Musik gehaltene Note, ausdrückliche Kanalstille, die nächste Note nach Aktivierung und schließlich Stopp. RAM-Prüfungen zeigen zudem: 30 Pausenupdates erhalten delay, während die bloße Musiksperre es bis 30 fortschreiten lässt.

Audio_SetMusicEnabled: DMG
DMG
Audio_SetMusicEnabled: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:114

Deklarationshinweise im Original
Set the music-processing gate. This does not silence notes already playing
or stop the legacy stream cursor from consuming commands.

kitaqgb/lib/audio.c:498

c
void __stackcall Audio_SetMusicEnabled(u8 on) {
    if (on != 0) Audio_MusicEnabled = 1;
    else Audio_MusicEnabled = 0;
}
Audio_SetPan

Ändert das Basispanorama einer physischen Stimme und wendet aktive Effektüberschreibungen erneut an.

Syntax

c
void __stackcall Audio_SetPan(u8 ch, u8 pan);

Parameter

ch

Kanal-ID: 0=CH1, 1=CH2, 2=CH3, 3=CH4. Direkte APIs und Musikstreams verwenden dieselben IDs.

pan

0=Mitte, 1=links, 2=rechts, 3=stumm. Effekt-APIs übernehmen bei Werten über 3 einschließlich 0xFF das Basispanorama.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein unbekannter Kanal wählt CH4. pan außerhalb 0..3 bedeutet hier stumm, nicht die Übernahmeeinstellung der Effekt-API.

Anwendungsbeispiel

c
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
    sound_begin("PAN AND VOLUME");
    Audio_SetMasterVolume(7,7);
    Audio_Ch1NoteOn(33,0xC0,2);
    Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
    sound_result[0]=NR51;
    sound_wait(30);
    // Packed low two bits are CH1: 2 means right. Other channels remain centered.
    Audio_SetPanPacked(2);
    sound_result[1]=NR51;
    sound_wait(30);
    Audio_SetPanPacked(0);
    sound_result[2]=NR51;
    Audio_FadeToMasterVolume(1,1,5);
    sound_wait(30);
    sound_result[3]=NR50;
    sound_result[4]=Audio_FadeActive;
    sound_wait(30);
    // Cancel halfway through a rise: retain volume 4 instead of reaching 7.
    Audio_FadeToMasterVolume(7,7,5);
    sound_wait(15);
    Audio_CancelMasterVolumeFade();
    sound_result[5]=NR50;
    sound_wait(30);
    sound_result[6]=NR50;
    // A zero fade interval sets the target immediately. Level zero is not mute.
    Audio_FadeToMasterVolume(0,0,0);
    sound_result[7]=NR50;
    sound_wait(30);
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

A4 wandert nach links, rechts und in die Mitte. Dort sinkt der Pegel von 7 auf 1, steigt dann auf 4 und bleibt so. Pegel 0 ist noch leise hörbar; erst der Kanalstopp erzeugt Stille. Routingänderungen können einen abklingenden Filtertransienten hinterlassen.

Audio_SetPan: DMG
DMG
Audio_SetPan: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:129

Deklarationshinweise im Original
Update the base pan for a physical channel and reapply active effect overrides.
Unknown channel IDs select CH4; unsupported pan values mute the selected channel.

kitaqgb/lib/audio.c:558

c
void __stackcall Audio_SetPan(u8 ch, u8 pan) {
    u8 r_bit;
    u8 l_bit;
    u8 mask;

    if (ch == AUDIO_CHANNEL_CH1) {
        r_bit = 0x01;
        l_bit = 0x10;
    } else if (ch == AUDIO_CHANNEL_CH2) {
        r_bit = 0x02;
        l_bit = 0x20;
    } else if (ch == AUDIO_CHANNEL_CH3) {
        r_bit = 0x04;
        l_bit = 0x40;
    } else {
        r_bit = 0x08;
        l_bit = 0x80;
    }

    mask = (u8)(l_bit | r_bit);
    Audio_Pan = (u8)(Audio_Pan & (u8)~mask);

    if (pan == AUDIO_PAN_CENTER) Audio_Pan = (u8)(Audio_Pan | mask);
    else if (pan == AUDIO_PAN_LEFT) Audio_Pan = (u8)(Audio_Pan | l_bit);
    else if (pan == AUDIO_PAN_RIGHT) Audio_Pan = (u8)(Audio_Pan | r_bit);

    Audio_UpdateNR51();
}
Audio_SetPanPacked

Entpackt vier Basispanoramen aus einem Byte und aktualisiert NR51 einmal.

Syntax

c
void __stackcall Audio_SetPanPacked(u8 packed);

Parameter

packed

Zwei Bits pro physischem Kanal: CH1 Bits 0..1, CH2 2..3, CH3 4..5, CH4 6..7. Jedes Feld verwendet die Panoramawerte.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Anwendungsbeispiel

c
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
    sound_begin("PAN AND VOLUME");
    Audio_SetMasterVolume(7,7);
    Audio_Ch1NoteOn(33,0xC0,2);
    Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
    sound_result[0]=NR51;
    sound_wait(30);
    // Packed low two bits are CH1: 2 means right. Other channels remain centered.
    Audio_SetPanPacked(2);
    sound_result[1]=NR51;
    sound_wait(30);
    Audio_SetPanPacked(0);
    sound_result[2]=NR51;
    Audio_FadeToMasterVolume(1,1,5);
    sound_wait(30);
    sound_result[3]=NR50;
    sound_result[4]=Audio_FadeActive;
    sound_wait(30);
    // Cancel halfway through a rise: retain volume 4 instead of reaching 7.
    Audio_FadeToMasterVolume(7,7,5);
    sound_wait(15);
    Audio_CancelMasterVolumeFade();
    sound_result[5]=NR50;
    sound_wait(30);
    sound_result[6]=NR50;
    // A zero fade interval sets the target immediately. Level zero is not mute.
    Audio_FadeToMasterVolume(0,0,0);
    sound_result[7]=NR50;
    sound_wait(30);
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

A4 wandert nach links, rechts und in die Mitte. Dort sinkt der Pegel von 7 auf 1, steigt dann auf 4 und bleibt so. Pegel 0 ist noch leise hörbar; erst der Kanalstopp erzeugt Stille. Routingänderungen können einen abklingenden Filtertransienten hinterlassen.

Audio_SetPanPacked: DMG
DMG
Audio_SetPanPacked: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:132

Deklarationshinweise im Original
Two bits per channel (CH1 in bits 0-1): center, left, right, mute.
Applies all four positions with one NR51 update for sequencer automation.

kitaqgb/lib/audio.c:589

c
void __stackcall Audio_SetPanPacked(u8 packed) {
    u8 mix = 0;
    u8 pan = (u8)(packed & 3);
    if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x11);
    else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x10);
    else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x01);
    pan = (u8)((packed >> 2) & 3);
    if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x22);
    else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x20);
    else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x02);
    pan = (u8)((packed >> 4) & 3);
    if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x44);
    else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x40);
    else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x04);
    pan = (u8)((packed >> 6) & 3);
    if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x88);
    else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x80);
    else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x08);
    Audio_Pan = mix;
    Audio_UpdateNR51();
}
Audio_SetPaused

Schaltet bei Pause stumm und erhält Musik-/Effektpositionen. Beim Fortsetzen werden geeignete CH1-, CH2- und CH4-Noten erneut ausgelöst.

Syntax

c
void __stackcall Audio_SetPaused(u8 on);

Parameter

on

Null deaktiviert, ungleich null aktiviert. Unterscheiden Sie anhand der Funktionsbeschreibung zwischen Stummschaltung und Sperren der Aktualisierung.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Diese Routine triggert CH3 nicht erneut. Effekte laufen bei späterer Aktualisierung weiter. Direkte Note-on-Aufrufe können auch während der Pause klingen.

Anwendungsbeispiel

c
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
    AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_LOOP
};
void main() {
    u8 delay;
    sound_begin("MUSIC PAUSE GATE");
    Audio_SetMasterVolume(3,3);
    Audio_PlayMusic(0,song);
    sound_wait(30);
    delay=Audio_Delay;
    Audio_SetPaused(1);
    sound_wait(30);
    sound_result[0]=(u8)(Audio_Delay==delay);
    sound_result[1]=Audio_Paused;
    Audio_SetPaused(0);
    sound_wait(30);
    sound_result[2]=Audio_Paused;
    // Disabling suppresses note writes; the next 30 updates still consume data.
    Audio_SetMusicEnabled(0);
    sound_wait(30);
    sound_result[3]=Audio_Delay;
    sound_result[4]=Audio_MusicEnabled;
    // Explicitly stop the sounding channel while leaving the stream running.
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(30);
    Audio_SetMusicEnabled(1);
    sound_wait(30);
    Audio_StopMusic();
    sound_result[5]=Audio_PlayingMusic;
    sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Es folgen eine Note, Pausenstille, Fortsetzung, eine bei deaktivierter Musik gehaltene Note, ausdrückliche Kanalstille, die nächste Note nach Aktivierung und schließlich Stopp. RAM-Prüfungen zeigen zudem: 30 Pausenupdates erhalten delay, während die bloße Musiksperre es bis 30 fortschreiten lässt.

Audio_SetPaused: DMG
DMG
Audio_SetPaused: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:90

Deklarationshinweise im Original
On pause entry, silence hardware while retaining cursors. On resume, retrigger
eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still
advance master fades while paused, and effect playback resumes on a later update.

kitaqgb/lib/audio.c:1010

c
void __stackcall Audio_SetPaused(u8 on) {
    if (on != 0) {
        if (Audio_Paused == 0) {
            Audio_Paused = 1;
            Audio_SilenceAll();
        }
    } else {
        if (Audio_Paused != 0) {
            Audio_Paused = 0;
            if (Audio_PlayingMusic != 0 && Audio_MusicEnabled != 0) {
                if ((Audio_LastChMask & AUDIO_RESUME_CH1) != 0 && Audio_EffectPointer == 0) {
                    Audio_Ch1NoteOn(Audio_LastCh1Note, Audio_Ch1Env, Audio_Ch1Duty);
                }
                if ((Audio_LastChMask & AUDIO_RESUME_CH2) != 0) {
                    Audio_Ch2NoteOn(Audio_LastCh2Note, Audio_Ch2Env, Audio_Ch2Duty);
                }
                if ((Audio_LastChMask & AUDIO_RESUME_CH4) != 0) {
                    Audio_Ch4NoteOn(Audio_LastCh4Param, Audio_Ch4Env);
                }
            }
        }
    }
}
Audio_SetSfxEnabled

Gibt Effektnotenschreibzugriffe frei oder sperrt sie; Deaktivieren gibt auch die Effektslots frei.

Syntax

c
void __stackcall Audio_SetSfxEnabled(u8 on);

Parameter

on

Null deaktiviert, ungleich null aktiviert. Unterscheiden Sie anhand der Funktionsbeschreibung zwischen Stummschaltung und Sperren der Aktualisierung.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Ein Start bei deaktivierten Effekten kann einen Stream registrieren, doch Updates unterdrücken seine Notenschreibzugriffe. Aktivieren Sie Effekte vor einer hörbaren Wiedergabeanforderung.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_SetSfxEnabled: DMG
DMG
Audio_SetSfxEnabled: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:117

Deklarationshinweise im Original
Enable effect note writes, or disable them and release both effect streams.
Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.

kitaqgb/lib/audio.c:505

c
void __stackcall Audio_SetSfxEnabled(u8 on) {
    if (on != 0) {
        Audio_SfxEnabled = 1;
    } else {
        Audio_SfxEnabled = 0;
        Audio_StopSfx();
    }
}
Audio_StopChannel

Stoppt eine physische Stimme und entfernt ihre Musiknote aus der Fortsetzungsmaske.

Syntax

c
void __stackcall Audio_StopChannel(u8 ch);

Parameter

ch

Kanal-ID: 0=CH1, 1=CH2, 2=CH3, 3=CH4. Direkte APIs und Musikstreams verwenden dieselben IDs.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

CH1/CH3 löschen auch ihren Effektslot. Werte außerhalb 0..3 bewirken nichts. Von VBlank gespeicherte Noten werden separat verwaltet.

Anwendungsbeispiel

c
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
    sound_begin("FOUR SOUND CHANNELS");
    Audio_SetMasterVolume(3,3);
    // CH1: A4, 50% duty, fixed envelope volume 12.
    Audio_SetCh1Duty(2);
    sound_result[0]=Audio_Ch1Duty;
    Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
    sound_result[1]=NR12;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
    // CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
    Audio_SetCh2Duty(1);
    sound_result[2]=Audio_Ch2Duty;
    Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
    sound_result[3]=NR22;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
    // CH3: the initialized triangle wave, at 50% digital output level.
    Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
    sound_result[4]=Audio_Ch3Level;
    Audio_Ch3NoteOn(33,Audio_Ch3Level);
    sound_result[5]=NR32;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
    // CH4: a sustained noise burst; param is NR43, not a pitched note number.
    Audio_SetCh4Param(0x35);
    sound_result[6]=Audio_Ch4Param;
    Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
    sound_result[7]=NR43;
    sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
    sound_end();
}

Erwartetes Ergebnis

Nach etwa einer halben Sekunde Stille folgen CH1 A4, CH2 A4, CH3 A3 und Rauschen. Jede Stimme dauert 30 Frames, dazwischen liegen 15 Frames Pause. SEQUENCE COMPLETE zeigt den Programmabschluss; beurteilen Sie den Klang anhand der Aufnahme.

Audio_StopChannel: DMG
DMG
Audio_StopChannel: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:110

Deklarationshinweise im Original
Stop a physical channel and clear its legacy resume bit. CH1 also clears the
pulse effect stream; CH3 clears the wave effect stream. This is the legacy
channel API and does not clear a VBlank driver's independently latched notes.

kitaqgb/lib/audio.c:981

c
void __stackcall Audio_StopChannel(u8 ch) {
    if (ch == AUDIO_CHANNEL_CH1) {
        Audio_EffectPointer = 0;
        Audio_EffectPriority = 0;
        Audio_EffectBank = 0;
        Audio_EffectPan = AUDIO_PAN_INHERIT;
        Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH1);
        Audio_UpdateNR51();
        Audio_SilenceCh1();
    } else if (ch == AUDIO_CHANNEL_CH2) {
        Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH2);
        Audio_SilenceCh2();
    } else if (ch == AUDIO_CHANNEL_CH3) {
        Audio_EffectPointer3 = 0;
        Audio_EffectPriority3 = 0;
        Audio_EffectBank3 = 0;
        Audio_EffectPan3 = AUDIO_PAN_INHERIT;
        Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH3);
        Audio_UpdateNR51();
        Audio_Ch3Off();
    } else if (ch == AUDIO_CHANNEL_CH4) {
        Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH4);
        Audio_SilenceCh4();
    }
}
Audio_StopMusic

Löscht Liedwiedergabe und Fortsetzungsmaske und schaltet sofort alle vier Stimmen stumm.

Syntax

c
void Audio_StopMusic();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Effektzeiger bleiben erhalten; ein späteres Audio_Update kann daher einen Effekt erklingen lassen. Rufen Sie zum vollständigen Stoppen auch Audio_StopSfx auf.

Anwendungsbeispiel

c
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
    AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_LOOP
};
void main() {
    u8 delay;
    sound_begin("MUSIC PAUSE GATE");
    Audio_SetMasterVolume(3,3);
    Audio_PlayMusic(0,song);
    sound_wait(30);
    delay=Audio_Delay;
    Audio_SetPaused(1);
    sound_wait(30);
    sound_result[0]=(u8)(Audio_Delay==delay);
    sound_result[1]=Audio_Paused;
    Audio_SetPaused(0);
    sound_wait(30);
    sound_result[2]=Audio_Paused;
    // Disabling suppresses note writes; the next 30 updates still consume data.
    Audio_SetMusicEnabled(0);
    sound_wait(30);
    sound_result[3]=Audio_Delay;
    sound_result[4]=Audio_MusicEnabled;
    // Explicitly stop the sounding channel while leaving the stream running.
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(30);
    Audio_SetMusicEnabled(1);
    sound_wait(30);
    Audio_StopMusic();
    sound_result[5]=Audio_PlayingMusic;
    sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Es folgen eine Note, Pausenstille, Fortsetzung, eine bei deaktivierter Musik gehaltene Note, ausdrückliche Kanalstille, die nächste Note nach Aktivierung und schließlich Stopp. RAM-Prüfungen zeigen zudem: 30 Pausenupdates erhalten delay, während die bloße Musiksperre es bis 30 fortschreiten lässt.

Audio_StopMusic: DMG
DMG
Audio_StopMusic: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:86

Deklarationshinweise im Original
Stop legacy music and clear its resume mask, then silence all physical channels.
Effect pointers remain active and may produce sound on a later update.

kitaqgb/lib/audio.c:952

c
void Audio_StopMusic() {
    Audio_PlayingMusic = 0;
    Audio_LastChMask = 0;
    Audio_SilenceAll();
}
Audio_StopSfx

Löscht beide Effektstreams und deren Panoramaüberschreibungen und gibt die ausgeliehenen Kanäle frei.

Syntax

c
void Audio_StopSfx();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Ein Effekt verbraucht pro Aktualisierung ein Paar (note,value) und endet bei note=0. value ist bei Pulseffekten NR12, bei CH3 NR32. Stellen Sie CH3-Daten 0xFF voran und halten Sie den Speicher bis zum Ende gültig. Prioritäten konkurrieren innerhalb eines Slots; auch gleiche Priorität kann den bisherigen Effekt ersetzen.

In der normalen Konfiguration schaltet das Freigeben eines Effekts CH3 aus. Bei gestoppter Musik wird CH1 stumm, bei laufender Musik aber keine frühere Musiknote automatisch wiederholt. Mit AUDIO_VBLANK_SFX_RESTORE fordert die Freigabe eine Wiederherstellung durch die ISR an.

Anwendungsbeispiel

c
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
    40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
    33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
    40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
    sound_begin("BANKED SOUND EFFECT");
    Audio_SetMasterVolume(3,3);
    // Read the marker in bank 2 while restoring the caller's original mapping.
    Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
    sound_result[0]=Audio_EffectPriority;
    Audio_PlaySFXBanked(2,effect,4);
    sound_result[1]=Audio_EffectPriority;
    sound_wait(30);
    Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
    sound_result[2]=Audio_EffectPriority3;
    sound_wait(30);
    // Implicit-bank entry points capture bank 2; the service restores bank 1.
    __bankswitch(2);
    Audio_PlaySFX(effect,5);
    __bankswitch(1);
    sound_result[3]=Audio_EffectBank;
    sound_wait(30);
    __bankswitch(2);
    Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
    __bankswitch(1);
    sound_wait(6);
    Audio_StopSfx();
    sound_result[4]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    // Disabling effects releases current owners; re-enable before the next request.
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(6);
    Audio_SetSfxEnabled(0);
    sound_result[5]=Audio_SfxEnabled;
    sound_result[6]=(u8)(Audio_EffectPointer==0);
    sound_wait(24);
    Audio_SetSfxEnabled(1);
    Audio_PlaySFXBanked(2,effect,5);
    sound_wait(30);
    sound_result[7]=Audio_SfxEnabled;
    sound_end();
}

Erwartetes Ergebnis

Daten aus Bank 2 spielen einen kurzen ansteigenden Puls links, einen Welleneffekt rechts und einen mittigen Puls. Spätere Beispiele stoppen einen rechten Puls frühzeitig, deaktivieren einen Effekt und aktivieren die Wiedergabe erneut. Eine Anforderung mit Priorität 4 kann Priorität 5 nicht ersetzen.

Audio_StopSfx: DMG
DMG
Audio_StopSfx: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:106

Deklarationshinweise im Original
Clear both effect streams and their pan overrides. When not paused, release
borrowed channels through the configured legacy or VBlank recovery path.

kitaqgb/lib/audio.c:960

c
void Audio_StopSfx() {
    Audio_EffectPointer = 0;
    Audio_EffectPriority = 0;
    Audio_EffectBank = 0;
    Audio_EffectPointer3 = 0;
    Audio_EffectPriority3 = 0;
    Audio_EffectBank3 = 0;
    Audio_EffectPan = AUDIO_PAN_INHERIT;
    Audio_EffectPan3 = AUDIO_PAN_INHERIT;
    Audio_UpdateNR51();

    if (Audio_Paused != 0) return;
    Audio_ReleaseCh1AfterSfx();
    Audio_RestoreCh3FromMusic();
}
Audio_Update

Führt einen Lautstärkeübergangsschritt aus; außerhalb der Pause werden danach Effekte und anschließend Musik verarbeitet.

Syntax

c
void Audio_Update();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

Binden Sie audio_hwregs_gb.c vor audio.c ein und rufen Sie beim Start Audio_Init auf. Audio_Update muss genau einmal pro Frame laufen, etwa mit 59,7 Hz. Stream-Lesezugriffe ändern vorübergehend die ROM-Zuordnung; rufen Sie diesen Treiber nicht erneut aus einem Interrupt auf.

Lautstärkeübergänge laufen während der Pause weiter. Auf das Lesen von WAIT n folgen n Warteaufrufe; der nächste Befehl erfolgt daher nach n+1 Aktualisierungen.

Anwendungsbeispiel

c
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
    AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
    AUDIO_CMD_LOOP
};
void main() {
    u8 delay;
    sound_begin("MUSIC PAUSE GATE");
    Audio_SetMasterVolume(3,3);
    Audio_PlayMusic(0,song);
    sound_wait(30);
    delay=Audio_Delay;
    Audio_SetPaused(1);
    sound_wait(30);
    sound_result[0]=(u8)(Audio_Delay==delay);
    sound_result[1]=Audio_Paused;
    Audio_SetPaused(0);
    sound_wait(30);
    sound_result[2]=Audio_Paused;
    // Disabling suppresses note writes; the next 30 updates still consume data.
    Audio_SetMusicEnabled(0);
    sound_wait(30);
    sound_result[3]=Audio_Delay;
    sound_result[4]=Audio_MusicEnabled;
    // Explicitly stop the sounding channel while leaving the stream running.
    Audio_StopChannel(AUDIO_CHANNEL_CH1);
    sound_wait(30);
    Audio_SetMusicEnabled(1);
    sound_wait(30);
    Audio_StopMusic();
    sound_result[5]=Audio_PlayingMusic;
    sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Es folgen eine Note, Pausenstille, Fortsetzung, eine bei deaktivierter Musik gehaltene Note, ausdrückliche Kanalstille, die nächste Note nach Aktivierung und schließlich Stopp. RAM-Prüfungen zeigen zudem: 30 Pausenupdates erhalten delay, während die bloße Musiksperre es bis 30 fortschreiten lässt.

Audio_Update: DMG
DMG
Audio_Update: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio.h:79

Deklarationshinweise im Original
Advance the master fade first. Unless paused, service both effect streams
then the optional legacy music decoder. Call once per frame for frame-based timing.

kitaqgb/lib/audio.c:849

c
void Audio_Update() {
    Audio_UpdateFade();
    if (Audio_Paused != 0) return;

    Audio_ServiceSfx();
#ifndef AUDIO_EXCLUDE_LEGACY_MUSIC_SERVICE
    Audio_ServiceMusic();
#endif
}

audio_vblank.h — Musikwiedergabe im VBlank-Interrupt

Verarbeitet Musik im VBlank, koordiniert Effektbelegung und bietet einen Frame-Hook. Schalten Sie dasselbe Lied nicht zusätzlich über den normalen Musikdecoder weiter.

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

AudioVBlank_DisableIrq

Löscht nur das VBlank-Bit in IE; andere Interruptquellen und Ton bleiben unverändert.

Syntax

c
void AudioVBlank_DisableIrq();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_DisableIrq: DMG
DMG
AudioVBlank_DisableIrq: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:118

Deklarationshinweise im Original
Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.

kitaqgb/lib/audio_vblank_control.inc:129

c
void AudioVBlank_DisableIrq()
{
    AudioVBlank_IE = (u8)(AudioVBlank_IE & 0xFE);
}
AudioVBlank_EnableIrq

Setzt das VBlank-Bit in IE und führt EI aus, um CPU-Interrupts global zu aktivieren.

Syntax

c
void AudioVBlank_EnableIrq();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_EnableIrq: DMG
DMG
AudioVBlank_EnableIrq: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:116

Deklarationshinweise im Original
Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally.
Install the correct interrupt vector and initialize driver state first.

kitaqgb/lib/audio_vblank_control.inc:122

c
void AudioVBlank_EnableIrq()
{
    AudioVBlank_IE = (u8)(AudioVBlank_IE | 0x01);
    __asm { EI }
}
AudioVBlank_Init

Initialisiert VBlank-Musikzustand, Warteschlange, Instrumente und Hook. Initialisiert weder die APU noch sperrt es Interrupts.

Syntax

c
void AudioVBlank_Init();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_Init: DMG
DMG
AudioVBlank_Init: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:85

Deklarationshinweise im Original
Reset software playback state, queue counters, instruments and the frame hook.
Call before enabling this ISR; the routine does not mask interrupts or
initialize the APU registers and cannot synchronize with an active handler.

kitaqgb/lib/audio_vblank_control.inc:6

c
void AudioVBlank_Init()
{
    AudioVBlank_MusicEnabled = 1;
    AudioVBlank_MusicPlaying = 0;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_MusicStart = 0;
    AudioVBlank_MusicPointer = 0;
    AudioVBlank_MusicLoopPoint = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_Ch2Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch1Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch3Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch2LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch1LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch3LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_RestoreCh1Pending = 0;
    AudioVBlank_RestoreCh3Pending = 0;
    AudioVBlank_Ch4Param = AUDIO_VBLANK_REST;
    AudioVBlank_Ch1Envelope = 0xF1;
    AudioVBlank_Ch2Envelope = 0xF2;
    AudioVBlank_Ch4Envelope = 0xF1;
    AudioVBlank_Ch1Duty = 0x80;
    AudioVBlank_Ch2Duty = 0x80;
    AudioVBlank_Ch1Sweep = 0x00;
    AudioVBlank_Ch3Level = 0x20;
    AudioVBlank_ControlCommand = 0;
    AudioVBlank_ControlArg0 = 0;
    AudioVBlank_ControlArg1 = 0;
    AudioVBlank_ControlArg2 = 0;
    AudioVBlank_QueueMode = 0;
    AudioVBlank_QueueReadIndex = 0;
    AudioVBlank_QueueWriteIndex = 0;
    AudioVBlank_QueueCount = 0;
    AudioVBlank_QueueUnderruns = 0;
    AudioVBlank_FrameHook = 0;
}
AudioVBlank_Play

Startet das gewählte Lied von vorn und verlässt den Warteschlangenmodus. Ein NULL-Lied stoppt die Wiedergabe.

Syntax

c
void AudioVBlank_Play();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_Play: DMG
DMG
AudioVBlank_Play: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:103

Deklarationshinweise im Original
Restart the selected direct song at its beginning, leaving queue mode.
A null song invokes Stop; this does not enable the music or IRQ gates.

kitaqgb/lib/audio_vblank_control.inc:58

c
void AudioVBlank_Play()
{
    if (AudioVBlank_MusicStart == 0) {
        AudioVBlank_Stop();
        return;
    }
    AudioVBlank_MusicPointer = AudioVBlank_MusicStart;
    AudioVBlank_MusicLoopPoint = AudioVBlank_MusicStart;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_QueueMode = 0;
    AudioVBlank_MusicPlaying = 1;
}
AudioVBlank_PlayMusic

Wählt ein direkt gelesenes Lied und bereitet seine Wiedergabe von Anfang an vor.

Syntax

c
void __stackcall AudioVBlank_PlayMusic(u8 *song);

Parameter

song

Startadresse des Lieds. Der Treiber leiht das Array aus; es muss während der gesamten Wiedergabe lesbar bleiben.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_PlayMusic: DMG
DMG
AudioVBlank_PlayMusic: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:105

Deklarationshinweise im Original
Select and restart a directly addressed song. This is not the banked WRAM-queue path.

kitaqgb/lib/audio_vblank_control.inc:73

c
void __stackcall AudioVBlank_PlayMusic(u8 *song)
{
    AudioVBlank_SetMusic(song);
    AudioVBlank_Play();
}
AudioVBlank_QueuePlay

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Aktiviert die Wiedergabe, wenn der Queue-Modus aktiv und mindestens ein Datensatz vorhanden ist. Zeigerpositionen, Verzögerung, Musikaktivierung und Pausenzustand bleiben erhalten. Setzen Sie die Queue vor einem neuen Datenstrom zurück und befüllen Sie sie vorab.

Syntax

c
u8 AudioVBlank_QueuePlay();

Rückgabewert

Gibt bei Annahme eins zurück, bei leerer Queue oder außerhalb des Queue-Modus null. Zum Abarbeiten muss die ISR laufen, die Musik aktiviert und der Treiber nicht pausiert sein.

Bedingungen und Grenzen

Rufen Sie nach AudioVBlank_Init nacheinander QueueReset, QueueRefill und QueuePlay auf. Binden Sie die normale audio_vblank.c ein; AUDIO_VBLANK_CORE_ONLY schließt die in C geschriebenen Funktionen zum Befüllen der Queue aus. Der Hauptprogrammcode füllt eine Queue mit sechzehn Datensätzen zu je fünf Bytes, die die VBlank-ISR abarbeitet.

Die Queue darf nur von einer Stelle im Hauptprogramm befüllt werden. Vermeiden Sie rekursive Aufrufe und Aufrufe aus einer ISR oder FrameHook. Beim kurzen Freigabeschritt jedes Datensatzes wird IE gesichert und werden die Interruptquellen gesperrt; anschließend werden IE und SVBK wiederhergestellt. IME bleibt unverändert. Der aufrufende Code muss die Quellbank im ROM/RAM auswählen und währenddessen beibehalten.

Zeitgesteuerte Datensätze enthalten delay, ch1_note, ch2_note, ch3_note und ch4_noise_param. Auch END muss als vollständiger Datensatz mit fünf Bytes vorliegen. LOOP wird im befüllenden Code durch erneutes Einreihen der gewünschten Datensätze umgesetzt. Übergeben Sie keinen unveränderten Befehlsstrom variabler Länge für die direkte Wiedergabe.

Anwendungsbeispiel

c
if(AudioVBlank_QueuePlay()==0) sound_result[0]++;
    AudioVBlank_EnableIrq();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel spielt eine selbst komponierte Phrase mit acht Noten sechsmal ab und stoppt danach. Dabei werden 49 Datensätze — 48 Noten und END — durch die Queue mit sechzehn Plätzen geleitet. Geprüft werden die Annahme aller 49 Datensätze, null Unterläufe, das Ende der Wiedergabe, leere und volle Queue, Nullzeiger und Anzahl null, die Wiederherstellung der CGB-WRAM-Bank, unverändertes IME sowie Ton während und Stille nach der Wiedergabe.

AudioVBlank_QueuePlay: DMG
DMG
AudioVBlank_QueuePlay: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:96

Deklarationshinweise im Original
Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode.
Does not enable the interrupt, music gate or clear pause. Queue before starting.

kitaqgb/lib/audio_vblank_queue.inc:112

c
u8 AudioVBlank_QueuePlay()
{
    u8 saved_ie;
    u8 started;
    saved_ie = AudioVBlank_IE;
    AudioVBlank_IE = 0;
    started = 0;
    if (AudioVBlank_QueueMode != 0 && AudioVBlank_QueueCount != 0) {
        AudioVBlank_MusicPlaying = 1;
        started = 1;
    }
    AudioVBlank_IE = saved_ie;
    return started;
}
AudioVBlank_QueueRefill

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Kopiert vollständige Datensätze mit je fünf Bytes in freie Queue-Plätze und gibt jeden erst nach Abschluss seiner Kopie frei. Pro Aufruf werden höchstens sechzehn Datensätze angenommen.

Syntax

c
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count);

Parameter

records

Datensatzarray in der aktuell lesbaren Bank. Für jeden angenommenen Datensatz müssen fünf Bytes lesbar sein. Bei einem Nullzeiger wird null zurückgegeben.

count

Anzahl der Datensätze, deren Aufnahme versucht werden soll, keine Byteanzahl. Werte über sechzehn werden auf sechzehn begrenzt; null bewirkt nichts.

Rückgabewert

Gibt die tatsächlich angenommene Anzahl von Datensätzen zurück, von 0 bis 16. Bei voller Queue, Nullzeiger, Anzahl null oder außerhalb des Queue-Modus wird null zurückgegeben. Rücken Sie den Quellzeiger um das Fünffache des Rückgabewerts vor. Da die ISR während des Aufrufs Plätze freigeben kann, entspricht das Ergebnis nicht unbedingt der Zahl freier Plätze beim Eintritt.

Bedingungen und Grenzen

Rufen Sie nach AudioVBlank_Init nacheinander QueueReset, QueueRefill und QueuePlay auf. Binden Sie die normale audio_vblank.c ein; AUDIO_VBLANK_CORE_ONLY schließt die in C geschriebenen Funktionen zum Befüllen der Queue aus. Der Hauptprogrammcode füllt eine Queue mit sechzehn Datensätzen zu je fünf Bytes, die die VBlank-ISR abarbeitet.

Die Queue darf nur von einer Stelle im Hauptprogramm befüllt werden. Vermeiden Sie rekursive Aufrufe und Aufrufe aus einer ISR oder FrameHook. Beim kurzen Freigabeschritt jedes Datensatzes wird IE gesichert und werden die Interruptquellen gesperrt; anschließend werden IE und SVBK wiederhergestellt. IME bleibt unverändert. Der aufrufende Code muss die Quellbank im ROM/RAM auswählen und währenddessen beibehalten.

Zeitgesteuerte Datensätze enthalten delay, ch1_note, ch2_note, ch3_note und ch4_noise_param. Auch END muss als vollständiger Datensatz mit fünf Bytes vorliegen. LOOP wird im befüllenden Code durch erneutes Einreihen der gewünschten Datensätze umgesetzt. Übergeben Sie keinen unveränderten Befehlsstrom variabler Länge für die direkte Wiedergabe.

Anwendungsbeispiel

c
next=AudioVBlank_QueueRefill(queue_song,16);
    // next counts records; each record occupies five source bytes.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel spielt eine selbst komponierte Phrase mit acht Noten sechsmal ab und stoppt danach. Dabei werden 49 Datensätze — 48 Noten und END — durch die Queue mit sechzehn Plätzen geleitet. Geprüft werden die Annahme aller 49 Datensätze, null Unterläufe, das Ende der Wiedergabe, leere und volle Queue, Nullzeiger und Anzahl null, die Wiederherstellung der CGB-WRAM-Bank, unverändertes IME sowie Ton während und Stille nach der Wiedergabe.

AudioVBlank_QueueRefill: DMG
DMG
AudioVBlank_QueueRefill: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:93

Deklarationshinweise im Original
Copy complete records from the currently mapped source; return records accepted.
Each call attempts at most 16 records and stops when full. Null/zero returns 0.
Supports ROM and RAM sources, restores SVBK and IE, and never changes IME.
Single foreground producer only: do not call from an ISR or frame hook.
LOOP must be expanded by the producer. END occupies a full five-byte record.

kitaqgb/lib/audio_vblank_queue.inc:93

c
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count)
{
    u8 accepted;
    u8 i;
    if (records == 0 || count == 0 || AudioVBlank_QueueMode == 0) return 0;
    if (count > AUDIO_VBLANK_QUEUE_RECORDS) count = AUDIO_VBLANK_QUEUE_RECORDS;
    accepted = 0;
    while (accepted < count) {
        if (AudioVBlank_QueueCount >= AUDIO_VBLANK_QUEUE_RECORDS) break;
        for (i = 0; i < 5; i++) AudioVBlank_QueueStaging[i] = records[i];
        if (AudioVBlank_QueuePublish() == 0) break;
        records += 5;
        accepted++;
    }
    return accepted;
}
AudioVBlank_QueueReset

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Stoppt die Wiedergabe, schaltet den Ton stumm, wählt den Queue-Modus und setzt Lese- und Schreibposition, Anzahl und Unterlaufzähler auf null. Ausstehende Datensätze werden verworfen, um einen neuen Datenstrom vorzubereiten.

Syntax

c
void AudioVBlank_QueueReset();

Rückgabewert

Kein Rückgabewert. Die Einstellungen für Musikaktivierung und Pause bleiben erhalten.

Bedingungen und Grenzen

Rufen Sie nach AudioVBlank_Init nacheinander QueueReset, QueueRefill und QueuePlay auf. Binden Sie die normale audio_vblank.c ein; AUDIO_VBLANK_CORE_ONLY schließt die in C geschriebenen Funktionen zum Befüllen der Queue aus. Der Hauptprogrammcode füllt eine Queue mit sechzehn Datensätzen zu je fünf Bytes, die die VBlank-ISR abarbeitet.

Die Queue darf nur von einer Stelle im Hauptprogramm befüllt werden. Vermeiden Sie rekursive Aufrufe und Aufrufe aus einer ISR oder FrameHook. Beim kurzen Freigabeschritt jedes Datensatzes wird IE gesichert und werden die Interruptquellen gesperrt; anschließend werden IE und SVBK wiederhergestellt. IME bleibt unverändert. Der aufrufende Code muss die Quellbank im ROM/RAM auswählen und währenddessen beibehalten.

Zeitgesteuerte Datensätze enthalten delay, ch1_note, ch2_note, ch3_note und ch4_noise_param. Auch END muss als vollständiger Datensatz mit fünf Bytes vorliegen. LOOP wird im befüllenden Code durch erneutes Einreihen der gewünschten Datensätze umgesetzt. Übergeben Sie keinen unveränderten Befehlsstrom variabler Länge für die direkte Wiedergabe.

Anwendungsbeispiel

c
AudioVBlank_QueueReset(); // Silence playback and discard any queued records.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel spielt eine selbst komponierte Phrase mit acht Noten sechsmal ab und stoppt danach. Dabei werden 49 Datensätze — 48 Noten und END — durch die Queue mit sechzehn Plätzen geleitet. Geprüft werden die Annahme aller 49 Datensätze, null Unterläufe, das Ende der Wiedergabe, leere und volle Queue, Nullzeiger und Anzahl null, die Wiederherstellung der CGB-WRAM-Bank, unverändertes IME sowie Ton während und Stille nach der Wiedergabe.

AudioVBlank_QueueReset: DMG
DMG
AudioVBlank_QueueReset: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:87

Deklarationshinweise im Original
Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.

kitaqgb/lib/audio_vblank_queue.inc:76

c
void AudioVBlank_QueueReset()
{
    u8 saved_ie;
    saved_ie = AudioVBlank_IE;
    AudioVBlank_IE = 0;
    AudioVBlank_Stop();
    AudioVBlank_QueueMode = 1;
    AudioVBlank_QueueReadIndex = 0;
    AudioVBlank_QueueWriteIndex = 0;
    AudioVBlank_QueueCount = 0;
    AudioVBlank_QueueUnderruns = 0;
    AudioVBlank_IE = saved_ie;
}
AudioVBlank_RequestRestoreCh1

Setzt die reine Pulsfreigabeanforderung 2, falls nichts aussteht, und erhält eine vorhandene Wiederherstellungsanforderung 1.

Syntax

c
void AudioVBlank_RequestRestoreCh1();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Bei direktem Wiederherstellungsaufruf stellt der Aufrufer sicher, dass der Effekt die Stimme freigegeben hat, und löscht danach das ausstehende Flag. Anforderungsfunktionen allein schreiben keine Audioregister.

Anwendungsbeispiel

c
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
    sound_begin("EFFECT RECOVERY");
    Audio_NoiseEffectActive=0; AudioVBlank_Init();
    Audio_SetMasterVolume(3,3);
    AudioVBlank_MusicPlaying=1;
    AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
    AudioVBlank_Ch3LatchedNote=33;
    // Value 1 represents a suppressed BGM event and survives a release request.
    AudioVBlank_RestoreCh1Pending=1;
    AudioVBlank_RequestRestoreCh1();
    sound_result[0]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    // Without a pending event, RequestRestore creates release-only value 2.
    AudioVBlank_RequestRestoreCh1();
    sound_result[1]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    AudioVBlank_RestoreCh3Pending=1;
    AudioVBlank_RequestRestoreCh3();
    sound_result[2]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_RequestRestoreCh3();
    sound_result[3]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_Stop();
    sound_end();
}

Erwartetes Ergebnis

Es folgen Pulswiederherstellung, Stille, Wellenwiederherstellung und Stille, jeweils 30 Frames. Eine Freigabeanforderung erhält den ausstehenden Wert 1; ohne ausstehendes Ereignis ergibt sie den reinen Freigabewert 2. IRQ ist hier deaktiviert, und der Aufrufer verwaltet die Kanalbelegung ausdrücklich.

AudioVBlank_RequestRestoreCh1: DMG
DMG
AudioVBlank_RequestRestoreCh1: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:129

Deklarationshinweise im Original
Request deferred pulse-channel release only when no recovery is pending.
Preserve value 1, which records a music event suppressed while an effect owned it.

kitaqgb/lib/audio_vblank.c:908

c
void AudioVBlank_RequestRestoreCh1()
{
    if (AudioVBlank_RestoreCh1Pending == 0)
        AudioVBlank_RestoreCh1Pending = 2;
}
AudioVBlank_RequestRestoreCh3

Setzt die reine Wellenfreigabeanforderung 2, falls nichts aussteht, und erhält eine vorhandene Wiederherstellungsanforderung 1.

Syntax

c
void AudioVBlank_RequestRestoreCh3();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Bei direktem Wiederherstellungsaufruf stellt der Aufrufer sicher, dass der Effekt die Stimme freigegeben hat, und löscht danach das ausstehende Flag. Anforderungsfunktionen allein schreiben keine Audioregister.

Anwendungsbeispiel

c
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
    sound_begin("EFFECT RECOVERY");
    Audio_NoiseEffectActive=0; AudioVBlank_Init();
    Audio_SetMasterVolume(3,3);
    AudioVBlank_MusicPlaying=1;
    AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
    AudioVBlank_Ch3LatchedNote=33;
    // Value 1 represents a suppressed BGM event and survives a release request.
    AudioVBlank_RestoreCh1Pending=1;
    AudioVBlank_RequestRestoreCh1();
    sound_result[0]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    // Without a pending event, RequestRestore creates release-only value 2.
    AudioVBlank_RequestRestoreCh1();
    sound_result[1]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    AudioVBlank_RestoreCh3Pending=1;
    AudioVBlank_RequestRestoreCh3();
    sound_result[2]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_RequestRestoreCh3();
    sound_result[3]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_Stop();
    sound_end();
}

Erwartetes Ergebnis

Es folgen Pulswiederherstellung, Stille, Wellenwiederherstellung und Stille, jeweils 30 Frames. Eine Freigabeanforderung erhält den ausstehenden Wert 1; ohne ausstehendes Ereignis ergibt sie den reinen Freigabewert 2. IRQ ist hier deaktiviert, und der Aufrufer verwaltet die Kanalbelegung ausdrücklich.

AudioVBlank_RequestRestoreCh3: DMG
DMG
AudioVBlank_RequestRestoreCh3: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:132

Deklarationshinweise im Original
Request a deferred wave-channel release only if no recovery is pending.
Preserve value 1, which records a new music event suppressed by the effect.

kitaqgb/lib/audio_vblank.c:916

c
void AudioVBlank_RequestRestoreCh3()
{
    if (AudioVBlank_RestoreCh3Pending == 0)
        AudioVBlank_RestoreCh3Pending = 2;
}
AudioVBlank_RestoreCh1

Stellt eine gespeicherte Musiknote auf der vom Effekt belegten Pulsstimme (CH1 oder CH2) wieder her oder gibt sie stumm frei.

Syntax

c
void AudioVBlank_RestoreCh1();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Bei direktem Wiederherstellungsaufruf stellt der Aufrufer sicher, dass der Effekt die Stimme freigegeben hat, und löscht danach das ausstehende Flag. Anforderungsfunktionen allein schreiben keine Audioregister.

Anwendungsbeispiel

c
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
    sound_begin("EFFECT RECOVERY");
    Audio_NoiseEffectActive=0; AudioVBlank_Init();
    Audio_SetMasterVolume(3,3);
    AudioVBlank_MusicPlaying=1;
    AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
    AudioVBlank_Ch3LatchedNote=33;
    // Value 1 represents a suppressed BGM event and survives a release request.
    AudioVBlank_RestoreCh1Pending=1;
    AudioVBlank_RequestRestoreCh1();
    sound_result[0]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    // Without a pending event, RequestRestore creates release-only value 2.
    AudioVBlank_RequestRestoreCh1();
    sound_result[1]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    AudioVBlank_RestoreCh3Pending=1;
    AudioVBlank_RequestRestoreCh3();
    sound_result[2]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_RequestRestoreCh3();
    sound_result[3]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_Stop();
    sound_end();
}

Erwartetes Ergebnis

Es folgen Pulswiederherstellung, Stille, Wellenwiederherstellung und Stille, jeweils 30 Frames. Eine Freigabeanforderung erhält den ausstehenden Wert 1; ohne ausstehendes Ereignis ergibt sie den reinen Freigabewert 2. IRQ ist hier deaktiviert, und der Aufrufer verwaltet die Kanalbelegung ausdrücklich.

AudioVBlank_RestoreCh1: DMG
DMG
AudioVBlank_RestoreCh1: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:122

Deklarationshinweise im Original
Recover the borrowed pulse channel (CH1 or CH2) from its latched music event.
Pending value 2, disabled music, or a non-note latch silences it instead.
The caller must first establish that the effect has released the channel.

kitaqgb/lib/audio_vblank.c:769

c
void AudioVBlank_RestoreCh1()
{
    __asm {
        LD_A_MEM Audio_EffectUsesCh2
        OR_A
        JR_NZ audiovb_restore_ch2
        LD_A_MEM AudioVBlank_RestoreCh1Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_Ch1LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch1_off
        LD_C_A
        LD_A_MEM AudioVBlank_Ch1Sweep
        LDH_MEM_A 0x10
        LD_A_MEM AudioVBlank_Ch1Duty
        LDH_MEM_A 0x11
        LD_A_MEM AudioVBlank_Ch1Envelope
        LDH_MEM_A 0x12
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x13
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x14
        JR audiovb_restore_ch1_done
audiovb_restore_ch1_off:
        XOR_A
        LDH_MEM_A 0x12
audiovb_restore_ch1_done:
        JR audiovb_restore_square_done

audiovb_restore_ch2:
        LD_A_MEM AudioVBlank_RestoreCh1Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_Ch2LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch2_off
        LD_C_A
        LD_A_MEM AudioVBlank_Ch2Duty
        LDH_MEM_A 0x16
        LD_A_MEM AudioVBlank_Ch2Envelope
        LDH_MEM_A 0x17
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x18
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x19
        JR audiovb_restore_square_done
audiovb_restore_ch2_off:
        XOR_A
        LDH_MEM_A 0x17
audiovb_restore_square_done:
    }
}
AudioVBlank_RestoreCh3

Stellt nach Effektfreigabe die gespeicherte CH3-Note wieder her oder deaktiviert dessen DAC.

Syntax

c
void AudioVBlank_RestoreCh3();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Bei direktem Wiederherstellungsaufruf stellt der Aufrufer sicher, dass der Effekt die Stimme freigegeben hat, und löscht danach das ausstehende Flag. Anforderungsfunktionen allein schreiben keine Audioregister.

Anwendungsbeispiel

c
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
    sound_begin("EFFECT RECOVERY");
    Audio_NoiseEffectActive=0; AudioVBlank_Init();
    Audio_SetMasterVolume(3,3);
    AudioVBlank_MusicPlaying=1;
    AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
    AudioVBlank_Ch3LatchedNote=33;
    // Value 1 represents a suppressed BGM event and survives a release request.
    AudioVBlank_RestoreCh1Pending=1;
    AudioVBlank_RequestRestoreCh1();
    sound_result[0]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    // Without a pending event, RequestRestore creates release-only value 2.
    AudioVBlank_RequestRestoreCh1();
    sound_result[1]=AudioVBlank_RestoreCh1Pending;
    AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
    sound_wait(30);
    AudioVBlank_RestoreCh3Pending=1;
    AudioVBlank_RequestRestoreCh3();
    sound_result[2]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_RequestRestoreCh3();
    sound_result[3]=AudioVBlank_RestoreCh3Pending;
    AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
    sound_wait(30);
    AudioVBlank_Stop();
    sound_end();
}

Erwartetes Ergebnis

Es folgen Pulswiederherstellung, Stille, Wellenwiederherstellung und Stille, jeweils 30 Frames. Eine Freigabeanforderung erhält den ausstehenden Wert 1; ohne ausstehendes Ereignis ergibt sie den reinen Freigabewert 2. IRQ ist hier deaktiviert, und der Aufrufer verwaltet die Kanalbelegung ausdrücklich.

AudioVBlank_RestoreCh3: DMG
DMG
AudioVBlank_RestoreCh3: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:126

Deklarationshinweise im Original
Recover a latched wave-channel music event after effect release, or disable
the DAC for a release-only request, disabled music, or a non-note latch.
The caller owns effect arbitration and clearing the pending flag.

kitaqgb/lib/audio_vblank.c:860

c
void AudioVBlank_RestoreCh3()
{
    __asm {
        LD_A_MEM AudioVBlank_RestoreCh3Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_Ch3LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch3_off
        LD_C_A
        LD_A_IMM 0x80
        LDH_MEM_A 0x1A
        XOR_A
        LDH_MEM_A 0x1B
        LD_A_MEM AudioVBlank_Ch3Level
        LDH_MEM_A 0x1C
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x1D
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x1E
        JR audiovb_restore_ch3_done
audiovb_restore_ch3_off:
        XOR_A
        LDH_MEM_A 0x1A
audiovb_restore_ch3_done:
    }
}
AudioVBlank_SetEnabled

Gibt VBlank-Musik frei oder sperrt sie und löscht beim Deaktivieren Wiederherstellungsanforderungen. Aktueller Ton und IRQ bleiben unverändert.

Syntax

c
void __stackcall AudioVBlank_SetEnabled(u8 on);

Parameter

on

Null deaktiviert, ungleich null aktiviert. Unterscheiden Sie anhand der Funktionsbeschreibung zwischen Stummschaltung und Sperren der Aktualisierung.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_SetEnabled: DMG
DMG
AudioVBlank_SetEnabled: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:113

Deklarationshinweise im Original
Gate music processing and clear pending CH1/CH3 recovery on disable.
No audio register is written here: disabling does not itself silence a note
already playing or disable the VBlank interrupt.

kitaqgb/lib/audio_vblank_control.inc:109

c
void __stackcall AudioVBlank_SetEnabled(u8 on)
{
    if (on != 0) AudioVBlank_MusicEnabled = 1;
    else {
        AudioVBlank_MusicEnabled = 0;
        // Do not carry a stale SFX-recovery request into a later song.
        AudioVBlank_RestoreCh1Pending = 0;
        AudioVBlank_RestoreCh3Pending = 0;
    }
}
AudioVBlank_SetMusic

Wählt ein direkt gelesenes Lied und setzt seine Cursor zurück, ohne das Wiedergabeflag zu ändern.

Syntax

c
void __stackcall AudioVBlank_SetMusic(u8 *song);

Parameter

song

Startadresse des Lieds. Der Treiber leiht das Array aus; es muss während der gesamten Wiedergabe lesbar bleiben.

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_SetMusic: DMG
DMG
AudioVBlank_SetMusic: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:100

Deklarationshinweise im Original
Select a directly addressed song and reset its cursors, leaving the playing
flag unchanged. Song storage must remain accessible to the fixed-bank ISR;
coordinate this multi-field update with interrupt execution.

kitaqgb/lib/audio_vblank_control.inc:46

c
void __stackcall AudioVBlank_SetMusic(u8 *song)
{
    AudioVBlank_MusicStart = song;
    AudioVBlank_MusicPointer = song;
    AudioVBlank_MusicLoopPoint = song;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_QueueMode = 0;
}
AudioVBlank_Stop

Löscht Wiedergabe-, delay- und Wiederherstellungszustand und schaltet Puls-, Rausch- und Wellenstimmen sofort stumm. IRQ bleibt aktiviert.

Syntax

c
void AudioVBlank_Stop();

Rückgabewert

Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.

Bedingungen und Grenzen

audio_vblank.c implementiert __kq_vblank_vector; installieren Sie keinen konkurrierenden VBlank-Vektor. Das Beispiel definiert Audio_NoiseEffectActive, schließt den normalen Musikdecoder aus und nutzt Audio_Update nur für Effekte und Lautstärkeübergänge. Sperren Sie Interrupts beim Ändern von Liedzeigern oder gemeinsamem Zustand.

Halten Sie direkt gelesene Lieddaten in festem ROM oder einem für die ISR stets sichtbaren Bereich. Ein Datensatz hat fünf Bytes: delay, CH1, CH2, CH3, CH4. In Notenfeldern hält 0xFF die aktuelle Stimme, 0xFD stoppt sie. Im delay-Feld beendet 0xFF die Wiedergabe, 0xFE wiederholt sie. Dies ist das Datensatzlayout, nicht die Kanal-ID-Nummerierung. WRAM-Warteschlangenwiedergabe ist ein separater Modus; übergeben Sie vollständige Fünfbyte-Datensätze mit AudioVBlank_QueueRefill.

Anwendungsbeispiel

c
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
    u8 before;
    sound_begin("VBLANK MUSIC GATES");
    Audio_NoiseEffectActive=0;
    AudioVBlank_Init();
    sound_result[0]=AudioVBlank_MusicPlaying;
    AudioVBlank_Ch1Envelope=0xC0;
    Audio_SetMasterVolume(3,3);
    hook_count=0; AudioVBlank_FrameHook=frame_hook;
    AudioVBlank_SetMusic(irq_song);
    AudioVBlank_Play();
    AudioVBlank_EnableIrq();
    sound_wait(45);
    // Disable music processing while the hook and current note remain active.
    __asm { DI }
    AudioVBlank_SetEnabled(0); before=hook_count;
    __asm { EI }
    sound_wait(30);
    sound_result[1]=(u8)(hook_count!=before);
    __asm { DI }
    AudioVBlank_Stop();
    __asm { EI }
    sound_wait(30);
    __asm { DI }
    AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
    __asm { EI }
    sound_wait(45);
    AudioVBlank_DisableIrq();
    before=hook_count;
    sound_wait(30);
    sound_result[2]=(u8)(hook_count==before);
    sound_result[3]=(u8)(AudioVBlank_IE&1);
    AudioVBlank_Stop(); sound_wait(30);
    sound_end();
}

Erwartetes Ergebnis

Die ISR spielt ein Lied mit zwei Noten. Vergleichen Sie die Musiksperre, die den aktuellen Ton erhält, Stop, das ihn stummschaltet, und die IRQ-Sperre nach Neustart, die ihn ebenfalls erhält. RAM-Prüfungen bestätigen, dass der Hook bei deaktivierter Musik läuft und bei deaktiviertem IRQ stoppt.

AudioVBlank_Stop: DMG
DMG
AudioVBlank_Stop: CGB
CGB
DMG — Aufgenommenes Audio
CGB — Aufgenommenes Audio

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/audio_vblank.h:109

Deklarationshinweise im Original
Stop software playback and silence pulse/noise envelopes and the wave DAC.
Song pointers and the IRQ enable remain unchanged; the routine writes the
physical channels directly, so coordinate ownership with sound effects.

kitaqgb/lib/audio_vblank_control.inc:82

c
void AudioVBlank_Stop()
{
    AudioVBlank_MusicPlaying = 0;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_Ch2Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch1Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch3Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch2LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch1LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch3LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_RestoreCh1Pending = 0;
    AudioVBlank_RestoreCh3Pending = 0;
    AudioVBlank_Ch4Param = AUDIO_VBLANK_REST;
    __asm {
        XOR_A
        LDH_MEM_A 0x12
        LDH_MEM_A 0x17
        LDH_MEM_A 0x1C
        LDH_MEM_A 0x1A
        LDH_MEM_A 0x21
    }
}

bank.h — Bankabhängiger Zugriff auf Code und Daten

Eine ROM-Bank ist ein Speicherblock des Moduls, der in den CPU-Adressraum eingeblendet wird. Verschiedene Banken können an derselben CPU-Adresse liegen; ein 16-Bit-Zeiger allein identifiziert Bankdaten deshalb nicht eindeutig. BankPtr ist ein gepackter Deskriptor aus drei Bytes: einem Bankbyte und einem Zwei-Byte-Zeiger. Er wird mit farptr_make erstellt und mit farptr_read8, farptr_read16 oder farptr_read gelesen.

Das GB-Beispiel verwendet ein MBC5-Modul: Code in der festen Bank 0 bleibt unter $0000–$3FFF erreichbar, während die Banken 1, 2 und 3 unter $4000–$7FFF eingeblendet werden. Legen Sie bank_switch und den danach ausgeführten Code im festen ROM ab. Initialisieren Sie den Bibliothekszustand mit bank_switch, bevor Sie ihn abfragen. Auf GB akzeptiert far_call einen Callback-Zeiger; __farcall benötigt einen Funktionsnamen.

bank_get_current

Liefert die zuletzt von bank_switch gespeicherte Banknummer. Gelesen wird der Softwarezustand, nicht ein Register des Moduls.

Syntax

c
u8 bank_get_current();

Rückgabewert

Der zuletzt von bank_switch gespeicherte u8-Wert; vor der Initialisierung null.

Bedingungen und Grenzen

Der Bibliothekszustand beginnt bei null und erkennt die Startzuordnung des Moduls nicht. Initialisieren Sie ihn mit bank_switch. Direkte Intrinsics und Mapper-Schreibzugriffe aktualisieren diesen separaten Zustand nicht; bank_get_current kann die tatsächliche Hardwarezuordnung daher nicht prüfen.

Anwendungsbeispiel

c
starting_bank=bank_get_current(); // Last value recorded by bank_switch.
bank_expect(starting_bank==2,1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der anfängliche Aufruf bank_switch(2) speichert und wählt Bank 2. Ein späterer direkter Wechsel wählt Bank 1 und liest A1 aus home1, während bank_get_current weiterhin 2 meldet. Nach dem Zurückschalten liefert home2 wieder B2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

bank_get_current: DMG
DMG
bank_get_current: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:21

Deklarationshinweise im Original
Return the last bank recorded by bank_switch; this does not read cartridge hardware.

kitaqgb/lib/bank.c:15

c
u8 bank_get_current()
{
    return kq_bank_current;
}
bank_switch

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Wählt die ROM-Bank und speichert ihre Nummer sowohl in der bank-Bibliothek als auch im Bankzustand des Compilers. Fernzugriffe und Fernaufrufe stellen damit die vorherige Zuordnung wieder her.

Syntax

c
void bank_switch(u8 bank);

Parameter

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Ein dauerhafter Bankwechsel darf weder den laufenden Code noch seine Rückkehradresse ausblenden. Legen Sie den Aufruf, gegebenenfalls bank_switch selbst und den anschließend ausgeführten Code wie im Beispiel in die gemeinsame beziehungsweise feste Bank 0.

Der Bibliothekszustand beginnt bei null und erkennt die Startzuordnung des Moduls nicht. Initialisieren Sie ihn mit bank_switch. Direkte Intrinsics und Mapper-Schreibzugriffe aktualisieren diesen separaten Zustand nicht; bank_get_current kann die tatsächliche Hardwarezuordnung daher nicht prüfen.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
bank_switch(2); // Select the payload window and update library bookkeeping.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der anfängliche Aufruf bank_switch(2) speichert und wählt Bank 2. Ein späterer direkter Wechsel wählt Bank 1 und liest A1 aus home1, während bank_get_current weiterhin 2 meldet. Nach dem Zurückschalten liefert home2 wieder B2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

bank_switch: DMG
DMG
bank_switch: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:19

Deklarationshinweise im Original
Update both the library bank record and the compiler shadow used by far
reads and calls. Invoke this permanent bank change from fixed-bank code.

kitaqgb/lib/bank.c:8

c
void bank_switch(u8 bank)
{
    kq_bank_current = bank;
    __bankswitch(bank);
}
far_call

Übergibt Banknummer und Callback-Zeiger an __farcall_ptr. Diese Bibliotheksfunktion führt den Callback ohne Argumente aus und kehrt nach Wiederherstellung der Aufruferbank zurück.

Syntax

c
void far_call(u8 bank, const void* func);

Parameter

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

func

Gültige ausführbare Adresse eines Callbacks ohne Parameter, angegeben als Funktionsname oder Laufzeitzeiger. Nullzeiger und falsche Bank-Adress-Paare werden zur Laufzeit nicht geprüft.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Diese Aufrufe reichen keine Benutzerargumente weiter und machen den Callback nicht interrupt-reentrant. Verwalten Sie seine Daten, seinen Stack und seine Interruptnutzung korrekt. Die Bankwiederherstellung ist mit verschachtelten und wiederholten Aufrufen geprüft; reale Hardware und beliebige Interruptverschachtelungen deckt dieses Beispiel nicht ab.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
far_call(3,callback); // No arguments; callback reads payload[0] in bank 3.
bank_expect(callback_count==1 && callback_byte==0xD3,15);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

An dieser Stelle des vollständigen Programms erhöht far_call den Wert von callback_count auf 1. Der Callback liest D3 aus Bank 3. Ein späterer Nahzugriff auf home2 mit Ergebnis B2 bestätigt die Rückkehr bei eingeblendeter Bank 2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

far_call: DMG
DMG
far_call: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:30

Deklarationshinweise im Original
Invoke a no-argument callback in its ROM bank, then restore the caller
bank. The pointer must identify executable code; no arguments are forwarded.

kitaqgb/lib/bank.c:40

c
void far_call(u8 bank, const void* func)
{
    __farcall_ptr(bank, func);
}
far_data_read

Kopiert über das Fernspeicher-Intrinsic len Bytes aus der angegebenen ROM-Bank in den RAM-Puffer des Aufrufers. Vor der Rückkehr wird die vorherige Bank wiederhergestellt.

Syntax

c
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);

Parameter

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

addr

Nahzeiger auf lesbare Bytes in der gewählten ROM-Bank. Er enthält keine Banknummer.

dst

Ziel in beschreibbarem Speicher mit genügend Platz für alle kopierten Byte. Abgesehen von einem Transfer mit Länge null erfolgt keine Prüfung auf Nullzeiger oder ungültige Zieladressen.

len

Byteanzahl, 0–65535. Bei null wird kein Speicher kopiert; Bankauswahl und Wiederherstellung werden trotzdem ausgeführt.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der gesamte Quellbereich muss in der vorgesehenen ROM-Zuordnung lesbar und der gesamte Zielbereich beschreibbar sein. Die Kopie schaltet am Fensterende nicht automatisch zur nächsten Bank, behandelt Überlappungen nicht wie memmove und steuert keine sicheren VRAM-Schreibzeitpunkte. Verwenden Sie für VRAM die Grafikübertragungs-APIs.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
far_data_read(3,payload,buffer,4); // Copy into four writable RAM bytes.
bank_expect(buffer[0]==0xD3 && buffer[1]==0x7A && buffer[2]==0x5C && buffer[3]==0x96,7);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt kopiert mit far_data_read 4 Bytes und prüft den Puffer gegen D3 7A 5C 96. Quelldeskriptor oder Quellzeiger des Aufrufers bleiben erhalten; das vollständige Programm prüft zusätzlich eine Kopie der Länge null und die Bankwiederherstellung.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

far_data_read: DMG
DMG
far_data_read: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:27

Deklarationshinweise im Original
Copy len bytes from banked ROM into caller-owned writable storage.

kitaqgb/lib/bank.c:33

c
void far_data_read(u8 bank, const void* addr, void* dst, u16 len)
{
    __farmemcpy(dst, bank, addr, len);
}
far_data_read16

Liest mit __farpeek16 zwei aufeinanderfolgende Bytes als Little-Endian-Wort. Das erste Byte bildet die unteren acht Bits.

Syntax

c
u16 far_data_read16(u8 bank, const void* addr);

Parameter

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

addr

Nahzeiger auf lesbare Bytes in der gewählten ROM-Bank. Er enthält keine Banknummer.

Rückgabewert

Das gelesene Little-Endian-Wort als u16 (0–65535).

Bedingungen und Grenzen

Das gesamte Byte oder Wort muss in der gewählten CPU-Zuordnung lesbar sein. Zeiger werden nicht geprüft, Adressen nicht begrenzt und Fenstergrenzen lösen keinen automatischen Wechsel zur nächsten ROM-Bank aus. Ein Wort benötigt zwei gültige aufeinanderfolgende Bytes.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
word_value=far_data_read16(3,payload+1); // Little-endian 7A 5C -> 0x5C7A.
bank_expect(word_value==0x5C7A,6);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt liest mit far_data_read16 den Ausdruck payload+1 in Bank 3 und prüft 5C7A. Das vollständige Programm bestätigt durch einen Nahzugriff auf home2 außerdem die Wiederherstellung von Bank 2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

far_data_read16: DMG
DMG
far_data_read16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:25

Deklarationshinweise im Original
Read a 16-bit value from the supplied bank and address through the far-read intrinsic.

kitaqgb/lib/bank.c:27

c
u16 far_data_read16(u8 bank, const void* addr)
{
    return __farpeek16(bank, addr);
}
far_data_read8

Liest über __farpeek8 ein Byte aus der angegebenen ROM-Bank und Adresse, stellt die vorherige Bank wieder her und liefert den Wert.

Syntax

c
u8 far_data_read8(u8 bank, const void* addr);

Parameter

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

addr

Nahzeiger auf lesbare Bytes in der gewählten ROM-Bank. Er enthält keine Banknummer.

Rückgabewert

Das gelesene Byte als u8 (0–255).

Bedingungen und Grenzen

Das gesamte Byte oder Wort muss in der gewählten CPU-Zuordnung lesbar sein. Zeiger werden nicht geprüft, Adressen nicht begrenzt und Fenstergrenzen lösen keinen automatischen Wechsel zur nächsten ROM-Bank aus. Ein Wort benötigt zwei gültige aufeinanderfolgende Bytes.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
byte_value=far_data_read8(3,payload); // One byte: 0xD3.
bank_expect(byte_value==0xD3,5);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt liest mit far_data_read8 den Ausdruck payload in Bank 3 und prüft D3. Das vollständige Programm bestätigt durch einen Nahzugriff auf home2 außerdem die Wiederherstellung von Bank 2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

far_data_read8: DMG
DMG
far_data_read8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:23

Deklarationshinweise im Original
Read one byte through the compiler intrinsic that accepts an explicit ROM bank.

kitaqgb/lib/bank.c:21

c
u8 far_data_read8(u8 bank, const void* addr)
{
    return __farpeek8(bank, addr);
}
farptr_make

Speichert ein Bankbyte und einen CPU-sichtbaren Zeiger im BankPtr des Aufrufers. Dabei entsteht nur ein Deskriptor; weder wird die Bank umgeschaltet noch werden die referenzierten Daten gelesen.

Syntax

c
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);

Parameter

out

Zeiger auf beschreibbaren Speicher für einen drei Byte großen BankPtr. Ein Nullzeiger für out führt zu keiner Schreiboperation.

bank

Vorzeichenlose 8-Bit-ROM-Banknummer. Bei Aufrufen muss sie zur Funktionsplatzierung passen, bei Lesezugriffen wählt sie die Quelle. Verwenden Sie den gültigen Bereich des Modultyps.

ptr

Im Deskriptor zu speichernde CPU-sichtbare 16-Bit-Adresse. Sie wird unverändert übernommen; ihre Gültigkeit in der gewählten Bank wird nicht geprüft.

Rückgabewert

Keiner (void).

Anwendungsbeispiel

c
farptr_make(&pointer,3,payload+1); // Store a bank and address; do not read ROM.
bank_expect(pointer.bank==3 && pointer.ptr==payload+1,8);
farptr_make(0,1,home1); // A null destination is ignored.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Deskriptor erhält Bank 3 und payload+1. Seine Leseoperationen liefern 7A, 5C7A und die drei Bytes 7A 5C 96. Der Aufruf mit Nullausgabe darf keinen Zustand ändern.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

farptr_make: DMG
DMG
farptr_make: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:32

Deklarationshinweise im Original
Store a bank/address pair without accessing ROM; a null output pointer is ignored.

kitaqgb/lib/bank.c:46

c
void farptr_make(BankPtr* out, u8 bank, const u8* ptr)
{
    if (out == 0) return;
    out->bank = bank;
    out->ptr = ptr;
}
farptr_read

Kopiert len Bytes von einem BankPtr in beschreibbaren RAM. Da der Deskriptor als Wert übergeben wird, zeigt der Zeiger des Aufrufers weiterhin auf den Anfang der Quelle.

Syntax

c
void farptr_read(BankPtr ptr, void* dst, u16 len);

Parameter

ptr

Ein BankPtr-Wert mit den Feldern bank und ptr. Übergeben Sie den Deskriptor selbst, nicht seine Adresse. Der Deskriptor des Aufrufers bleibt unverändert.

dst

Ziel in beschreibbarem Speicher mit genügend Platz für alle kopierten Byte. Abgesehen von einem Transfer mit Länge null erfolgt keine Prüfung auf Nullzeiger oder ungültige Zieladressen.

len

Byteanzahl, 0–65535. Bei null wird kein Speicher kopiert; Bankauswahl und Wiederherstellung werden trotzdem ausgeführt.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der gesamte Quellbereich muss in der vorgesehenen ROM-Zuordnung lesbar und der gesamte Zielbereich beschreibbar sein. Die Kopie schaltet am Fensterende nicht automatisch zur nächsten Bank, behandelt Überlappungen nicht wie memmove und steuert keine sicheren VRAM-Schreibzeitpunkte. Verwenden Sie für VRAM die Grafikübertragungs-APIs.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
farptr_read(pointer,buffer,3);
bank_expect(buffer[0]==0x7A && buffer[1]==0x5C && buffer[2]==0x96,11);
bank_expect(pointer.bank==3 && pointer.ptr==payload+1,23);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt kopiert mit farptr_read 3 Bytes und prüft den Puffer gegen 7A 5C 96. Quelldeskriptor oder Quellzeiger des Aufrufers bleiben erhalten; das vollständige Programm prüft zusätzlich eine Kopie der Länge null und die Bankwiederherstellung.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

farptr_read: DMG
DMG
farptr_read: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:38

Deklarationshinweise im Original
Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.

kitaqgb/lib/bank.c:66

c
void farptr_read(BankPtr ptr, void* dst, u16 len)
{
    __farmemcpy(dst, ptr.bank, ptr.ptr, len);
}
farptr_read16

Liest ein Little-Endian-Wort aus Bank und Adresse eines BankPtr. Der Deskriptor wird als Wert übergeben; sein Zeiger wird nicht weitergesetzt.

Syntax

c
u16 farptr_read16(BankPtr ptr);

Parameter

ptr

Ein BankPtr-Wert mit den Feldern bank und ptr. Übergeben Sie den Deskriptor selbst, nicht seine Adresse. Der Deskriptor des Aufrufers bleibt unverändert.

Rückgabewert

Das gelesene Little-Endian-Wort als u16 (0–65535).

Bedingungen und Grenzen

Das gesamte Byte oder Wort muss in der gewählten CPU-Zuordnung lesbar sein. Zeiger werden nicht geprüft, Adressen nicht begrenzt und Fenstergrenzen lösen keinen automatischen Wechsel zur nächsten ROM-Bank aus. Ein Wort benötigt zwei gültige aufeinanderfolgende Bytes.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
bank_expect(farptr_read16(pointer)==0x5C7A,10);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt liest mit farptr_read16 den Ausdruck pointer.ptr in Bank 3 und prüft 5C7A. Das vollständige Programm bestätigt durch einen Nahzugriff auf home2 außerdem die Wiederherstellung von Bank 2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

farptr_read16: DMG
DMG
farptr_read16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:36

Deklarationshinweise im Original
Read a 16-bit value using both components of the bank-qualified pointer.

kitaqgb/lib/bank.c:60

c
u16 farptr_read16(BankPtr ptr)
{
    return __farpeek16(ptr.bank, ptr.ptr);
}
farptr_read8

Liest ein Byte über beide Felder eines als Wert übergebenen BankPtr. Der Deskriptor ergänzt die Banknummer, die einem gewöhnlichen Nahzeiger fehlt.

Syntax

c
u8 farptr_read8(BankPtr ptr);

Parameter

ptr

Ein BankPtr-Wert mit den Feldern bank und ptr. Übergeben Sie den Deskriptor selbst, nicht seine Adresse. Der Deskriptor des Aufrufers bleibt unverändert.

Rückgabewert

Das gelesene Byte als u8 (0–255).

Bedingungen und Grenzen

Das gesamte Byte oder Wort muss in der gewählten CPU-Zuordnung lesbar sein. Zeiger werden nicht geprüft, Adressen nicht begrenzt und Fenstergrenzen lösen keinen automatischen Wechsel zur nächsten ROM-Bank aus. Ein Wort benötigt zwei gültige aufeinanderfolgende Bytes.

Fernlesezugriffe und Kopien arbeiten synchron und nutzen gemeinsamen Arbeitsspeicher des Compilers. Ein Interrupt darf währenddessen keinen weiteren Banktransfer über denselben Speicher ausführen. Auf GB nutzt die Kopierhilfe außerdem einen gemeinsamen HRAM-Platz für die gespeicherte Bank. Das Beispiel führt die Operationen aus festem Code ohne konkurrierenden Transfer-Handler aus.

Diese GB-Bankschnittstellen verwenden acht Bankbits und setzen das neunte MBC5-Bankbit nicht. Modulregeln, etwa die Behandlung von Bank null, gelten weiterhin. Das Beispiel nutzt ausdrücklich MBC5-Banken 1–3; mischen Sie diesen Zustand nicht mit unprotokollierten direkten Mapper-Schreibzugriffen.

Anwendungsbeispiel

c
bank_expect(farptr_read8(pointer)==0x7A,9);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieser Ausschnitt liest mit farptr_read8 den Ausdruck pointer.ptr in Bank 3 und prüft 7A. Das vollständige Programm bestätigt durch einen Nahzugriff auf home2 außerdem die Wiederherstellung von Bank 2.

Das vollständige Programm zeigt Datenzugriffe über Bank und Nahadresse, bankübergreifende Callbacks und den Unterschied zwischen Bibliothekszustand und tatsächlicher Zuordnung. Alle Zahlen sind hexadezimal. BANK IN und BANK OUT müssen 02 zeigen, BYTE HEX D3, WORD HEX 5C7A sowie FAILED CHECKS und FIRST FAILURE jeweils 00. CGB und FC zeigen blaue Schrift, DMG schwarze.

CALL COUNT zeigt 03: far_call, __farcall und __farcall_ptr rufen den Callback jeweils einmal auf.

farptr_read8: DMG
DMG
farptr_read8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/bank.h:34

Deklarationshinweise im Original
Read one byte using both components of the bank-qualified pointer.

kitaqgb/lib/bank.c:54

c
u8 farptr_read8(BankPtr ptr)
{
    return __farpeek8(ptr.bank, ptr.ptr);
}

camera.h — Weltkoordinaten und sichtbare Bereiche

Verwaltet Q8.8-Kamerapositionen, Ziele und Grenzen und rechnet Welt-/Bildschirmkoordinaten um. Wählen Sie eigene Camera8_8-Objekte oder die kleingeschriebene API für eine gemeinsame Kamera.

Camera_Add

Addiert Q8.8-Verschiebungen zur aktuellen Position und wendet danach aktivierte Grenzen an.

Syntax

c
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

dfx

Vorzeichenbehaftete Q8.8-Verschiebung; 256 entspricht einem Pixel.

dfy

Vorzeichenbehaftete Q8.8-Verschiebung; 256 entspricht einem Pixel.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_Add(&cam,256,512);result[13]=cam.fx;result[14]=cam.fy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_Add: DMG
DMG
Camera_Add: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_Add: DMG
DMG
Camera_Add: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:34

Deklarationshinweise im Original
Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16;
clamping cannot repair arithmetic that already overflowed.

kitaqgb/lib/camera.c:79

c
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy)
{
    cam->fx += dfx;
    cam->fy += dfy;
    Camera_ApplyBounds(cam);
}
camera_apply

Überträgt die aktuelle Position der gemeinsamen Kamera sofort auf die Hintergrundverschiebung.

Syntax

c
void camera_apply();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht auf VBlank gewartet. Synchronisieren Sie im aufrufenden Code, wenn Änderungen innerhalb eines Frames unerwünscht sind. Negative Brüche werden abgerundet: −1/256 wird zu −1 Pixel, also zum Registerwert 255.

Anwendungsbeispiel

c
camera_apply();result[31]=M_SCX;result[32]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_apply: DMG
DMG
camera_apply: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_apply: DMG
DMG
camera_apply: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:64

Deklarationshinweise im Original
Write the shared camera's current integer position to background scroll registers.

kitaqgb/lib/camera.c:179

c
void camera_apply()
{
    Camera_ApplyBg(&camera_default);
}
Camera_ApplyBg

Rundet die Kameraposition auf ganze Pixel ab und schreibt die unteren acht Bits sofort in die Hintergrund-Scrollregister.

Syntax

c
void Camera_ApplyBg(const Camera8_8* cam);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht auf VBlank gewartet. Synchronisieren Sie im aufrufenden Code, wenn Änderungen innerhalb eines Frames unerwünscht sind. Negative Brüche werden abgerundet: −1/256 wird zu −1 Pixel, also zum Registerwert 255.

Anwendungsbeispiel

c
Camera_ApplyBg(&cam);result[21]=M_SCX;result[22]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ApplyBg: DMG
DMG
Camera_ApplyBg: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ApplyBg: DMG
DMG
Camera_ApplyBg: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:40

Deklarationshinweise im Original
Discard fractional bits and write the low eight integer bits to background scroll registers.

kitaqgb/lib/camera.c:109

c
void Camera_ApplyBg(const Camera8_8* cam)
{
    __scroll_bg_set((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}
Camera_ApplyBgBuffered

Rundet die Kameraposition auf ganze Pixel ab und merkt sie als ausstehende Hintergrundverschiebung vor.

Syntax

c
void Camera_ApplyBgBuffered(const Camera8_8* cam);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Hardware und nachgeführte aktuelle Werte bleiben bis zu Scroll_Flush oder __scroll_flush unverändert. Dieser Aufruf wartet nicht auf VBlank.

Anwendungsbeispiel

c
Camera_Set(&cam,2048,4096);Camera_ApplyBgBuffered(&cam);result[23]=M_SCX;Scroll_Flush();result[24]=M_SCX;result[25]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ApplyBgBuffered: DMG
DMG
Camera_ApplyBgBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ApplyBgBuffered: DMG
DMG
Camera_ApplyBgBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:42

Deklarationshinweise im Original
Convert the Q8.8 position to byte scroll values and stage them for a later flush.

kitaqgb/lib/camera.c:115

c
void Camera_ApplyBgBuffered(const Camera8_8* cam)
{
    __scroll_bg_set_buffered((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}
camera_clamp

Wendet die aus Weltgröße minus Bildschirmgröße ermittelten Grenzen auf die gemeinsame Kamera an.

Syntax

c
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);

Parameter

world_w_px

Weltgröße in ganzen Pixeln; der positive Überschuss gegenüber dem Bildschirm muss zwischen 0 und 127 liegen.

world_h_px

Weltgröße in ganzen Pixeln; der positive Überschuss gegenüber dem Bildschirm muss zwischen 0 und 127 liegen.

screen_w_px

Größe des sichtbaren Ausschnitts in ganzen Pixeln; ist er mindestens so groß wie die Welt, ist der Bewegungsspielraum auf dieser Achse null.

screen_h_px

Größe des sichtbaren Ausschnitts in ganzen Pixeln; ist er mindestens so groß wie die Welt, ist der Bewegungsspielraum auf dieser Achse null.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ist die Welt kleiner als der sichtbare Ausschnitt, beträgt der Bewegungsspielraum null. Eine positive Differenz von mindestens 128 überschreitet bei der Umrechnung den vorzeichenbehafteten Q8.8-Bereich. Die u16-Parameter bedeuten nicht, dass die Kamera beliebig große Welten durchfahren kann. Diese Aufrufe teilen sich eine Kamera; verwenden Sie für unabhängige Kameraobjekte die mit Großbuchstaben beginnende API. Positionen, die von ganzen Pixeln nach Q8.8 umgerechnet werden, müssen zwischen −128 und 127 liegen.

Anwendungsbeispiel

c
camera_clamp(176,160,160,144);result[29]=camera_world_to_screen_x(100);result[30]=camera_world_to_screen_y(90);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_clamp: DMG
DMG
camera_clamp: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_clamp: DMG
DMG
camera_clamp: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:62

Deklarationshinweise im Original
Derive and apply world/screen bounds to the shared convenience camera.

kitaqgb/lib/camera.c:173

c
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
    Camera_ClampToSize(&camera_default, world_w_px, world_h_px, screen_w_px, screen_h_px);
}
Camera_ClampToSize

Zieht die Bildschirmgröße von der Weltgröße ab und legt die daraus entstehenden nichtnegativen Kameragrenzen fest.

Syntax

c
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

world_w_px

Weltgröße in ganzen Pixeln; der positive Überschuss gegenüber dem Bildschirm muss zwischen 0 und 127 liegen.

world_h_px

Weltgröße in ganzen Pixeln; der positive Überschuss gegenüber dem Bildschirm muss zwischen 0 und 127 liegen.

screen_w_px

Größe des sichtbaren Ausschnitts in ganzen Pixeln; ist er mindestens so groß wie die Welt, ist der Bewegungsspielraum auf dieser Achse null.

screen_h_px

Größe des sichtbaren Ausschnitts in ganzen Pixeln; ist er mindestens so groß wie die Welt, ist der Bewegungsspielraum auf dieser Achse null.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ist die Welt kleiner als der sichtbare Ausschnitt, beträgt der Bewegungsspielraum null. Eine positive Differenz von mindestens 128 überschreitet bei der Umrechnung den vorzeichenbehafteten Q8.8-Bereich. Die u16-Parameter bedeuten nicht, dass die Kamera beliebig große Welten durchfahren kann.

Anwendungsbeispiel

c
Camera_ClampToSize(&cam,176,160,160,144);result[15]=cam.max_fx;result[16]=cam.max_fy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ClampToSize: DMG
DMG
Camera_ClampToSize: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ClampToSize: DMG
DMG
Camera_ClampToSize: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:46

Deklarationshinweise im Original
Derive nonnegative camera extents from world minus screen size, then convert
them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does
not imply support for arbitrary large worlds.

kitaqgb/lib/camera.c:123

c
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
    s16 max_x = 0;
    s16 max_y = 0;

    if (world_w_px > screen_w_px) max_x = (s16)((u16)(world_w_px - screen_w_px) << 8);
    if (world_h_px > screen_h_px) max_y = (s16)((u16)(world_h_px - screen_h_px) << 8);
    Camera_SetBounds(cam, (s16)0, (s16)0, max_x, max_y);
}
Camera_ClearBounds

Deaktiviert die Begrenzung, ohne Position, Ziel oder gespeicherte Grenzen zu ändern.

Syntax

c
void Camera_ClearBounds(Camera8_8* cam);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_ClearBounds(&cam);result[12]=cam.use_bounds;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ClearBounds: DMG
DMG
Camera_ClearBounds: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ClearBounds: DMG
DMG
Camera_ClearBounds: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:31

Deklarationshinweise im Original
Disable clamping while retaining the stored bounds and current position.

kitaqgb/lib/camera.c:72

c
void Camera_ClearBounds(Camera8_8* cam)
{
    cam->use_bounds = 0;
}
Camera_ClearTarget

Deaktiviert die Verfolgung und behält die aktuelle Position sowie das gespeicherte Ziel bei.

Syntax

c
void Camera_ClearTarget(Camera8_8* cam);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_ClearTarget(&cam);result[8]=cam.use_target;result[9]=cam.target_fx;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ClearTarget: DMG
DMG
Camera_ClearTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ClearTarget: DMG
DMG
Camera_ClearTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:27

Deklarationshinweise im Original
Disable target following without moving the camera or erasing the stored target.

kitaqgb/lib/camera.c:55

c
void Camera_ClearTarget(Camera8_8* cam)
{
    cam->use_target = 0;
}
camera_follow_xy

Verschiebt die gemeinsame Kamera sofort so, dass ein Weltpunkt am gewünschten Bildschirmanker erscheint.

Syntax

c
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);

Parameter

x

Welt-X-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

y

Welt-Y-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

screen_cx

Koordinate des Bildschirmankers in ganzen Pixeln, 0–255.

screen_cy

Koordinate des Bildschirmankers in ganzen Pixeln, 0–255.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte. Diese Aufrufe teilen sich eine Kamera; verwenden Sie für unabhängige Kameraobjekte die mit Großbuchstaben beginnende API. Positionen, die von ganzen Pixeln nach Q8.8 umgerechnet werden, müssen zwischen −128 und 127 liegen.

Anwendungsbeispiel

c
camera_follow_xy(100,90,80,72);result[27]=camera_world_to_screen_x(100);result[28]=camera_world_to_screen_y(90);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_follow_xy: DMG
DMG
camera_follow_xy: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_follow_xy: DMG
DMG
camera_follow_xy: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:60

Deklarationshinweise im Original
Position the shared camera so the world point appears at the requested screen
anchor. This is an immediate move, not the smoothed target-following path.

kitaqgb/lib/camera.c:165

c
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy)
{
    s16 cx = (s16)(x - screen_cx);
    s16 cy = (s16)(y - screen_cy);
    Camera_Set(&camera_default, (s16)(cx << 8), (s16)(cy << 8));
}
Camera_Init

Setzt Position, Ziel und Grenzen auf null und deaktiviert Verfolgung und Begrenzung.

Syntax

c
void Camera_Init(Camera8_8* cam);

Parameter

cam

Zu initialisierendes, beschreibbares Camera8_8; darf nicht NULL sein.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_Init(&cam);result[0]=cam.fx;result[1]=cam.use_target;result[2]=cam.use_bounds;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_Init: DMG
DMG
Camera_Init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_Init: DMG
DMG
Camera_Init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:21

Deklarationshinweise im Original
Zero all position/target/bound fields and disable targeting and bounds.

kitaqgb/lib/camera.c:24

c
void Camera_Init(Camera8_8* cam)
{
    cam->fx = 0;
    cam->fy = 0;
    cam->target_fx = 0;
    cam->target_fy = 0;
    cam->min_fx = 0;
    cam->min_fy = 0;
    cam->max_fx = 0;
    cam->max_fy = 0;
    cam->use_target = 0;
    cam->use_bounds = 0;
}
Camera_ScreenToWorldX

Addiert den ganzzahligen X-Anteil der Kamera zu Bildschirm-X und erhält so Welt-X.

Syntax

c
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

screen_x

Bildschirm-X-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
result[19]=Camera_ScreenToWorldX(&cam,27);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ScreenToWorldX: DMG
DMG
Camera_ScreenToWorldX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ScreenToWorldX: DMG
DMG
Camera_ScreenToWorldX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:52

Deklarationshinweise im Original
Convert integer-pixel screen X back to world X using the camera's integer component.

kitaqgb/lib/camera.c:146

c
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x)
{
    return (s16)(screen_x + (cam->fx >> 8));
}
Camera_ScreenToWorldY

Addiert den ganzzahligen Y-Anteil der Kamera zu Bildschirm-Y und erhält so Welt-Y.

Syntax

c
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

screen_y

Bildschirm-Y-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
result[20]=Camera_ScreenToWorldY(&cam,24);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_ScreenToWorldY: DMG
DMG
Camera_ScreenToWorldY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_ScreenToWorldY: DMG
DMG
Camera_ScreenToWorldY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:54

Deklarationshinweise im Original
Convert integer-pixel screen Y back to world Y using the camera's integer component.

kitaqgb/lib/camera.c:152

c
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y)
{
    return (s16)(screen_y + (cam->fy >> 8));
}
Camera_Set

Ersetzt die aktuelle Kameraposition und begrenzt sie sofort auf gegebenenfalls aktivierte Grenzen.

Syntax

c
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

fx

X-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

fy

Y-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_Set(&cam,2560,5120);result[3]=cam.fx;result[4]=cam.fy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_Set: DMG
DMG
Camera_Set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_Set: DMG
DMG
Camera_Set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:23

Deklarationshinweise im Original
Replace the current Q8.8 position and immediately apply enabled bounds.

kitaqgb/lib/camera.c:39

c
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy)
{
    cam->fx = fx;
    cam->fy = fy;
    Camera_ApplyBounds(cam);
}
camera_set

Verschiebt die gemeinsame Kamera anhand ganzzahliger Pixelkoordinaten und wendet ihre aktivierten Grenzen an.

Syntax

c
void camera_set(s16 x, s16 y);

Parameter

x

Welt-X-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

y

Welt-Y-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte. Diese Aufrufe teilen sich eine Kamera; verwenden Sie für unabhängige Kameraobjekte die mit Großbuchstaben beginnende API. Positionen, die von ganzen Pixeln nach Q8.8 umgerechnet werden, müssen zwischen −128 und 127 liegen.

Anwendungsbeispiel

c
camera_set(5,6);result[26]=camera_world_to_screen_x(20);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_set: DMG
DMG
camera_set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_set: DMG
DMG
camera_set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:57

Deklarationshinweise im Original
Set the shared camera from integer pixels, converting to the representable Q8.8 range.

kitaqgb/lib/camera.c:158

c
void camera_set(s16 x, s16 y)
{
    Camera_Set(&camera_default, (s16)(x << 8), (s16)(y << 8));
}
Camera_SetBounds

Legt die Mindest- und Höchstkoordinaten fest, aktiviert die Begrenzung und begrenzt sofort die aktuelle Position.

Syntax

c
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

min_fx

Kleinste X-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

min_fy

Kleinste Y-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

max_fx

Größte X-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

max_fy

Größte Y-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Übergeben Sie je Achse Minimum ≤ Maximum; die Grenzen werden nicht umgeordnet. Das gespeicherte Ziel wird nicht begrenzt.

Anwendungsbeispiel

c
Camera_SetBounds(&cam,0,0,3072,3584);result[10]=cam.fx;result[11]=cam.fy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_SetBounds: DMG
DMG
Camera_SetBounds: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_SetBounds: DMG
DMG
Camera_SetBounds: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:29

Deklarationshinweise im Original
Install ordered Q8.8 bounds, enable them and clamp the current position immediately.

kitaqgb/lib/camera.c:61

c
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy)
{
    cam->min_fx = min_fx;
    cam->min_fy = min_fy;
    cam->max_fx = max_fx;
    cam->max_fy = max_fy;
    cam->use_bounds = 1;
    Camera_ApplyBounds(cam);
}
Camera_SetTarget

Speichert ein Ziel und aktiviert die Verfolgung, ohne die aktuelle Position zu verschieben.

Syntax

c
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

fx

X-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

fy

Y-Koordinate. Vorzeichenbehaftete Q8.8-Koordinate: 256 entspricht einem Pixel; der Bereich reicht von −128 bis 127+255/256 Pixel.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
Camera_SetTarget(&cam,4608,3072);result[5]=cam.use_target;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_SetTarget: DMG
DMG
Camera_SetTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_SetTarget: DMG
DMG
Camera_SetTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:25

Deklarationshinweise im Original
Store a Q8.8 target and enable subsequent step-toward-target updates.

kitaqgb/lib/camera.c:47

c
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy)
{
    cam->target_fx = fx;
    cam->target_fy = fy;
    cam->use_target = 1;
}
Camera_StepTowardTarget

Nähert sich dem Ziel um einen durch Rechtsschieben bestimmten Anteil der Reststrecke; bei deaktivierter Verfolgung geschieht nichts.

Syntax

c
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

shift

Exponent der Zweierpotenz, durch die die Differenz geteilt wird: 0 verwendet die ganze Differenz, 1 die Hälfte. Werte über 7 werden auf 7 begrenzt.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Eine kleine positive Differenz kann auf null abgeschnitten werden; ein arithmetischer Rechtsshift kann eine kleine negative Differenz zu −1 machen. Die Gleichheit mit dem Ziel wird vor der Begrenzung geprüft. Ein Ziel außerhalb der Grenzen kann die Verfolgung daher aktiv halten oder sie beenden, obwohl die endgültige begrenzte Position vom Ziel abweicht.

Anwendungsbeispiel

c
Camera_StepTowardTarget(&cam,1);result[6]=cam.fx;result[7]=cam.fy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_StepTowardTarget: DMG
DMG
Camera_StepTowardTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_StepTowardTarget: DMG
DMG
Camera_StepTowardTarget: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:38

Deklarationshinweise im Original
Move by the signed target delta shifted by 0..7 bits, then apply bounds.
Quantization can make a small delta produce no movement; only exact equality
clears targeting, and a target outside the bounds may remain active indefinitely.

kitaqgb/lib/camera.c:89

c
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift)
{
    s16 dx;
    s16 dy;

    if (cam->use_target == 0) return;
    if (shift > 7) shift = 7;

    // Keep target-minus-position differences within s16 as well as the individual positions.
    dx = cam->target_fx - cam->fx;
    dy = cam->target_fy - cam->fy;

    if (dx != 0) cam->fx += (dx >> shift);
    if (dy != 0) cam->fy += (dy >> shift);

    if (cam->fx == cam->target_fx && cam->fy == cam->target_fy) cam->use_target = 0;
    Camera_ApplyBounds(cam);
}
camera_world_to_screen_x

Wandelt Welt-X in Bildschirm-X um, indem der ganzzahlige X-Anteil der gemeinsamen Kamera abgezogen wird.

Syntax

c
s16 camera_world_to_screen_x(s16 world_x);

Parameter

world_x

Welt-X-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte. Diese Aufrufe teilen sich eine Kamera; verwenden Sie für unabhängige Kameraobjekte die mit Großbuchstaben beginnende API. Positionen, die von ganzen Pixeln nach Q8.8 umgerechnet werden, müssen zwischen −128 und 127 liegen.

Anwendungsbeispiel

c
result[33]=camera_world_to_screen_x(20);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_world_to_screen_x: DMG
DMG
camera_world_to_screen_x: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_world_to_screen_x: DMG
DMG
camera_world_to_screen_x: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:66

Deklarationshinweise im Original
Convert integer-pixel world X using the shared convenience camera.

kitaqgb/lib/camera.c:185

c
s16 camera_world_to_screen_x(s16 world_x)
{
    return Camera_WorldToScreenX(&camera_default, world_x);
}
camera_world_to_screen_y

Wandelt Welt-Y in Bildschirm-Y um, indem der ganzzahlige Y-Anteil der gemeinsamen Kamera abgezogen wird.

Syntax

c
s16 camera_world_to_screen_y(s16 world_y);

Parameter

world_y

Welt-Y-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte. Diese Aufrufe teilen sich eine Kamera; verwenden Sie für unabhängige Kameraobjekte die mit Großbuchstaben beginnende API. Positionen, die von ganzen Pixeln nach Q8.8 umgerechnet werden, müssen zwischen −128 und 127 liegen.

Anwendungsbeispiel

c
result[34]=camera_world_to_screen_y(20);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

camera_world_to_screen_y: DMG
DMG
camera_world_to_screen_y: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

camera_world_to_screen_y: DMG
DMG
camera_world_to_screen_y: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:68

Deklarationshinweise im Original
Convert integer-pixel world Y using the shared convenience camera.

kitaqgb/lib/camera.c:191

c
s16 camera_world_to_screen_y(s16 world_y)
{
    return Camera_WorldToScreenY(&camera_default, world_y);
}
Camera_WorldToScreenX

Zieht den ganzzahligen X-Anteil der Kamera von einer ganzzahligen Welt-X-Koordinate ab und liefert so Bildschirm-X.

Syntax

c
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

world_x

Welt-X-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
result[17]=Camera_WorldToScreenX(&cam,40);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_WorldToScreenX: DMG
DMG
Camera_WorldToScreenX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_WorldToScreenX: DMG
DMG
Camera_WorldToScreenX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:48

Deklarationshinweise im Original
Convert an integer-pixel world X by subtracting the camera's integer X component.

kitaqgb/lib/camera.c:134

c
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x)
{
    return (s16)(world_x - (cam->fx >> 8));
}
Camera_WorldToScreenY

Zieht den ganzzahligen Y-Anteil der Kamera von einer ganzzahligen Welt-Y-Koordinate ab und liefert so Bildschirm-Y.

Syntax

c
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);

Parameter

cam

Gültiger Zeiger auf ein initialisiertes Camera8_8, das dem aufrufenden Code gehört.

world_y

Welt-Y-Koordinate in ganzen Pixeln; Ergebnis und Zwischendifferenz müssen in s16 passen.

Rückgabewert

Gibt die umgerechnete ganzzahlige Pixelkoordinate als s16 zurück; prüft weder die Sichtbarkeit noch beschneidet sie den Wert.

Bedingungen und Grenzen

Koordinaten haben acht Nachkommabits. Halten Sie Positionen, Ziele sowie Zwischensummen und -differenzen im Bereich von s16. Aktualisieren Sie die Anzeige getrennt mit Camera_ApplyBg oder durch Übertragen der gepufferten Werte.

Anwendungsbeispiel

c
result[18]=Camera_WorldToScreenY(&cam,40);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel vermittelt Q8.8-Verfolgung, Begrenzung und Koordinatenumrechnung. Die Verfolgung ergibt X/Y=3584/4096; die Grenzen ergeben 3072/3584. BG X bleibt bei einer vorgemerkten Änderung 13 und wird nach der Übertragung 8. Das zusätzliche Bild zeigt, wie eine Kamera bei (8,16) ein 32×24-Weltrechteck von (32,32) an Bildschirmposition (24,16) bringt.

Camera_WorldToScreenY: DMG
DMG
Camera_WorldToScreenY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Camera_WorldToScreenY: DMG
DMG
Camera_WorldToScreenY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/camera.h:50

Deklarationshinweise im Original
Convert an integer-pixel world Y by subtracting the camera's integer Y component.

kitaqgb/lib/camera.c:140

c
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y)
{
    return (s16)(world_y - (cam->fy >> 8));
}

cgb_palette.h — CGB-Paletten für BG und OBJ

cgb_palette.h und cgb_palette.c bieten RGB15-Packung und sofortige CGB-Palettenaktualisierung. BG-Funktionen dienen Hintergrund/Fenster, OBJ-Funktionen den Sprites. Einzel- und Komponentenfunktionen ändern eine Farbe, Bereichsfunktionen aufeinanderfolgende Wörter, Ganzpalettenfunktionen vier Wörter. Raw-Bereiche verwenden absolute Farbplätze, Registerintrinsics Bytepositionen. Die Palettenzuweisung erfolgt getrennt über Kartenattribute oder OAM. Binden Sie die Implementierung wie im vollständigen Beispiel genau einmal ein.

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

cgb_bg_color

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Schreibt sofort einen gepackten RGB15-Farbwert in den Palettenspeicher für Hintergrund/Fenster. Paletten- und Farbindex wählen einen von 32 Farbplätzen aus; Kachelmuster und die einer Kachel zugewiesene Palette bleiben dabei unverändert.

Syntax

c
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

rgb15

Gepackte 15-Bit-RGB-Farbe, gewöhnlich 0–32767. Beide Bytes des u16 werden geschrieben, das niederwertige zuerst; die Bibliothek löscht Bit 15 nicht ausdrücklich. Erzeugen Sie gültige Werte mit CGB_RGB15 oder cgb_rgb15.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_bg_color(1,3,31); // Red background color 3 of palette 1.
expect_color(0,7,31);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_bg_color: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_color: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_color: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_color: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:22

Deklarationshinweise im Original
Set one background color through the indexed palette wrapper.

kitaqgb/lib/cgb_palette.c:110

c
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15)
{
    cgb__write_color_bg_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}
cgb_bg_colors

Schreibt aufeinanderfolgende RGB15-Wörter in den Palettenspeicher für Hintergrund/Fenster, beginnend bei den angegebenen Paletten- und Farbindizes. Die Folge darf eine Vierfarbenpalette überschreiten, endet aber spätestens am Ende der 32 Farbplätze.

Syntax

c
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

start_color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

color_count

Anzahl der Farbwörter, nicht Bytes, als u8 (0–255). Null bewirkt nichts. Begrenzt auf 32 - normalisierter_Startplatz; nur entsprechend viele Quellwörter werden gelesen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_bg_colors(3,2,tail_green,2); // Two color words; color 3 becomes green.
expect_color(0,14,0); expect_color(0,15,992);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_bg_colors: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_colors: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_colors: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_colors: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:32

Deklarationshinweise im Original
Write background colors starting at the indexed slot. The range may cross
palette boundaries and is clamped only at the end of all 32 slots.

kitaqgb/lib/cgb_palette.c:135

c
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
    cgb__write_colors_bg_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}
cgb_bg_colors_raw

Schreibt aufeinanderfolgende RGB15-Wörter in den Palettenspeicher für Hintergrund/Fenster, ausgehend von einem absoluten Farbplatz. Der Start ist ein einzelner Index von 0 bis 31 statt eines Paletten-/Farbindexpaares. Die Daten sind Farbwörter, keine Musterbytes.

Syntax

c
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

Parameter

start_color_slot

Absoluter Farbplatz 0–31, vor der Längenbegrenzung mit & 31 normalisiert. Farbplatz = Palette × 4 + Farbe; kein Byteoffset.

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

color_count

Anzahl der Farbwörter, nicht Bytes, als u8 (0–255). Null bewirkt nichts. Begrenzt auf 32 - normalisierter_Startplatz; nur entsprechend viele Quellwörter werden gelesen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_bg_colors_raw(23,blue_word,1); // Absolute slot 23 = palette 5, color 3.
expect_color(0,23,31744);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_bg_colors_raw: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_colors_raw: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_colors_raw: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_colors_raw: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:42

Deklarationshinweise im Original
Expose sequential background writes using an absolute color-slot index.

kitaqgb/lib/cgb_palette.c:159

c
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
    cgb__write_colors_bg_raw(start_color_slot, colors, color_count);
}
cgb_bg_palette

Ersetzt alle vier Farben einer Palette für Hintergrund/Fenster durch vier RGB15-Wörter. Entspricht einem Bereichsschreibvorgang ab Farbe null mit Anzahl vier; weist die Palette keiner Kachel und keinem Sprite zu.

Syntax

c
void cgb_bg_palette(u8 palette_index, const u16* colors);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_bg_palette(4,red_palette); // Exactly four color words for BG palette 4.
expect_color(0,16,32767); expect_color(0,19,31);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_bg_palette: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_palette: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_palette: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_palette: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:37

Deklarationshinweise im Original
Write four consecutive colors for one background palette.

kitaqgb/lib/cgb_palette.c:147

c
void cgb_bg_palette(u8 palette_index, const u16* colors)
{
    cgb_bg_colors(palette_index, 0, colors, 4);
}
cgb_bg_rgb

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Packt Rot, Grün und Blau mit cgb_rgb15 und schreibt eine Farbe in den Palettenspeicher für Hintergrund/Fenster. Geeignet, wenn die Komponenten einzeln statt als gepacktes Wort vorliegen.

Syntax

c
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

r5, g5, b5

Rot-, Grün- und Blaukomponente in dieser Reihenfolge, üblicherweise jeweils 0–31. Maskierung statt Sättigung; jedes Argument erscheint genau einmal in der Makroexpansion.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_bg_rgb(2,3,0,0,31); // Blue, supplied as three five-bit components.
expect_color(0,11,31744);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_bg_rgb: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_rgb: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_rgb: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_rgb: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:26

Deklarationshinweise im Original
Pack component values and write one background color.

kitaqgb/lib/cgb_palette.c:122

c
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
    cgb_bg_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}
cgb_obj_color

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Schreibt sofort einen gepackten RGB15-Farbwert in den Palettenspeicher für Sprites (OBJ). Paletten- und Farbindex wählen einen von 32 Farbplätzen aus; Kachelmuster und die einer Kachel zugewiesene Palette bleiben dabei unverändert.

Syntax

c
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

rgb15

Gepackte 15-Bit-RGB-Farbe, gewöhnlich 0–32767. Beide Bytes des u16 werden geschrieben, das niederwertige zuerst; die Bibliothek löscht Bit 15 nicht ausdrücklich. Erzeugen Sie gültige Werte mit CGB_RGB15 oder cgb_rgb15.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_obj_color(1,3,31744); // Blue sprite color at the same palette/color indices.
expect_color(1,7,31744);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_obj_color: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_color: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_color: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_color: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:24

Deklarationshinweise im Original
Set one object color through the indexed palette wrapper.

kitaqgb/lib/cgb_palette.c:116

c
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15)
{
    cgb__write_color_obj_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}
cgb_obj_colors

Schreibt aufeinanderfolgende RGB15-Wörter in den Palettenspeicher für Sprites (OBJ), beginnend bei den angegebenen Paletten- und Farbindizes. Die Folge darf eine Vierfarbenpalette überschreiten, endet aber spätestens am Ende der 32 Farbplätze.

Syntax

c
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

start_color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

color_count

Anzahl der Farbwörter, nicht Bytes, als u8 (0–255). Null bewirkt nichts. Begrenzt auf 32 - normalisierter_Startplatz; nur entsprechend viele Quellwörter werden gelesen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_obj_colors(3,2,tail_red,2); // Sprite color 3 becomes red.
expect_color(1,14,0); expect_color(1,15,31);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_obj_colors: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_colors: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_colors: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_colors: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:34

Deklarationshinweise im Original
Write object colors from the indexed slot, potentially crossing into later palettes.

kitaqgb/lib/cgb_palette.c:141

c
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
    cgb__write_colors_obj_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}
cgb_obj_colors_raw

Schreibt aufeinanderfolgende RGB15-Wörter in den Palettenspeicher für Sprites (OBJ), ausgehend von einem absoluten Farbplatz. Der Start ist ein einzelner Index von 0 bis 31 statt eines Paletten-/Farbindexpaares. Die Daten sind Farbwörter, keine Musterbytes.

Syntax

c
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

Parameter

start_color_slot

Absoluter Farbplatz 0–31, vor der Längenbegrenzung mit & 31 normalisiert. Farbplatz = Palette × 4 + Farbe; kein Byteoffset.

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

color_count

Anzahl der Farbwörter, nicht Bytes, als u8 (0–255). Null bewirkt nichts. Begrenzt auf 32 - normalisierter_Startplatz; nur entsprechend viele Quellwörter werden gelesen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_obj_colors_raw(23,green_word,1); // Same absolute slot in the separate OBJ store.
expect_color(1,23,992);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_obj_colors_raw: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_colors_raw: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_colors_raw: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_colors_raw: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:44

Deklarationshinweise im Original
Expose sequential object writes using an absolute color-slot index.

kitaqgb/lib/cgb_palette.c:165

c
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
    cgb__write_colors_obj_raw(start_color_slot, colors, color_count);
}
cgb_obj_palette

Ersetzt alle vier Farben einer Palette für Sprites (OBJ) durch vier RGB15-Wörter. Entspricht einem Bereichsschreibvorgang ab Farbe null mit Anzahl vier; weist die Palette keiner Kachel und keinem Sprite zu.

Syntax

c
void cgb_obj_palette(u8 palette_index, const u16* colors);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

colors

Lesbarer const u16* mit den benötigten Farbwörtern. Die Daten werden während des Aufrufs gelesen, nicht eingereiht. Quelle und ROM-Bank müssen erreichbar bleiben; es erfolgt kein automatischer Bankwechsel. Ein Nullzeiger bewirkt keine Schreibzugriffe.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_obj_palette(4,blue_palette); // Exactly four words; OBJ color zero is transparent on screen.
expect_color(1,16,32767); expect_color(1,19,31744);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_obj_palette: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_palette: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_palette: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_palette: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:39

Deklarationshinweise im Original
Write four consecutive colors for one object palette.

kitaqgb/lib/cgb_palette.c:153

c
void cgb_obj_palette(u8 palette_index, const u16* colors)
{
    cgb_obj_colors(palette_index, 0, colors, 4);
}
cgb_obj_rgb

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Packt Rot, Grün und Blau mit cgb_rgb15 und schreibt eine Farbe in den Palettenspeicher für Sprites (OBJ). Geeignet, wenn die Komponenten einzeln statt als gepacktes Wort vorliegen.

Syntax

c
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

Parameter

palette_index

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

color_index

Farbindex innerhalb der Palette, 0–3; nur die unteren zwei Bits werden verwendet (& 3).

r5, g5, b5

Rot-, Grün- und Blaukomponente in dieser Reihenfolge, üblicherweise jeweils 0–31. Maskierung statt Sättigung; jedes Argument erscheint genau einmal in der Makroexpansion.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Paletten- und geschützte Registerschreibzugriffe schreiben im DMG-Modus nichts. Safe bedeutet hier eine CGB-Modusprüfung, keine PPU-Zugriffswarteschleife und keinen kritischen Abschnitt. Verwenden Sie die Funktionen bei ausgeschaltetem LCD oder für kurze Aktualisierungen innerhalb einer zugänglichen PPU-Phase. Sie warten nicht auf VBlank und schützen mehrbyteige Updates nicht vor Interrupts.

BG-/Fenster- und OBJ-Paletten haben getrennte Speicher. Bibliothekszugriffe aktivieren die Indexerhöhung und lassen das Indexregister verändert. OBJ-Farbindex null ist beim Zeichnen von Sprites transparent, obwohl seine Bytes gespeichert und gelesen werden können.

Anwendungsbeispiel

c
cgb_obj_rgb(2,3,0,31,0); // Green sprite color.
expect_color(1,11,992);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_obj_rgb: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_rgb: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_rgb: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_rgb: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:28

Deklarationshinweise im Original
Pack component values and write one object color.

kitaqgb/lib/cgb_palette.c:128

c
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
    cgb_obj_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}
CGB_RGB15

Packt RGB in einen u16: Rot in Bits 0–4, Grün in 5–9 und Blau in 10–14; Bit 15 ist null. Die Maske 31 erhält nur die unteren fünf Bits jeder Komponente, ohne Sättigung. Berechnet lediglich einen Wert, auf DMG wie CGB, ohne Hardwarezugriff.

Syntax

c
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))

Parameter

r5, g5, b5

Rot-, Grün- und Blaukomponente in dieser Reihenfolge, üblicherweise jeweils 0–31. Maskierung statt Sättigung; jedes Argument erscheint genau einmal in der Makroexpansion.

Rückgabewert

Gepackter RGB15-Wert als u16, von 0 bis 32767.

Anwendungsbeispiel

c
if (CGB_RGB15(component,64,95)!=31775) failures++; // (31,0,31), not saturation.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

CGB_RGB15: --cgb=cgb / DMG
--cgb=cgb / DMG
CGB_RGB15: --cgb=cgb / CGB
--cgb=cgb / CGB
CGB_RGB15: --cgb=dmg / DMG
--cgb=dmg / DMG
CGB_RGB15: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:16

cgb_rgb15

Packt RGB in einen u16: Rot in Bits 0–4, Grün in 5–9 und Blau in 10–14; Bit 15 ist null. Die Maske 31 erhält nur die unteren fünf Bits jeder Komponente, ohne Sättigung. Berechnet lediglich einen Wert, auf DMG wie CGB, ohne Hardwarezugriff.

Syntax

c
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);

Parameter

r5, g5, b5

Rot-, Grün- und Blaukomponente in dieser Reihenfolge, üblicherweise jeweils 0–31. Maskierung statt Sättigung; jedes Argument erscheint genau einmal in der Makroexpansion.

Rückgabewert

Gepackter RGB15-Wert als u16, von 0 bis 32767.

Anwendungsbeispiel

c
if (cgb_rgb15(component,64,95)!=31775) failures++; // Same packed value through a function.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

cgb_rgb15: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_rgb15: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_rgb15: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_rgb15: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_palette.h:19

Deklarationshinweise im Original
Pack the red, green and blue components using the public RGB15 macro.

kitaqgb/lib/cgb_palette.c:104

c
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5)
{
    return CGB_RGB15(r5, g5, b5);
}

cgb_tile.h — CGB-Kachelnummern und -attribute

cgb_tile.h bündelt Deklarationen für Kachelkarten-Intrinsics und Makros zum Erzeugen von CGB-Kachelattributen. Eine Kachelnummer wählt ein Muster; das Attribut wählt Palette, Muster-VRAM-Bank, Spiegelungen und Hintergrundpriorität. Attribute verändern keine Musterpixel.

Die Familie __settile adressiert Karte 0x9800; __settileat nutzt eine ausdrückliche Kartenbasis, __settilebg die von LCDC gewählte Hintergrundkarte und __settilewin dessen Fensterkarte. Die attr-Formen schreiben nur Attribute, die cgb-Formen Kachelnummern und Attribute. bulk-Formen übertragen fortlaufende Bytes an die angegebene Adresse. Wählen Sie nach Ziel und geschriebenen Daten.

Verwenden Sie Makros wie KQ_CGB_ATTR_PAL für einzelne Attributbits oder KQ_CGB_ATTR zum Kombinieren der Felder. Das Bankfeld wählt die VRAM-Bank des Musters, keine ROM-Bank. Gewöhnliche Kachelnummern-Schreibzugriffe nutzen die aktuelle VRAM-Bank; wählen Sie vor kombinierten Kachel-/Attributoperationen Bank null. Auf dem DMG bleiben reine Attributoperationen ohne Wirkung; kombinierte Operationen schreiben weiterhin die Kachelnummern.

Der Compiler erzeugt die Implementierung der __-Intrinsics; cgb_tile.c muss nicht eingebunden werden. Gewöhnliche Schreibpfade warten auf VRAM-Zugriff, ändern teilweise aber auch den Interruptfreigabezustand. _unsafe- und _fast-Formen lassen diese Wartezeiten aus. Verwenden Sie sie nur bei garantiert beschreibbarem VRAM, etwa bei ausgeschaltetem LCD. Prüfen Sie die Interrupt-, Bank- und Längenbedingungen jedes Eintrags.

KQ_CGB_ATTR

Erzeugt ein vollständiges CGB-Kartenattributbyte aus Palette, Musterbank, horizontaler und vertikaler Spiegelung sowie BG-Priorität. Palette belegt Bits 0–2, die vier booleschen Felder setzen Bits 3, 5, 6 und 7. Bit 4 bleibt null.

Syntax

c
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))

Parameter

palette

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

bank, xflip, yflip, priority

Null deaktiviert das Feld; jeder Wert ungleich null aktiviert es. Auch 2 aktiviert es: geprüft wird der Wahrheitswert, nicht das unterste Bit.

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Erzeugt Bit 3 eines CGB-Kartenattributs: 0x08 bei jedem bank-Wert ungleich null, sonst 0. Wählt die VRAM-Bank des angezeigten Musters; schreibt weder VBK noch die CPU-Bankauswahl.

Erzeugt das Flag für horizontale Spiegelung: 0x20 bei enabled ungleich null, sonst 0. Im CGB-Kartenattribut werden die acht Pixel jeder Kachelzeile umgekehrt angezeigt; das gespeicherte Muster bleibt unverändert.

Erzeugt das Flag für vertikale Spiegelung: 0x40 bei enabled ungleich null, sonst 0. Im CGB-Kartenattribut werden die acht Zeilen umgekehrt angezeigt, ohne das gespeicherte Muster zu ändern.

Erzeugt das BG-vor-OBJ-Prioritätsflag: 0x80 bei enabled ungleich null, sonst 0. Bei aktivierter CGB-Gesamtpriorität (LCDC-Bit 0) verdecken BG-Farbindizes ungleich null die Sprites. Durch Farbindex null bleiben Sprites sichtbar; die ganze Kachel wird dadurch nicht deckend.

Anwendungsbeispiel

c
attr=KQ_CGB_ATTR(10,0,2,2,0); // Palette 2, bank 0, both reflections: 0x62.
if (attr!=98 || KQ_CGB_ATTR(10,2,3,4,5)!=234) failures++;
cell(10,11,1,attr);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:23

KQ_CGB_ATTR_BANK

Erzeugt Bit 3 eines CGB-Kartenattributs: 0x08 bei jedem bank-Wert ungleich null, sonst 0. Wählt die VRAM-Bank des angezeigten Musters; schreibt weder VBK noch die CPU-Bankauswahl.

Syntax

c
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))

Parameter

bank

Null deaktiviert das Feld; jeder Wert ungleich null aktiviert es. Auch 2 aktiviert es: geprüft wird der Wahrheitswert, nicht das unterste Bit.

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Anwendungsbeispiel

c
attr=(u8)(2|KQ_CGB_ATTR_BANK(enabled)); // Any nonzero value selects tile-data bank 1.
if (attr!=10) failures++;
cell(4,11,1,attr); // Blue hollow square, unlike the bank-0 triangle.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR_BANK: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_BANK: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_BANK: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_BANK: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:19

KQ_CGB_ATTR_PAL

Erzeugt das Palettenfeld eines CGB-Kartenattributs: n & 7, als u8. Mit anderen Attributflags durch bitweises ODER kombinierbar.

Syntax

c
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))

Parameter

n

Palettennummer 0–7; nur die unteren drei Bits werden verwendet (& 7).

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Anwendungsbeispiel

c
attr=KQ_CGB_ATTR_PAL(9); // 9 & 7 = palette 1, red in this BG example.
if (attr!=1) failures++;
cell(2,11,1,attr);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR_PAL: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_PAL: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_PAL: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_PAL: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:18

KQ_CGB_ATTR_PRIORITY_IF

Erzeugt das BG-vor-OBJ-Prioritätsflag: 0x80 bei enabled ungleich null, sonst 0. Bei aktivierter CGB-Gesamtpriorität (LCDC-Bit 0) verdecken BG-Farbindizes ungleich null die Sprites. Durch Farbindex null bleiben Sprites sichtbar; die ganze Kachel wird dadurch nicht deckend.

Syntax

c
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))

Parameter

enabled

Null deaktiviert das Feld; jeder Wert ungleich null aktiviert es. Auch 2 aktiviert es: geprüft wird der Wahrheitswert, nicht das unterste Bit.

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Anwendungsbeispiel

c
attr=(u8)(3|KQ_CGB_ATTR_PRIORITY_IF(enabled)); // Keep nonzero BG pixels in front of sprites.
if (attr!=131) failures++;
cell(12,11,1,attr);
sprite(7,96,88,2,3); // Red full tile behind the green priority triangle.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_PRIORITY_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:22

KQ_CGB_ATTR_XFLIP_IF

Erzeugt das Flag für horizontale Spiegelung: 0x20 bei enabled ungleich null, sonst 0. Im CGB-Kartenattribut werden die acht Pixel jeder Kachelzeile umgekehrt angezeigt; das gespeicherte Muster bleibt unverändert.

Syntax

c
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))

Parameter

enabled

Null deaktiviert das Feld; jeder Wert ungleich null aktiviert es. Auch 2 aktiviert es: geprüft wird der Wahrheitswert, nicht das unterste Bit.

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Anwendungsbeispiel

c
attr=(u8)(3|KQ_CGB_ATTR_XFLIP_IF(enabled));
if (attr!=35) failures++;
cell(6,11,1,attr); // Green triangle reflected horizontally.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_XFLIP_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:20

KQ_CGB_ATTR_YFLIP_IF

Erzeugt das Flag für vertikale Spiegelung: 0x40 bei enabled ungleich null, sonst 0. Im CGB-Kartenattribut werden die acht Zeilen umgekehrt angezeigt, ohne das gespeicherte Muster zu ändern.

Syntax

c
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))

Parameter

enabled

Null deaktiviert das Feld; jeder Wert ungleich null aktiviert es. Auch 2 aktiviert es: geprüft wird der Wahrheitswert, nicht das unterste Bit.

Rückgabewert

Attributfeld oder kombiniertes Attributbyte als u8, mit der oben beschriebenen Bitbelegung.

Bedingungen und Grenzen

Diese Makros berechnen nur u8-Werte, ohne VRAM- oder Registerzugriffe. Jedes Argument erscheint einmal. Übernehmen Sie das Ergebnis mit einer CGB-Attribut-API oder einem ausdrücklichen Schreibzugriff auf die Karte in Bank 1. DMG zeigt keine CGB-Kartenattribute an.

Anwendungsbeispiel

c
attr=(u8)(1|KQ_CGB_ATTR_YFLIP_IF(enabled));
if (attr!=65) failures++;
cell(8,11,1,attr); // Red triangle reflected vertically.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm zeigt, wie BG- und OBJ-Paletten dasselbe Muster unabhängig einfärben. Jedes Dreieck ist 8 × 8 Pixel groß: oben ein Pixel links, unten eine volle Zeile. Bei x = 16, 32, 48, 64, 80, 96, 112 ist die BG-Reihe bei y = 24 rot, blau, grün, rot, blau, grün, rot; die OBJ-Reihe bei y = 64 ist blau, grün, rot, blau, grün, rot, blau. Die Spalten verwenden der Reihe nach Einzelfarbe, Komponenten, indizierten Bereich, ganze Palette, absoluten Bereich, kanonischen Registernamen und Registeralias.

Bei y = 88 zeigen sieben 8 × 8-Felder: rotes Dreieck (x = 16), blauen quadratischen Rahmen mit einem Pixel Strichstärke aus Bank 1 (32), horizontal gespiegeltes grünes Dreieck (48), vertikal gespiegeltes rotes Dreieck (64), in beiden Richtungen gespiegeltes blaues Dreieck (80), grünes Dreieck vor einem roten Sprite, das durch Farbindex null sichtbar bleibt (96), sowie ein volles rotes Sprite vor dem BG-Dreieck als Kontrolle ohne BG-Priorität (112). Koordinaten in Pixeln ab der linken oberen Ecke; weiße Freiflächen und schwarzer Text.

FAILED CHECKS 000 bestätigt RGB-Masken, Wahrheitsflags einschließlich Wert 2, normalisierte Palettenindizes, palettenübergreifende Zugriffe, Begrenzung bei Platz 31, Nullzeiger/Nullängen ohne Schreibzugriff und Farbrücklesen bei ausgeschaltetem LCD. Vier Kombinationen werden geprüft: duales ROM auf DMG/CGB, reines DMG-ROM auf DMG und reines CGB-ROM auf CGB. Auf DMG ist CGB MODE 0, Dreiecke sind schwarz, Bank-/Spiegelattribute ändern die Anzeige nicht und die letzten beiden unteren Felder sind schwarze Quadrate. Auf CGB ist CGB MODE 1. Echte Hardware und Palettenzugriffskonflikte bei eingeschaltetem LCD sind nicht geprüft.

KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_YFLIP_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/cgb_tile.h:21

chain.h — Ringpuffer für Positionsverläufe

Verwenden Sie ChainBody für gegliederte Schlangen oder Seile und Chain für einen aufgezeichneten Positionsverlauf. Jedes Körpergelenk speichert seine aktuelle Position und eine von 16 Richtungen; Biegungen wandern pro Aktualisierung um ein Gelenk nach hinten. Die Körperoperationen unterstützen umlaufende Spielfelder, Wachstum durch Duplizieren des Schwanzendes und Korrekturen von bis zu zwei Pixeln je Achse.

chain_wrap_delta

Berechnet die kürzeste vorzeichenbehaftete Verschiebung von der aktuellen Position zu einem Ziel auf einer Achse mit verbundenen Enden. Verwenden Sie dies für Verfolgung oder Distanzvergleiche über einen Feldrand hinweg.

Syntax

c
s16 chain_wrap_delta(u8 target, u8 current, u16 size);

Parameter

target

Zielkoordinate, 0..size−1.

current

Aktuelle Koordinate, 0..size−1.

size

Länge der umlaufenden Achse, 1..256: Breite für X, Höhe für Y. Das Argument hat 16 Bit, damit 256 darstellbar ist.

Rückgabewert

Gibt die kürzeste Verschiebung als s16 zurück: positiv zu steigenden, negativ zu fallenden Koordinaten, null bei gleicher Position. Gültige Eingaben ergeben −128..+128. Auf dem Bildschirm sind Verschiebungen nach rechts und unten positiv.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. Chain oder ChainBody müssen nicht initialisiert werden. Die Funktion berechnet nur eine Verschiebung und ändert weder Koordinatenarrays noch Gelenkanzahl oder Bildschirm.

Die Funktion prüft und normalisiert Eingaben nicht. Übergeben Sie weder size=0 noch size>256 noch Koordinaten ab size. Bilden Sie Koordinaten aus einem größeren System vor dem Aufruf umlaufend auf 0..size−1 ab.

Bei gleich langen Wegen bleibt das Vorzeichen der direkten Differenz target−current erhalten. Bei size=160 liefert 0→80 den Wert +80 und 80→0 den Wert −80. Bei size=1 ist null die einzige gültige Koordinate und auch das Ergebnis ist null.

Anwendungsbeispiel

c
distances[0]=chain_wrap_delta(1,159,160);   // +2: cross the right edge.
    distances[1]=chain_wrap_delta(159,1,160);   // -2: cross the left edge.
    distances[2]=chain_wrap_delta(80,0,160);    // +80: keep the direct sign.
    distances[3]=chain_wrap_delta(0,80,160);    // -80: same-length routes.
    distances[4]=chain_wrap_delta(0,0,1);       // 0: the only valid position.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel zeigt umlaufende Koordinaten. Jeder Pfeil führt von der aktuellen Position zum Ziel. Angezeigt werden +02/−02 beim Überqueren eines Rands bei Breite 160, +80/−80 für ein halbes Feld und +00 bei Breite 1. Die führende Null ist dezimale Stellenfüllung. Das Beispiel zeichnet und bewegt kein Objekt.

chain_wrap_delta: DMG
DMG
chain_wrap_delta: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_wrap.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_wrap.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:35

Deklarationshinweise im Original
Return target minus current along the shortest wrapped route.
Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized.
Exactly half a field retains the direct displacement sign.

kitaqgb/lib/chain.c:98

c
s16 chain_wrap_delta(u8 target, u8 current, u16 size)
{
    s16 delta;
    s16 half;
    delta = (s16)((s16)target - (s16)current);
    half = (s16)(size >> 1);
    // At exactly half a field, retain the sign of the direct displacement.
    if (delta > half) delta = (s16)(delta - (s16)size);
    else if (delta < (s16)(0 - half)) delta = (s16)(delta + (s16)size);
    return delta;
}
chain_body_init

Verknüpft drei Gelenkarrays des aufrufenden Codes und setzt die Gelenkanzahl auf null, ohne Speicher zu reservieren.

Syntax

c
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);

Parameter

body

Ziel-ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.

x

Array der Gelenk-X-Koordinaten.

y

Array der Gelenk-Y-Koordinaten.

heading

Array der Gelenkrichtungen.

capacity

Reservierte Array-Länge, 1..255.

width

Breite des umlaufenden Felds, 1..256.

height

Höhe des umlaufenden Felds, 1..256.

Rückgabewert

Gibt bei Erfolg 1 zurück, bei ungültigen Argumenten 0. Ein Fehlschlag bei nicht leerem Körperzeiger setzt capacity und count auf null und deaktiviert Aktualisierungen.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. ChainBody speichert die aktuelle Position und Richtung jedes Gelenks. Es ist ein eigener Zustandstyp, getrennt vom Positionsverlaufsring Chain.

Stellen Sie drei getrennte beschreibbare Arrays x, y und heading mit je capacity Bytes bereit und halten Sie sie während der Körpernutzung gültig. Index null ist der Kopf und in count enthalten. Ändern Sie nach der Initialisierung weder Speicherzeiger noch Kapazität oder Feldabmessungen.

Richtungen verwenden 16 Sektoren im Uhrzeigersinn: 0=rechts, 4=unten, 8=links, 12=oben. Nur die unteren vier Eingabebits werden verwendet. Bildschirmkoordinaten steigen nach rechts und unten; jede Abmessung beträgt 1..256 Pixel.

Anwendungsbeispiel

c
chain_body_init(&body,joint_x,joint_y,joint_heading,8,160,144);
    // Eight caller-owned slots, including the head, on a wrapped 160x144 field.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

chain_body_init: DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
chain_body_init: CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:53

Deklarationshinweise im Original
Attach three non-overlapping capacity-byte arrays. Return 1 on success.
Invalid storage, zero capacity or dimensions outside 1..256 disable the body.

kitaqgb/lib/chain.c:119

c
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height)
{
    if (body == 0) return 0;
    body->x = x;
    body->y = y;
    body->heading = heading;
    body->count = 0;
    body->capacity = 0;
    body->width = width;
    body->height = height;
    if (x == 0 || y == 0 || heading == 0 || capacity == 0) return 0;
    if (width == 0 || width > 256 || height == 0 || height > 256) return 0;
    body->capacity = capacity;
    return 1;
}
chain_body_reset

Erzeugt eine gerade Anfangsanordnung, indem Gelenke hinter dem angegebenen Kopf platziert werden.

Syntax

c
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);

Parameter

body

Ziel-ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.

count

Gelenkanzahl einschließlich Kopf, 1..capacity.

head_x

Kopf-X-Koordinate, auf die Feldbreite umlaufend abgebildet.

head_y

Kopf-Y-Koordinate, auf die Feldhöhe umlaufend abgebildet.

heading

Kopfrichtung im System mit 16 Sektoren.

Rückgabewert

Gibt bei Erfolg 1 zurück. Eine Anzahl von null oder über der Kapazität oder ein Nullzeiger liefert 0, ohne die Anordnung zu ändern.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. ChainBody speichert die aktuelle Position und Richtung jedes Gelenks. Es ist ein eigener Zustandstyp, getrennt vom Positionsverlaufsring Chain.

Stellen Sie drei getrennte beschreibbare Arrays x, y und heading mit je capacity Bytes bereit und halten Sie sie während der Körpernutzung gültig. Index null ist der Kopf und in count enthalten. Ändern Sie nach der Initialisierung weder Speicherzeiger noch Kapazität oder Feldabmessungen.

Richtungen verwenden 16 Sektoren im Uhrzeigersinn: 0=rechts, 4=unten, 8=links, 12=oben. Nur die unteren vier Eingabebits werden verwendet. Bildschirmkoordinaten steigen nach rechts und unten; jede Abmessung beträgt 1..256 Pixel.

Der orthogonale Abstand beträgt vier Pixel. Zwischenrichtungen verwenden Ganzzahlvektoren wie (4,1), (3,3) und (1,4); die euklidische Distanz beträgt daher nicht exakt vier Pixel. Die anfängliche Anordnung kann einen Feldrand überschreiten.

Anwendungsbeispiel

c
chain_body_reset(&body,7,48,16,0); // Seven joints, facing right.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

chain_body_reset: DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
chain_body_reset: CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:57

Deklarationshinweise im Original
Seed count joints in a straight pose behind the head; count includes the head.
Return 0 without changing the pose if count is zero or exceeds capacity.
Coordinates wrap to the playfield and headings are masked to 0..15.

kitaqgb/lib/chain.c:135

c
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading)
{
    u8 i;
    u8 x;
    u8 y;
    s16 ox;
    s16 oy;
    if (body == 0) return 0;
    if (count == 0 || count > body->capacity) return 0;
    heading = (u8)(heading & 15);
    x = chain_body_wrap((s16)head_x, body->width);
    y = chain_body_wrap((s16)head_y, body->height);
    ox = chain_body_offset_x(heading);
    oy = chain_body_offset_y(heading);
    i = 0;
    while (i < count) {
        body->x[(__safe_index u8)i] = x;
        body->y[(__safe_index u8)i] = y;
        body->heading[(__safe_index u8)i] = heading;
        x = chain_body_wrap((s16)((s16)x - ox), body->width);
        y = chain_body_wrap((s16)((s16)y - oy), body->height);
        i = (u8)(i + 1);
    }
    body->count = count;
    return 1;
}
chain_body_step

Setzt die Kopfanordnung und zieht jedes Gelenk schrittweise zu einem Anschlusspunkt hinter seinem Vorgänger. Richtungsänderungen wandern pro Aktualisierung um ein Gelenk weiter.

Syntax

c
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);

Parameter

body

Ziel-ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.

head_x

Kopf-X-Koordinate, auf die Feldbreite umlaufend abgebildet.

head_y

Kopf-Y-Koordinate, auf die Feldhöhe umlaufend abgebildet.

heading

Kopfrichtung im System mit 16 Sektoren.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. ChainBody speichert die aktuelle Position und Richtung jedes Gelenks. Es ist ein eigener Zustandstyp, getrennt vom Positionsverlaufsring Chain.

Stellen Sie drei getrennte beschreibbare Arrays x, y und heading mit je capacity Bytes bereit und halten Sie sie während der Körpernutzung gültig. Index null ist der Kopf und in count enthalten. Ändern Sie nach der Initialisierung weder Speicherzeiger noch Kapazität oder Feldabmessungen.

Richtungen verwenden 16 Sektoren im Uhrzeigersinn: 0=rechts, 4=unten, 8=links, 12=oben. Nur die unteren vier Eingabebits werden verwendet. Bildschirmkoordinaten steigen nach rechts und unten; jede Abmessung beträgt 1..256 Pixel.

Ermittelt aus der aktualisierten Position des Vorgängers den Zielanschlusspunkt und berechnet dann je Achse die kürzeste umlaufende Verschiebung. Null bewegt nicht; Betrag 1..4 bewegt ein Pixel, ab 5 zwei Pixel. Bei genau einer halben Feldlänge bleibt das ursprüngliche Vorzeichen erhalten.

Gibt die vor der Aktualisierung gespeicherte Richtung jedes Gelenks an das nächste weiter, sodass eine Biegung durch den Körper wandert. Ein leerer Körper bleibt unverändert.

Der aufrufende Code verwaltet Kopfgeschwindigkeit, Beschleunigung, Kollisionen, Zeichnen und Warten. Aktualisieren Sie gewöhnlich zuerst den Kopf und rufen Sie chain_body_step einmal pro Simulationsschritt auf. Dies ist Gelenkverfolgung, kein Starrkörper- oder exakter Längenbedingungslöser.

Anwendungsbeispiel

c
chain_body_step(&body,48,20,4); // The head turns down; only joint 1 receives 4.
    show_pose(8,34);
    for(step=1;step<4;step++) {
        chain_body_step(&body,48,(u8)(20+step),4);
    }
    // After four ticks, the new heading has reached joints 1 through 4.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

chain_body_step: DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
chain_body_step: CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:62

Deklarationshinweise im Original
Install the caller's head pose, then pull joints from front to rear.
Each joint aims four pixels behind its updated predecessor and receives that
predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4.
Call once per simulation tick; this does not advance head physics or render.

kitaqgb/lib/chain.c:162

c
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading)
{
    u8 i;
    u8 previous;
    u8 pull;
    u8 old;
    u8 x;
    u8 y;
    u8 tx;
    u8 ty;
    s16 sx;
    s16 sy;
    if (body == 0) return;
    if (body->count == 0) return;
    heading = (u8)(heading & 15);
    body->x[0] = chain_body_wrap((s16)head_x, body->width);
    body->y[0] = chain_body_wrap((s16)head_y, body->height);
    body->heading[0] = heading;
    pull = heading;
    i = 1;
    while (i < body->count) {
        previous = (u8)(i - 1);
        old = body->heading[(__safe_index u8)i];
        x = body->x[(__safe_index u8)i];
        y = body->y[(__safe_index u8)i];
        tx = chain_body_wrap((s16)((s16)body->x[(__safe_index u8)previous] - chain_body_offset_x(pull)), body->width);
        ty = chain_body_wrap((s16)((s16)body->y[(__safe_index u8)previous] - chain_body_offset_y(pull)), body->height);
        sx = chain_body_correction(chain_wrap_delta(tx, x, body->width));
        sy = chain_body_correction(chain_wrap_delta(ty, y, body->height));
        body->heading[(__safe_index u8)i] = pull;
        body->x[(__safe_index u8)i] = chain_body_wrap((s16)((s16)x + sx), body->width);
        body->y[(__safe_index u8)i] = chain_body_wrap((s16)((s16)y + sy), body->height);
        // Save before overwriting: a bend advances by one joint per update.
        pull = old;
        i = (u8)(i + 1);
    }
}
chain_body_grow

Kopiert aktuelle Position und Richtung des Schwanzendes in den nächsten freien Platz und erhöht die Anzahl um eins.

Syntax

c
u8 chain_body_grow(ChainBody* body);

Parameter

body

Ziel-ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.

Rückgabewert

Gibt beim Anhängen eines Gelenks 1 zurück; bei leerem, vollem, deaktiviertem Körper oder Nullzeiger 0.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. ChainBody speichert die aktuelle Position und Richtung jedes Gelenks. Es ist ein eigener Zustandstyp, getrennt vom Positionsverlaufsring Chain.

Stellen Sie drei getrennte beschreibbare Arrays x, y und heading mit je capacity Bytes bereit und halten Sie sie während der Körpernutzung gültig. Index null ist der Kopf und in count enthalten. Ändern Sie nach der Initialisierung weder Speicherzeiger noch Kapazität oder Feldabmessungen.

Richtungen verwenden 16 Sektoren im Uhrzeigersinn: 0=rechts, 4=unten, 8=links, 12=oben. Nur die unteren vier Eingabebits werden verwendet. Bildschirmkoordinaten steigen nach rechts und unten; jede Abmessung beträgt 1..256 Pixel.

Das neue Schwanzende überlappt zunächst das vorige und trennt sich bei folgenden chain_body_step-Aufrufen. Wachstum allein bewegt weder Kopf noch andere Gelenke.

Anwendungsbeispiel

c
chain_body_grow(&body); // Copy the tail pose into the eighth slot.
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0); // Allow the duplicated tail to separate.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

chain_body_grow: DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
chain_body_grow: CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:65

Deklarationshinweise im Original
Append a copy of the current tail; later steps separate the new joint.
Return 1 on growth, or 0 for an empty, disabled or full body.

kitaqgb/lib/chain.c:200

c
u8 chain_body_grow(ChainBody* body)
{
    u8 tail;
    u8 next;
    if (body == 0) return 0;
    next = body->count;
    if (next == 0 || next >= body->capacity) return 0;
    tail = (u8)(next - 1);
    body->x[(__safe_index u8)next] = body->x[(__safe_index u8)tail];
    body->y[(__safe_index u8)next] = body->y[(__safe_index u8)tail];
    body->heading[(__safe_index u8)next] = body->heading[(__safe_index u8)tail];
    body->count = (u8)(next + 1);
    return 1;
}
chain_body_clear

Setzt die Gelenkanzahl auf null und erhält Arrays sowie Feldeinstellungen.

Syntax

c
void chain_body_clear(ChainBody* body);

Parameter

body

Ziel-ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Binden Sie chain.h ein und kompilieren Sie chain.c genau einmal. ChainBody speichert die aktuelle Position und Richtung jedes Gelenks. Es ist ein eigener Zustandstyp, getrennt vom Positionsverlaufsring Chain.

Stellen Sie drei getrennte beschreibbare Arrays x, y und heading mit je capacity Bytes bereit und halten Sie sie während der Körpernutzung gültig. Index null ist der Kopf und in count enthalten. Ändern Sie nach der Initialisierung weder Speicherzeiger noch Kapazität oder Feldabmessungen.

Richtungen verwenden 16 Sektoren im Uhrzeigersinn: 0=rechts, 4=unten, 8=links, 12=oben. Nur die unteren vier Eingabebits werden verwendet. Bildschirmkoordinaten steigen nach rechts und unten; jede Abmessung beträgt 1..256 Pixel.

Die Array-Bytes werden nicht gelöscht. Beginnen Sie mit chain_body_reset neu; chain_body_grow unmittelbar nach dem Leeren hängt kein Gelenk an.

Anwendungsbeispiel

c
chain_body_clear(&body); // Forget the pose; the three arrays remain owned by us.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

chain_body_clear: DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
DMG — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
chain_body_clear: CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.
CGB — Das Bild zeigt oben einen geraden Körper, in der Mitte eine Aktualisierung nach einer Abwärtskurve und unten vier Aktualisierungen danach. Koordinaten werden in doppelter logischer Größe gezeichnet. Die Biegung wandert vom Kopf rechts nach hinten. CGB und FC zeigen Kopf rot, Körper blau und Schwanz grün; DMG verwendet Schwarz. Vier Ausgleichsaktualisierungen trennen das duplizierte Schwanzende nach dem Wachstum. Es sind drei Ansichten derselben acht Gelenke, kein Körper mit 24 Gelenken.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/chain.h:67

Deklarationshinweise im Original
Remove all joints while retaining caller-owned storage and playfield settings.

kitaqgb/lib/chain.c:215

c
void chain_body_clear(ChainBody* body)
{
    if (body == 0) return;
    body->count = 0;
}
chain_clear

Verwirft den aufgezeichneten Verlauf, damit dasselbe Speicherarray erneut verwendet werden kann.

Syntax

c
void chain_clear(Chain* chain);

Parameter

chain

Zeiger auf das initialisierte Chain-Objekt.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Setzt Anzahl und head auf null, ohne das Speicherarray zu löschen oder freizugeben. Der Aufrufer verwaltet Chain und das Punktarray und muss beide gültig halten. Die Kapazität darf höchstens 128 betragen, damit die 8-Bit-Indexaddition beim Lesen nicht überläuft.

Die GB-Version benötigt einen gültigen chain-Zeiger.

Anwendungsbeispiel

c
chain_clear(&trail);result[11]=chain_get_count(&trail);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel leert einen Verlauf mit vier Punkten und prüft, dass die Anzahl danach null ist.

chain_clear: DMG
DMG
chain_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/chain.h:21

Deklarationshinweise im Original
Forget the recorded points without clearing or freeing the backing storage.

kitaqgb/lib/chain.c:14

c
void chain_clear(Chain* chain)
{
    chain->count = 0;
    chain->head = 0;
}
chain_get_count

Liest die Anzahl der aktuell im Verlauf verfügbaren Positionen.

Syntax

c
u8 chain_get_count(const Chain* chain);

Parameter

chain

Zeiger auf das initialisierte Chain-Objekt.

Rückgabewert

Gibt eine Anzahl zwischen null und der Kapazität zurück, bei Nullzeiger null.

Bedingungen und Grenzen

Der Aufrufer verwaltet sowohl Chain als auch das Punktarray und muss beide gültig halten. Verwenden Sie höchstens 128 Plätze, damit die 8-Bit-Indexaddition beim Lesen nicht überläuft.

Anwendungsbeispiel

c
result[4]=chain_get_count(&trail);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach fünf Einfügungen in vier Plätze bleibt die Anzahl vier. Nach dem Leeren ist sie null; bei Kapazität null bleibt sie stets null.

chain_get_count: DMG
DMG
chain_get_count: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/chain.h:30

Deklarationshinweise im Original
Return the number of stored points, or zero for a null chain.

kitaqgb/lib/chain.c:63

c
u8 chain_get_count(const Chain* chain)
{
    if (chain == 0) return 0;
    return chain->count;
}
chain_get_segment

Liest eine gespeicherte Position anhand ihres Alters im Verlauf.

Syntax

c
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);

Parameter

chain

Zeiger auf das initialisierte Chain-Objekt.

index

Alter des Punkts: 0 bezeichnet den neuesten, count - 1 den ältesten noch gespeicherten Punkt.

out

Eigenständiges, beschreibbares ChainPoint-Objekt für das Ergebnis; ein Nullzeiger führt zum Fehlschlag.

Rückgabewert

Gibt bei Erfolg 1, bei ungültiger Anfrage 0 zurück. Ein nichtnulliger out-Zeiger wird vor der Prüfung auf (0,0) gesetzt.

Bedingungen und Grenzen

out darf keinen Speicher mit dem zugrunde liegenden Array oder mit Chain teilen, da das Nullsetzen der Ausgabe Quelldaten zerstören würde. Der Aufrufer verwaltet Chain und das Punktarray und muss beide gültig halten. Höchstens 128 Plätze verhindern einen Überlauf der 8-Bit-Indexaddition beim Lesen.

Anwendungsbeispiel

c
result[1]=chain_get_segment(&trail,0,&point);result[2]=point.x;result[3]=point.y;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Index 0 liest den neuesten Punkt (40,24), Index 3 den ältesten (16,8). Der ungültige Index 4 meldet einen Fehler und setzt die Ausgabe auf (0,0).

chain_get_segment: DMG
DMG
chain_get_segment: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/chain.h:28

Deklarationshinweise im Original
Read a point by age, with index zero denoting the newest point. Return zero
for an invalid request and clear a non-null output first. Keep head + index
within the 8-bit range: addition is narrowed before the capacity wrap.

kitaqgb/lib/chain.c:40

c
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out)
{
    u8 pos;
    if (out != 0) {
        out->x = 0;
        out->y = 0;
    }

    if (out == 0) return 0;
    if (chain == 0) return 0;
    if (chain->capacity == 0) return 0;
    if (index >= chain->count) return 0;

    pos = (u8)(chain->head + index);
    while (pos >= chain->capacity) {
        pos = (u8)(pos - chain->capacity);
    }
    out->x = chain->points[pos].x;
    out->y = chain->points[pos].y;
    return 1;
}
chain_init

Verknüpft Speicher mit einem Ringpuffer für Positionsverläufe und beginnt ohne aufgezeichnete Punkte.

Syntax

c
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);

Parameter

chain

Zu initialisierendes, beschreibbares Chain-Objekt.

storage

Array mit Platz für capacity Einträge vom Typ ChainPoint.

capacity

Anzahl der Punktplätze. Für einen nutzbaren Verlauf sind 1 bis 128 zulässig; null deaktiviert die Aufzeichnung.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Aufrufer verwaltet sowohl Chain als auch das Punktarray und muss beide gültig halten. Verwenden Sie höchstens 128 Plätze, damit die 8-Bit-Indexaddition beim Lesen nicht überläuft.

Die GB-Version benötigt einen gültigen chain-Zeiger.

Anwendungsbeispiel

c
chain_init(&trail,storage,4);result[0]=chain_get_count(&trail);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel bindet vier Punktplätze ein und prüft, dass die anfängliche Anzahl null ist.

chain_init: DMG
DMG
chain_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/chain.h:19

Deklarationshinweise im Original
Attach caller-owned ring storage and start with no recorded points.
The storage must remain valid for the lifetime of the chain.
Use a valid chain pointer and capacity entries of caller-owned storage.
Capacity at most 128 keeps every head+age sum in the byte range used by the reader.

kitaqgb/lib/chain.c:5

c
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity)
{
    chain->points = storage;
    chain->capacity = capacity;
    chain->count = 0;
    chain->head = 0;
}
chain_push_head

Fügt die neueste Position am Kopf des Verlaufs ein und ersetzt bei vollem Puffer den ältesten Punkt.

Syntax

c
void chain_push_head(Chain* chain, s16 x, s16 y);

Parameter

chain

Zeiger auf das initialisierte Chain-Objekt.

x

X-Koordinate des neuen Punkts mit Vorzeichen.

y

Y-Koordinate des neuen Punkts mit Vorzeichen.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bei Nullzeiger oder Kapazität null geschieht nichts. Der Aufrufer verwaltet Chain und das Punktarray und muss beide gültig halten. Die Kapazität darf höchstens 128 betragen, damit die 8-Bit-Indexaddition beim Lesen nicht überläuft.

Anwendungsbeispiel

c
chain_push_head(&trail,8,8);chain_push_head(&trail,16,8);chain_push_head(&trail,24,16);chain_push_head(&trail,32,16);chain_push_head(&trail,40,24);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach fünf Einfügungen in vier Plätze ist (40,24) der neueste und (16,8) der älteste noch vorhandene Punkt. Der ursprüngliche Punkt (8,8) wurde ersetzt.

chain_push_head: DMG
DMG
chain_push_head: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/chain.h:24

Deklarationshinweise im Original
Move the ring head backward and store the newest point. Once full, each push
replaces the oldest point; zero capacity is a no-op.

kitaqgb/lib/chain.c:22

c
void chain_push_head(Chain* chain, s16 x, s16 y)
{
    if (chain == 0) return;
    if (chain->capacity == 0) return;

    if (chain->head == 0) chain->head = (u8)(chain->capacity - 1);
    else chain->head--;

    chain->points[chain->head].x = x;
    chain->points[chain->head].y = y;

    if (chain->count < chain->capacity) chain->count++;
}

danmaku.h — Geschosspools, Fächermuster, Treffer und Streiferkennung

Projektilfeld ohne dynamische Speichervergabe für bis zu 96 Schüsse auf 160×128 Pixeln. Bietet Sechzehntelpixelbewegung, Fächer mit 32 Richtungen, Treffer-/Streifereignisse und Kachelzusammensetzung aus vier Quadranten. Die Simulation läuft auf dem GB; die Übertragung mit present_now ist CGB-exklusiv.

danmaku_clear

Deaktiviert alle Projektile und löscht aktive Anzahl, aktuelle Treffer-/Streifereignisse und den Vergabecursor.

Syntax

c
void danmaku_clear();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Behält Spitzen- und Gesamtzähler bei. Löschen und übertragen Sie die RAM-Karte, um Projektile aus der Anzeige zu entfernen.

Anwendungsbeispiel

c
danmaku_clear();result[6]=dm_count;result[7]=dm_spawned;result[8]=dm_peak;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:35

Deklarationshinweise im Original
Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.

kitaqgb/lib/danmaku.c:28

c
void danmaku_clear() {
    u8 i;
    for (i=0; i<DANMAKU_MAX; i++) dm_bullets[i].active=0;
    dm_count=0; dm_hit=0; dm_graze=0; dm_cursor=0;
}
danmaku_clear_map

Löscht alle 576 Bytes der 32×18-RAM-Kachelkarte.

Syntax

c
void danmaku_clear_map();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Lässt Projektilzustand und VRAM unverändert. Verwenden Sie pro Frame die Reihenfolge clear_map, Dekoration schreiben, step, übertragen.

Anwendungsbeispiel

c
danmaku_clear_map();result[11]=dm_map[0];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_clear_map: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:42

Deklarationshinweise im Original
32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px.
Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.

kitaqgb/lib/danmaku.c:78

c
void danmaku_clear_map() {
    __asm {
        LD_HL_IMM dm_map
        LD_B_IMM 72
        XOR_A
    dm_clm_loop:
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        DEC_B
        JR_NZ dm_clm_loop
        RET
    }
}
danmaku_fan

Erzeugt einen Fächer mithilfe einer Geschwindigkeitstabelle mit 32 Richtungen und festem Winkelschritt.

Syntax

c
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);

Parameter

x

Anfängliches Pixel-X, 0..159.

y

Anfängliches Pixel-Y, 0..127.

direction

Anfangswinkel, auf fünf Bits maskiert: 0=rechts, 8=unten, 16=links, 24=oben.

step

Winkelzuwachs je Projektil, mit Umlauf über 32 Richtungen.

count

Anzahl der Versuche, auf 96 begrenzt.

speed

Geschwindigkeit in Sechzehntelpixeln, höchstens 64 beziehungsweise vier Pixel pro Aktualisierung.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Versucht auch bei vollem Pool die verbleibenden Erzeugungen. Ganzzahlige sin/cos-Tabellenwerte führen bei diagonaler Bewegung zu Rundungen.

Anwendungsbeispiel

c
danmaku_fan(80,64,0,4,8,64);result[9]=dm_count;result[10]=dm_spawned;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_fan: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:39

Deklarationshinweise im Original
Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.

kitaqgb/lib/danmaku.c:62

c
void danmaku_fan(u8 x,u8 y,u8 direction,u8 step,u8 count,u8 speed) {
    u8 n;
    u8 a;
    s8 vx;
    s8 vy;
    if(count>DANMAKU_MAX) count=DANMAKU_MAX;
    if(speed>64) speed=64;
    a=direction&31;
    for(n=0;n<count;n++) {
        vx=(s8)(((s16)dm_cos[a]*(s16)speed)>>6);
        vy=(s8)(((s16)dm_sin[a]*(s16)speed)>>6);
        danmaku_spawn(x,y,vx,vy);
        a=(u8)((a+step)&31);
    }
}
danmaku_present_now

Überträgt alle 576 dm_map-Bytes synchron per CGB-GDMA zur Hintergrundkarte $9800.

Syntax

c
void danmaku_present_now();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Nur für CGB; nicht auf dem DMG aufrufen. Verwenden Sie die Funktion bei ausgeschaltetem LCD oder am VBlank-Anfang. Sie wählt VRAM-Bank null, ohne den bisherigen VBK-Wert wiederherzustellen. Die Anwendung stellt Projektilgrafiken in Kacheln 0..15 bereit.

Anwendungsbeispiel

c
// CGB general DMA; the LCD is stopped for this complete-map upload.
danmaku_present_now();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_present_now: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:48

Deklarationshinweise im Original
Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0.
Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.

kitaqgb/lib/danmaku.c:301

c
void danmaku_present_now() {
    __asm {
        XOR_A
        LDH_MEM_A 0x4F
        LD_HL_IMM dm_map
        LD_A_H
        LDH_MEM_A 0x51
        LD_A_L
        LDH_MEM_A 0x52
        LD_A_IMM 0x18
        LDH_MEM_A 0x53
        XOR_A
        LDH_MEM_A 0x54
        LD_A_IMM 35
        LDH_MEM_A 0x55
        RET
    }
}
danmaku_reset

Leert den Pool mit 96 Projektilen und setzt Spitzenwert, kumulierte Erzeugungen und Ablehnungen wegen voller Belegung zurück.

Syntax

c
void danmaku_reset();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Lässt Spielerkoordinaten, Unverwundbarkeit und RAM-Kachelkarte unverändert; richten Sie diese bei Spielbeginn getrennt ein.

Anwendungsbeispiel

c
danmaku_reset();result[0]=dm_count;result[1]=dm_peak;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_reset: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:33

Deklarationshinweise im Original
Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.

kitaqgb/lib/danmaku.c:34

c
void danmaku_reset() {
    danmaku_clear(); dm_peak=0; dm_spawned=0; dm_rejected=0;
}
danmaku_spawn

Sucht zyklisch nach freien Plätzen und erzeugt ein Projektil mit gewünschter Position und Geschwindigkeit.

Syntax

c
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);

Parameter

x

Anfängliches Pixel-X, 0..159.

y

Anfängliches Pixel-Y, 0..127.

vx

Vorzeichenbehaftete Q4.4-Geschwindigkeit −128..127; 16 bewegt pro Aktualisierung ein Pixel nach rechts.

vy

Vorzeichenbehaftete Q4.4-Geschwindigkeit; positive Werte bewegen nach unten.

Rückgabewert

Gibt bei erfolgreicher Vergabe 1 zurück, bei Koordinaten außerhalb oder vollem Pool 0. Anforderungen außerhalb erhöhen dm_rejected nicht.

Bedingungen und Grenzen

Positionen werden in Sechzehntelpixeln gespeichert. Die u16-Gesamtzähler für Erzeugungen und Ablehnungen laufen nach 65535 um. Es wird kein dynamischer Speicher vergeben.

Anwendungsbeispiel

c
result[2]=danmaku_spawn(40,40,16,0);result[3]=danmaku_spawn(160,40,0,0);result[4]=dm_count;result[5]=dm_rejected;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_spawn: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:37

Deklarationshinweise im Original
Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.

kitaqgb/lib/danmaku.c:39

c
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy) {
    u8 n;
    u8 i;
    if (x>=160 || y>=128) return 0;
    for(n=0;n<DANMAKU_MAX;n++) {
        i=dm_cursor;
        dm_cursor++;
        if(dm_cursor>=DANMAKU_MAX) dm_cursor=0;
        if(dm_bullets[i].active==0) {
            dm_bullets[i].x=(s16)((u16)x<<4);
            dm_bullets[i].y=(s16)((u16)y<<4);
            dm_bullets[i].vx=vx; dm_bullets[i].vy=vy;
            dm_bullets[i].active=1; dm_bullets[i].grazed=0;
            dm_count++; dm_spawned++;
            if(dm_count>dm_peak) dm_peak=dm_count;
            return 1;
        }
    }
    dm_rejected++;
    return 0;
}
danmaku_step

Bewegt jedes Projektil einmal, entfernt Projektile außerhalb, setzt Projektilkacheln zusammen und erkennt Treffer sowie Streifen.

Syntax

c
void danmaku_step();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Gezeichnete Mittelpunkte rasten auf Vier-Pixel-Zellen ein. Achsendifferenzen von höchstens acht ergeben das erste Streifen, höchstens drei einen Treffer. Unverwundbarkeit unterdrückt nur Treffer. dm_hit/dm_graze werden bei jedem Aufruf zurückgesetzt; jedes Projektil streift nur einmal. Kachel-IDs 0..15 codieren vier Quadrantenbits; belegte Dekorationskacheln mit IDs ab 16 werden ersetzt.

Anwendungsbeispiel

c
dm_player_x=0;dm_player_y=0;dm_invulnerable=0;for(i=0;i<8;i++){danmaku_clear_map();danmaku_step();}result[12]=dm_count;result[13]=dm_hit;result[14]=dm_graze;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

CGB-exklusives Zeichenbeispiel. Erzeugen Sie acht Richtungen bei (80,64), aktualisieren Sie achtmal und zeigen Sie acht rote 3×3-Punkte in radialer Anordnung. Orthogonale Projektile bewegen sich 32 Pixel; Diagonalen verwenden Ganzzahlnäherungen. Geprüft werden außerdem Poolleerung und Erhalt der kumulierten Erzeugungen.

danmaku_step: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/danmaku.h:45

Deklarationshinweise im Original
Caller fills decoration after clear_map, then calls step to overlay bullets.
hit and graze are events for this step. Collision uses rendered centers.

kitaqgb/lib/danmaku.c:99

c
void danmaku_step() {
    // One linear pass. No per-bullet bank calls, multiplication or division.
    // The 8-byte packed public layout is x16,y16,vx8,vy8,active,graze.
    __asm {
        XOR_A
        LD_MEM_A dm_hit
        LD_MEM_A dm_graze
        LD_A_IMM 96
        LD_MEM_A dm_remaining
        LD_HL_IMM dm_bullets
    dm_tick_loop:
        PUSH_HL
        LD_BC_IMM 6
        ADD_HL_BC
        LD_A_HL
        OR_A
        JP_Z dm_tick_next
        DEC_HL
        LD_A_HL
        LD_MEM_A dm_vy
        DEC_HL
        LD_A_HL
        LD_C_A
        LD_B_IMM 0
        AND_IMM 128
        JR_Z dm_tick_xsign
        DEC_B
    // B:C is the sign-extended X velocity. Add to Q12.4 position; high byte >=10 also rejects negative X.
    dm_tick_xsign:
        POP_HL
        PUSH_HL
        LD_A_HL
        ADD_C
        LDI_HL_A
        LD_E_A
        LD_A_HL
        ADC_B
        LDI_HL_A
        CP_IMM 10
        JP_NC dm_tick_kill
        RRCA
        RRCA
        RRCA
        RRCA
        LD_D_A
        LD_A_E
        RRCA
        RRCA
        RRCA
        RRCA
        AND_IMM 15
        OR_D
        LD_MEM_A dm_px
        LD_A_MEM dm_vy
        LD_C_A
        LD_B_IMM 0
        AND_IMM 128
        JR_Z dm_tick_ysign
        DEC_B
    // Apply signed Y velocity similarly; high byte >=8 rejects negative Y and positions at or below 128 pixels.
    dm_tick_ysign:
        LD_A_HL
        ADD_C
        LDI_HL_A
        LD_E_A
        LD_A_HL
        ADC_B
        LDI_HL_A
        CP_IMM 8
        JP_NC dm_tick_kill
        RRCA
        RRCA
        RRCA
        RRCA
        LD_D_A
        LD_A_E
        RRCA
        RRCA
        RRCA
        RRCA
        AND_IMM 15
        OR_D
        LD_MEM_A dm_py
        // Signed differences shifted into 0..16 for a wrap-safe range test.
        // Rendered centers are (pixel & FC)+2. Test a square of radius eight around the player for graze eligibility.
        LD_A_MEM dm_player_x
        LD_C_A
        LD_A_MEM dm_px
        AND_IMM 252
        ADD_A_IMM 10
        SUB_C
        CP_IMM 17
        JR_NC dm_tick_plot
        LD_B_A
        LD_A_MEM dm_player_y
        LD_C_A
        LD_A_MEM dm_py
        AND_IMM 252
        ADD_A_IMM 10
        SUB_C
        CP_IMM 17
        JR_NC dm_tick_plot
        LD_C_A
        INC_HL
        INC_HL
        INC_HL
        LD_A_HL
        OR_A
        JR_NZ dm_tick_check_hit
        LD_A_IMM 1
        LD_HL_A
        LD_A_MEM dm_graze
        INC_A
        LD_MEM_A dm_graze
    // A bullet grazes at most once during its lifetime. Invulnerability suppresses hits, but not first-graze events.
    // The inner hit test uses a square of radius three around the same quantized center.
    dm_tick_check_hit:
        LD_A_MEM dm_invulnerable
        OR_A
        JR_NZ dm_tick_plot
        LD_A_B
        SUB_IMM 5
        CP_IMM 7
        JR_NC dm_tick_plot
        LD_A_C
        SUB_IMM 5
        CP_IMM 7
        JR_NC dm_tick_plot
        LD_A_IMM 1
        LD_MEM_A dm_hit
    // Select one of four quadrant bits from pixel bit 2, then address map[(y>>3)*32+(x>>3)].
    // Decoration IDs >=16 are replaced at occupied cells; bullet IDs 0..15 merge with OR.
    dm_tick_plot:
        LD_A_MEM dm_py
        AND_IMM 4
        AND_IMM 254
        RRCA
        LD_B_A
        LD_A_MEM dm_px
        AND_IMM 4
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        OR_B
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM dm_bits
        ADD_HL_DE
        LD_A_HL
        LD_C_A
        LD_A_MEM dm_py
        AND_IMM 120
        LD_L_A
        LD_H_IMM 0
        ADD_HL_HL
        ADD_HL_HL
        LD_A_MEM dm_px
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        LD_E_A
        LD_D_IMM 0
        ADD_HL_DE
        LD_DE_IMM dm_map
        ADD_HL_DE
        LD_A_HL
        CP_IMM 16
        JR_C dm_tick_merge
        XOR_A
    dm_tick_merge:
        OR_C
        LD_HL_A
        JR dm_tick_next
    // Restore the saved record base, clear active at offset six and decrement the live count exactly once.
    dm_tick_kill:
        POP_HL
        PUSH_HL
        LD_BC_IMM 6
        ADD_HL_BC
        XOR_A
        LD_HL_A
        LD_A_MEM dm_count
        DEC_A
        LD_MEM_A dm_count
    // Restore the saved base even for inactive or culled bullets, then advance by the fixed eight-byte record size.
    dm_tick_next:
        POP_HL
        LD_BC_IMM 8
        ADD_HL_BC
        LD_A_MEM dm_remaining
        DEC_A
        LD_MEM_A dm_remaining
        JP_NZ dm_tick_loop
        RET
    }
}

debug.h — RAM-Protokolle und Zusicherungen

Protokolliert Namen, Werte und Frame-Kennungen in einem RAM-Protokoll fester Kapazität. Assertions bewahren Diagnoseinformationen auf und lassen die Ausführung weiterlaufen.

debug_assert_fail

Speichert einen Assertion-Fehlercode und versucht, einen ASSERT-Eintrag anzuhängen.

Syntax

c
void debug_assert_fail(u16 code);

Parameter

code

Zu speichernde 16-Bit-Fehlerkennung.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Die Ausführung läuft weiter. Der letzte Assertion-Code wird auch bei vollem Protokoll aktualisiert. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_assert_fail(42);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel speichert Code 42, füllt das Protokoll und speichert dann Code 999. Die Anzahl bleibt 32, der letzte Code wird jedoch zu 999.

debug_assert_fail: DMG
DMG
debug_assert_fail: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:33

Deklarationshinweise im Original
Record the assertion code and attempt to append an ASSERT entry. This helper
does not halt execution, and the code is retained even if the log is full.

kitaqgb/lib/debug.c:56

c
void debug_assert_fail(u16 code)
{
    kq_debug_last_assert = code;
    debug_push((const u8*)"ASSERT", code);
}
debug_get_last_assert

Liest den letzten Assertion-Code unabhängig vom verfügbaren Protokollspeicher.

Syntax

c
u16 debug_get_last_assert();

Rückgabewert

Gibt den letzten 16-Bit-Code zurück; nach der Initialisierung ist er null.

Bedingungen und Grenzen

Null ist zugleich der Anfangswert und lässt sich daher nicht von einem mit Code null protokollierten Fehler unterscheiden. Das Lesen löscht den Code nicht.

Anwendungsbeispiel

c
result[22]=debug_get_last_assert();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel prüft 77 aus dem Assertion-Makro, 999 nach dem Füllen des Protokolls und null nach erneuter Initialisierung.

debug_get_last_assert: DMG
DMG
debug_get_last_assert: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:39

Deklarationshinweise im Original
Read the last recorded assertion code, or the zero value installed by initialization.

kitaqgb/lib/debug.c:75

c
u16 debug_get_last_assert()
{
    return kq_debug_last_assert;
}
debug_get_trace_count

Liest die Anzahl gültiger Einträge im Trace-Array.

Syntax

c
u8 debug_get_trace_count();

Rückgabewert

Gibt eine Anzahl von null bis DEBUG_TRACE_MAX zurück.

Bedingungen und Grenzen

Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
result[1]=debug_get_trace_count();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel prüft die ersten zehn Einträge und nach weiteren Schreibzugriffen die Grenze von 32. Bei voller Belegung läuft der Zähler nicht auf null über.

debug_get_trace_count: DMG
DMG
debug_get_trace_count: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:35

Deklarationshinweise im Original
Return the number of valid entries in the fixed trace buffer.

kitaqgb/lib/debug.c:63

c
u8 debug_get_trace_count()
{
    return kq_debug_trace_count;
}
debug_get_trace_log

Liefert eine Referenz auf das interne Array zur Auswertung gespeicherter Namen, Werte und Frame-Kennungen.

Syntax

c
const DebugTraceEntry* debug_get_trace_log();

Rückgabewert

Gibt einen schreibgeschützten Zeiger auf das interne DebugTraceEntry-Array zurück.

Bedingungen und Grenzen

Dies ist keine Kopie. Lesen Sie nur die von debug_get_trace_count() gemeldete Anzahl von Einträgen. Nach der Initialisierung verbliebene alte Bytes sind keine gültigen Datensätze. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
entries=debug_get_trace_log();for(i=0;i<10;i++){result[2+i]=entries[i].value;result[12+i]=entries[i].frame;}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest alle zehn Wert- und Frame-Felder und prüft das führende B der Bezeichnung BEGIN.

debug_get_trace_log: DMG
DMG
debug_get_trace_log: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:37

Deklarationshinweise im Original
Expose the internal trace array for inspection; use the count to bound reads.

kitaqgb/lib/debug.c:69

c
const DebugTraceEntry* debug_get_trace_log()
{
    return kq_debug_trace_log;
}
debug_init

Initialisiert die gültige Protokolllänge, die Frame-Kennung und den letzten Assertion-Code.

Syntax

c
void debug_init();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Die Bytes vorhandener Einträge werden nicht gelöscht. Rufen Sie die Funktion vor dem ersten Protokolleintrag auf. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_init();result[0]=debug_get_trace_count();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel prüft zunächst die Anzahl null, setzt dann ein gefülltes Protokoll zurück und bestätigt, dass Anzahl und Assertion-Code gelöscht sind, während die alten Arraywerte erhalten bleiben.

debug_init: DMG
DMG
debug_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:22

Deklarationshinweise im Original
Reset log length, frame tag and last assertion code; existing entry bytes are not erased.

kitaqgb/lib/debug.c:10

c
void debug_init()
{
    kq_debug_trace_count = 0;
    kq_debug_frame = 0;
    kq_debug_last_assert = 0;
}
debug_mark_frame

Schreibt eine benannte Frame-Markierung, um eine Stelle im Ablauf zu kennzeichnen.

Syntax

c
void debug_mark_frame(const u8* label);

Parameter

label

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_mark_frame("BEGIN");

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Markierung BEGIN speichert den Wert 65535 (0xFFFF) mit der Frame-Kennung 513.

debug_mark_frame: DMG
DMG
debug_mark_frame: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:26

Deklarationshinweise im Original
Append a named frame marker using 0xFFFF as its value.

kitaqgb/lib/debug.c:37

c
void debug_mark_frame(const u8* label)
{
    debug_push(label, 0xFFFF);
}
debug_set_frame

Legt die Frame-Kennung fest, die in nachfolgende Protokolleinträge kopiert wird.

Syntax

c
void debug_set_frame(u16 frame);

Parameter

frame

16-Bit-Frame-Nummer für nachfolgende Einträge.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Die Funktion wartet weder auf einen Frame noch erhöht sie die Kennung automatisch. Übergeben Sie ausdrücklich den Frame-Zähler des Spiels. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_set_frame(513);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel setzt die Kennung auf 513, schreibt zehn Einträge und liest zur Kontrolle alle zehn Frame-Felder zurück.

debug_set_frame: DMG
DMG
debug_set_frame: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:24

Deklarationshinweise im Original
Set the frame tag copied into subsequently recorded entries.

kitaqgb/lib/debug.c:18

c
void debug_set_frame(u16 frame)
{
    kq_debug_frame = frame;
}
debug_trace_u16

Protokolliert einen benannten 16-Bit-Punktestand oder Zähler.

Syntax

c
void debug_trace_u16(const u8* name, u16 value);

Parameter

name

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

value

Zu protokollierender Wert von 0 bis 65535.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_trace_u16("WORD",4660);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Eintrag WORD speichert 4660 (0x1234); das Beispiel liest ihn zur Prüfung beider Bytes zurück.

debug_trace_u16: DMG
DMG
debug_trace_u16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:30

Deklarationshinweise im Original
Append a 16-bit value with the current frame tag.

kitaqgb/lib/debug.c:49

c
void debug_trace_u16(const u8* name, u16 value)
{
    debug_push(name, value);
}
debug_trace_u8

Protokolliert einen 8-Bit-Zustandswert mit Namen und aktueller Frame-Kennung.

Syntax

c
void debug_trace_u8(const u8* name, u8 value);

Parameter

name

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

value

Wert von 0 bis 255, der mit Nullen auf das 16-Bit-Protokollfeld erweitert wird.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
debug_trace_u8("BYTE",255);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Eintrag BYTE speichert 255 und prüft, dass das 16-Bit-Wertfeld im Protokoll ebenfalls 255 enthält.

debug_trace_u8: DMG
DMG
debug_trace_u8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:28

Deklarationshinweise im Original
Append an unsigned byte value, widened to the log's 16-bit value field.

kitaqgb/lib/debug.c:43

c
void debug_trace_u8(const u8* name, u8 value)
{
    debug_push(name, (u16)value);
}
KITAQGB_ASSERT

Als Anweisung verwendbares Makro, das bei falscher Bedingung Assertion-Code 1 protokolliert.

Syntax

c
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)

Parameter

cond

Bedingung, die erfüllt sein soll; null bedeutet einen Fehler.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Die Bedingung wird einmal ausgewertet. Bei wahr wird nichts protokolliert, bei falsch der Fehler aufgezeichnet, ohne die Ausführung anzuhalten. Durch die Form do…while (0) lässt sich das Makro in einem if…else als einzelne Anweisung verwenden.

Anwendungsbeispiel

c
KITAQGB_ASSERT(1);KITAQGB_ASSERT(0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Eine wahre und eine falsche Assertion erzeugen genau einen Eintrag mit Code 1.

KITAQGB_ASSERT: DMG
DMG
KITAQGB_ASSERT: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:45

c
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)
KITAQGB_ASSERT_CODE

Protokolliert den gewählten Assertion-Code nur bei falscher Bedingung.

Syntax

c
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)

Parameter

cond

Bedingung, die erfüllt sein soll.

code

Code-Ausdruck, der im Fehlerfall ausgewertet und in 16 Bits umgewandelt wird.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Die Bedingung wird einmal ausgewertet, der Code-Ausdruck nur im Fehlerfall. Nach dem Protokollieren läuft die Ausführung weiter.

Anwendungsbeispiel

c
KITAQGB_ASSERT_CODE(1,++side_effect);KITAQGB_ASSERT_CODE(0,77);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei wahrer Bedingung wird der Code-Ausdruck ++side_effect nicht ausgewertet; die Variable bleibt null. Eine falsche Bedingung protokolliert Code 77.

KITAQGB_ASSERT_CODE: DMG
DMG
KITAQGB_ASSERT_CODE: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:46

c
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)
KITAQGB_MARK_FRAME

Wandelt eine Bezeichnung in einen Zeichenkettenzeiger um und fügt eine Frame-Markierung mit dem Wert 0xFFFF hinzu.

Syntax

c
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))

Parameter

label

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
KITAQGB_MARK_FRAME("END");

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Markierung END wird auf den Wert 65535 und die Frame-Kennung 513 geprüft.

KITAQGB_MARK_FRAME: DMG
DMG
KITAQGB_MARK_FRAME: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:44

c
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))
KITAQGB_TRACE

Wandelt einen Wert ausdrücklich in 16 Bits um und protokolliert ihn mit Namen.

Syntax

c
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))

Parameter

name

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

value

Ausdruck, der vor dem Protokollieren in 16 Bits umgewandelt wird.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Makro ist immer aktiv; Build-Einstellungen deaktivieren es nicht automatisch. Es protokolliert 16-Bit-Werte genauso wie KITAQGB_TRACE_U16. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
KITAQGB_TRACE("SCORE",600);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel speichert 600 und liest den Wert zur Prüfung aus dem Protokoll zurück.

KITAQGB_TRACE: DMG
DMG
KITAQGB_TRACE: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:43

c
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
KITAQGB_TRACE_U16

Wandelt einen Wert ausdrücklich in 16 Bits um und protokolliert ihn mit Namen.

Syntax

c
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))

Parameter

name

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

value

Ausdruck, der vor dem Protokollieren in 16 Bits umgewandelt wird.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Makro ist immer aktiv; Build-Einstellungen deaktivieren es nicht automatisch. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
KITAQGB_TRACE_U16("WORD2",500);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel speichert 500 und liest den Wert zur Prüfung aus dem Protokoll zurück.

KITAQGB_TRACE_U16: DMG
DMG
KITAQGB_TRACE_U16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:42

c
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
KITAQGB_TRACE_U8

Wandelt einen Wert ausdrücklich in 8 Bits um und protokolliert ihn mit Namen.

Syntax

c
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))

Parameter

name

Nullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.

value

Ausdruck, der vor dem Protokollieren in 8 Bits umgewandelt wird.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Das Makro ist immer aktiv; Build-Einstellungen deaktivieren es nicht automatisch. Das Protokoll fasst standardmäßig 32 Einträge und verwirft bei voller Belegung neue Einträge. Wenn Sie DEBUG_TRACE_MAX überschreiben, verwenden Sie in allen Übersetzungseinheiten denselben Wert zwischen 1 und 255. Namen werden als Zeiger gespeichert, nicht kopiert; ihr Speicher muss bis zum Ende der Auswertung lesbar bleiben. Zugriffe aus Hauptprogramm und Interrupts müssen Sie selbst gegeneinander absichern.

Anwendungsbeispiel

c
KITAQGB_TRACE_U8("CAST",0x1234);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel speichert 52. Von 0x1234 bleibt nur das niederwertige Byte 0x34 erhalten.

KITAQGB_TRACE_U8: DMG
DMG
KITAQGB_TRACE_U8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/debug.h:41

c
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))

dmg3d.h — Monochrome Drahtgitterdarstellung mit 128×120 Pixeln für DMG

Monochromes 3D-Linienzeichnen. Übergeben Sie Modelleckpunkte, Kanten und Flächen sowie Objektposition, Rotation und Skalierung. Verwenden Sie Initialisierung, Frame-Beginn, Zeichnen und Übertragung in dieser Reihenfolge. Physik ist getrennt. Winkel haben sechzehn Schritte pro Umdrehung; Modellskalierung 256 bedeutet Originalgröße.

Vec3 enthält x/y/z, Edge die Eckpunktindizes a/b und Face die Dreiecksindizes a/b/c. vertices, edges und faces in Model zeigen auf diese Arrays; die jeweilige Anzahl gibt ihre Länge an. edge_faces enthält die Nachbarflächenindizes f0/f1, bei fehlender Fläche FACE_NONE. MODEL_HIDDEN_LINES in flags fordert flächenbasierte Kantenauswahl an. Die vorzeichenbehaftete projizierte Fläche bestimmt die Ausrichtung; die Eckpunktreihenfolge ist daher wichtig.

Object speichert Modellreferenz, Position x/y/z, Winkel rx/ry/rz, scale_q8 und visible. Objekte können ein Modell teilen; Zeichnen kopiert aber keine Tabellen und schaltet deren ROM-Bänke nicht automatisch um. Referenzierte Daten müssen während des gesamten Zeichnens lesbar bleiben. CGB-Object besitzt zusätzlich einen Farbindex.

DMG3D_BeginFrame

Beginnt das Zeichnen eines Frames und deaktiviert die Verdeckungsprüfung.

Syntax

c
void DMG3D_BeginFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Deaktiviert nur die Verdeckungsfilterung. Staging wird normalerweise während der Übertragung gelöscht; Init liefert den ersten leeren Bereich. Verwirft keinen ungesendeten Frame, löscht keine Maske und setzt weder ausstehende BG-Schreibzugriffe noch Änderungsflags zurück.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_BeginFrame: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_BeginFrame: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:17

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Disable occlusion filtering only. Stage clearing normally happens during
transfer, and Init supplies the first clean stage. This does not discard an
unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.

kitaqgb/lib/wire3d_dmg.c:2641

c
void Wire3DDMG_BeginFrame()
{




    /* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
       resets draw state. Wire3DDMG_Init supplies the first clean buffer. */

    w3ddmg_occlusion_active = 0;
}
DMG3D_DrawIndexedEdges

Zeichnet ein ganzzahlig skaliertes Linienmodell aus Eckpunkten und Zwei-Byte-Kantenindexpaaren.

Syntax

c
void DMG3D_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);

Parameter

vertices

Array von 3D-Eckpunkten.

vertex_count

Anzahl der Einträge im Eckpunktarray.

edges

Eckpunktindizes je Kante im deklarierten Struct- oder Bytepaar-Format.

edge_count

Anzahl der Kanten.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

scale

Ganzzahlige Skalierung; null wird als eins behandelt.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Zeichnet per Bytepaar indizierte Kanten nach ganzzahliger Skalierung und Verschiebung; Skalierung null bedeutet eins, ohne Objektrotation oder Flächenfilterung. Projiziert höchstens 24 Eckpunkte. Übergeben Sie höchstens 128 Kantenpaare, da Byte-Offsets nach 255 umbrechen. Ungültige Eckpunkt-IDs und tiefenbedingt verworfene Endpunkte werden übersprungen; Nullarrays werden ignoriert. Koordinatenprodukte und -summen müssen als s16 darstellbar sein.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

DMG3D_DrawIndexedEdges: DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG3D_DrawIndexedEdges: CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:20

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Draw byte-pair edge indices after integer scaling and translation; scale
zero means one, and there is no object rotation or face filtering. Project at
most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
are ignored. Keep coordinate products/sums representable as s16.

kitaqgb/lib/wire3d_dmg.c:3824

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
    w3ddmg_u8 i;
    w3ddmg_u8 count;

    if (vertices == 0) return;
    if (edges == 0) return;

    count = vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
    if (scale == 0) scale = 1;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
        vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
        vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }

        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < edge_count)
    {
        w3ddmg_u8 a;
        w3ddmg_u8 b;

        a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
        b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
        if ((a < count) && (b < count) &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
        {
            Wire3DDMG_DrawLine2D(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
        }

        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_DrawLine2D

Zeichnet eine vierfach zusammenhängende Bildschirmlinie einschließlich Endpunkten in den Staging-Bereich.

Syntax

c
void DMG3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Bei aktivierter Änderungsübertragung wird das umschließende Tile-Rechteck markiert und danach eine zusammenhängende Staging-Linie gezeichnet. Szenenzeichnen kann sie anhand von fünf Maskenabtastungen verwerfen. Geben Sie Endpunkte im 128×120-Viewport an; niedrige Pixelgrenzprüfungen schneiden das Segment nicht geometrisch zu.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_DrawLine2D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_DrawLine2D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:21

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Mark the bounding tile rectangle when dirty transfer is enabled, then draw
a connected staged line. Scene drawing may reject it using five mask samples.
Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
the segment geometrically.

kitaqgb/lib/wire3d_dmg.c:2685

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{

    w3ddmg_mark_line_dirty(ax, ay, bx, by);


    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
DMG3D_DrawLine3D

Projiziert zwei Weltendpunkte und zeichnet eine Linie dazwischen.

Syntax

c
void DMG3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parameter

ax

X-Komponente des Startpunkts in Weltkoordinaten.

ay

Y-Komponente des Startpunkts in Weltkoordinaten.

az

Z-Komponente des Startpunkts in Weltkoordinaten.

bx

X-Komponente des Endpunkts in Weltkoordinaten.

by

Y-Komponente des Endpunkts in Weltkoordinaten.

bz

Z-Komponente des Endpunkts in Weltkoordinaten.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Projiziert beide Weltendpunkte und zeichnet nur, wenn beide den Tiefenbereich bestehen. Bildet keine Schnittpunkte eines kreuzenden Segments mit Nah- oder Fernebene; projizierte Endpunkte werden einzeln auf die Bildschirmränder begrenzt.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_DrawLine3D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_DrawLine3D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:22

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:2808

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
DMG3D_DrawModel

Zeichnet ein Eckpunkt-Kanten-Modell an der gewünschten Position und mit der gewünschten Rotation in Originalgröße.

Syntax

c
void DMG3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Zeichnet ein unskaliertes Modell, indem DrawModelScaled mit Skalierung 256 aufgerufen wird.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

DMG3D_DrawModel: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG3D_DrawModel: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:23

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:2827

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)

{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
DMG3D_DrawModelScaled

Skaliert ein Modell, dreht es in Y/X/Z-Reihenfolge, verschiebt und projiziert seine Eckpunkte und zeichnet die Kanten.

Syntax

c
void DMG3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Skaliert bis zu 24 Eckpunkte, dreht Y/X/Z, verschiebt und projiziert sie und durchläuft dann alle edge_count-Einträge mit optionaler Nachbarflächenfilterung. edge_count ist ein Byte-Zähler. Der Flächen-Arbeitspuffer ist auf 16 begrenzt; Kantentabellen müssen alle deklarierten Einträge enthalten. Nichtpositive Skalierung bedeutet 256. Nullzeiger für Modell, Eckpunkte oder Kanten werden ignoriert. Produkte und Verschiebungen müssen in vorzeichenbehaftete 16 Bit passen; Kanten über Tiefengrenzen werden verworfen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

DMG3D_DrawModelScaled: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG3D_DrawModelScaled: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:24

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
all edge_count entries (a byte count) with optional adjacent-face filtering.
Face scratch is capped at 16; edge tables must contain all declared entries.
Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.

kitaqgb/lib/wire3d_dmg.c:2972

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;




    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&



                w3ddmg_is_edge_visible(model, i, face_count))

            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_DrawScene

Zeichnet bis zu acht Objekte von nah nach fern; nähere Flächen verdecken spätere Kanten.

Syntax

c
void DMG3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parameter

objects

Objektarray mit Positionen, Rotationen, Skalierungen und Sichtbarkeitsflags.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Sortiert bis zu acht Objektursprünge nach Kameratiefe von nah nach fern. Zeichnet sichtbare gültige Modelle und markiert Vorderseiten-Begrenzungsrechtecke für spätere Objekte. Der erste sortierte Platz überspringt Maskentests; der letzte benötigt keinen neuen Verdeckungsbereich. Dies ist grobes Linienverwerfen, kein Tiefenpuffer. Null oder leere Eingaben werden ignoriert; Aufruferdaten und aktueller Projektionscache müssen während des Durchlaufs gültig bleiben.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

DMG3D_DrawScene: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG3D_DrawScene: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:25

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Sort at most eight object origins by camera depth, near to far. Draw visible
valid models and mark front-face bounding rectangles for later objects. The
first sorted slot bypasses mask tests and the last needs no new occluder.
This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
caller data and the current projection cache must remain valid during traversal.

kitaqgb/lib/wire3d_dmg.c:2723

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;

    if (scene_count == 0) return;


    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];





            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();



    w3ddmg_occlusion_active = 0;


    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {




            w3ddmg_occlusion_active = i == 0 ? 0 : 1;
            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
            if ((w3ddmg_u8)(i + 1) < scene_count)
            {
                w3ddmg_mark_model_occluder(obj->model);
            }

        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
DMG3D_EndFrame

Übergibt ausstehende Hintergrund-Schreibzugriffe und vorbereitete Zeichnungen an VRAM.

Syntax

c
void DMG3D_EndFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Wartet auf den nächsten VBlank und führt BG-Schreibzugriffe aus. Verbraucht dann optional zuerst die Hilfsstreifen, bevor geänderte Tiles oder das gesamte Haupt-Staging übertragen werden. Wegen überlappender Hilfs- und Hauptquellen ist diese Reihenfolge wichtig. STAT wird über Zugriffsfenster hinweg weiter abgefragt; die Aktualisierung muss nicht in einen VBlank passen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_EndFrame: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_EndFrame: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:28

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Wait for the next VBlank and flush BG writes, then optionally consume the
auxiliary strips before uploading either dirty tiles or the entire main stage.
Auxiliary/main source overlap makes that ordering significant. STAT polling
continues across access windows; the update need not fit one VBlank.

kitaqgb/lib/wire3d_dmg.c:3081

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    w3ddmg_flush_bg_queue();



    if (w3ddmg_aux_transfer_enabled)
    {
        w3ddmg_transfer_stage_aux_asm();
    }
    if (w3ddmg_dirty_transfer_enabled)
    {
        w3ddmg_transfer_dirty_stage();
    }
    else
    {
        w3ddmg_transfer_stage_asm();
    }

}
DMG3D_EraseModelFaces

Projiziert nach vorn gerichtete Modelldreiecke und löscht vorbereitete Pixel in ihrem Inneren.

Syntax

c
void DMG3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Projiziert bis zu 24 Eckpunkte und löscht das Innere nach vorn gerichteter Dreiecke aus dem Staging-Bereich für ein Modell mit Verdeckungsflags und Flächendaten. Nichtpositive Skalierung bedeutet 256, also Originalgröße. Bis zu 16 Flächen werden betrachtet; Flächen über Tiefengrenzen werden übersprungen. Ersetzt auch gemeinsame Projektionscaches, aktualisiert aber kein VRAM.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    DMG3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
    DMG3D_EraseTriangle2D(12,12,28,12,12,28);
    DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

DMG3D_EraseModelFaces: DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG3D_EraseModelFaces: CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:29

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:2843

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_EraseSpan2D

Löscht einen waagerechten Span einschließlich Endpunkten in einer vorbereiteten Zeile.

Syntax

c
void DMG3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parameter

y

Pixel-Y-Koordinate der zu löschenden Zeile.

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Ordnet die X-Endpunkte und löscht den vorbereiteten Span einschließlich Endpunkten. Beide müssen in 0..127 liegen; ungültiges Y wird ignoriert. Die Routine begrenzt X nicht automatisch.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_EraseSpan2D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_EraseSpan2D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:30

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:2943

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
DMG3D_EraseTriangle2D

Löscht ein Bildschirmdreieck über waagerechte Rasterzeilen-Spans aus dem Staging-Bereich.

Syntax

c
void DMG3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

cx

X-Koordinate von Eckpunkt C in Viewport-Pixeln.

cy

Y-Koordinate von Eckpunkt C in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Löscht ein Dreieck aus vorbereiteten Pixeln über ganzzahlige Rasterzeilenschnittpunkte. Geben Sie Viewport-Koordinaten an. Entartete Dreiecke werden ignoriert; Verdeckungsmaske und VRAM bleiben unverändert.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    DMG3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
    DMG3D_EraseTriangle2D(12,12,28,12,12,28);
    DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

DMG3D_EraseTriangle2D: DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG3D_EraseTriangle2D: CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:31

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:2933

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
DMG3D_Init

Initialisiert LCD, Tiles und Hintergrundkarte für einen monochromen Drahtgitter-Viewport.

Syntax

c
void DMG3D_Init();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Übernimmt den LCD-Zustand, löscht Tile-VRAM und BG-Karte und richtet einen 16×15-Viewport ab Kartentile (3,1) ein. Setzt Scrolling (8,0), BGP=0xB4 und BG-Anzeige. Setzt Kamera, Warteschlangen, Übertragungsmodi, beide Änderungstabellen und Staging zurück. Reservieren Sie 0xD000..0xDFFF und erhalten Sie die WRAM-Einblendung; Hilfsspeicher verwendet dieselben Adressen. Rufen Sie vor dem Zeichnen BeginFrame auf, um den Verdeckungszustand herzustellen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_Init: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_Init: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:35

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
Call BeginFrame before drawing to establish occlusion state.

kitaqgb/lib/wire3d_dmg.c:2572

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();



    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {



        off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));

        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }




    w3ddmg_reg_scx = 8;

    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;

    w3ddmg_aux_transfer_enabled = 0;
    w3ddmg_dirty_transfer_enabled = 0;


    Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
    w3ddmg_clear_stage_asm();

    w3ddmg_clear_stage_aux_asm();
    w3ddmg_clear_dirty_tables();

}
DMG3D_ProjectPoint

Projiziert einen Weltpunkt durch die Kamera in Viewport-Koordinaten.

Syntax

c
w3ddmg_u8 DMG3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parameter

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

sx

Gültiger beschreibbarer u8-Zeiger für die projizierte X-Koordinate.

sy

Gültiger beschreibbarer u8-Zeiger für die projizierte Y-Koordinate.

Rückgabewert

Liefert 1 bei erfolgreicher Projektion oder 0 bei verworfener Tiefe.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Projiziert einen Weltpunkt mit der aktuellen Kamera. Ungültige Tiefe liefert null ohne Ausgabeänderung; bei Erfolg werden auf 128×120 begrenzte Koordinaten geschrieben. Beide Ausgabezeiger müssen gültig sein. Koordinatendifferenzen müssen in s16 passen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_ProjectPoint: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_ProjectPoint: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:43

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Project a world point with the current camera. Return zero for invalid
depth without changing outputs; success writes clamped 128x120 coordinates.
Both output pointers must be valid. Coordinate differences must fit s16.

kitaqgb/lib/wire3d_dmg.c:549

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
DMG3D_PutBgTile

Reiht einen Tile-Nummer-Schreibzugriff für eine Hintergrundkartenzelle ein.

Syntax

c
void DMG3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parameter

x

X-Tile-Koordinate in der 32×32-Hintergrundkarte.

y

Y-Tile-Koordinate in der 32×32-Hintergrundkarte.

tile

Acht-Bit-Tile-Nummer für die Hintergrundzelle.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Reiht einen Tile-Schreibzugriff auf die 32×32-Karte bei 0x9800 für EndFrame ein. Ungültige Kartenkoordinaten und Anfragen über 48 ausstehende Schreibzugriffe hinaus werden ohne Meldung ignoriert. Diese Warteschlange ist von der allgemeinen vram-Bibliothekswarteschlange getrennt.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_PutBgTile: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_PutBgTile: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:44

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:582

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
DMG3D_RotatePoint

Dreht einen Punkt mit den angegebenen Winkeln direkt in seinen Variablen.

Syntax

c
void DMG3D_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parameter

x

Separater beschreibbarer s16-Zeiger für die X-Komponente.

y

Separater beschreibbarer s16-Zeiger für die Y-Komponente.

z

Separater beschreibbarer s16-Zeiger für die Z-Komponente.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Dreht direkt in den Variablen in Y/X/Z-Reihenfolge mit 16 Schritten pro Umdrehung. Ein Nullzeiger für eine Komponente macht den gesamten Aufruf wirkungslos; verwenden Sie getrennte Zeiger. Jede Achsrotation begrenzt ihre Eingaben auf ±220.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

DMG3D_RotatePoint: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG3D_RotatePoint: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:46

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Rotate in place in Y/X/Z order using 16 steps per full turn. A null
component pointer makes the whole call a no-op; use distinct pointers.
Each axis rotation clamps its inputs to +/-220.

kitaqgb/lib/wire3d_dmg.c:3121

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
    if (x == 0) return;
    if (y == 0) return;
    if (z == 0) return;

    w3ddmg_rotate_y(x, z, ry);
    w3ddmg_rotate_x(y, z, rx);
    w3ddmg_rotate_z(x, y, rz);
}
DMG3D_SetAuxTransfer

Wählt, ob EndFrame auch die Hilfsstreifen überträgt.

Syntax

c
void DMG3D_SetAuxTransfer(w3ddmg_u8 flag);

Parameter

flag

Null deaktiviert die Übertragungsfunktion; jeder andere Wert aktiviert sie.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Speichert die Hilfsübertragungsfreigabe für EndFrame; jeder Wert ungleich null aktiviert sie. Hier werden keine Daten kopiert oder gelöscht. Hilfsquellbytes teilen sich die Adressen mit dem Haupt-Staging-Bereich.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(1);
    DMG3D_BeginFrame();
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    // Auxiliary upload consumes this source before the dirty main tile is sent.

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.

DMG3D_SetAuxTransfer: DMG — Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.
DMG — Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.
DMG3D_SetAuxTransfer: CGB — Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.
CGB — Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_aux_gate.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:50

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
No data is copied or cleared here. Auxiliary source bytes alias the main stage.

kitaqgb/lib/wire3d_dmg.c:3895

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
    w3ddmg_aux_transfer_enabled = flag;
}
DMG3D_SetCamera

Speichert Kameraposition und -ausrichtung für spätere Projektionen.

Syntax

c
void DMG3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);

Parameter

x

X-Komponente der Kamera in Weltkoordinaten.

y

Y-Komponente der Kamera in Weltkoordinaten.

z

Z-Komponente der Kamera in Weltkoordinaten.

pitch

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

yaw

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

roll

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Speichert Kameraposition und -winkel für späteres Zeichnen; 16 Winkelschritte ergeben eine Umdrehung. Vorhandene Zeichnungen werden nicht neu projiziert und Eingabebereiche nicht geprüft.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_SetCamera: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_SetCamera: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:51

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:2661

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)

{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
DMG3D_SetDirtyTransfer

Wählt die Übertragung geänderter Tiles für den Haupt-Viewport mit 120 Zeilen.

Syntax

c
void DMG3D_SetDirtyTransfer(w3ddmg_u8 flag);

Parameter

flag

Null deaktiviert die Übertragungsfunktion; jeder andere Wert aktiviert sie.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Speichert die Freigabe für Änderungsübertragung und löscht beide Änderungsverläufe sowie den Haupt-Staging-Bereich, selbst bei unverändertem Wert. VRAM bleibt erhalten; beim Aktivieren über einem alten Bild können unmarkierte alte Tiles zurückbleiben. Sorgen Sie daher für einen sauberen angezeigten Ausgangszustand.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,24,8); DMG3D_DrawLine2D(24,8,24,24);
    DMG3D_DrawLine2D(24,24,8,24); DMG3D_DrawLine2D(8,24,8,8);
    DMG3D_EndFrame();
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(80,80,104,80); DMG3D_DrawLine2D(104,80,104,104);
    DMG3D_DrawLine2D(104,104,80,104); DMG3D_DrawLine2D(80,104,80,80);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.

DMG3D_SetDirtyTransfer: DMG — Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.
DMG — Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.
DMG3D_SetDirtyTransfer: CGB — Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.
CGB — Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_dirty.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:52

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Store the dirty-transfer gate and clear both dirty histories and the main
stage, even if the value is unchanged. VRAM is retained; enabling this over an
old image can leave unmarked old tiles, so arrange a clean displayed baseline.

kitaqgb/lib/wire3d_dmg.c:3955

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
    w3ddmg_dirty_transfer_enabled = flag;
    w3ddmg_clear_dirty_tables();
    w3ddmg_clear_stage_asm();
}
DMG3D_SetPalette

Schreibt die Zuordnung der vier Helligkeitsstufen ins monochrome Hintergrund-Palettenregister BGP.

Syntax

c
void DMG3D_SetPalette(w3ddmg_u8 bgp);

Parameter

bgp

BGP-Registerwert mit vier Zwei-Bit-Helligkeitszuordnungen.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Schreibt die rohe DMG-BGP-Palettencodierung sofort, ohne Frame-Synchronisierung.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

DMG3D_SetPalette: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG3D_SetPalette: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:53

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:597

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}
DMG3D_TransferAuxNow

Überträgt sechs Hilfsstreifen sofort und löscht ihre Quellbytes.

Syntax

c
void DMG3D_TransferAuxNow();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Überträgt und verbraucht die Hilfsquellstreifen sofort, unabhängig von der Hilfsfreigabe. Wartet nicht auf den VBlank-Start und aktualisiert weder Änderungsverlauf noch BG-Warteschlange. Die Quelle überlappt den Haupt-Staging-Bereich; stimmen Sie die Übertragungen aufeinander ab.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

DMG3D_TransferAuxNow: DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG3D_TransferAuxNow: CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:57

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Upload and consume auxiliary source strips immediately, independent of the
auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
The source overlaps the main stage and must be coordinated with its upload.

kitaqgb/lib/wire3d_dmg.c:3983

c
void Wire3DDMG_TransferAuxNow()
{
    w3ddmg_transfer_stage_aux_asm();
}
DMG3D_TransferMainNow

Überträgt den gesamten Haupt-Staging-Bereich sofort und löscht die verbrauchten Quellpixel.

Syntax

c
void DMG3D_TransferMainNow();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120. Überträgt und verbraucht den gesamten Haupt-Staging-Bereich sofort, fragt dabei STAT ab, wartet aber nicht auf den nächsten VBlank. Ignoriert Übertragungsfreigaben und erhält Änderungsverläufe sowie BG-Tile-Warteschlange; der Aufrufer koordiniert den Frame-Ablauf.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

DMG3D_TransferMainNow: DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
DMG3D_TransferMainNow: CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.
CGB — Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/dmg3d.h:58

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 120.
Upload and consume the full main stage immediately, polling STAT but not
waiting for the next VBlank. Ignore transfer gates and leave dirty histories
and BG tile queue unchanged; the caller coordinates the frame lifecycle.

kitaqgb/lib/wire3d_dmg.c:3970

c
void Wire3DDMG_TransferMainNow()
{
    w3ddmg_transfer_stage_asm();
}

entity.h — Objektpools mit festen Arrays

entity ist ein Objektpool mit einem Array fester Größe für Zustände wie Gegner, Geschosse und Sammelobjekte. Sie belegen einen freien Platz, greifen über dessen ID darauf zu und verwenden den Platz erneut, sobald das Objekt nicht mehr benötigt wird. Es wird kein Heap-Speicher angefordert. Koordinaten- und Geschwindigkeitseinheiten, Bewegung, Kollisionen und Timer-Aktualisierungen legt das Spiel fest.

Binden Sie entity.h ein und kompilieren Sie entity.c genau einmal. Rufen Sie zuerst entity_init auf und prüfen Sie, dass entity_create nicht 0xFF zurückgibt. ENTITY_MAX hat standardmäßig den Wert 16. Die IDs unterstützen 1 bis 255 Plätze; die tatsächlich nutzbare Anzahl hängt jedoch vom verfügbaren RAM ab. Verwenden Sie in allen Übersetzungseinheiten dieselbe Kapazitätsdefinition.

Der von entity_get zurückgegebene Zeiger verweist auf wiederverwendbaren Poolspeicher. Nach der Freigabe kann dieselbe ID ein anderes Objekt bezeichnen. Weder ID noch Zeiger stellen daher eine dauerhafte Identität dar. entity_destroy deaktiviert lediglich den Platz. Der Aufrufer muss Sprites ausblenden oder freigeben und andere Ressourcen aufräumen. Das Feld sprite dient der Verwaltung und aktualisiert OAM nicht automatisch.

entity_update_all und entity_draw_all durchlaufen aktive Plätze in aufsteigender ID-Reihenfolge und rufen fn(id) auf. Implementieren Sie die eigentliche Aktualisierung oder Darstellung im Callback. Ein Null-Callback bewirkt nichts. Wenn ein Callback einen späteren Platz belegt oder freigibt, wirkt sich das bereits auf den laufenden Durchlauf aus. Ein Aktualisierungsdurchlauf vor dem Zeichendurchlauf trennt beide Aufgaben.

entity_clear_all

Gibt alle Entities frei und setzt ihre Felder einschließlich der Markierung für fehlende Sprites zurück.

Syntax

c
void entity_clear_all();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Setzt in allen Plätzen active,type,x,y,vx,vy,state,timer auf null und sprite auf 0xFF. Hardware-Sprites werden dadurch weder verborgen noch freigegeben; ihre Ressourcen müssen separat aufgeräumt werden.

Anwendungsbeispiel

c
entity_clear_all();
after_clear = entity_count_active();
if (after_clear != 0 || entity_get(reused) != 0) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_clear_all: DMG
DMG
entity_clear_all: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:43

Deklarationshinweise im Original
Release every entity and restore deterministic defaults, including the no-sprite sentinel.

kitaqgb/lib/entity.c:14

c
void entity_clear_all()
{
    u8 i = 0;
    while (i < ENTITY_MAX) {
        entity_pool[i].active = 0;
        entity_pool[i].type = 0;
        entity_pool[i].x = 0;
        entity_pool[i].y = 0;
        entity_pool[i].vx = 0;
        entity_pool[i].vy = 0;
        entity_pool[i].state = 0;
        entity_pool[i].timer = 0;
        entity_pool[i].sprite = 0xFF;
        i++;
    }
}
entity_count_active

Zählt belegte Entity-Plätze, ohne ihren Zustand zu ändern.

Syntax

c
u8 entity_count_active();

Rückgabewert

Anzahl der Plätze mit einem von null verschiedenen active-Byte, von 0 bis ENTITY_MAX. Das ist die Belegung, nicht die höchste ID oder die Anzahl sichtbarer Sprites.

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Anwendungsbeispiel

c
created = entity_count_active();
if (created != 2) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_count_active: DMG
DMG
entity_count_active: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:41

Deklarationshinweise im Original
Count occupied slots without changing entity state.

kitaqgb/lib/entity.c:93

c
u8 entity_count_active()
{
    u8 i = 0;
    u8 count = 0;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active != 0) count++;
        i++;
    }
    return count;
}
entity_create

Reserviert eine Entity mit Typ und Position; liefert ihre wiederverwendbare ID oder bei vollem Pool 0xFF.

Syntax

c
u8 entity_create(u8 type, s16 x, s16 y);

Parameter

type

Vom Spiel definierte Typkennung von 0 bis 255. Der Pool speichert sie, wählt damit aber weder Verhalten noch Zeichenroutinen aus.

x, y

Vorzeichenbehaftete 16-Bit-Koordinaten (-32768–32767). Die Einheit bestimmt das Spiel, etwa Pixel oder Q8.8. Der Pool rechnet keine Einheiten um, begrenzt keine Positionen und wendet Geschwindigkeiten nicht automatisch an.

Rückgabewert

Die kleinste freie Platz-ID (0–ENTITY_MAX-1) oder 0xFF, falls keiner frei ist. Erfolgreiche Belegung setzt active=1, speichert Typ und Position, löscht Geschwindigkeit/Zustand/Timer und setzt sprite=0xFF.

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Anwendungsbeispiel

c
first = entity_create(1, 2, 12);
second = entity_create(2, 6, 12);
if (first == 0xFF || second == 0xFF) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_create: DMG
DMG
entity_create: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:29

Deklarationshinweise im Original
Returns a reusable slot ID, or 0xFF if no slot is free.

kitaqgb/lib/entity.c:33

c
u8 entity_create(u8 type, s16 x, s16 y)
{
    u8 i = 0;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active == 0) {
            entity_pool[i].active = 1;
            entity_pool[i].type = type;
            entity_pool[i].x = x;
            entity_pool[i].y = y;
            entity_pool[i].vx = 0;
            entity_pool[i].vy = 0;
            entity_pool[i].state = 0;
            entity_pool[i].timer = 0;
            entity_pool[i].sprite = 0xFF;
            return i;
        }
        i++;
    }
    return 0xFF;
}
entity_destroy

Gibt den Platz von Entity id frei; die Nutzdaten werden erst bei erneuter Belegung zurückgesetzt.

Syntax

c
void entity_destroy(u8 id);

Parameter

id

Wiederverwendbarer Platzindex von 0 bis ENTITY_MAX-1. Werte außerhalb dieses Bereichs sind ungültig. Das Freigeben einer ungültigen ID bewirkt nichts; die Abfrage liefert null.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Freigeben löscht nur active, nicht die übrigen Felder, Sprites oder Assets. Spätere Belegung kann dieselbe ID und Adresse für eine andere Entity verwenden. Das Spiel muss die zugehörigen Ressourcen selbst aufräumen.

Anwendungsbeispiel

c
entity_destroy(first);
after_free = entity_count_active();
if (entity_get(first) != 0 || after_free != 1) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_destroy: DMG
DMG
entity_destroy: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:32

Deklarationshinweise im Original
Release a valid slot without clearing its payload. Reallocation resets the payload;
a saved pointer or ID must not be treated as a persistent entity identity.

kitaqgb/lib/entity.c:56

c
void entity_destroy(u8 id)
{
    if (id >= ENTITY_MAX) return;
    // Deactivation only releases this pool slot; the caller handles sprite/resource cleanup.
    entity_pool[id].active = 0;
}
entity_draw_all

Durchläuft aktive Entities und übergibt jede ID an den Zeichen-Callback. Der Durchlauf entspricht entity_update_all; ohne vom Callback eingereichte Zeichendaten werden keine Sprites oder Pixel gezeichnet.

Syntax

c
void entity_draw_all(EntityFn fn);

Parameter

fn

Funktionszeiger mit Signatur void fn(u8 id). Er erhält eine Platz-ID; auf Felder greifen Sie über entity_get(id) zu. Null ist zulässig und führt zu keinen Aufrufen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Der Durchlauf prüft die Aktivität erst beim Erreichen eines Platzes. Ein Callback kann spätere Plätze deaktivieren und damit überspringen lassen oder aktivieren und noch im selben Durchlauf besuchen lassen. Es wird kein Schnappschuss der anfänglichen Belegung verwendet.

Anwendungsbeispiel

c
void demo_draw(u8 id) {
    Entity* entity;
    entity = entity_get(id);
    if (entity != 0) {
        m_put((u8)entity->x, (u8)entity->y, (u8)('A' + entity->type - 1));
        draw_calls++;
    }
}

// From main(), after creating two entities:
draw_calls = 0;
entity_draw_all(demo_draw);
automatic_draws = draw_calls;
if (automatic_draws != 2) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_draw_all: DMG
DMG
entity_draw_all: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:39

Deklarationshinweise im Original
Use the same active-slot traversal for drawing; the callback supplies all rendering.

kitaqgb/lib/entity.c:87

c
void entity_draw_all(EntityFn fn)
{
    entity_update_all(fn);
}
entity_get

Liefert einen Zeiger auf die aktive Entity oder null bei ungültiger bzw. freier ID. Der Speicherplatz wird wiederverwendet.

Syntax

c
Entity* entity_get(u8 id);

Parameter

id

Wiederverwendbarer Platzindex von 0 bis ENTITY_MAX-1. Werte außerhalb dieses Bereichs sind ungültig. Das Freigeben einer ungültigen ID bewirkt nichts; die Abfrage liefert null.

Rückgabewert

Schreibbarer Zeiger auf den aktiven Pool-Platz oder null bei ungültiger bzw. inaktiver ID. Der Speicher gehört dem Pool; geben Sie ihn nicht selbst frei und verwenden Sie den Zeiger nicht als dauerhafte Identität über Freigabe und Neubelegung hinweg.

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Freigeben löscht nur active, nicht die übrigen Felder, Sprites oder Assets. Spätere Belegung kann dieselbe ID und Adresse für eine andere Entity verwenden. Das Spiel muss die zugehörigen Ressourcen selbst aufräumen.

Anwendungsbeispiel

c
current_entity = entity_get(first);
if (current_entity != 0) { current_entity->vx = 5; }
else { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_get: DMG
DMG
entity_get: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:34

Deklarationshinweise im Original
Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.

kitaqgb/lib/entity.c:65

c
Entity* entity_get(u8 id)
{
    if (id >= ENTITY_MAX) return 0;
    if (entity_pool[id].active == 0) return 0;
    return &entity_pool[(__safe_index u8)id];
}
entity_init

Initialisiert alle Plätze im Entity-Pool.

Syntax

c
void entity_init();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Setzt in allen Plätzen active,type,x,y,vx,vy,state,timer auf null und sprite auf 0xFF. Hardware-Sprites werden dadurch weder verborgen noch freigegeben; ihre Ressourcen müssen separat aufgeräumt werden.

Anwendungsbeispiel

c
entity_init();
if (entity_count_active() != 0) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_init: DMG
DMG
entity_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:27

Deklarationshinweise im Original
Reset every slot before the game starts using the pool.

kitaqgb/lib/entity.c:8

c
void entity_init()
{
    entity_clear_all();
}
entity_update_all

Durchläuft aktive Plätze nach aufsteigender ID und ruft für jeden einmal fn(id) auf. Bewegung, Kollisionen oder Timer implementiert der Callback; der Pool stellt diese Logik nicht bereit. Ein null-Callback bewirkt nichts.

Syntax

c
void entity_update_all(EntityFn fn);

Parameter

fn

Funktionszeiger mit Signatur void fn(u8 id). Er erhält eine Platz-ID; auf Felder greifen Sie über entity_get(id) zu. Null ist zulässig und führt zu keinen Aufrufen.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Der Pool ist ein festes Array ohne Heap-Allokation. ENTITY_MAX ist standardmäßig 16 und muss in allen Übersetzungseinheiten gleich mit einem Wert von 1 bis 255 definiert sein. IDs beginnen bei null; 0xFF kennzeichnet einen Fehlschlag.

Der Durchlauf prüft die Aktivität erst beim Erreichen eines Platzes. Ein Callback kann spätere Plätze deaktivieren und damit überspringen lassen oder aktivieren und noch im selben Durchlauf besuchen lassen. Es wird kein Schnappschuss der anfänglichen Belegung verwendet.

Anwendungsbeispiel

c
void demo_update(u8 id) {
    Entity* entity;
    entity = entity_get(id);
    if (entity != 0) { entity->x = entity->x + 1; update_calls++; }
}

// From main(), after creating two entities:
update_calls = 0;
entity_update_all(demo_update);
automatic_updates = update_calls;
if (automatic_updates != 2) { failures++; }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt den Lebenszyklus eines wiederverwendbaren Platzes. Lesen Sie Zahlen mit ihren Beschriftungen: CREATED 002 nach zwei Belegungen, AFTER FREE 001 nach Freigabe der ersten, REUSED ID 000 bei Wiederverwendung der kleinsten freien ID und AFTER CLEAR 000 nach Leeren des Pools. Geprüft werden auch null-Abfrage nach Freigabe und zurückgesetzte Felder nach Neubelegung. FAILED CHECKS 000 bestätigt die erwarteten Werte.

Der GB-Durchlauf ruft jeden Callback für beide aktiven Entities auf: UPDATE CALLS 002 und DRAW CALLS 002. Der Aktualisierungs-Callback verschiebt beide um ein Tile nach rechts. Der Zeichen-Callback setzt zur Darstellung der Objekte A auf Tile (3,12) und B auf (7,12). Das sind vom Callback gezeichnete Hintergrund-Schrift-Tiles, keine automatisch belegten Sprites.

entity_update_all: DMG
DMG
entity_update_all: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementierung und Quelltext

kitaqgb/lib/entity.h:37

Deklarationshinweise im Original
Call fn for each slot that is active when the scan reaches it; null is a no-op.
Callbacks may change the pool, so newly activated later slots can run in this pass.

kitaqgb/lib/entity.c:74

c
void entity_update_all(EntityFn fn)
{
    u8 i = 0;
    if (fn == 0) return;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active != 0) {
            fn(i);
        }
        i++;
    }
}

fixed.h — Q8.8-Festkommaarithmetik und Rechtecke

Q8.8-Arithmetik stellt gebrochene Koordinaten und Geschwindigkeiten mit Ganzzahlen dar und ergänzt sie um Kollisionsprüfungen für Rechtecke und Punkte. Beachten Sie die Genauigkeit und Wertebereiche jeder Operation.

fix_div

Dividiert Q8.8-Werte nach einer Verringerung der Operandengenauigkeit.

Syntax

c
fix8 fix_div(fix8 a, fix8 b);

Parameter

a

Linker Operand im Q8.8-Format.

b

Rechter Operand im Q8.8-Format.

Rückgabewert

Gibt einen Q8.8-Quotienten zurück, bei b == 0 hingegen null.

Bedingungen und Grenzen

Berechnet wird ((a >> 4) * 256) / (b >> 4). Ein von null verschiedener Divisor darf durch die Verschiebung nicht null werden; übergeben Sie daher keine positiven Rohwerte von 1 bis 15. Auch der skalierte Zähler muss in 16 Bits passen.

Anwendungsbeispiel

c
result[3]=fix_div(768,512);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

3,0 geteilt durch 2,0 ergibt 1,5 (Rohwert 384). Ein eigener Test prüft den ausdrücklich vorgesehenen Rückgabewert bei Divisor null.

fix_div: DMG
DMG
fix_div: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:32

Deklarationshinweise im Original
Scale the reduced-precision quotient back to 8.8 and return zero for b == 0.
Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b.
The intermediate product must fit the compiler's integer arithmetic.

kitaqgb/lib/fixed.c:26

c
fix8 fix_div(fix8 a, fix8 b)
{
    if (b == 0) return 0;
    return (fix8)(((a >> 4) * 256) / (b >> 4));
}
fix_from_int

Wandelt eine ganzzahlige Koordinate oder Geschwindigkeit in Q8.8 um, damit nachfolgende Berechnungen Nachkommastellen erhalten können.

Syntax

c
fix8 fix_from_int(s16 n);

Parameter

n

Die umzuwandelnde ganze Zahl im Bereich −128 bis 127.

Rückgabewert

Gibt den Rohwert n × 256 zurück.

Bedingungen und Grenzen

fix8 ist ein vorzeichenbehaftetes Q8.8-Format: Der Rohwert 256 steht für 1,0. Zwischenwerte und Ergebnisse müssen im 16-Bit-Wertebereich bleiben.

Anwendungsbeispiel

c
result[0]=fix_from_int(-3);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel wandelt −3 um. Die Anzeige −00768 entspricht dem Q8.8-Rohwert −768.

fix_from_int: DMG
DMG
fix_from_int: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:23

Deklarationshinweise im Original
Convert an integer to signed 8.8 fixed point by moving it into the high byte.
The caller must keep the result within the representable 16-bit range.

kitaqgb/lib/fixed.c:5

c
fix8 fix_from_int(s16 n)
{
    return (fix8)(n << 8);
}
fix_lerp

Interpoliert mit einem 8-Bit-Gewicht von einem Q8.8-Wert in Richtung eines anderen.

Syntax

c
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);

Parameter

a

Linker Operand im Q8.8-Format.

b

Rechter Operand im Q8.8-Format.

t_q8

Interpolationsgewicht von 0 bis 255.

Rückgabewert

Gibt den näherungsweise interpolierten Q8.8-Wert zurück.

Bedingungen und Grenzen

Differenz und Gewicht werden jeweils um vier Bits nach rechts geschoben. Dadurch gibt es nur 16 Gewichtsstufen; selbst 255 muss den Endwert nicht erreichen. b - a und das Endergebnis müssen im 16-Bit-Bereich bleiben.

Anwendungsbeispiel

c
result[4]=fix_lerp(0,1024,128);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Zwischen 0 und 4,0 ergibt Gewicht 128 den Wert 2,0 (Rohwert 512). Gewicht 255 liefert 3,75 (Rohwert 960) und zeigt damit, dass der Endwert nicht erreicht wird.

fix_lerp: DMG
DMG
fix_lerp: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:35

Deklarationshinweise im Original
Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low
bits, so small changes may vanish and a weight of 255 need not reach b.

kitaqgb/lib/fixed.c:34

c
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8)
{
    // The endpoint difference must fit s16 before the reduced-precision multiplication.
    fix8 d = (fix8)(b - a);
    return (fix8)(a + (fix8)((d >> 4) * (s16)(t_q8 >> 4)));
}
fix_mul

Multipliziert zwei Q8.8-Werte mit einem rechenarmen Näherungsverfahren.

Syntax

c
fix8 fix_mul(fix8 a, fix8 b);

Parameter

a

Linker Operand im Q8.8-Format.

b

Rechter Operand im Q8.8-Format.

Rückgabewert

Gibt das Produkt im Q8.8-Format zurück.

Bedingungen und Grenzen

Vor der Multiplikation wird jeder Operand um vier Bits nach rechts geschoben; seine vier niederwertigsten Bits gehen verloren. Das ist ungenauer als ein vollständiges 16-mal-16-Bit-Produkt. fix8 ist vorzeichenbehaftetes Q8.8, wobei der Rohwert 256 für 1,0 steht. Zwischenwerte und Ergebnisse müssen im 16-Bit-Bereich bleiben.

Anwendungsbeispiel

c
result[2]=fix_mul(384,512);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

1,5 mal 2,0 ergibt 3,0 (Rohwert 768). Das Programm prüft auch die Quantisierung: Rohwert 271 mal Rohwert 271 ergibt 256.

fix_mul: DMG
DMG
fix_mul: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:28

Deklarationshinweise im Original
Approximate 8.8 multiplication by discarding four low bits from each operand
before multiplying. This trades precision for a smaller intermediate product.

kitaqgb/lib/fixed.c:18

c
fix8 fix_mul(fix8 a, fix8 b)
{
    return (fix8)((a >> 4) * (b >> 4));
}
fix_to_int

Gewinnt eine ganzzahlige Koordinate aus Q8.8, indem die Nachkommabits verworfen werden. Negative Werte werden gegen minus unendlich abgerundet.

Syntax

c
s16 fix_to_int(fix8 x);

Parameter

x

Der in eine ganze Zahl umzuwandelnde Q8.8-Wert.

Rückgabewert

Gibt eine vorzeichenbehaftete ganze Zahl zurück.

Bedingungen und Grenzen

fix8 ist ein vorzeichenbehaftetes Q8.8-Format: Der Rohwert 256 steht für 1,0. Zwischenwerte und Ergebnisse müssen im 16-Bit-Wertebereich bleiben.

Anwendungsbeispiel

c
result[1]=fix_to_int(-384);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Rohwert −384 (−1,5) ergibt −2 und wird als −00002 angezeigt. Ein Grenzwerttest bestätigt außerdem, dass der Rohwert −1 zu −1 wird.

fix_to_int: DMG
DMG
fix_to_int: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:25

Deklarationshinweise im Original
Discard the eight fractional bits using a signed right shift.

kitaqgb/lib/fixed.c:11

c
s16 fix_to_int(fix8 x)
{
    return (s16)(x >> 8);
}
kq_abs_s16

Ermittelt den Betrag eines vorzeichenbehafteten 16-Bit-Werts.

Syntax

c
s16 kq_abs_s16(s16 v);

Parameter

v

Vorzeichenbehafteter 16-Bit-Wert, dessen Betrag benötigt wird.

Rückgabewert

Gibt einen nichtnegativen Betrag zurück, mit Ausnahme des nicht darstellbaren Betrags von −32768.

Bedingungen und Grenzen

Der positive Betrag 32768 passt nicht in s16. Schließen Sie −32768 aus, wenn das Ergebnis nichtnegativ sein muss.

Anwendungsbeispiel

c
result[0]=kq_abs_s16(-123);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel wandelt −123 in 123 um, etwa zur Bestimmung des Betrags einer Koordinatendifferenz.

kq_abs_s16: DMG
DMG
kq_abs_s16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:38

Deklarationshinweise im Original
Return the magnitude in s16. The most-negative s16 has no positive s16
representation and must be excluded by callers needing a nonnegative result.

kitaqgb/lib/fixed.c:43

c
s16 kq_abs_s16(s16 v)
{
    if (v < 0) return (s16)(0 - v);
    return v;
}
kq_clamp_s16

Begrenzt eine Koordinate oder Geschwindigkeit auf ein Intervall einschließlich seiner Grenzen.

Syntax

c
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);

Parameter

v

Zu begrenzender Wert mit Vorzeichen.

lo

Einschließlich geltende Untergrenze.

hi

Einschließlich geltende Obergrenze.

Rückgabewert

Gibt unterhalb des Intervalls lo, oberhalb hi und innerhalb v zurück.

Bedingungen und Grenzen

Geben Sie ein gültiges Intervall mit lo <= hi an.

Anwendungsbeispiel

c
result[3]=kq_clamp_s16(25,-10,10);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Begrenzen von 25 auf −10…10 ergibt 10. Geprüft werden auch −11→−10 an der unteren Grenze und 3→3 innerhalb des Intervalls.

kq_clamp_s16: DMG
DMG
kq_clamp_s16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:44

Deklarationshinweise im Original
Clamp to an inclusive interval; callers must provide lo <= hi.

kitaqgb/lib/fixed.c:64

c
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi)
{
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
}
kq_max_s16

Wählt den größeren von zwei vorzeichenbehafteten 16-Bit-Werten.

Syntax

c
s16 kq_max_s16(s16 a, s16 b);

Parameter

a

Erster zu vergleichender Wert mit Vorzeichen.

b

Zweiter zu vergleichender Wert mit Vorzeichen.

Rückgabewert

Gibt den ausgewählten Operanden zurück.

Bedingungen und Grenzen

Der Vergleich berücksichtigt das Vorzeichen. Bei gleichen Operanden wird dieser gemeinsame Wert zurückgegeben; beide Eingaben bleiben unverändert.

Anwendungsbeispiel

c
result[2]=kq_max_s16(-7,4);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Vergleich von −7 und 4 ergibt 4. Negative Ergebnisse werden mit Minuszeichen angezeigt.

kq_max_s16: DMG
DMG
kq_max_s16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:42

Deklarationshinweise im Original
Select the larger signed value.

kitaqgb/lib/fixed.c:57

c
s16 kq_max_s16(s16 a, s16 b)
{
    if (a > b) return a;
    return b;
}
kq_min_s16

Wählt den kleineren von zwei vorzeichenbehafteten 16-Bit-Werten.

Syntax

c
s16 kq_min_s16(s16 a, s16 b);

Parameter

a

Erster zu vergleichender Wert mit Vorzeichen.

b

Zweiter zu vergleichender Wert mit Vorzeichen.

Rückgabewert

Gibt den ausgewählten Operanden zurück.

Bedingungen und Grenzen

Der Vergleich berücksichtigt das Vorzeichen. Bei gleichen Operanden wird dieser gemeinsame Wert zurückgegeben; beide Eingaben bleiben unverändert.

Anwendungsbeispiel

c
result[1]=kq_min_s16(-7,4);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der Vergleich von −7 und 4 ergibt -7. Negative Ergebnisse werden mit Minuszeichen angezeigt.

kq_min_s16: DMG
DMG
kq_min_s16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:40

Deklarationshinweise im Original
Select the smaller signed value.

kitaqgb/lib/fixed.c:50

c
s16 kq_min_s16(s16 a, s16 b)
{
    if (a < b) return a;
    return b;
}
kq_point_in_rect

Prüft, ob ein Punkt im Rechteck liegt; linke und obere Kante sind eingeschlossen.

Syntax

c
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);

Parameter

x

X-Koordinate des Punkts im Koordinatensystem des Rechtecks.

y

Y-Koordinate des Punkts.

r

Zu prüfendes Rechteck, als Wert übergeben.

Rückgabewert

Gibt innen 1 und außen 0 zurück.

Bedingungen und Grenzen

Verwenden Sie positive Abmessungen; Koordinate plus Größe muss als s16 darstellbar bleiben. Rechte und untere Kante sind ausgeschlossen. Rechtecke mit Fläche null werden nicht ausdrücklich abgewiesen.

Anwendungsbeispiel

c
result[1]=kq_point_in_rect(9,1,a);
for(gy=0;gy<11;gy++){for(gx=0;gx<15;gx++){
inside_a=kq_point_in_rect(gx,gy,a);inside_b=kq_point_in_rect(gx,gy,b);
tile=0;if(inside_a){tile=65;result[3]=result[3]+1;}if(inside_b)tile=66;if(inside_a && inside_b){tile=79;result[4]=result[4]+1;}
m_put(1+gx,2+gy,tile);if(tile!=0)vram_example_color(1+gx,2+gy,1,1,tile==65?1:(tile==66?2:3));
}}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Jede Koordinateneinheit entspricht einer Kachel. Rechteck A bei (1,1) und B bei (5,4) sind jeweils 8×6 groß. Nur von A belegte Zellen zeigen A, nur von B belegte zeigen B, und die 4×3 große Überlappung zeigt zwölf O-Zellen. Die rechte Kante von A bei x=9 zählt nicht dazu. Auf dem CGB ist A rot, B blau und O grün.

kq_point_in_rect: DMG
DMG
kq_point_in_rect: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:51

Deklarationshinweise im Original
Test a half-open rectangle: left/top edges are included, right/bottom excluded.
The coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/fixed.c:85

c
u8 kq_point_in_rect(s16 x, s16 y, KQRect r)
{
    if (x < r.x) return 0;
    if (y < r.y) return 0;
    if (x >= (s16)(r.x + r.w)) return 0;
    if (y >= (s16)(r.y + r.h)) return 0;
    return 1;
}
kq_rect_intersect

Prüft, ob sich zwei achsenparallele Rechtecke mit positiver Fläche überschneiden.

Syntax

c
u8 kq_rect_intersect(KQRect a, KQRect b);

Parameter

a

Erstes Rechteck, als Wert übergeben: x, y geben die linke obere Ecke an, w, h seine Breite und Höhe.

b

Zweites Rechteck im selben Koordinatensystem wie A.

Rückgabewert

Gibt bei Überschneidung 1 zurück, bei Trennung oder bloßer Kantenberührung 0.

Bedingungen und Grenzen

Verwenden Sie positive Abmessungen; Koordinate plus Größe muss als s16 darstellbar bleiben. Rechte und untere Kante sind ausgeschlossen. Rechtecke mit Fläche null werden nicht ausdrücklich abgewiesen.

Anwendungsbeispiel

c
result[0]=kq_rect_intersect(a,b);result[2]=kq_rect_intersect(a,touch);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Jede Koordinateneinheit entspricht einer Kachel. Rechteck A bei (1,1) und B bei (5,4) sind jeweils 8×6 groß. Nur von A belegte Zellen zeigen A, nur von B belegte zeigen B, und die 4×3 große Überlappung zeigt zwölf O-Zellen. Die rechte Kante von A bei x=9 zählt nicht dazu. Auf dem CGB ist A rot, B blau und O grün.

kq_rect_intersect: DMG
DMG
kq_rect_intersect: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/fixed.h:48

Deklarationshinweise im Original
Test overlap using exclusive right/bottom edges; touching edges do not collide.
Require positive dimensions and edge sums that fit s16; zero-sized rectangles
are not explicitly rejected and may be reported as overlapping.

kitaqgb/lib/fixed.c:74

c
u8 kq_rect_intersect(KQRect a, KQRect b)
{
    if ((s16)(a.x + a.w) <= b.x) return 0;
    if ((s16)(b.x + b.w) <= a.x) return 0;
    if ((s16)(a.y + a.h) <= b.y) return 0;
    if ((s16)(b.y + b.h) <= a.y) return 0;
    return 1;
}

input.h — Tastenzustand, Drücken, Loslassen und Wiederholung

Verwende input_down für fortlaufende Bewegung, input_pressed für einmalige Aktionen, input_released für Aktionen beim Loslassen und input_repeat für Menüs mit Tastenwiederholung. Einmal initialisieren, einmal pro Eingabetakt aktualisieren, danach beliebig oft abfragen. btn_down, btn_pressed, btn_released und btn_repeat sind Aliase dieser vier Abfragen.

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Die Intervalle zählen Updates, keine Millisekunden. Ein neuer Tastendruck erzeugt sofort einen Impuls. Bei INPUT_REPEAT_DELAY=18 und INPUT_REPEAT_RATE=5 folgt der nächste nach 19 Updates, weitere jeweils nach 6. Jede Taste hat einen eigenen Zähler. Die Makros müssen auch beim Kompilieren von input.c entsprechend gesetzt sein; nur den Header des aufrufenden Codes zu ändern, konfiguriert die Bibliothek nicht um.

btn_down

btn_down ist ein Alias für input_down. Prüft, ob mindestens eine der ausgewählten Tasten gerade gehalten wird.

Prüft, ob eine durch mask gewählte Taste gerade gehalten wird.

Syntax

c
u8 btn_down(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

input_down

Anwendungsbeispiel

c
if (btn_down(BTN_A)!=0) held_ticks++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

btn_down: DMG
DMG
btn_down: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:48

c
#define btn_down input_down

kitaqgb/lib/input.c:68

c
u8 input_down(u8 mask)
{
    return (u8)((kq_input_keys & mask) != 0);
}
btn_pressed

btn_pressed ist ein Alias für input_pressed. Prüft, ob bei der letzten Eingabeaktualisierung mindestens eine ausgewählte Taste neu gedrückt wurde.

Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung neu gedrückt wurde.

Syntax

c
u8 btn_pressed(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

input_pressed

Anwendungsbeispiel

c
if (btn_pressed(BTN_A)!=0) {
        press_count++; seen_press=1;
        first_down=btn_down(BTN_A); first_press=btn_pressed(BTN_A);
        first_repeat=btn_repeat(BTN_A);
        first_current=input_current(); // Only A held: BTN_A, or decimal 16.
        first_previous=input_previous(); // No buttons in the preceding sample: 0.
        if (first_down!=1 || first_press!=1 || first_repeat!=1) failures++;
        if (first_current!=BTN_A || first_previous!=0) failures++;
        if (btn_down(BTN_A|BTN_B)!=1 || btn_down(0)!=0) failures++;
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

btn_pressed: DMG
DMG
btn_pressed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:49

c
#define btn_pressed input_pressed

kitaqgb/lib/input.c:74

c
u8 input_pressed(u8 mask)
{
    return (u8)((kq_input_press_keys & mask) != 0);
}
btn_released

btn_released ist ein Alias für input_released. Prüft, ob bei der letzten Eingabeaktualisierung mindestens eine ausgewählte Taste losgelassen wurde.

Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung losgelassen wurde.

Syntax

c
u8 btn_released(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

input_released

Anwendungsbeispiel

c
if (btn_released(BTN_A)!=0) {
        release_result=btn_released(BTN_A);
        last_current=input_current(); last_previous=input_previous();
        if (btn_down(BTN_A)!=0 || btn_pressed(BTN_A)!=0 || btn_repeat(BTN_A)!=0) failures++;
        break;
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

btn_released: DMG
DMG
btn_released: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:50

c
#define btn_released input_released

kitaqgb/lib/input.c:80

c
u8 input_released(u8 mask)
{
    return (u8)((kq_input_release_keys & mask) != 0);
}
btn_repeat

btn_repeat ist ein Alias für input_repeat. Prüft auf den ersten Tastendruck oder einen vorgesehenen Wiederholungsimpuls bei gehaltener Taste.

Prüft auf erstmaligen Tastendruck oder einen Wiederholungsimpuls einer maskierten Taste.

Syntax

c
u8 btn_repeat(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Die Intervalle zählen Updates, keine Millisekunden. Ein neuer Tastendruck erzeugt sofort einen Impuls. Bei INPUT_REPEAT_DELAY=18 und INPUT_REPEAT_RATE=5 folgt der nächste nach 19 Updates, weitere jeweils nach 6. Jede Taste hat einen eigenen Zähler. Die Makros müssen auch beim Kompilieren von input.c entsprechend gesetzt sein; nur den Header des aufrufenden Codes zu ändern, konfiguriert die Bibliothek nicht um.

input_repeat

Anwendungsbeispiel

c
if (btn_repeat(BTN_A)!=0) {
        // The initial press is pulse 1. Defaults then wait 19 updates, followed by 6.
        if (repeat_count==1 && held_ticks-previous_pulse!=19) failures++;
        if (repeat_count>1 && held_ticks-previous_pulse!=6) failures++;
        previous_pulse=held_ticks; repeat_count++;
        if (btn_repeat(BTN_A)!=1) failures++; // Reading again does not consume it.
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

btn_repeat: DMG
DMG
btn_repeat: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:51

c
#define btn_repeat input_repeat

kitaqgb/lib/input.c:86

c
u8 input_repeat(u8 mask)
{
    return (u8)((kq_input_repeat_keys & mask) != 0);
}
input_current

Liefert die vollständige Maske gehaltener Tasten der letzten Aktualisierung.

Syntax

c
u8 input_current();

Rückgabewert

Eine 8-Bit-Maske im gemeinsamen BTN_*-Format. Mehrere Tasten können zugleich gesetzt sein; 0 bedeutet keine.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Anwendungsbeispiel

c
first_current=input_current(); // Only A held: BTN_A, or decimal 16.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_current: DMG
DMG
input_current: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:44

Deklarationshinweise im Original
Return the complete held-button mask from the latest update.

kitaqgb/lib/input.c:92

c
u8 input_current()
{
    return kq_input_keys;
}
input_down

Prüft, ob eine durch mask gewählte Taste gerade gehalten wird.

Syntax

c
u8 input_down(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Anwendungsbeispiel

c
if (input_down(BTN_A)!=0) held_ticks++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_down: DMG
DMG
input_down: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:36

Deklarationshinweise im Original
Return whether any masked button is currently held.

kitaqgb/lib/input.c:68

c
u8 input_down(u8 mask)
{
    return (u8)((kq_input_keys & mask) != 0);
}
input_init

Setzt die Masken für aktuellen und vorherigen Zustand, neue Tastendrücke, Loslassen und Wiederholung auf 0 und alle acht Wiederholungszähler auf INPUT_REPEAT_DELAY. Liest den Controller nicht. Eine beim ersten anschließenden Update gehaltene Taste gilt als neu gedrückt.

Syntax

c
void input_init();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Die Intervalle zählen Updates, keine Millisekunden. Ein neuer Tastendruck erzeugt sofort einen Impuls. Bei INPUT_REPEAT_DELAY=18 und INPUT_REPEAT_RATE=5 folgt der nächste nach 19 Updates, weitere jeweils nach 6. Jede Taste hat einen eigenen Zähler. Die Makros müssen auch beim Kompilieren von input.c entsprechend gesetzt sein; nur den Header des aufrufenden Codes zu ändern, konfiguriert die Bibliothek nicht um.

Anwendungsbeispiel

c
input_init();
if (input_current()!=0 || input_previous()!=0) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_init: DMG
DMG
input_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:31

Deklarationshinweise im Original
Clear sampled/edge state and initialize an independent repeat timer for each button.

kitaqgb/lib/input.c:18

c
void input_init()
{
    u8 i;
    kq_input_prev_keys = 0;
    kq_input_keys = 0;
    kq_input_press_keys = 0;
    kq_input_release_keys = 0;
    kq_input_repeat_keys = 0;
    i = 0;
    while (i < 8) {
        input_repeat_timer[i] = INPUT_REPEAT_DELAY;
        i++;
    }
}
input_pressed

Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung neu gedrückt wurde.

Syntax

c
u8 input_pressed(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Anwendungsbeispiel

c
if (input_pressed(BTN_A)!=0) {
        press_count++; seen_press=1;
        first_down=input_down(BTN_A); first_press=input_pressed(BTN_A);
        first_repeat=input_repeat(BTN_A);
        first_current=input_current(); // Only A held: BTN_A, or decimal 16.
        first_previous=input_previous(); // No buttons in the preceding sample: 0.
        if (first_down!=1 || first_press!=1 || first_repeat!=1) failures++;
        if (first_current!=BTN_A || first_previous!=0) failures++;
        if (input_down(BTN_A|BTN_B)!=1 || input_down(0)!=0) failures++;
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_pressed: DMG
DMG
input_pressed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:38

Deklarationshinweise im Original
Return whether any masked button became pressed in the latest sample.

kitaqgb/lib/input.c:74

c
u8 input_pressed(u8 mask)
{
    return (u8)((kq_input_press_keys & mask) != 0);
}
input_previous

Liefert die gespeicherte Tastenmaske vor der letzten Eingabeaktualisierung.

Syntax

c
u8 input_previous();

Rückgabewert

Eine 8-Bit-Maske im gemeinsamen BTN_*-Format. Mehrere Tasten können zugleich gesetzt sein; 0 bedeutet keine.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Anwendungsbeispiel

c
first_previous=input_previous(); // No buttons in the preceding sample: 0.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_previous: DMG
DMG
input_previous: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:46

Deklarationshinweise im Original
Return the held-button mask that preceded the latest update.

kitaqgb/lib/input.c:98

c
u8 input_previous()
{
    return kq_input_prev_keys;
}
input_released

Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung losgelassen wurde.

Syntax

c
u8 input_released(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Anwendungsbeispiel

c
if (input_released(BTN_A)!=0) {
        release_result=input_released(BTN_A);
        last_current=input_current(); last_previous=input_previous();
        if (input_down(BTN_A)!=0 || input_pressed(BTN_A)!=0 || input_repeat(BTN_A)!=0) failures++;
        break;
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_released: DMG
DMG
input_released: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:40

Deklarationshinweise im Original
Return whether any masked button became released in the latest sample.

kitaqgb/lib/input.c:80

c
u8 input_released(u8 mask)
{
    return (u8)((kq_input_release_keys & mask) != 0);
}
input_repeat

Prüft auf erstmaligen Tastendruck oder einen Wiederholungsimpuls einer maskierten Taste.

Syntax

c
u8 input_repeat(u8 mask);

Parameter

mask

Eine BTN_*-Maske oder mehrere mit | verknüpfte Masken. Eine einzige passende Taste genügt; BTN_A | BTN_B verlangt nicht beide zugleich. Maske 0 liefert immer 0. Alle gehaltenen Tasten prüfst du mit (input_current() & mask) == mask.

Rückgabewert

Genau 1, wenn mindestens eine gewählte Taste die abgefragte Bedingung erfüllt, sonst 0. Der Rückgabewert ist keine Tastenmaske.

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Abfragen lesen den letzten input_update()-Zustand, ohne erneut abzufragen, ein Ereignis zu verbrauchen oder einen Zähler weiterzuführen. Mehrfache Abfragen im selben Takt liefern dasselbe Ergebnis. Bei zweimaligem input_update() mit gehaltener Taste ist das neue Druckereignis im zweiten Aufruf gelöscht.

Die Intervalle zählen Updates, keine Millisekunden. Ein neuer Tastendruck erzeugt sofort einen Impuls. Bei INPUT_REPEAT_DELAY=18 und INPUT_REPEAT_RATE=5 folgt der nächste nach 19 Updates, weitere jeweils nach 6. Jede Taste hat einen eigenen Zähler. Die Makros müssen auch beim Kompilieren von input.c entsprechend gesetzt sein; nur den Header des aufrufenden Codes zu ändern, konfiguriert die Bibliothek nicht um.

Anwendungsbeispiel

c
if (input_repeat(BTN_A)!=0) {
        // The initial press is pulse 1. Defaults then wait 19 updates, followed by 6.
        if (repeat_count==1 && held_ticks-previous_pulse!=19) failures++;
        if (repeat_count>1 && held_ticks-previous_pulse!=6) failures++;
        previous_pulse=held_ticks; repeat_count++;
        if (input_repeat(BTN_A)!=1) failures++; // Reading again does not consume it.
    }

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_repeat: DMG
DMG
input_repeat: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:42

Deklarationshinweise im Original
Return whether any masked button produced a fresh press or scheduled repeat pulse.

kitaqgb/lib/input.c:86

c
u8 input_repeat(u8 mask)
{
    return (u8)((kq_input_repeat_keys & mask) != 0);
}
input_update

Speichert die aktuelle Maske als vorherigen Zustand, liest die Game-Boy-Tasten mit __readpadex, ermittelt losgelassene Tasten und führt jeden unabhängigen Wiederholungszähler um einen Schritt weiter. Einmal pro Eingabetakt aufrufen, danach den gespeicherten Zustand abfragen.

Syntax

c
void input_update();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Gemeinsame Masken: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Ein gesetztes Bit bedeutet gedrückt. input_* verwendet dieses Format auf GB und FC; rohe FC-Pad-Abfragen verwenden eine andere Bitreihenfolge.

Die Intervalle zählen Updates, keine Millisekunden. Ein neuer Tastendruck erzeugt sofort einen Impuls. Bei INPUT_REPEAT_DELAY=18 und INPUT_REPEAT_RATE=5 folgt der nächste nach 19 Updates, weitere jeweils nach 6. Jede Taste hat einen eigenen Zähler. Die Makros müssen auch beim Kompilieren von input.c entsprechend gesetzt sein; nur den Header des aufrufenden Codes zu ändern, konfiguriert die Bibliothek nicht um.

Anwendungsbeispiel

c
input_update(); // One update per input tick, followed by any number of queries.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Programm zeigt den Unterschied zwischen einer gehaltenen Taste, einem neuen Tastendruck, dem Loslassen und der automatischen Wiederholung. Halten Sie A für 40 Aktualisierungen gedrückt und lassen Sie die Taste dann los. FIRST DOWN, FIRST PRESS und FIRST REPEAT sind 1; FIRST CURRENT ist 16. HELD TICKS ist 40, PRESS COUNT ist 1 und REPEAT COUNT ist 5. Beim Loslassen ist RELEASE 1, LAST CURRENT 0 und LAST PREVIOUS 16. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Zähler; das Programm prüft die Wiederholungsabstände anhand der tatsächlich beobachteten Dauer.

input_update: DMG
DMG
input_update: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementierung und Quelltext

kitaqgb/lib/input.h:34

Deklarationshinweise im Original
Sample input once per game tick and derive press, release and repeat masks.
Repeat delays are measured in calls to this function, not elapsed wall-clock time.

kitaqgb/lib/input.c:35

c
void input_update()
{
    u8 i;
    u16 kt;

    kq_input_prev_keys = kq_input_keys;
    // The intrinsic packs held buttons in the low byte and new presses in the high byte.
    kt = __readpadex(kq_input_prev_keys);
    kq_input_keys = (u8)kt;
    kq_input_press_keys = (u8)(kt >> 8);
    kq_input_release_keys = (u8)(kq_input_prev_keys & (u8)(kq_input_keys ^ 0xFF));
    kq_input_repeat_keys = kq_input_press_keys;

    i = 0;
    while (i < 8) {
        u8 mask = input_mask_for_index(i);
        if ((kq_input_keys & mask) != 0) {
            if ((kq_input_press_keys & mask) != 0) {
                input_repeat_timer[i] = INPUT_REPEAT_DELAY;
            } else if (input_repeat_timer[i] != 0) {
                input_repeat_timer[i]--;
            } else {
                kq_input_repeat_keys = (u8)(kq_input_repeat_keys | mask);
                input_repeat_timer[i] = INPUT_REPEAT_RATE;
            }
        } else {
            input_repeat_timer[i] = INPUT_REPEAT_DELAY;
        }
        i++;
    }
}

Die Bibliothek bietet drei Ebenen: Byteaustausch, Pakete mit bis zu 24 Bytes und Warteschlangen pro Gegenstelle. Beginnen Sie mit BYTE MASTER/SLAVE, danach PACKET und LINK4, um Taktzuständigkeit und Empfangsbereitschaft kennenzulernen. Binden Sie die Hardwareregister-Einheit, link.c und link_packet.c je genau einmal in ein Programm ein. gb_link_example.h stellt diese Reihenfolge bereit.

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Fragen Sie beide Endpunkte fortlaufend ab. Ein Timeout zählt 90 Aufrufe ohne Fortschritt, keine Hardwareframes. Das Senden von 0xFF allein zur Taktversorgung eines ACK verlängert die Frist nicht; höchstens drei Sendeversuche sind erlaubt. Wiederholungen können Duplikate liefern. Ergänzen Sie Kennungen auf Anwendungsebene, wenn ein Befehl genau einmal ausgeführt werden muss.

Link4_BeginTransferTo

Wählt ein Ziel und startet anschließend einen Byteaustausch.

Syntax

c
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

out

Ausgehender Acht-Bit-Wert.

Rückgabewert

Gibt den ersten Auswahl- oder Startfehler zurück, bei Erfolg 0.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Fehlercodes: 0=kein Fehler, 1=belegt, 2=Timeout, 3=Empfangsüberlauf, 4=ungültige Konfiguration/Protokoll, 5=ACK-Timeout mit einer Antwort wie bei einer getrennten Verbindung. Start- und Konfigurationsaufrufe melden Erfolg mit 0, Empfangs- und Entnahmeaufrufe mit 1. Erfolgreiche Aufrufe löschen keinen gespeicherten Fehler.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[6+slot]=Link4_BeginTransferTo(slot,16+slot);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_BeginTransferTo: DMG
DMG
Link4_BeginTransferTo: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:129

Deklarationshinweise im Original
Select the logical peer and start a byte exchange, returning the first error.

kitaqgb/lib/link.c:584

c
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out) {
    u8 err = Link4_SelectPeer(peer_slot);
    if (err != LINK_ERR_NONE) return err;
    return Link_BeginTransfer(out);
}
Link4_GetLastRxPeer

Liest die dem letzten abgeschlossenen Byte zugeordnete Gegenstelle.

Syntax

c
u8 Link4_GetLastRxPeer();

Rückgabewert

Der Host liefert die ausgewählte Gegenstelle, eine Gegenstelle 0; vor dem ersten Empfang wird 255 geliefert.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[19]=Link4_GetLastRxPeer();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetLastRxPeer: DMG
DMG
Link4_GetLastRxPeer: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:121

Deklarationshinweise im Original
Return the peer attributed to the last completed byte transfer.

kitaqgb/lib/link.c:540

c
u8 Link4_GetLastRxPeer() {
    return Link4_LastRxPeer;
}
Link4_GetLastTxPeer

Liest das beim Start des letzten Bytetransfers gespeicherte Ziel.

Syntax

c
u8 Link4_GetLastTxPeer();

Rückgabewert

Gibt das gespeicherte Ziel zurück, vor dem ersten Start 255.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[20]=Link4_GetLastTxPeer();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetLastTxPeer: DMG
DMG
Link4_GetLastTxPeer: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:123

Deklarationshinweise im Original
Return the peer attributed when the last byte transfer was started.

kitaqgb/lib/link.c:545

c
u8 Link4_GetLastTxPeer() {
    return Link4_LastTxPeer;
}
Link4_GetLocalSlot

Liest den für dieses Gerät konfigurierten Platz.

Syntax

c
u8 Link4_GetLocalSlot();

Rückgabewert

Host ist 0, Gegenstellen sind 1 bis 3. Nicht konfiguriert ergibt ebenfalls 0.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[2]=Link4_GetLocalSlot();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetLocalSlot: DMG
DMG
Link4_GetLocalSlot: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:115

Deklarationshinweise im Original
Return the configured zero-based local slot.

kitaqgb/lib/link.c:525

c
u8 Link4_GetLocalSlot() {
    return Link4_LocalSlot;
}
Link4_GetMode

Liest die konfigurierte logische Rolle.

Syntax

c
u8 Link4_GetMode();

Rückgabewert

0=nicht konfiguriert, 1=Host, 2=Gegenstelle.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[1]=Link4_GetMode();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetMode: DMG
DMG
Link4_GetMode: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:113

Deklarationshinweise im Original
Return the configured cooperative role; this is not a hardware connection probe.

kitaqgb/lib/link.c:520

c
u8 Link4_GetMode() {
    return Link4_ModeState;
}
Link4_GetSelectedPeer

Liest das aktuell ausgewählte logische Ziel.

Syntax

c
u8 Link4_GetSelectedPeer();

Rückgabewert

Der Host liefert seine ausgewählte Gegenstelle, eine Gegenstelle 0 und der unkonfigurierte Zustand 255.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[4]=Link4_GetSelectedPeer();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetSelectedPeer: DMG
DMG
Link4_GetSelectedPeer: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:119

Deklarationshinweise im Original
Return the current logical destination, or the invalid-slot sentinel when unset.

kitaqgb/lib/link.c:535

c
u8 Link4_GetSelectedPeer() {
    return Link4_SelectedPeer;
}
Link4_GetSlotCount

Liest die konfigurierte Gesamtzahl der Plätze.

Syntax

c
u8 Link4_GetSlotCount();

Rückgabewert

Gültige Konfigurationen liefern 2 bis 4, nicht konfiguriert liefert 0.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Diese Funktionen lesen Konfiguration und Verlauf. Sie erkennen keine physischen Verbindungen, fragen nicht alle Gegenstellen ab und warten nicht auf Transferabschluss.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[3]=Link4_GetSlotCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_GetSlotCount: DMG
DMG
Link4_GetSlotCount: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:117

Deklarationshinweise im Original
Return the configured number of logical slots, not a live connection count.

kitaqgb/lib/link.c:530

c
u8 Link4_GetSlotCount() {
    return Link4_SlotCount;
}
Link4_HasByteFrom

Prüft ungelesene Daten im Empfangsring einer Gegenstelle.

Syntax

c
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

Rückgabewert

Gibt bei wartenden Daten 1 zurück, bei leerem Ring oder ungültiger Gegenstelle 0.

Bedingungen und Grenzen

Der Empfangsring mit acht Einträgen fasst sieben Bytes. Ein voller Ring verwirft das neue Byte und speichert Fehler 3. Ein empfangenes Nullbyte ist gültige Nutzlast.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Diese Abfrage liest die Hardware nicht aus; eine ungültige Gegenstelle ändert den gespeicherten Fehler nicht.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[9+slot]=Link4_HasByteFrom(slot);value=0;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_HasByteFrom: DMG
DMG
Link4_HasByteFrom: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:131

Deklarationshinweise im Original
Inspect a valid peer ring without polling the hardware.

kitaqgb/lib/link.c:591

c
u8 __stackcall Link4_HasByteFrom(u8 peer_slot) {
    if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) return 0;
    if (Link4_RxHead[(__safe_index u8)peer_slot] == Link4_RxTail[(__safe_index u8)peer_slot]) return 0;
    return 1;
}
Link4_HasPacketFrom

Prüft den Briefkasten vollständiger Pakete eines entfernten Platzes.

Syntax

c
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

Rückgabewert

Gibt bei einem ungelesenen Paket 1 zurück, bei leerem Briefkasten oder ungültiger Gegenstelle 0.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Ein Paket enthält 0xA5, Befehl, Länge, 0 bis 24 Nutzdatenbytes und eine XOR-Prüfsumme. Die Antwort ist 0x79 (ACK, angenommen) oder 0x1F (NAK, abgewiesen). Die Prüfsumme verknüpft Befehl, Länge und Nutzdaten per XOR. Jedes Gerät hat einen gemeinsamen Paketbriefkasten; Link4 besitzt zusätzlich einen pro Gegenstelle.

Diese Abfrage liest die Hardware nicht aus; eine ungültige Gegenstelle ändert den gespeicherten Fehler nicht.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[9]=Link4_HasPacketFrom(0);result[10]=Link4_ReadPacketFrom(0,&cmd,&len,data);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Als Gegenstelle 1 von vier Plätzen sind HOST BYTE=17, COMMAND=65, LENGTH=3 und PAYLOAD 2=42 zu erwarten. CONSUMED=0 ist das Hostbriefkasten-Flag nach der Entnahme.

Link4_HasPacketFrom: DMG
DMG
Link4_HasPacketFrom: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:142

Deklarationshinweise im Original
Inspect the one-packet mailbox for a valid remote slot without consuming it.

kitaqgb/lib/link_packet.c:484

c
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot) {
    return Link4_PacketPeerReady(peer_slot);
}
Link4_InitHost

Initialisiert einen logischen Host mit zwei bis vier Plätzen und wählt Gegenstelle 1.

Syntax

c
u8 __stackcall Link4_InitHost(u8 slot_count);

Parameter

slot_count

Anzahl der Plätze einschließlich Host, 2 bis 4.

Rückgabewert

Gibt bei gültiger Konfiguration 0 zurück, bei ungültiger Platzanzahl 4.

Bedingungen und Grenzen

Die Initialisierung verwirft Bytewarteschlangen, Pakete, Gegenstellenauswahl und Fehler und deaktiviert Übertragung sowie serielle IRQ-Quelle. Ein laufender Austausch bleibt nicht erhalten.

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Interne kritische Abschnitte verfolgen ihre Software-Verschachtelungstiefe. Beim Verlassen des äußersten Abschnitts werden CPU-Interrupts aktiviert. Gehen Sie daher nicht davon aus, dass ein zuvor deaktivierter IME-Zustand erhalten bleibt.

Die Initialisierung erfolgt vor der Prüfung. Auch ein fehlgeschlagener Aufruf verwirft die bisherige Topologie und ungelesene Daten.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[0]=Link4_InitHost(4);result[1]=Link4_GetMode();result[2]=Link4_GetLocalSlot();result[3]=Link4_GetSlotCount();result[4]=Link4_GetSelectedPeer();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_InitHost: DMG
DMG
Link4_InitHost: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:108

Deklarationshinweise im Original
Cooperative 4-player adapter helpers.

This layer models the common host-selected adapter pattern:
- Slot 0 is always the host.
- The host selects one active peer slot at a time.
- Packet mailboxes stay one-deep per peer.
- The original Link_* API remains available for normal 2-player projects.
Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.

kitaqgb/lib/link.c:489

c
u8 __stackcall Link4_InitHost(u8 slot_count) {
    u8 err;

    Link_InitMaster();
    err = Link4_ValidateConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
    if (err != LINK_ERR_NONE) {
        Link_SetErrorInternal(err);
        return err;
    }

    Link4_ApplyConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
    return LINK_ERR_NONE;
}
Link4_InitPeer

Initialisiert eine Gegenstelle mit externem Takt und wählt Hostplatz 0.

Syntax

c
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);

Parameter

local_slot

Lokaler Platz, 1 bis slot_count−1.

slot_count

Gesamtzahl der Plätze einschließlich Host, 2 bis 4.

Rückgabewert

Gibt bei gültiger Konfiguration 0 zurück, bei ungültiger Platzanzahl oder ungültigem lokalen Platz 4.

Bedingungen und Grenzen

Die Initialisierung verwirft Bytewarteschlangen, Pakete, Gegenstellenauswahl und Fehler und deaktiviert Übertragung sowie serielle IRQ-Quelle. Ein laufender Austausch bleibt nicht erhalten.

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Interne kritische Abschnitte verfolgen ihre Software-Verschachtelungstiefe. Beim Verlassen des äußersten Abschnitts werden CPU-Interrupts aktiviert. Gehen Sie daher nicht davon aus, dass ein zuvor deaktivierter IME-Zustand erhalten bleibt.

Die Initialisierung erfolgt vor der Prüfung. Auch ein fehlgeschlagener Aufruf verwirft die bisherige Topologie und ungelesene Daten.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[0]=Link4_InitPeer(1,4);result[1]=Link4_GetMode();result[2]=Link4_GetLocalSlot();result[3]=Link4_GetSlotCount();result[4]=Link4_GetSelectedPeer();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Als Gegenstelle 1 von vier Plätzen sind HOST BYTE=17, COMMAND=65, LENGTH=3 und PAYLOAD 2=42 zu erwarten. CONSUMED=0 ist das Hostbriefkasten-Flag nach der Entnahme.

Link4_InitPeer: DMG
DMG
Link4_InitPeer: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:111

Deklarationshinweise im Original
Reset as slave and validate the local nonzero slot and total slot count.
An invalid configuration still discards the previous link state.

kitaqgb/lib/link.c:505

c
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count) {
    u8 err;

    Link_InitSlave();
    err = Link4_ValidateConfig(LINK4_MODE_PEER, local_slot, slot_count);
    if (err != LINK_ERR_NONE) {
        Link_SetErrorInternal(err);
        return err;
    }

    Link4_ApplyConfig(LINK4_MODE_PEER, local_slot, slot_count);
    return LINK_ERR_NONE;
}
Link4_PollPacket

Führt die gemeinsame Paketverarbeitung für die aktuell gewählte Gegenstelle einmal weiter.

Syntax

c
void Link4_PollPacket();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Ein Paket enthält 0xA5, Befehl, Länge, 0 bis 24 Nutzdatenbytes und eine XOR-Prüfsumme. Die Antwort ist 0x79 (ACK, angenommen) oder 0x1F (NAK, abgewiesen). Die Prüfsumme verknüpft Befehl, Länge und Nutzdaten per XOR. Jedes Gerät hat einen gemeinsamen Paketbriefkasten; Link4 besitzt zusätzlich einen pro Gegenstelle.

Fragen Sie beide Endpunkte fortlaufend ab. Ein Timeout zählt 90 Aufrufe ohne Fortschritt, keine Hardwareframes. Das Senden von 0xFF allein zur Taktversorgung eines ACK verlängert die Frist nicht; höchstens drei Sendeversuche sind erlaubt. Wiederholungen können Duplikate liefern. Ergänzen Sie Kennungen auf Anwendungsebene, wenn ein Befehl genau einmal ausgeführt werden muss.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Wechselt nicht zyklisch durch alle Plätze. Ändern Sie die Gegenstelle erst nach Abschluss des Austauschs, wenn eine Auswahl erlaubt ist.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
for(i=0;i<50;i++){Link4_PollPacket();while(Link4_TryReadByteFrom(slot,0)){}m_wait();}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_PollPacket: DMG
DMG
Link4_PollPacket: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:140

Deklarationshinweise im Original
Advance the shared packet engine; this does not poll every logical peer in turn.

kitaqgb/lib/link_packet.c:479

c
void Link4_PollPacket() {
    Link_PollPacket();
}
Link4_ReadPacketFrom

Kopiert ein Paket einer bestimmten Gegenstelle und entnimmt es aus deren Briefkasten.

Syntax

c
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

cmd

Beschreibbares Befehlsbyte; null lässt diese Ausgabe aus.

len

Beschreibbares Längenbyte von 0 bis 24; null lässt diese Ausgabe aus.

dst

Beschreibbarer Nutzdatenpuffer mit Platz für 24 Bytes; null verwirft die Nutzdaten.

Rückgabewert

Gibt bei Entnahme 1 zurück, bei leerem Briefkasten oder ungültiger Gegenstelle 0.

Bedingungen und Grenzen

Es gibt keinen Parameter für die Zielkapazität. Stellen Sie bei Verwendung von dst 24 beschreibbare Bytes bereit. cmd, len und dst dürfen unabhängig voneinander null sein. Koordinieren Sie Prüfung und Entnahme des Briefkasteninhalts so, dass anderer Code oder Interrupts nicht gleichzeitig darauf zugreifen.

Leert den gemeinsamen Briefkasten nur, wenn er auf das Paket derselben Gegenstelle verweist. Ungelesene Pakete anderer Gegenstellen bleiben verfügbar.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[9]=Link4_HasPacketFrom(0);result[10]=Link4_ReadPacketFrom(0,&cmd,&len,data);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Als Gegenstelle 1 von vier Plätzen sind HOST BYTE=17, COMMAND=65, LENGTH=3 und PAYLOAD 2=42 zu erwarten. CONSUMED=0 ist das Hostbriefkasten-Flag nach der Entnahme.

Link4_ReadPacketFrom: DMG
DMG
Link4_ReadPacketFrom: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:146

Deklarationshinweise im Original
Consume a peer mailbox, copying to optional outputs. A nonnull destination
needs room for the entire payload. Clear the shared mailbox only when it
refers to this same peer.

kitaqgb/lib/link_packet.c:491

c
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst) {
    u8 i;
    u8 offset;

    if (Link4_PacketPeerReady(peer_slot) == 0) return 0;

    if (cmd != 0) *cmd = Link4_ReceivedPacketCmd[(__safe_index u8)peer_slot];
    if (len != 0) *len = Link4_ReceivedPacketLen[(__safe_index u8)peer_slot];

    if (dst != 0) {
        for (i = 0; i < Link4_ReceivedPacketLen[(__safe_index u8)peer_slot]; ++i) {
            offset = Link4_PacketOffset(peer_slot, i);
            dst[(__safe_index u8)i] = Link4_ReceivedPacketBuf[(__safe_index u8)offset];
        }
    }

    Link4_ReceivedPacketReady[(__safe_index u8)peer_slot] = 0;
    if (Link4_LastPacketPeer == peer_slot) {
        Link_ReceivedPacketReady = 0;
        Link4_LastPacketPeer = LINK4_INVALID_SLOT;
    }
    return 1;
}
Link4_SelectPeer

Prüft auf Abschluss und ändert das logische Ziel nur im Ruhezustand.

Syntax

c
u8 __stackcall Link4_SelectPeer(u8 peer_slot);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

Rückgabewert

Gibt bei Auswahl 0 zurück, bei belegtem Byte-, Paket- oder ACK-Zustand 1 und bei fehlender Konfiguration oder ungültiger Gegenstelle 4.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Fehlercodes: 0=kein Fehler, 1=belegt, 2=Timeout, 3=Empfangsüberlauf, 4=ungültige Konfiguration/Protokoll, 5=ACK-Timeout mit einer Antwort wie bei einer getrennten Verbindung. Start- und Konfigurationsaufrufe melden Erfolg mit 0, Empfangs- und Entnahmeaufrufe mit 1. Erfolgreiche Aufrufe löschen keinen gespeicherten Fehler.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[25]=Link4_SelectPeer(1);result[26]=Link_LastError();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_SelectPeer: DMG
DMG
Link4_SelectPeer: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:127

Deklarationshinweise im Original
Poll completion, then change the logical destination only while byte and
packet state are idle. A peer can select only the host. No adapter-routing
command is sent here; the transport must provide the matching physical route.

kitaqgb/lib/link.c:552

c
u8 __stackcall Link4_SelectPeer(u8 peer_slot) {
    Link_Poll();

    if (Link4_IsEnabledInternal() == 0) {
        Link_SetErrorInternal(LINK_ERR_PROTOCOL);
        return LINK_ERR_PROTOCOL;
    }

    if (Link_Busy != 0 || Link_PacketState != LINK_PKT_STATE_IDLE || Link_PendingAck != 0) {
        Link_SetErrorInternal(LINK_ERR_BUSY);
        return LINK_ERR_BUSY;
    }

    if (Link4_ModeState == LINK4_MODE_HOST) {
        if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) {
            Link_SetErrorInternal(LINK_ERR_PROTOCOL);
            return LINK_ERR_PROTOCOL;
        }
        Link4_SelectedPeer = peer_slot;
        return LINK_ERR_NONE;
    }

    if (Link4_ModeState == LINK4_MODE_PEER && peer_slot == LINK4_HOST_SLOT) {
        Link4_SelectedPeer = LINK4_HOST_SLOT;
        return LINK_ERR_NONE;
    }

    Link_SetErrorInternal(LINK_ERR_PROTOCOL);
    return LINK_ERR_PROTOCOL;
}
Link4_SendPacketTo

Wählt eine logische Gegenstelle, kopiert das Paket und plant dessen Versand ein.

Syntax

c
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

data

Über len Bytes lesbare Quelle; nur bei len gleich null darf sie null sein.

len

Nutzdatenlänge in Bytes von 0 bis 24.

cmd

Von der Anwendung definierter Acht-Bit-Befehl.

Rückgabewert

Gibt den ersten Auswahl- oder Einreihungsfehler zurück. 0 bedeutet angenommen.

Bedingungen und Grenzen

Link4 verwaltet den logischen Hostplatz 0 und Gegenstellenplätze 1 bis 3. SelectPeer sendet keinen Befehl zum Umschalten physischer Leitungen. KOKURAs link4-Topologie folgt der ausgewählten Gegenstelle anhand der Compilermetadaten. Verwenden Sie LinkDmg07 für das Protokoll des echten DMG-07-Adapters.

Fehlercodes: 0=kein Fehler, 1=belegt, 2=Timeout, 3=Empfangsüberlauf, 4=ungültige Konfiguration/Protokoll, 5=ACK-Timeout mit einer Antwort wie bei einer getrennten Verbindung. Start- und Konfigurationsaufrufe melden Erfolg mit 0, Empfangs- und Entnahmeaufrufe mit 1. Erfolgreiche Aufrufe löschen keinen gespeicherten Fehler.

Ein Paket enthält 0xA5, Befehl, Länge, 0 bis 24 Nutzdatenbytes und eine XOR-Prüfsumme. Die Antwort ist 0x79 (ACK, angenommen) oder 0x1F (NAK, abgewiesen). Die Prüfsumme verknüpft Befehl, Länge und Nutzdaten per XOR. Jedes Gerät hat einen gemeinsamen Paketbriefkasten; Link4 besitzt zusätzlich einen pro Gegenstelle.

Fragen Sie beide Endpunkte fortlaufend ab. Ein Timeout zählt 90 Aufrufe ohne Fortschritt, keine Hardwareframes. Das Senden von 0xFF allein zur Taktversorgung eines ACK verlängert die Frist nicht; höchstens drei Sendeversuche sind erlaubt. Wiederholungen können Duplikate liefern. Ergänzen Sie Kennungen auf Anwendungsebene, wenn ein Befehl genau einmal ausgeführt werden muss.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Die Auswahl erfolgt vor der Nutzdatenprüfung. Auch bei abgewiesenen Nutzdaten kann das neue Ziel ausgewählt bleiben.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[21+slot]=Link4_SendPacketTo(slot,data,3,64+slot);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_SendPacketTo: DMG
DMG
Link4_SendPacketTo: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:138

Deklarationshinweise im Original
Select a logical peer, then copy and schedule a packet; return the first error.

kitaqgb/lib/link_packet.c:472

c
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd) {
    u8 err = Link4_SelectPeer(peer_slot);
    if (err != LINK_ERR_NONE) return err;
    return Link_SendPacket(data, len, cmd);
}
Link4_TryReadByteAny

Prüft entfernte Plätze in aufsteigender Reihenfolge und entnimmt das erste verfügbare Byte.

Syntax

c
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);

Parameter

peer_slot

Beschreibbares Byte für den Herkunftsplatz; null lässt diese Ausgabe aus.

out

Beschreibbares Byteziel; bei null wird das Byte verworfen.

Rückgabewert

Gibt bei Empfang 1 zurück, sonst 0.

Bedingungen und Grenzen

Der Empfangsring mit acht Einträgen fasst sieben Bytes. Ein voller Ring verwirft das neue Byte und speichert Fehler 3. Ein empfangenes Nullbyte ist gültige Nutzlast.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Interne kritische Abschnitte verfolgen ihre Software-Verschachtelungstiefe. Beim Verlassen des äußersten Abschnitts werden CPU-Interrupts aktiviert. Gehen Sie daher nicht davon aus, dass ein zuvor deaktivierter IME-Zustand erhalten bleibt.

Überspringt den lokalen Platz. Niedrigere Plätze mit ständig wartenden Daten haben Vorrang. Verwenden Sie bei gewünschter gleichmäßiger Rundumverteilung einzelne Gegenstellen-Leseaufrufe.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
else {other=255;Link4_TryReadByteAny(&other,&value);result[12+slot]=other;}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_TryReadByteAny: DMG
DMG
Link4_TryReadByteAny: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:136

Deklarationshinweise im Original
Scan remote rings in increasing slot order and return the first available
byte. Null output pointers are allowed; lower slots have polling priority.

kitaqgb/lib/link.c:604

c
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out) {
    u8 slot;

    if (Link4_IsEnabledInternal() == 0) return 0;

    for (slot = 0; slot < Link4_SlotCount; ++slot) {
        if (slot != Link4_LocalSlot) {
            if (Link4_PopRxByte(slot, out) != 0) {
                if (peer_slot != 0) *peer_slot = slot;
                return 1;
            }
        }
    }

    return 0;
}
Link4_TryReadByteFrom

Entnimmt ein Byte aus dem Empfangsring einer bestimmten Gegenstelle.

Syntax

c
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);

Parameter

peer_slot

Konfigurierter entfernter Platz: vom Host aus 1 bis slot_count−1, von einer Gegenstelle aus 0.

out

Beschreibbares Byteziel; bei null wird das Byte verworfen.

Rückgabewert

Gibt bei Entnahme 1 zurück. Bei leerem Ring oder ungültiger Gegenstelle wird 0 zurückgegeben und out bleibt erhalten.

Bedingungen und Grenzen

Der Empfangsring mit acht Einträgen fasst sieben Bytes. Ein voller Ring verwirft das neue Byte und speichert Fehler 3. Ein empfangenes Nullbyte ist gültige Nutzlast.

Link4 kopiert jedes empfangene Byte sowohl in den allgemeinen Ring als auch in einen Ring pro Gegenstelle. Das Lesen eines Rings leert den anderen nicht. Die Paketabfrage verbraucht den allgemeinen Ring. Verwerfen Sie auch regelmäßig ungenutzte Rohbytes in den Gegenstellenringen, um Überläufe zu vermeiden.

Interne kritische Abschnitte verfolgen ihre Software-Verschachtelungstiefe. Beim Verlassen des äußersten Abschnitts werden CPU-Interrupts aktiviert. Gehen Sie daher nicht davon aus, dass ein zuvor deaktivierter IME-Zustand erhalten bleibt.

Die Bilder stammen aus KOKURA. Beispiele mit mehreren Endpunkten prüfen Werte in verbundenen Emulatorinstanzen und nehmen Bilder aus deren abschließend gespeicherten Zuständen auf. Diese Prüfungen belegen kein Verhalten echter Kabel oder Vier-Spieler-Adapter.

Führen Sie diese PowerShell-Befehle im gemeinsamen übergeordneten Ordner von kitaqgb, kokura und kitaq-docs aus. Bauen Sie alle beteiligten ROMs vor dem Start der verbundenen Sitzung. Belassen Sie bei Link4 die erzeugten Symbolmetadaten neben den ROMs. Ersetzen Sie für DMG-Läufe überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
if(slot==1)result[13]=Link4_TryReadByteFrom(slot,&value);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verbinden Sie alle vier ROMs über KOKURAs link4-Topologie. Der Host empfängt 161/162/163 von Gegenstellen 1/2/3 und zeigt LAST PEER=3. Danach sendet er die Befehle 65/66/67 mit Nutzdaten 7/42/255. Prüfen Sie diese Werte auch auf jedem Gegenstellenbildschirm.

Link4_TryReadByteFrom: DMG
DMG
Link4_TryReadByteFrom: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementierung und Quelltext

kitaqgb/lib/link.h:133

Deklarationshinweise im Original
Pop one byte from the selected peer ring; null output discards it.

kitaqgb/lib/link.c:598

c
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out) {
    return Link4_PopRxByte(peer_slot, out);
}

DMG-07 verteilt ein Byte jeder Konsole an alle vier Spieler. Diese Bibliothek verwaltet Erkennung, Start durch Spieler 1, verzögerte Paketrundsendungen und ausgerichtete Neustartsteuerung. EXCHANGE erklärt Vier-Konsolen-Austausch, NO ADAPTER Zeitüberschreitungen, OVERFLOW ungelesene Daten und RESTART Wiederherstellung.

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Dieser Treiber beansprucht den seriellen Port. Führen Sie gewöhnliches Link oder Link4 nicht gleichzeitig aus; binden Sie link_hwregs_gb.c und link_dmg07.c je einmal ein. Der Adapter liefert externe Takte; der Treiber wählt nicht den schnellen CGB-Seriellmodus.

Rufen Sie Poll über den ganzen Frame wiederholt und TickFrame genau einmal pro Frame auf. Ein Poll pro VBlank kann den Port zwischen Adapterbytes nicht neu vorbereiten. d_poll im gemeinsamen Header erkennt den Eintritt in LY >= 144 und ruft TickFrame einmal auf. Serialisieren Sie beide Operationen, statt ISR und Hauptschleife konkurrieren zu lassen.

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

LinkDmg07_ClearError

Setzt den letzten Fehlercode auf null zurück.

Syntax

c
void LinkDmg07_ClearError();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Erhält Empfangsdaten, Phase, Verbindungsinformationen und Timeout-Markierung. Dieser Aufruf allein verbindet nicht neu und setzt den Empfang nicht fort.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
LinkDmg07_ClearError();result[21]=LinkDmg07_LastError();result[22]=LinkDmg07_GetErrorCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lassen Sie das erste gültige Paket bis zum nächsten ungelesen. Erwartet werden SENT SEQ=3, PACKET SEQ=2 und ERROR=6; gelesen werden die neuesten 33/34/35/36. ClearError setzt CLEAR ERROR auf null, während ErrorCount eins bleibt.

LinkDmg07_ClearError: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_ClearError: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:125

Deklarationshinweise im Original
Clear only the latest error code, preserving counters and protocol state.

kitaqgb/lib/link_dmg07.c:541

c
void LinkDmg07_ClearError() {
    LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
}
LinkDmg07_ConsumePingStatus

Verbraucht und löscht eine abgeschlossene Erkennungsmeldung.

Syntax

c
u8 LinkDmg07_ConsumePingStatus();

Rückgabewert

Gibt bei Verbrauch 1 zurück, sonst 0.

Bedingungen und Grenzen

Löscht nur die Meldung und erhält Slot, Maske und LastStatus. Weitere Aufrufe liefern bis zur nächsten Meldung null.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[3]=LinkDmg07_ConsumePingStatus();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_ConsumePingStatus: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_ConsumePingStatus: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:71

Deklarationshinweise im Original
Clear and report the completed-discovery flag; return zero if no new status exists.

kitaqgb/lib/link_dmg07.c:418

c
u8 LinkDmg07_ConsumePingStatus() {
    if (LinkDmg07_PingStatusReady == 0) return 0;
    LinkDmg07_PingStatusReady = 0;
    return 1;
}
LinkDmg07_GetConnectedMask

Liest die Vier-Bit-Spielermenge des zuletzt akzeptierten Status.

Syntax

c
u8 LinkDmg07_GetConnectedMask();

Rückgabewert

Bits 0..3 melden verbundene Spieler. Nicht erkannt ist null; vier verbundene Spieler ergeben 15.

Bedingungen und Grenzen

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Gibt den gespeicherten Erkennungsstatus zurück, ohne physische Verkabelung zu prüfen. Während des Transfers gilt die zuletzt akzeptierte Meldung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[1]=LinkDmg07_GetConnectedMask();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetConnectedMask: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetConnectedMask: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:65

Deklarationshinweise im Original
Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.

kitaqgb/lib/link_dmg07.c:403

c
u8 LinkDmg07_GetConnectedMask() {
    return LinkDmg07_ConnectedMask;
}
LinkDmg07_GetDisconnectCount

Liest erfasste Verlustereignisse: Stille nach Adaptererkennung oder aus dem Erkennungsstatus verschwundene Spieler.

Syntax

c
u8 LinkDmg07_GetDisconnectCount();

Rückgabewert

Gibt 0..255 Ereignisse zurück, nicht die Anzahl verlorener Spieler.

Bedingungen und Grenzen

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Fristablauf vor der ersten Adaptererkennung erhöht ihn nicht. Mehrere bei einer Statusänderung verschwundene Spieler zählen als ein Ereignis.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[8]=LinkDmg07_GetDisconnectCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Führen Sie das Beispiel ohne Adapter aus. Erwartet werden PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 und ERROR=4. DISCONNECTS bleibt null, weil noch kein Adapter erkannt wurde. Leeres Lesen erhält EMPTY BUFFER=77; ClearError ergibt CLEARED=0.

LinkDmg07_GetDisconnectCount: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetDisconnectCount: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:118

Deklarationshinweise im Original
Return the saturating count of removed-player and previously-seen-adapter timeout events.

kitaqgb/lib/link_dmg07.c:525

c
u8 LinkDmg07_GetDisconnectCount() {
    return LinkDmg07_DisconnectCount;
}
LinkDmg07_GetErrorCount

Liest die Anzahl empfangener Protokollfehler und überschriebener ungelesener Pakete.

Syntax

c
u8 LinkDmg07_GetErrorCount();

Rückgabewert

Gibt 0..255 zurück. Anforderungsvalidierungs-/Zustandsfehler und Timeouts sind nicht enthalten.

Bedingungen und Grenzen

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Das Empfangsfach speichert nur das neueste Paket. Der Abschluss eines weiteren Pakets überschreibt ungelesene Daten, merkt Fehler 6 und erhöht ErrorCount. Der Adapter wartet nicht auf das Auslesen durch die Anwendung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[19]=LinkDmg07_GetErrorCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lassen Sie das erste gültige Paket bis zum nächsten ungelesen. Erwartet werden SENT SEQ=3, PACKET SEQ=2 und ERROR=6; gelesen werden die neuesten 33/34/35/36. ClearError setzt CLEAR ERROR auf null, während ErrorCount eins bleibt.

LinkDmg07_GetErrorCount: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetErrorCount: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:121

Deklarationshinweise im Original
Return the saturating protocol/overflow error count. Timeout and request
validation paths use separate counters or latches and do not increment this value.

kitaqgb/lib/link_dmg07.c:531

c
u8 LinkDmg07_GetErrorCount() {
    return LinkDmg07_ErrorCount;
}
LinkDmg07_GetLastStatus

Liest das zuletzt geprüfte rohe Adapterstatusbyte.

Syntax

c
u8 LinkDmg07_GetLastStatus();

Rückgabewert

Das obere Nibble enthält die Verbindungsmaske, die unteren drei Bits die lokale Spielernummer. Anfangswert null.

Bedingungen und Grenzen

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Lehnt Statuswerte mit gesetztem Bit 3, Spielernummer null oder über vier sowie nach Erkennung geänderter lokaler Nummer ab. Die Ablehnung merkt Fehler 5, ohne den Wert als LastStatus zu speichern.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[2]=LinkDmg07_GetLastStatus();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetLastStatus: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetLastStatus: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:67

Deklarationshinweise im Original
Return the last validated raw adapter status byte.

kitaqgb/lib/link_dmg07.c:408

c
u8 LinkDmg07_GetLastStatus() {
    return LinkDmg07_LastStatus;
}
LinkDmg07_GetLocalSlot

Liest die aus dem Adapterstatus ermittelte Spielernummer dieser Konsole.

Syntax

c
u8 LinkDmg07_GetLocalSlot();

Rückgabewert

Gibt nach Erkennung 1..4 zurück, davor oder unmittelbar nach einem Erkennungsreset null.

Bedingungen und Grenzen

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
slot=LinkDmg07_GetLocalSlot();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetLocalSlot: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetLocalSlot: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:62

Deklarationshinweise im Original
Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.

kitaqgb/lib/link_dmg07.c:398

c
u8 LinkDmg07_GetLocalSlot() {
    return LinkDmg07_LocalSlot;
}
LinkDmg07_GetPacketSequence

Liest die dem zuletzt bereitgestellten Paket zugewiesene Sequenz.

Syntax

c
u8 LinkDmg07_GetPacketSequence();

Rückgabewert

Gibt die 8-Bit-Paketsequenz zurück, ohne die Bereitschaft zu ändern.

Bedingungen und Grenzen

Sequenznummern laufen von 255 auf null um. Bei der Bereitstellung des Pakets ist PacketSequence gleich SentSequence minus eins. Spätere Sendestarts erhöhen SentSequence; später abgefragte Werte müssen daher nicht um eins differieren.

Das Empfangsfach speichert nur das neueste Paket. Der Abschluss eines weiteren Pakets überschreibt ungelesene Daten, merkt Fehler 6 und erhöht ErrorCount. Der Adapter wartet nicht auf das Auslesen durch die Anwendung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[7]=LinkDmg07_GetPacketSequence();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetPacketSequence: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetPacketSequence: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:109

Deklarationshinweise im Original
Return the modulo-256 sequence associated with the most recently published packet.

kitaqgb/lib/link_dmg07.c:510

c
u8 LinkDmg07_GetPacketSequence() {
    return LinkDmg07_PacketSequence;
}
LinkDmg07_GetPacketSlot

Liest das Byte eines Spielers aus dem gespeicherten Paket.

Syntax

c
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);

Parameter

player_slot

Physische Spielernummer, 1..4.

Rückgabewert

Gibt das gespeicherte Byte von Spieler 1..4 zurück, bei ungültiger Nummer null.

Bedingungen und Grenzen

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Prüft und verbraucht keine Bereitschaft. Liefert direkt nach Initialisierung null und eventuell erhaltene Bytes nach Verbrauch oder Erkennungsreset. Nicht als Neudatenprüfung verwenden.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[16]=LinkDmg07_GetPacketSlot(4);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetPacketSlot: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetPacketSlot: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:102

Deklarationshinweise im Original
Read one cached player byte using a one-based slot. Invalid slots return
zero; the function neither requires readiness nor consumes the packet.

kitaqgb/lib/link_dmg07.c:499

c
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot) {
    if ((player_slot == 0) || (player_slot > LINK_DMG07_MAX_PLAYERS)) return 0;
    return LinkDmg07_RxPacket[(__safe_index u8)(player_slot - 1)];
}
LinkDmg07_GetPhase

Liest die aktuelle Erkennungs-, Startanforderungs-, Bestätigungs- oder Transferphase.

Syntax

c
u8 LinkDmg07_GetPhase();

Rückgabewert

0=PING, 1=REQUEST_AA, 2=WAIT_CC, 3=TRANSFER.

Bedingungen und Grenzen

Fragt nicht ab und wartet nicht. Die Annahme einer Startanforderung reicht für TRANSFER nicht aus; vier aufeinanderfolgende 0xCC-Bytes sind erforderlich.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[8]=LinkDmg07_GetPhase();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetPhase: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetPhase: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:60

Deklarationshinweise im Original
Return the discovery, start-handshake or transfer phase without polling.

kitaqgb/lib/link_dmg07.c:393

c
u8 LinkDmg07_GetPhase() {
    return LinkDmg07_Phase;
}
LinkDmg07_GetRestartState

Liest, ob Neustartsteuerung fehlt, vorgemerkt ist oder gesendet wird.

Syntax

c
u8 LinkDmg07_GetRestartState();

Rückgabewert

0=keine, 1=Warten auf Grenze, 2=Steuerverkehr wird gesendet.

Bedingungen und Grenzen

Getrennt von der Kommunikationsphase. Null allein belegt keine aufgebaute oder nutzbare Verbindung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[4]=LinkDmg07_GetRestartState();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Spieler 2 fordert Neustart an. Seine Konsole erfasst PENDING=1 und SENT FF=1. Alle vier zeigen DATA VALID=1, RESET PHASE=0, SLOT AFTER=0 und RESET PRIME=0. Der Treiber erhält den laufenden Austausch, bis ihn das Adaptersignal zur Erkennung zurückführt.

LinkDmg07_GetRestartState: DMG / Spieler 2
DMG / Spieler 2
LinkDmg07_GetRestartState: CGB / Spieler 2
CGB / Spieler 2

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:85

Deklarationshinweise im Original
Return whether aligned recovery is absent, pending or sending control traffic.

kitaqgb/lib/link_dmg07.c:457

c
u8 LinkDmg07_GetRestartState() {
    return LinkDmg07_RestartState;
}
LinkDmg07_GetSentSequence

Liest die Anzahl der tatsächlich ausgetakteten Anwendungsbytes.

Syntax

c
u8 LinkDmg07_GetSentSequence();

Rückgabewert

Gibt die 8-Bit-Sendesequenz zurück. Zählt den ersten Beitrag, aber keinen Neustartsteuerverkehr.

Bedingungen und Grenzen

Sequenznummern laufen von 255 auf null um. Bei der Bereitstellung des Pakets ist PacketSequence gleich SentSequence minus eins. Spätere Sendestarts erhöhen SentSequence; später abgefragte Werte müssen daher nicht um eins differieren.

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[6]=LinkDmg07_GetSentSequence();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_GetSentSequence: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetSentSequence: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:107

Deklarationshinweise im Original
SentSequence increments when this console's packet byte is clocked out.
PacketSequence labels the returned four-byte packet.  For a valid packet it
is one less than SentSequence, making the DMG-07 one-packet delay explicit.

kitaqgb/lib/link_dmg07.c:505

c
u8 LinkDmg07_GetSentSequence() {
    return LinkDmg07_SentSequence;
}
LinkDmg07_GetSilenceFrames

Liest die seit dem letzten verarbeiteten seriellen Abschluss gezählten Frames.

Syntax

c
u8 LinkDmg07_GetSilenceFrames();

Rückgabewert

0..255; ein verarbeiteter Abschluss setzt zurück, jeder TickFrame erhöht den Wert.

Bedingungen und Grenzen

Rufen Sie Poll über den ganzen Frame wiederholt und TickFrame genau einmal pro Frame auf. Ein Poll pro VBlank kann den Port zwischen Adapterbytes nicht neu vorbereiten. d_poll im gemeinsamen Header erkennt den Eintritt in LY >= 144 und ruft TickFrame einmal auf. Serialisieren Sie beide Operationen, statt ISR und Hauptschleife konkurrieren zu lassen.

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[6]=LinkDmg07_GetSilenceFrames();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Führen Sie das Beispiel ohne Adapter aus. Erwartet werden PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 und ERROR=4. DISCONNECTS bleibt null, weil noch kein Adapter erkannt wurde. Leeres Lesen erhält EMPTY BUFFER=77; ClearError ergibt CLEARED=0.

LinkDmg07_GetSilenceFrames: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetSilenceFrames: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:114

Deklarationshinweise im Original
SilenceFrames is reset by every completed serial byte.  TimeoutCount counts
distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts
adapter-silence outages and ping-status membership drops.  All saturate.

kitaqgb/lib/link_dmg07.c:515

c
u8 LinkDmg07_GetSilenceFrames() {
    return LinkDmg07_SilenceFrames;
}
LinkDmg07_GetTimeoutCount

Liest die Anzahl abgelaufener Ruhe- oder Handshake-Fristen.

Syntax

c
u8 LinkDmg07_GetTimeoutCount();

Rückgabewert

Gibt einen Gesamtwert von 0..255 zurück.

Bedingungen und Grenzen

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Zählt dieselbe Ruhephase vor Wiederaufnahme nicht in jedem Frame erneut. ClearError erhält diese Unterdrückungsmarkierung und den Gesamtzähler.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[7]=LinkDmg07_GetTimeoutCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Führen Sie das Beispiel ohne Adapter aus. Erwartet werden PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 und ERROR=4. DISCONNECTS bleibt null, weil noch kein Adapter erkannt wurde. Leeres Lesen erhält EMPTY BUFFER=77; ClearError ergibt CLEARED=0.

LinkDmg07_GetTimeoutCount: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_GetTimeoutCount: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:116

Deklarationshinweise im Original
Return the saturating lifetime timeout count, preserved across protocol restarts.

kitaqgb/lib/link_dmg07.c:520

c
u8 LinkDmg07_GetTimeoutCount() {
    return LinkDmg07_TimeoutCount;
}
LinkDmg07_HasPacket

Prüft auf ein abgeschlossenes ungelesenes Vier-Byte-Datenpaket.

Syntax

c
u8 LinkDmg07_HasPacket();

Rückgabewert

Gibt bei ungelesenen Daten 1 zurück, sonst 0.

Bedingungen und Grenzen

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Das Empfangsfach speichert nur das neueste Paket. Der Abschluss eines weiteren Pakets überschreibt ungelesene Daten, merkt Fehler 6 und erhöht ErrorCount. Der Adapter wartet nicht auf das Auslesen durch die Anwendung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[15]=LinkDmg07_HasPacket();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_HasPacket: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_HasPacket: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:96

Deklarationshinweise im Original
Inspect the one-packet receive mailbox without consuming it.

kitaqgb/lib/link_dmg07.c:473

c
u8 LinkDmg07_HasPacket() {
    return LinkDmg07_PacketReady;
}
LinkDmg07_HasPingStatus

Prüft, ob ein abgeschlossener Vier-Byte-Erkennungsaustausch auf Bestätigung wartet.

Syntax

c
u8 LinkDmg07_HasPingStatus();

Rückgabewert

Gibt bei unverbrauchter Meldung 1 zurück, sonst 0.

Bedingungen und Grenzen

Liest nur ein Flag. Ein Erkennungsaustausch kann trotz abgelehntem Statusbyte fortschreiten. Leiten Sie daraus allein weder vollständig gültige Daten noch abgeschlossenen Start ab. Prüfen Sie auch Slot, Maske und LastError.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[4]=LinkDmg07_HasPingStatus();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_HasPingStatus: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_HasPingStatus: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:69

Deklarationshinweise im Original
Read the completed-discovery status flag without clearing it.

kitaqgb/lib/link_dmg07.c:413

c
u8 LinkDmg07_HasPingStatus() {
    return LinkDmg07_PingStatusReady;
}
LinkDmg07_Init

Setzt Erkennung, Empfangsspeicher und Diagnose zurück und bereitet den Empfang von Adaptertakten vor.

Syntax

c
void __stackcall LinkDmg07_Init(u8 rate);

Parameter

rate

8-Bit-RATE-Antwort an den Adapter; null wählt den Standardwert 0x10.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Dieser Treiber beansprucht den seriellen Port. Führen Sie gewöhnliches Link oder Link4 nicht gleichzeitig aus; binden Sie link_hwregs_gb.c und link_dmg07.c je einmal ein. Der Adapter liefert externe Takte; der Treiber wählt nicht den schnellen CGB-Seriellmodus.

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Setzt SC auf 0x80 und SB auf 0x88; löscht nur die seriellen Bits in IE und IF. Andere Interruptfreigabebits und CPU-IME bleiben unverändert.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
LinkDmg07_Init(0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_Init: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_Init: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:50

Deklarationshinweise im Original
Initializes polling-only external-clock operation.  A zero RATE is replaced
with LINK_DMG07_DEFAULT_RATE.  This driver disables only the serial IRQ bit.

kitaqgb/lib/link_dmg07.c:282

c
void __stackcall LinkDmg07_Init(u8 rate) {
    u8 i;

    LinkDmg07_Rate = rate;
    if (LinkDmg07_Rate == 0) LinkDmg07_Rate = LINK_DMG07_DEFAULT_RATE;
    LinkDmg07_LocalByte = 0;
    LinkDmg07_SentSequence = 0;
    LinkDmg07_PacketSequence = 0;
    LinkDmg07_RestartState = LINK_DMG07_RESTART_NONE;
    LinkDmg07_SilenceFrames = 0;
    LinkDmg07_TimeoutCount = 0;
    LinkDmg07_DisconnectCount = 0;
    LinkDmg07_ErrorCount = 0;
    LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
    LinkDmg07_SeenAdapter = 0;
    LinkDmg07_TimeoutLatched = 0;
    for (i = 0; i < LINK_DMG07_PACKET_BYTES; ++i) {
        LinkDmg07_RxBuild[(__safe_index u8)i] = 0;
        LinkDmg07_RxPacket[(__safe_index u8)i] = 0;
    }
    LinkDmg07_ResetToPingInternal();

    LinkHw_WriteIE((u8)(LinkHw_ReadIE() & LINK_DMG07_IRQ_SERIAL_CLEAR));
    LinkHw_WriteIF((u8)(LinkHw_ReadIF() & LINK_DMG07_IRQ_SERIAL_CLEAR));
    LinkDmg07_ArmInternal(LINK_DMG07_ACK);
}
LinkDmg07_IsPipelinePrimed

Prüft, ob die anfängliche undefinierte Rundsendung verworfen wurde.

Syntax

c
u8 LinkDmg07_IsPipelinePrimed();

Rückgabewert

Gibt nach der ersten Rundsendung 1 zurück; Initialisierung, Erkennungsreset und Startbestätigung löschen den Wert.

Bedingungen und Grenzen

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Eine vorbereitete Pipeline enthält nicht zwingend ein vollständiges Paket. Prüfen Sie die Lesebereitschaft mit HasPacket.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[9]=LinkDmg07_IsPipelinePrimed();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_IsPipelinePrimed: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_IsPipelinePrimed: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:94

Deklarationshinweise im Original
The first incoming adapter data packet is discarded.  Thereafter ReadPacket
copies four bytes in physical slot order (players 1..4).

kitaqgb/lib/link_dmg07.c:468

c
u8 LinkDmg07_IsPipelinePrimed() {
    return LinkDmg07_PipelinePrimed;
}
LinkDmg07_LastError

Liest den zuletzt gespeicherten Fehlercode.

Syntax

c
u8 LinkDmg07_LastError();

Rückgabewert

Gibt einen Fehlercode von 0..6 zurück.

Bedingungen und Grenzen

Fehlercodes: 0=kein Fehler, 1=falsche Phase, 2=nicht Spieler 1, 3=nicht bereit, 4=Zeitüberschreitung, 5=Protokollfehler, 6=ungelesenes Paket überschrieben. Anforderungen sind mit null erfolgreich, Empfang/Pop mit eins. Eine erfolgreiche Anforderung löscht keinen früheren Fehler.

Lesen löscht den Wert nicht. Gespeichert wird nur der neueste Code, kein Fehlerverlauf.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[9]=LinkDmg07_LastError();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Führen Sie das Beispiel ohne Adapter aus. Erwartet werden PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 und ERROR=4. DISCONNECTS bleibt null, weil noch kein Adapter erkannt wurde. Leeres Lesen erhält EMPTY BUFFER=77; ClearError ergibt CLEARED=0.

LinkDmg07_LastError: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_LastError: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:123

Deklarationshinweise im Original
Return the latest error latch without clearing counters or restarting the protocol.

kitaqgb/lib/link_dmg07.c:536

c
u8 LinkDmg07_LastError() {
    return LinkDmg07_LastErrorCode;
}
LinkDmg07_Poll

Verarbeitet ein abgeschlossenes serielles Byte in der aktuellen Phase und bereitet sofort die nächste Antwort vor.

Syntax

c
void LinkDmg07_Poll();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Dieser Treiber beansprucht den seriellen Port. Führen Sie gewöhnliches Link oder Link4 nicht gleichzeitig aus; binden Sie link_hwregs_gb.c und link_dmg07.c je einmal ein. Der Adapter liefert externe Takte; der Treiber wählt nicht den schnellen CGB-Seriellmodus.

Rufen Sie Poll über den ganzen Frame wiederholt und TickFrame genau einmal pro Frame auf. Ein Poll pro VBlank kann den Port zwischen Adapterbytes nicht neu vorbereiten. d_poll im gemeinsamen Header erkennt den Eintritt in LY >= 144 und ruft TickFrame einmal auf. Serialisieren Sie beide Operationen, statt ISR und Hauptschleife konkurrieren zu lassen.

Tut nichts bei gesetztem SC-Startbit. Die Verarbeitung eines Abschlusses setzt SilenceFrames und die gespeicherte Timeout-Markierung zurück. Initialisieren Sie vor dem Abfragen.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
void d_poll(){LinkDmg07_Poll();if(D_LY>=144){if(d_vblank==0){d_vblank=1;LinkDmg07_TickFrame();}}else d_vblank=0;}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_Poll: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_Poll: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:54

Deklarationshinweise im Original
Services at most one completed serial byte and immediately re-arms SC=$80.
Call continuously from the main loop, including between VBlanks.

kitaqgb/lib/link_dmg07.c:311

c
void LinkDmg07_Poll() {
    u8 value;
    u8 next;

    if ((LinkHw_ReadSC() & LINK_DMG07_SC_EXTERNAL_START) != 0) return;

    value = LinkHw_ReadSB();
    LinkDmg07_SilenceFrames = 0;
    LinkDmg07_TimeoutLatched = 0;
    LinkDmg07_SeenAdapter = 1;

    next = 0;
    if (LinkDmg07_Phase == LINK_DMG07_PHASE_PING) {
        next = LinkDmg07_ProcessPingInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) {
        next = LinkDmg07_ProcessRequestInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) {
        next = LinkDmg07_ProcessWaitCcInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_TRANSFER) {
        next = LinkDmg07_ProcessTransferInternal(value);
    } else {
        LinkDmg07_SetRuntimeErrorInternal(LINK_DMG07_ERR_PROTOCOL);
        LinkDmg07_ResetToPingInternal();
        next = LINK_DMG07_ACK;
    }

    LinkDmg07_ArmInternal(next);
}
LinkDmg07_ReadPacket

Kopiert das zuletzt abgeschlossene Paket und löscht dessen Ungelesen-Flag.

Syntax

c
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);

Parameter

dst

Vier beschreibbare Bytes; null verwirft das Paket.

Rückgabewert

Gibt bei Verbrauch 1 zurück, bei Leere 0. Leeres Lesen lässt dst unverändert.

Bedingungen und Grenzen

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Das Empfangsfach speichert nur das neueste Paket. Der Abschluss eines weiteren Pakets überschreibt ungelesene Daten, merkt Fehler 6 und erhöht ErrorCount. Der Adapter wartet nicht auf das Auslesen durch die Anwendung.

Gespeicherte Bytes bleiben nach dem Verbrauch über GetPacketSlot verfügbar. Ein leeres ReadPacket kopiert sie nicht erneut.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[10]=LinkDmg07_ReadPacket(packet);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_ReadPacket: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_ReadPacket: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:99

Deklarationshinweise im Original
Consume the latest four-byte packet. A nonnull destination must hold four
bytes; null discards the packet. Packet storage remains after the flag clears.

kitaqgb/lib/link_dmg07.c:479

c
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst) {
    if (LinkDmg07_PacketReady == 0) return 0;
    if (dst != 0) {
        // Keep this as a sequential pointer copy.  Besides being smaller for a
        // fixed four-byte packet, it avoids making a serial hot-path copy
        // depend on general variable-index pointer lowering.
        *dst = LinkDmg07_RxPacket[0];
        dst++;
        *dst = LinkDmg07_RxPacket[1];
        dst++;
        *dst = LinkDmg07_RxPacket[2];
        dst++;
        *dst = LinkDmg07_RxPacket[3];
    }
    LinkDmg07_PacketReady = 0;
    return 1;
}
LinkDmg07_RequestRestart

Plant Neustartsteuerverkehr ab einer Transferpaketgrenze ein.

Syntax

c
u8 LinkDmg07_RequestRestart();

Rückgabewert

Gibt in TRANSFER 0 zurück, sonst 1. Wiederholte Anforderungen während Vormerkung oder Senden liefern ebenfalls 0.

Bedingungen und Grenzen

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Fehlercodes: 0=kein Fehler, 1=falsche Phase, 2=nicht Spieler 1, 3=nicht bereit, 4=Zeitüberschreitung, 5=Protokollfehler, 6=ungelesenes Paket überschrieben. Anforderungen sind mit null erfolgreich, Empfang/Pop mit eins. Eine erfolgreiche Anforderung löscht keinen früheren Fehler.

Jeder Spieler darf dies anfordern. Erhält die aktuelle Byteposition, sendet ausgerichteten 0xFF-Verkehr und kehrt nach dem vollständigen 0xFF-Signal des Adapters zur Erkennung zurück. Die bloße Anforderung löscht weder lokalen Slot noch Empfangspipeline.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[3]=LinkDmg07_RequestRestart();result[4]=LinkDmg07_GetRestartState();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Spieler 2 fordert Neustart an. Seine Konsole erfasst PENDING=1 und SENT FF=1. Alle vier zeigen DATA VALID=1, RESET PHASE=0, SLOT AFTER=0 und RESET PRIME=0. Der Treiber erhält den laufenden Austausch, bis ihn das Adaptersignal zur Erkennung zurückführt.

LinkDmg07_RequestRestart: DMG / Spieler 2
DMG / Spieler 2
LinkDmg07_RequestRestart: CGB / Spieler 2
CGB / Spieler 2

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:83

Deklarationshinweise im Original
Any physical slot may schedule FF FF FF FF at the next four-byte packet
boundary while remaining in TRANSFER phase.  The driver keeps sending aligned
FF bytes until it sees the adapter's complete all-FF indicator packet, then
returns to PING.  A transfer-phase silence timeout schedules the same recovery
automatically and preserves the current byte position for clocks that resume.

kitaqgb/lib/link_dmg07.c:445

c
u8 LinkDmg07_RequestRestart() {
    if (LinkDmg07_Phase != LINK_DMG07_PHASE_TRANSFER) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
        return LINK_DMG07_ERR_STATE;
    }
    if (LinkDmg07_RestartState == LINK_DMG07_RESTART_NONE) {
        LinkDmg07_RestartState = LINK_DMG07_RESTART_PENDING;
    }
    return LINK_DMG07_ERR_NONE;
}
LinkDmg07_RequestTransmission

Plant die Startanforderung des physischen Spielers 1 an der nächsten Erkennungspaketgrenze ein.

Syntax

c
u8 LinkDmg07_RequestTransmission();

Rückgabewert

Gibt bei Einplanung 0 zurück, bei falscher Phase 1, wenn nicht Spieler 1 dann 2 und bei fehlendem lokalem Verbindungsbit 3.

Bedingungen und Grenzen

Die Bibliothek nummeriert Spieler 1..4; null bedeutet noch nicht erkannt. Verbindungsbits 0..3 entsprechen Spielern 1..4. Die Slotwerte von KOKURA --link-session sind 0..3, eine von der ROM-API getrennte Nummerierung.

Fehlercodes: 0=kein Fehler, 1=falsche Phase, 2=nicht Spieler 1, 3=nicht bereit, 4=Zeitüberschreitung, 5=Protokollfehler, 6=ungelesenes Paket überschrieben. Anforderungen sind mit null erfolgreich, Empfang/Pop mit eins. Eine erfolgreiche Anforderung löscht keinen früheren Fehler.

Kann nur in PING eingeplant werden. Wartet nicht selbst auf alle vier Spieler; das Beispiel prüft Maske 15 im Anwendungscode. Die Einplanung ist asynchron: Ausgerichteter 0xAA-Verkehr geht der 0xCC-Bestätigung voraus.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
result[5]=LinkDmg07_RequestTransmission();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_RequestTransmission: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_RequestTransmission: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:76

Deklarationshinweise im Original
Only physical player 1 may request AA AA AA AA.  The bytes are aligned to
the next FE/status/status/status ping packet.  All consoles enter transfer
mode only after receiving four consecutive CC bytes.

kitaqgb/lib/link_dmg07.c:426

c
u8 LinkDmg07_RequestTransmission() {
    if (LinkDmg07_Phase != LINK_DMG07_PHASE_PING) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
        return LINK_DMG07_ERR_STATE;
    }
    if (LinkDmg07_LocalSlot != 1) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_PLAYER1;
        return LINK_DMG07_ERR_NOT_PLAYER1;
    }
    if ((LinkDmg07_ConnectedMask & (u8)0x01) == 0) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_READY;
        return LINK_DMG07_ERR_NOT_READY;
    }
    LinkDmg07_StartRequested = 1;
    return LINK_DMG07_ERR_NONE;
}
LinkDmg07_SetLocalByte

Setzt den Ein-Byte-Anwendungswert für ein künftiges ausgehendes Paket.

Syntax

c
void __stackcall LinkDmg07_SetLocalByte(u8 value);

Parameter

value

Zu übermittelnder 8-Bit-Anwendungswert.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bei SIZE=1 liefert jede Konsole ein Byte; die Vier-Byte-Rundsendung folgt Spielern 1..4. Die erste wird verworfen. Spätere Rundsendungen enthalten die Beiträge des vorigen Pakets. Vier Bytes mit ausschließlich 0xFF sind als Neustartsignal reserviert.

Wird beim Vorbereiten von Paketbyte null übernommen. Ändert kein bereits vorbereitetes SB-Byte. Setzen Sie den ersten Sendewert vor der Startanforderung.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
LinkDmg07_SetLocalByte(32+slot);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Starten Sie dieselbe ROM auf vier Konsolen; jede sendet 32 plus ihre Spielernummer. Alle empfangen PLAYER 1..4 = 33/34/35/36. Die erste gültige Rundsendung hält SENT SEQ=2 und PACKET SEQ=1 fest und zeigt die Verzögerung um ein Paket. Das Bild friert diese Beobachtung ein; ein Spiel fragt anschließend weiter ab.

LinkDmg07_SetLocalByte: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_SetLocalByte: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:90

Deklarationshinweise im Original
Sets the byte sampled when byte 0 of the next adapter packet is armed.
Set it before the current packet completes (and before requesting start for
the first submission).  During normal transfer, bytes 1..3 are sent as zero.

kitaqgb/lib/link_dmg07.c:463

c
void __stackcall LinkDmg07_SetLocalByte(u8 value) {
    LinkDmg07_LocalByte = value;
}
LinkDmg07_TickFrame

Rückt Ruhe- und Start-/Neustartüberwachung um einen Frame vor und fordert bei Fristablauf Wiederherstellung an.

Syntax

c
void LinkDmg07_TickFrame();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Rufen Sie Poll über den ganzen Frame wiederholt und TickFrame genau einmal pro Frame auf. Ein Poll pro VBlank kann den Port zwischen Adapterbytes nicht neu vorbereiten. d_poll im gemeinsamen Header erkennt den Eintritt in LY >= 144 und ruft TickFrame einmal auf. Serialisieren Sie beide Operationen, statt ISR und Hauptschleife konkurrieren zu lassen.

SilenceFrames und Diagnosezähler sättigen bei 255. Init setzt alle zurück; gewöhnliche Protokollneustarts erhalten die Diagnosezähler. ClearError löscht nur den Fehlercode.

Die Standardfrist beträgt 12 Aufrufe; definieren Sie vor dem Einbinden LINK_DMG07_TIMEOUT_FRAMES als 1..255 für einen anderen Wert. Eine Ruhephase wird nur einmal gezählt, bis ein weiteres Byte ihre Markierung löscht. Transferwiederherstellung erhält die Byteausrichtung; Wiederherstellung bei Erkennung/Start kehrt zur Erkennung zurück.

Die Bilder stammen aus KOKURAs DMG-07-Modell. Jede Konsole läuft unabhängig; gesendete und empfangene Werte werden verglichen. Elektrisches Verhalten und Timing physischer Adapter und Kabel sind ungeprüft. CGB-Bilder zeigen Zahlen blau.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Vier-Konsolen-Beispiele starten dieselbe ROM in vier Sitzungen. Ersetzen Sie für DMG-Prüfungen überall --cgb=cgb durch --cgb=dmg und --hardware cgb durch --hardware dmg.

Anwendungsbeispiel

c
void d_poll(){LinkDmg07_Poll();if(D_LY>=144){if(d_vblank==0){d_vblank=1;LinkDmg07_TickFrame();}}else d_vblank=0;}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Führen Sie das Beispiel ohne Adapter aus. Erwartet werden PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 und ERROR=4. DISCONNECTS bleibt null, weil noch kein Adapter erkannt wurde. Leeres Lesen erhält EMPTY BUFFER=77; ClearError ergibt CLEARED=0.

LinkDmg07_TickFrame: DMG / Spieler 1
DMG / Spieler 1
LinkDmg07_TickFrame: CGB / Spieler 1
CGB / Spieler 1

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementierung und Quelltext

kitaqgb/lib/link_dmg07.h:57

Deklarationshinweise im Original
Advances saturating frame-based silence and handshake timeout counters.

kitaqgb/lib/link_dmg07.c:369

c
void LinkDmg07_TickFrame() {
    LinkDmg07_SilenceFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_SilenceFrames);

    if ((LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) ||
        (LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) ||
        (LinkDmg07_RestartState == LINK_DMG07_RESTART_SENDING)) {
        LinkDmg07_HandshakeFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_HandshakeFrames);
    } else {
        LinkDmg07_HandshakeFrames = 0;
    }

    if ((LinkDmg07_SilenceFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
        (LinkDmg07_TimeoutLatched == 0)) {
        LinkDmg07_TimeoutInternal(1);
        return;
    }

    if ((LinkDmg07_HandshakeFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
        (LinkDmg07_TimeoutLatched == 0)) {
        LinkDmg07_TimeoutInternal(0);
    }
}

physics2d.h — 2D-Bewegung und Kollisionen

Bietet Boxintegration, AABB-Kontakte und einen optionalen Löser für Oberflächenreaktionen. Körper werden durch Mittelpunkt und halbe Ausdehnungen beschrieben; active=0 schließt einen Arrayplatz aus, inv_mass_q8<=0 macht ihn statisch. KQRect verwendet dagegen linke obere Ecke und Breite/Höhe. Kontakte zwischen Boxen nutzen das restitution-Feld des Körpers nicht; Oberflächenreaktionen verwenden KQSurface2D-Koeffizienten.

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

kq2d_body_apply_friction

Skaliert beide Geschwindigkeitskomponenten mit einem vorzeichenbehafteten Bytekoeffizienten geteilt durch 256, ohne Position oder Aktivität zu prüfen.

Syntax

c
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

friction_q8

Von dieser Funktion verwendeter Geschwindigkeitsfaktor. Er wird in s8 umgewandelt; dadurch werden 128..255 zu negativen Koeffizienten.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Werte von 0 bis 127 ergeben Faktoren von 0 bis 127/256. Werte von 128 bis 255 werden durch die s8-Umwandlung negativ und kehren die Geschwindigkeit um. Für nichtnegative Dämpfung über den gesamten Bereich 0..255 verwenden Sie kq2d_scale_q8 für jede Komponente. Produkte werden gegen null abgeschnitten. NULL wird ignoriert.

Anwendungsbeispiel

c
kq2d_body_apply_friction(&temp,64);
    result[11]=temp.vx; result[12]=temp.vy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_body_apply_friction: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_body_apply_friction: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:66

Deklarationshinweise im Original
Scale both velocities through the signed 8-bit coefficient intrinsic.
Despite the unsigned parameter, values 128..255 become negative coefficients;
this is not a full-range unsigned Q8 damping helper. Null is ignored.

kitaqgb/lib/physics2d.c:654

c
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8)
{
    if (body == 0) return;
    body->vx = (s16)__smul16x8(body->vx, (s8)friction_q8);
    body->vy = (s16)__smul16x8(body->vy, (s8)friction_q8);
}
kq2d_body_apply_gravity

Addiert die Schwerkraft zu einem aktiven dynamischen Körper und begrenzt jede Achse auf +/-max_speed, ohne die Position zu ändern.

Syntax

c
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

gravity_x

Beschleunigung, die dieser Aufruf zur X-Geschwindigkeit addiert.

gravity_y

Beschleunigung, die dieser Aufruf zur Y-Geschwindigkeit addiert.

max_speed

Geschwindigkeitsgrenze. Der jeweilige Eintrag erläutert, ob sie für jede Achse einzeln oder den gesamten Vektor gilt.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Integration und Kollisionserkennung für Boxen verwenden gemeinsamen Arbeitsspeicher. Rufen Sie diese Physikroutinen nicht während ihrer Ausführung erneut aus einem Interrupt auf.

Ignoriert NULL, inaktive Körper und Körper mit inverser Masse kleiner oder gleich null. Geben Sie eine nichtnegative Geschwindigkeitsgrenze an.

Anwendungsbeispiel

c
kq2d_body_apply_gravity(&temp,5,-10,32);
    result[9]=temp.vx; result[10]=temp.vy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_body_apply_gravity: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_body_apply_gravity: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:62

Deklarationshinweise im Original
Add gravity and clamp each velocity axis separately for an active dynamic
body. Null, inactive and static bodies are ignored. Supply a nonnegative limit
and avoid overflow in the additions before clamping; position is unchanged.

kitaqgb/lib/physics2d.c:630

c
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed)
{
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    kq2d_asm_value = body->vx;
    kq2d_asm_operand = gravity_x;
    kq2d_add_s16_asm();
    kq2d_asm_limit = max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vx = kq2d_asm_value;

    kq2d_asm_value = body->vy;
    kq2d_asm_operand = gravity_y;
    kq2d_add_s16_asm();
    kq2d_asm_limit = max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vy = kq2d_asm_value;
}
kq2d_body_init

Initialisiert eine über ihren Mittelpunkt definierte Box mit den angegebenen halben Ausdehnungen, Geschwindigkeit null, inverser Masse 256 und aktivem Zustand.

Syntax

c
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

x

X-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.

y

Y-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.

half_x

Halbe Ausdehnung entlang X; die gesamte Boxbreite ist doppelt so groß.

half_y

Halbe Ausdehnung entlang Y; die gesamte Boxhöhe ist doppelt so groß.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Setzt restitution_q8 auf null. Ein NULL-Körper wird ignoriert. Geben Sie positive halbe Ausdehnungen an.

Anwendungsbeispiel

c
kq2d_body_init(&temp,10,20,8,8);
    result[3]=temp.inv_mass_q8; result[4]=temp.active;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_body_init: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_body_init: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:54

Deklarationshinweise im Original
Initialize an active unit-inverse-mass body at the supplied center and half
extents, with zero velocity and reserved restitution set to zero. Null is ignored.

kitaqgb/lib/physics2d.c:597

c
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y)
{
    if (body == 0) return;
    body->x = x;
    body->y = y;
    body->vx = 0;
    body->vy = 0;
    body->half_x = half_x;
    body->half_y = half_y;
    body->inv_mass_q8 = 256;
    body->restitution_q8 = 0;
    body->active = 1;
}
kq2d_body_limit_speed

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Schätzt die Vektorlänge konservativ und skaliert beide Achsen gemeinsam, um die Gesamtgeschwindigkeit zu begrenzen.

Syntax

c
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

max_speed

Geschwindigkeitsgrenze. Der jeweilige Eintrag erläutert, ob sie für jede Achse einzeln oder den gesamten Vektor gilt.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Die Beträge der Geschwindigkeitskomponenten und ein positiver max_speed dürfen höchstens 16383 betragen. Eine Grenze kleiner oder gleich null setzt die Geschwindigkeit auf null. NULL wird ignoriert, Aktivität und Masse verhindern die Änderung jedoch nicht. Ganzzahlige Quantisierung kann das Ergebnis unter die Grenze drücken; sehr kleine Faktoren können null ergeben.

Anwendungsbeispiel

c
kq2d_body_limit_speed(&body,250);
    result[2]=body.vx; result[3]=body.vy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

kq2d_body_limit_speed: DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
kq2d_body_limit_speed: CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:92

Deklarationshinweise im Original
Conservative circular bound, with a shared Q8 scale for both components.
Quantizes toward zero; very small limits relative to input may yield zero.
Components and positive max_speed must be <= 16383 in magnitude.

kitaqgb/lib/physics2d.c:260

c
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed)
{
    u16 x;
    u16 y;
    u16 swap;
    u16 ratio;
    u16 length;
    if (body == 0) return;
    if (max_speed <= 0) { body->vx = 0; body->vy = 0; return; }
    x = (u16)body->vx;
    y = (u16)body->vy;
    if (body->vx < 0) x = (u16)(0 - body->vx);
    if (body->vy < 0) y = (u16)(0 - body->vy);
    if (x + y <= (u16)max_speed) return;
    if (x < y) { swap = x; x = y; y = swap; }
    // major + minor/2 bounds hypot from above for 0 <= minor <= major.
    if (x + (y >> 1) + 1 <= (u16)max_speed) return;
    // Round the minor/major ratio upward for the 65-entry upper-bound table.
    // The extra unit covers truncation when converting the estimate back to speed.
    ratio = (kq2d__fraction_q8(y, x) + 4) >> 2;
    if (ratio > 64) ratio = 64;
    length = x + (u16)kq2d_scale_q8((s16)x, (s16)kq2d_hypot_extra[(__safe_index u8)ratio]) + 1;
    if (length <= (u16)max_speed) return;
    ratio = kq2d__fraction_q8((u16)max_speed, length);
    body->vx = kq2d_scale_q8(body->vx, (s16)ratio);
    body->vy = kq2d_scale_q8(body->vy, (s16)ratio);
}
kq2d_body_resolve_surface

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Nutzt die Geschwindigkeit relativ zu einer bewegten Oberfläche, um normalen Rückprall, eine minimale Rückprallgeschwindigkeit und tangentiale Reibung anzuwenden.

Syntax

c
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

surface

Zeiger auf eine KQSurface2D mit Normale, Geschwindigkeit sowie Rückprall- und Reibungseinstellungen.

Rückgabewert

Liefert die positive Annäherungsgeschwindigkeit entlang der Normalen oder 0 bei NULL-Eingaben oder einer Trennbewegung.

Bedingungen und Grenzen

Verwenden Sie eine Q8-Einheitsnormale mit Länge 256. Relative Komponenten müssen in +/-8191 liegen, threshold/kick nichtnegativ und Koeffizienten in 0..255 sein. Rückprall wird nur bei striktem Überschreiten des Schwellwerts angewendet; kick gibt die minimale Rückprallgeschwindigkeit vor. Bei NULL-Eingaben oder einer Trennbewegung bleibt die Geschwindigkeit unverändert. Kontakterkennung und Eindringkorrektur erfolgen separat; Aktivität und Masse werden nicht geprüft.

Anwendungsbeispiel

c
result[6]=kq2d_body_resolve_surface(&body,&surface);
    result[7]=body.vx; result[8]=body.vy; result[9]=body.y;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

kq2d_body_resolve_surface: DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
kq2d_body_resolve_surface: CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:95

Deklarationshinweise im Original
Kinematic surface response; returns incoming normal speed, or zero if separating.
Caller resolves penetration separately. Relative components must fit +/-8191.

kitaqgb/lib/physics2d.c:314

c
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface)
{
    s16 vx;
    s16 vy;
    s16 speed;
    s16 tangent;
    s16 bounce = 0;
    s16 impulse;
    s16 friction;
    if (body == 0 || surface == 0) return 0;
    vx = (s16)(body->vx - surface->vx);
    vy = (s16)(body->vy - surface->vy);
    speed = (s16)(kq2d_scale_q8(vx,surface->nx_q8) + kq2d_scale_q8(vy,surface->ny_q8));
    if (speed >= 0) return 0;
    speed = (s16)(0 - speed);
    if (speed > surface->bounce_threshold) bounce = kq2d_scale_q8(speed,(s16)surface->restitution_q8);
    if (bounce < surface->kick) bounce = surface->kick;
    impulse = (s16)(speed + bounce);
    // A resting contact is a tangent constraint, not a tiny rounded bounce.
    if (bounce == 0) {
        tangent = (s16)(kq2d__rest_component(vy,surface->nx_q8) - kq2d__rest_component(vx,surface->ny_q8));
        friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
        if (tangent > friction) tangent = (s16)(tangent - friction);
        else if (tangent < (s16)(0 - friction)) tangent = (s16)(tangent + friction);
        else tangent = 0;
        body->vx = (s16)(surface->vx - kq2d__rest_component(tangent,surface->ny_q8));
        body->vy = (s16)(surface->vy + kq2d__rest_component(tangent,surface->nx_q8));
        return speed;
    }
    body->vx = (s16)(body->vx + kq2d_scale_q8(impulse,surface->nx_q8));
    body->vy = (s16)(body->vy + kq2d_scale_q8(impulse,surface->ny_q8));
    if (surface->friction_q8 != 0) {
        tangent = (s16)(kq2d_scale_q8(vy,surface->nx_q8) - kq2d_scale_q8(vx,surface->ny_q8));
        friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
        if (tangent > friction) tangent = friction;
        if (tangent < (s16)(0 - friction)) tangent = (s16)(0 - friction);
        body->vx = (s16)(body->vx + kq2d_scale_q8(tangent,surface->ny_q8));
        body->vy = (s16)(body->vy - kq2d_scale_q8(tangent,surface->nx_q8));
    }
    return speed;
}
kq2d_body_set_pos

Ersetzt nur den Körpermittelpunkt; Geschwindigkeit, Ausdehnungen und Aktivitätszustand bleiben erhalten.

Syntax

c
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

x

X-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.

y

Y-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

NULL wird ignoriert. Bei gültigem Zeiger werden auch inaktive und statische Körper geändert.

Anwendungsbeispiel

c
kq2d_body_set_pos(&temp,-12,20);
    result[5]=temp.x; result[6]=temp.y;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_body_set_pos: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_body_set_pos: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:56

Deklarationshinweise im Original
Replace the center without altering velocity, extents or activity. Null is ignored.

kitaqgb/lib/physics2d.c:612

c
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y)
{
    if (body == 0) return;
    body->x = x;
    body->y = y;
}
kq2d_body_set_velocity

Setzt die Geschwindigkeit direkt, ohne sie zu begrenzen oder die Position zu ändern.

Syntax

c
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

vx

X-Verschiebung pro Simulationstakt, in derselben Einheit wie die Position.

vy

Y-Verschiebung pro Simulationstakt, in derselben Einheit wie die Position.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

NULL wird ignoriert. Bei gültigem Zeiger werden auch inaktive und statische Körper geändert.

Anwendungsbeispiel

c
kq2d_body_set_velocity(&temp,40,-30);
    result[7]=temp.vx; result[8]=temp.vy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_body_set_velocity: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_body_set_velocity: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:58

Deklarationshinweise im Original
Replace velocity without clamping or checking activity/mass. Null is ignored.

kitaqgb/lib/physics2d.c:620

c
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy)
{
    if (body == 0) return;
    body->vx = vx;
    body->vy = vy;
}
kq2d_integrate_body

Wendet Weltschwerkraft und Geschwindigkeitsgrenzen pro Achse auf einen dynamischen Körper an und addiert anschließend die Geschwindigkeit zur Position.

Syntax

c
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Integration und Kollisionserkennung für Boxen verwenden gemeinsamen Arbeitsspeicher. Rufen Sie diese Physikroutinen nicht während ihrer Ausführung erneut aus einem Interrupt auf.

Ignoriert NULL, inaktive Körper und Körper mit inverser Masse kleiner oder gleich null. Geben Sie eine nichtnegative Geschwindigkeitsgrenze an.

Dieser Aufruf löst keine Kontakte mit anderen Körpern auf. Auch eine NULL-Welt wird ignoriert.

Anwendungsbeispiel

c
kq2d_integrate_body(&world,&temp);
    result[18]=temp.x; result[19]=temp.y;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_integrate_body: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_integrate_body: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:47

Deklarationshinweise im Original
For one active dynamic body, add gravity, clamp each velocity axis and then
add velocity to position. Null inputs are ignored; no contacts are solved.
Use a nonnegative speed limit and keep additions in signed 16-bit range.

kitaqgb/lib/physics2d.c:664

c
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body)
{
    if (world == 0) return;
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    kq2d_asm_value = body->vx;
    kq2d_asm_operand = world->gravity_x;
    kq2d_add_s16_asm();
    kq2d_asm_limit = world->max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vx = kq2d_asm_value;

    kq2d_asm_value = body->vy;
    kq2d_asm_operand = world->gravity_y;
    kq2d_add_s16_asm();
    kq2d_asm_limit = world->max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vy = kq2d_asm_value;

    kq2d_asm_value = body->x;
    kq2d_asm_operand = body->vx;
    kq2d_add_s16_asm();
    body->x = kq2d_asm_value;

    kq2d_asm_value = body->y;
    kq2d_asm_operand = body->vy;
    kq2d_add_s16_asm();
    body->y = kq2d_asm_value;
}
kq2d_overlap_aabb

Prüft zwei über ihren Mittelpunkt definierte Boxen auf echte Überlappung entlang X und Y.

Syntax

c
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);

Parameter

a

Gültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.

b

Gültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.

Rückgabewert

Liefert 1 bei Überlappung der Innenbereiche und 0 bei bloßer Berührung oder getrennten Formen.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Anwendungsbeispiel

c
result[20]=kq2d_overlap_aabb(&bodies[0],&bodies[1]);
    bodies[1].x=40; result[21]=kq2d_overlap_aabb(&bodies[0],&bodies[1]);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_overlap_aabb: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_overlap_aabb: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:51

Deklarationshinweise im Original
Test strict overlap of two centered boxes; touching edges return false.
Both pointers must be valid. Active/mass flags are ignored, and coordinate
differences and extent sums must fit the signed 16-bit calculations.

kitaqgb/lib/physics2d.c:579

c
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b)
{
    s16 dx = (s16)(b->x - a->x);
    s16 dy = (s16)(b->y - a->y);

    s16 adx = kq2d__abs_s16(dx);
    s16 ady = kq2d__abs_s16(dy);

    s16 sx = (s16)(a->half_x + b->half_x);
    s16 sy = (s16)(a->half_y + b->half_y);

    if (adx >= sx) return 0;
    if (ady >= sy) return 0;
    return 1;
}
kq2d_point_in_rect

Prüft, ob ein Punkt im Rechteck liegt. Linker und oberer Rand zählen dazu, rechter und unterer Rand nicht.

Syntax

c
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);

Parameter

x

X-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.

y

Y-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.

r

KQRect-Wert mit der Position x/y der linken oberen Ecke und Breite/Höhe w/h.

Rückgabewert

Gibt innen 1 und außen 0 zurück.

Bedingungen und Grenzen

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Anwendungsbeispiel

c
result[16]=kq2d_point_in_rect(0,0,r1);
    result[17]=kq2d_point_in_rect(16,0,r1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_point_in_rect: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_point_in_rect: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:72

Deklarationshinweise im Original
Delegate the half-open point test: include left/top and exclude right/bottom.
Coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/physics2d.c:705

c
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r)
{
    return kq_point_in_rect(x, y, r);
}
kq2d_rect_intersect

Prüft die Innenbereiche zweier Rechtecke auf Überlappung. Die Rechtecke werden durch linke obere Ecke und Größe angegeben.

Syntax

c
u8 kq2d_rect_intersect(KQRect a, KQRect b);

Parameter

a

KQRect-Wert mit den Koordinaten der linken oberen Ecke sowie positiver Breite und Höhe.

b

KQRect-Wert mit den Koordinaten der linken oberen Ecke sowie positiver Breite und Höhe.

Rückgabewert

Liefert 1 bei Überlappung der Innenbereiche und 0 bei bloßer Berührung oder getrennten Formen.

Bedingungen und Grenzen

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Abmessungen kleiner oder gleich null werden nicht ausdrücklich abgelehnt. Kopieren Sie Mittelpunkt und halbe Ausdehnungen eines Körpers nicht direkt in ein KQRect.

Anwendungsbeispiel

c
result[14]=kq2d_rect_intersect(r1,r2);
    r2.x=16; result[15]=kq2d_rect_intersect(r1,r2);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_rect_intersect: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_rect_intersect: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:69

Deklarationshinweise im Original
Delegate strict rectangle overlap to the fixed-point utility; edge-only
contact is false. Coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/physics2d.c:698

c
u8 kq2d_rect_intersect(KQRect a, KQRect b)
{
    return kq_rect_intersect(a, b);
}
kq2d_scale_q8

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Multipliziert mit einem vorzeichenbehafteten Koeffizienten geteilt durch 256 und schneidet bei beiden Vorzeichen gegen null ab.

Syntax

c
s16 kq2d_scale_q8(s16 value, s16 coefficient);

Parameter

value

Vorzeichenbehafteter 16-Bit-Wert, auf den der Skalierungsfaktor angewendet wird.

coefficient

Vorzeichenbehafteter Koeffizient von -256 bis 256; 256 steht für 1,0.

Rückgabewert

Liefert das gegen null abgeschnittene Ergebnis als vorzeichenbehafteten 16-Bit-Wert.

Bedingungen und Grenzen

Verwenden Sie nur Koeffizienten in -256..256; +/-256 entspricht +/-1. Für value=-32768 und coefficient=-256 lautet das mathematische Ergebnis 32768 und passt nicht in s16.

Anwendungsbeispiel

c
result[0]=kq2d_scale_q8(-257,128);
    result[1]=kq2d_scale_q8(300,-256);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

kq2d_scale_q8: DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
kq2d_scale_q8: CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:88

Deklarationshinweise im Original
Truncates toward zero, including negative values; coefficient is -256..256.

kitaqgb/lib/physics2d.c:8

c
s16 kq2d_scale_q8(s16 value, s16 coefficient)
{
    // Eight-bit shift/add product in HL:C, with sign applied after truncation.
    __asm {
        LD_HL_IMM value
        LD_A_HL
        LD_E_A
        INC_HL
        LD_A_HL
        LD_D_A
        OR_E
        JP_Z kqscale_zero
        LD_HL_IMM coefficient
        LD_A_HL
        LD_C_A
        INC_HL
        LD_A_HL
        LD_B_A
        LD_A_C
        OR_A
        JR_NZ kqscale_fraction
        LD_A_B
        OR_A
        JP_Z kqscale_zero
        LD_H_D
        LD_L_E
        AND_IMM 128
        RET_Z
        JP kqscale_negate
kqscale_fraction:
        LD_A_D
        XOR_B
        AND_IMM 128
        PUSH_AF
        LD_A_D
        AND_IMM 128
        JR_Z kqscale_value_positive
        XOR_A
        SUB_E
        LD_E_A
        LD_A_IMM 0
        SBC_D
        LD_D_A
kqscale_value_positive:
        LD_A_B
        AND_IMM 128
        JR_Z kqscale_coefficient_positive
        XOR_A
        SUB_C
        LD_C_A
kqscale_coefficient_positive:
        LD_HL_IMM 0
        // Unroll eight bits: avoid a loop branch on every fixed-point product.
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_0
        ADD_HL_DE
kqscale_shift_0:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_1
        ADD_HL_DE
kqscale_shift_1:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_2
        ADD_HL_DE
kqscale_shift_2:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_3
        ADD_HL_DE
kqscale_shift_3:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_4
        ADD_HL_DE
kqscale_shift_4:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_5
        ADD_HL_DE
kqscale_shift_5:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_6
        ADD_HL_DE
kqscale_shift_6:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_7
        ADD_HL_DE
kqscale_shift_7:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        POP_AF
        OR_A
        RET_Z
kqscale_negate:
        XOR_A
        SUB_L
        LD_L_A
        LD_A_IMM 0
        SBC_H
        LD_H_A
        RET
kqscale_zero:
        LD_HL_IMM 0
        RET
    }
}
kq2d_step

Integriert aktive dynamische Körper und löst anschließend Kontakte zwischen aktiven Arrayeinträgen auf.

Syntax

c
void kq2d_step(KQWorld2D* world);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Kontakte werden entlang der Achse mit der geringsten Eindringtiefe aufgelöst; bei Gleichstand wird Y gewählt. Die Positionskorrektur nutzt inverse Massen, zwei dynamische Körper erhalten auf dieser Achse jedoch den einfachen Mittelwert ihrer Geschwindigkeiten. Bei einer Kollision mit einem statischen Körper wird die Komponente null. Der Löser nutzt restitution_q8 nicht. Die diskrete Kollisionserkennung kann schnelle Durchquerungen übersehen.

Integration und Kollisionserkennung für Boxen verwenden gemeinsamen Arbeitsspeicher. Rufen Sie diese Physikroutinen nicht während ihrer Ausführung erneut aus einem Interrupt auf.

Eine NULL-Welt oder ein NULL-Array wird ignoriert. Auch bei solver_iterations gleich null wird ein Kontaktdurchlauf ausgeführt.

Anwendungsbeispiel

c
kq2d_step(&world);
    result[22]=bodies[0].x; result[23]=bodies[0].y;
    result[24]=bodies[0].vx; result[25]=bodies[0].vy;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_step: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_step: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:43

Deklarationshinweise im Original
Advance active dynamic bodies, then visit each active unordered pair for
the configured contact passes (zero means one). Static bodies still participate
as obstacles. The world borrows its array and shares non-reentrant ASM scratch.
This is discrete integration; fast bodies can pass through thin obstacles.

kitaqgb/lib/physics2d.c:794

c
void kq2d_step(KQWorld2D* world)
{
    if (world == 0) return;
    if (world->bodies == 0) return;

    KQBody2D* bodies = world->bodies;
    u8 count = world->body_count;

    // Integrate dynamic bodies.
    u8 i;
    for (i = 0; i < count; i++)
    {
        KQBody2D* b = &bodies[(__safe_index u8)i];
        if (b->active == 0) continue;
        if (b->inv_mass_q8 <= 0) continue;

        kq2d_asm_value = b->vx;
        kq2d_asm_operand = world->gravity_x;
        kq2d_add_s16_asm();
        kq2d_asm_limit = world->max_speed;
        kq2d_clamp_abs_s16_asm();
        b->vx = kq2d_asm_value;

        kq2d_asm_value = b->vy;
        kq2d_asm_operand = world->gravity_y;
        kq2d_add_s16_asm();
        kq2d_asm_limit = world->max_speed;
        kq2d_clamp_abs_s16_asm();
        b->vy = kq2d_asm_value;

        kq2d_asm_value = b->x;
        kq2d_asm_operand = b->vx;
        kq2d_add_s16_asm();
        b->x = kq2d_asm_value;

        kq2d_asm_value = b->y;
        kq2d_asm_operand = b->vy;
        kq2d_add_s16_asm();
        b->y = kq2d_asm_value;
    }

    // Solve contacts with a small fixed iteration count.
    u8 iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    u8 it;
    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQBody2D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;

            u8 j;
            for (j = (u8)(i + 1); j < count; j++)
            {
                KQBody2D* b = &bodies[(__safe_index u8)j];
                if (b->active == 0) continue;
                kq2d__resolve_pair(a, b);
            }
        }
    }
}
kq2d_surface_toi_q8

Schätzt bei linearer Bewegung den Übertrittszeitpunkt innerhalb des Takts anhand der vorzeichenbehafteten Start- und Endabstände.

Syntax

c
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);

Parameter

start_gap

Vorzeichenbehafteter Abstand zu Beginn des Takts; positiv bedeutet außerhalb der Oberfläche.

end_gap

Vorzeichenbehafteter Abstand am Ende des Takts; negativ bedeutet, dass die Oberfläche überschritten wurde.

Rückgabewert

Liefert einen Q8-Zeitpunkt in 0..256; 192 entspricht 75 % des Takts.

Bedingungen und Grenzen

Halten Sie Abstände innerhalb von +/-8191. Ein Startwert kleiner oder gleich null liefert 0; ein Endwert größer oder gleich null liefert 256. Anfangsüberlappung und Zeitpunkt null haben denselben Rückgabewert. Ebenso teilen sich fehlender Übertritt und Kontakt genau am Endpunkt einen Rückgabewert. Positionen werden nicht geändert.

Anwendungsbeispiel

c
result[4]=kq2d_surface_toi_q8(6,-2);
    result[5]=kq2d_surface_toi_q8(6,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

kq2d_surface_toi_q8: DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
DMG — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
kq2d_surface_toi_q8: CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.
CGB — Der rote Körper bleibt an seiner Position. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,-8) rechts und zeigt so Rückprall und tangentiale Reibung an der blauen Oberfläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48)/(88,48), der Körpermittelpunkt innerhalb des Panels bei (24,40). Die Anprallgeschwindigkeit beträgt 16, das Beispiel zum Übertrittszeitpunkt liefert 192/256. Das Beispiel zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196). Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:98

Deklarationshinweise im Original
Linear crossing time in Q8 (0..256); positive separation is outside.
Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.

kitaqgb/lib/physics2d.c:291

c
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap)
{
    if (start_gap <= 0) return 0;
    if (end_gap >= 0) return 256;
    return kq2d__fraction_q8((u16)start_gap, (u16)(start_gap - end_gap));
}
kq2d_world_init

Verknüpft ein Array mit einer 2D-Welt und setzt die Schwerkraft auf (0,32), die Kontaktiterationen auf vier und die Geschwindigkeitsgrenze pro Achse auf 512.

Syntax

c
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

bodies

Anfang eines vom aufrufenden Code gehaltenen Körperarrays mit body_count Elementen.

body_count

Anzahl der Arrayplätze von 0 bis 255, einschließlich inaktiver Einträge.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

Anwendungsbeispiel

c
kq2d_world_init(&world,bodies,2);
    result[0]=world.gravity_y; result[1]=world.solver_iterations; result[2]=world.max_speed;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

kq2d_world_init: DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
DMG — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
kq2d_world_init: CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.
CGB — Links ist der Anfangszustand zu sehen, rechts der Zustand nach einem Takt. Eine rote 16x16-Box mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden wird ihre Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). Auf dem DMG sind alle Markierungen schwarz. RAM-Prüfungen decken außerdem Initialisierung, Setzfunktionen, Integration, Rechteck-/Punktabfragen und vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d.h:38

Deklarationshinweise im Original
Retain the caller-owned body array without initializing its elements.
Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512.
A null world is ignored; the array must outlive subsequent world operations.

kitaqgb/lib/physics2d.c:564

c
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 32;
    world->solver_iterations = 4;
    world->max_speed = 512;
}

physics2d_circle.h — Kreisphysik

Unterstützt Kreisradius, inverse Masse, Rückprall, tangentiale Reibung, Weltdämpfung und Grenzen. Der aufrufende Code initialisiert alle Körperfelder. friction_q8 des Körpers und wall_friction_q8 beschreiben den entfernten Anteil tangentialer Bewegung, linear_damping_q8 dagegen den beibehaltenen Geschwindigkeitsanteil. Bytekoeffizienten werden durch 256 geteilt; 255 ist daher nicht genau 1,0.

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Abstände und Normalen bei Kreisen sind ganzzahlige Näherungen. Auch wenn jede Komponente höchstens 255 beträgt, muss die Summe ihrer Quadrate nicht in 65535 passen. Mittelpunktsdifferenzen, Radiensummen und Summen inverser Massen müssen darstellbar bleiben. Beim Berechnen der Gewichte darf inv_mass_q8 * 255 höchstens 32767 betragen; das Beispiel verwendet 64.

kq2dc_overlap_circle

Nähert die Überlappung der Innenbereiche anhand des reduzierten Mittelpunktabstands und der Radiensumme an.

Syntax

c
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);

Parameter

a

Gültiger Zeiger auf den ersten Kreis.

b

Gültiger Zeiger auf den zweiten Kreis.

Rückgabewert

Liefert 1 bei Überlappung der Innenbereiche und 0 bei bloßer Berührung oder getrennten Formen.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Abstände und Normalen bei Kreisen sind ganzzahlige Näherungen. Auch wenn jede Komponente höchstens 255 beträgt, muss die Summe ihrer Quadrate nicht in 65535 passen. Mittelpunktsdifferenzen, Radiensummen und Summen inverser Massen müssen darstellbar bleiben. Beim Berechnen der Gewichte darf inv_mass_q8 * 255 höchstens 32767 betragen; das Beispiel verwendet 64.

Benötigt zwei gültige Zeiger und positive Radien. Aktivität und Masse werden ignoriert. Reduktion und ganzzahlige Quadratwurzeln können zu Abweichungen von einem exakten geometrischen Abstandstest führen.

Anwendungsbeispiel

c
result[4]=kq2dc_overlap_circle(&balls[0],&balls[1]);
    balls[1].x=18; result[5]=kq2dc_overlap_circle(&balls[0],&balls[1]);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

kq2dc_overlap_circle: DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
kq2dc_overlap_circle: CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d_circle.h:55

Deklarationshinweise im Original
Compare a reduced integer center distance with the reduced radius sum.
Valid pointers and positive radii are required; activity and mass are ignored.
This approximate test requires representable differences, radius sums and
squared-distance sum. Touching at the computed distance returns false.

kitaqgb/lib/physics2d_circle.c:397

c
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b)
{
    s16 dx;
    s16 dy;
    s16 sdx;
    s16 sdy;
    u8 shift;
    u16 adx;
    u16 ady;
    u16 dist_sq;
    u16 dist_scaled;
    s16 radius_sum;
    u16 radius_sum_scaled;

    dx = (s16)(b->x - a->x);
    dy = (s16)(b->y - a->y);
    sdx = dx;
    sdy = dy;
    shift = kq2dc__reduce_vector(&sdx, &sdy);

    adx = (u16)kq2dc__abs_s16(sdx);
    ady = (u16)kq2dc__abs_s16(sdy);
    dist_sq = (u16)((adx * adx) + (ady * ady));
    dist_scaled = kq2dc__isqrt_u16(dist_sq);

    radius_sum = (s16)(a->radius + b->radius);
    radius_sum_scaled = kq2dc__scale_down_positive(radius_sum, shift);

    if (dist_scaled >= radius_sum_scaled) return 0;
    return 1;
}
kq2dc_set_bounds

Speichert und aktiviert die Grenzen der Kreiswelt, ohne Körper sofort zu verschieben.

Syntax

c
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

min_x

Linke Grenze; der Kreismittelpunkt wird auf mindestens min_x + radius begrenzt.

min_y

Obere Grenze; der Kreismittelpunkt wird auf mindestens min_y + radius begrenzt.

max_x

Rechte Grenze; der Kreismittelpunkt wird auf höchstens max_x - radius begrenzt.

max_y

Untere Grenze; der Kreismittelpunkt wird auf höchstens max_y - radius begrenzt.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

NULL wird ignoriert. Reihenfolge der Grenzen und ausreichender Platz werden nicht geprüft; Breite und Höhe müssen mindestens dem Kreisdurchmesser entsprechen. Die eigentliche Positionskorrektur erfolgt in einem Simulationsschritt.

Anwendungsbeispiel

c
kq2dc_set_bounds(&world,4,4,60,60);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

kq2dc_set_bounds: DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
kq2dc_set_bounds: CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d_circle.h:45

Deklarationshinweise im Original
Store and enable bounds without validating their order or fitting bodies
immediately. Supply extents large enough for body diameters. Null is ignored.

kitaqgb/lib/physics2d_circle.c:382

c
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y)
{
    if (world == 0) return;

    world->use_bounds = 1;
    world->min_x = min_x;
    world->min_y = min_y;
    world->max_x = max_x;
    world->max_y = max_y;
}
kq2dc_step

Integriert Kreise, behandelt Grenzen und Kreiskontakte und wendet anschließend lineare Dämpfung an.

Syntax

c
void kq2dc_step(KQCircleWorld2D* world);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

Abstände und Normalen bei Kreisen sind ganzzahlige Näherungen. Auch wenn jede Komponente höchstens 255 beträgt, muss die Summe ihrer Quadrate nicht in 65535 passen. Mittelpunktsdifferenzen, Radiensummen und Summen inverser Massen müssen darstellbar bleiben. Beim Berechnen der Gewichte darf inv_mass_q8 * 255 höchstens 32767 betragen; das Beispiel verwendet 64.

Setzt abschließend Geschwindigkeitskomponenten in -1..1 auf null. Selbst Dämpfung 255 verringert die Geschwindigkeit etwas. Überlappungen ruhender Kreise können bestehen bleiben. Auch statische Kreise werden in aktivierte Grenzen verschoben. Null Iterationen bedeutet einen Durchlauf; NULL-Welt oder -Array wird ignoriert. Dieser diskrete, quantisierte Löser kann Kontakte bei veränderten Geschwindigkeiten in anderer Reihenfolge bearbeiten.

Anwendungsbeispiel

c
kq2dc_step(&world);
    result[6]=balls[0].x; result[7]=balls[0].y; result[8]=balls[0].vx;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

kq2dc_step: DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
kq2dc_step: CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d_circle.h:50

Deklarationshinweise im Original
Integrate active dynamic bodies, apply bounds, solve contacts, then damp
velocity and snap components in -1..1 to zero. Zero solver iterations means one.
Pairs with both velocities zero are skipped, so resting overlaps can remain.
Bounds can reposition static bodies; null world/array inputs are ignored.

kitaqgb/lib/physics2d_circle.c:433

c
void kq2dc_step(KQCircleWorld2D* world)
{
    KQCircleBody2D* bodies;
    u8 count;
    u8 i;
    u8 iterations;
    u8 it;

    if (world == 0) return;
    if (world->bodies == 0) return;

    bodies = world->bodies;
    count = world->body_count;

    for (i = 0; i < count; i++)
    {
        KQCircleBody2D* body = &bodies[(__safe_index u8)i];
        if (body->active == 0) continue;
        if (body->inv_mass_q8 <= 0)
        {
            if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
            continue;
        }

        body->vx = (s16)(body->vx + world->gravity_x);
        body->vy = (s16)(body->vy + world->gravity_y);
        body->vx = kq2dc__clamp_abs(body->vx, world->max_speed);
        body->vy = kq2dc__clamp_abs(body->vy, world->max_speed);

        body->x = (s16)(body->x + body->vx);
        body->y = (s16)(body->y + body->vy);

        if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
    }

    iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQCircleBody2D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;
            if (a->vx == 0 && a->vy == 0) continue;

            if (world->use_bounds != 0) kq2dc__resolve_bounds(world, a);

            {
                u8 j;
                for (j = 0; j < count; j++)
                {
                    KQCircleBody2D* b = &bodies[(__safe_index u8)j];
                    s16 radius_sum;
                    if (j == i) continue;
                    if (b->active == 0) continue;
                    // Avoid revisiting an earlier moving body, but still allow a moving body
                    // to resolve against a stationary slot with a lower index. Velocities are live
                    // solver state, so contact ordering can change which later pairs are visited.
                    if (j < i && (b->vx != 0 || b->vy != 0)) continue;
                    radius_sum = (s16)(a->radius + b->radius);
                    if (kq2dc__abs_s16((s16)(b->x - a->x)) >= radius_sum) continue;
                    if (kq2dc__abs_s16((s16)(b->y - a->y)) >= radius_sum) continue;
                    kq2dc__resolve_pair(a, b);
                }
            }
        }
    }

    for (i = 0; i < count; i++)
    {
        KQCircleBody2D* body = &bodies[(__safe_index u8)i];
        if (body->active == 0) continue;
        if (body->inv_mass_q8 <= 0) continue;

        body->vx = kq2dc__mul_q8(body->vx, world->linear_damping_q8);
        body->vy = kq2dc__mul_q8(body->vy, world->linear_damping_q8);

        if (body->vx >= -1 && body->vx <= 1) body->vx = 0;
        if (body->vy >= -1 && body->vy <= 1) body->vy = 0;

        if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
    }
}
kq2dc_world_init

Verknüpft ein Kreisarray und setzt Schwerkraft null, vier Durchläufe, eine Geschwindigkeitsgrenze von 768 pro Achse und Dämpfung 252/256.

Syntax

c
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

bodies

Anfang eines vom aufrufenden Code gehaltenen Körperarrays mit body_count Elementen.

body_count

Anzahl der Arrayplätze von 0 bis 255, einschließlich inaktiver Einträge.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

Die Grenzen sind anfangs deaktiviert und auf (0,0)..(159,143) gesetzt; Wandrückprall beträgt 240, Wandreibung 16. Eine Initialisierungsfunktion für Kreiskörper gibt es nicht: Der aufrufende Code muss alle Körperfelder setzen. Eine NULL-Welt wird ignoriert.

Anwendungsbeispiel

c
kq2dc_world_init(&world,balls,1);
    result[0]=world.gravity_y; result[1]=world.solver_iterations;
    result[2]=world.max_speed; result[3]=world.linear_damping_q8;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

kq2dc_world_init: DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
DMG — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
kq2dc_world_init: CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.
CGB — Ein roter Kreis mit Radius 6 bewegt sich vom Mittelpunkt (24,24) links nach (54,24) rechts. Die lokalen Grenzen sind (4,4)..(60,60). Die rechte Wand begrenzt den Mittelpunkt auf 54 und ändert die X-Geschwindigkeit von 32 auf -15: Auf den Wandrückprall mit 128/256 folgt eine Dämpfung mit 255/256. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG werden Kreis und Begrenzung schwarz dargestellt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics2d_circle.h:42

Deklarationshinweise im Original
Retain a caller-owned array without initializing bodies. Set zero gravity,
four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled.
A null world is ignored. Keep the array alive for subsequent steps.

kitaqgb/lib/physics2d_circle.c:360

c
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 0;
    world->solver_iterations = 4;
    world->max_speed = 768;
    world->linear_damping_q8 = 252;
    world->use_bounds = 0;
    world->min_x = 0;
    world->min_y = 0;
    world->max_x = 159;
    world->max_y = 143;
    world->wall_restitution_q8 = 240;
    world->wall_friction_q8 = 16;
}

physics3d.h — Physik für achsenparallele 3D-Quader

Physik für nicht rotierende 3D-Boxen, beschrieben durch Mittelpunkt und halbe Ausdehnung je Achse. Masse und inverse Masse gewichten Kontakte, restitution_q8 steuert den Rückprall und ax/ay/az liefern eine dauerhafte Beschleunigung. Die Darstellung erfolgt separat. Das Beispiel zeichnet Vorder- und Draufsicht desselben Körpers, um Tiefenbewegung und Wandrückprall zu zeigen.

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

last_impact_speed speichert die größte Annäherungsgeschwindigkeit entlang einer Kontaktachse. Die Integration setzt sie bei aktiven dynamischen Körpern zurück; statische und inaktive Körper behalten sie bei. Weder break_speed noch KQ3D_BODY_BROKEN löst automatisch eine Zerstörung aus. Das Spiel entscheidet darüber und ändert flags/active selbst.

kq3d_body_init

Initialisiert 3D-Mittelpunkt, halbe Ausdehnungen und Masse; setzt Geschwindigkeit, Beschleunigung, Aufprallwert und Flags auf null und aktiviert den Körper.

Syntax

c
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

x

X-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.

y

Y-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.

z

Z-Koordinate des Mittelpunkts, in der Draufsicht des Beispiels vertikal dargestellt.

half_x

Halbe Ausdehnung entlang X; die gesamte Boxbreite ist doppelt so groß.

half_y

Halbe Ausdehnung entlang Y; die gesamte Boxhöhe ist doppelt so groß.

half_z

Halbe Ausdehnung entlang Z; die gesamte Tiefe ist doppelt so groß.

mass_q8

Massenwert, bei dem 256 für 1,0 steht. Werte kleiner oder gleich null erzeugen einen statischen Körper.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Der Rückprallkoeffizient beträgt 224, break_speed ist null. Für die Masse gelten die Regeln von kq3d_body_set_mass. NULL wird ignoriert; gültige halbe Ausdehnungen muss der aufrufende Code bereitstellen.

Anwendungsbeispiel

c
kq3d_body_init(&temp,10,20,30,8,8,8,256);
    result[3]=temp.inv_mass_q8; result[4]=temp.restitution_q8; result[5]=temp.active;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_body_init: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_body_init: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:50

Deklarationshinweise im Original
Initialize an active centered box with zero velocity/acceleration,
restitution 224, cleared impact/flags and mass set through the weight helper.
The caller supplies valid half extents. Null body is ignored.

kitaqgb/lib/physics3d.c:330

c
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8)
{
    if (body == 0) return;

    body->x = x;
    body->y = y;
    body->z = z;
    body->vx = 0;
    body->vy = 0;
    body->vz = 0;
    body->ax = 0;
    body->ay = 0;
    body->az = 0;
    body->half_x = half_x;
    body->half_y = half_y;
    body->half_z = half_z;
    body->restitution_q8 = 224;
    body->break_speed = 0;
    body->last_impact_speed = 0;
    body->active = 1;
    body->flags = 0;
    kq3d_body_set_mass(body, mass_q8);
}
kq3d_body_set_mass

Speichert die angeforderte Masse und berechnet ein Gewicht aus der inversen Masse für Korrektur und Rückprall.

Syntax

c
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);

Parameter

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

mass_q8

Massenwert, bei dem 256 für 1,0 steht. Werte kleiner oder gleich null erzeugen einen statischen Körper.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Masse kleiner oder gleich null ergibt inverse Masse null und damit einen statischen Körper. Bei positiver Masse wird ganzzahlig 32767/max(mass,64) berechnet, mindestens jedoch 1. Die gespeicherte Masse behält den angeforderten Wert; das Gewicht ist daher kein exakter Q8-Kehrwert. Masse 256 ergibt inverse Masse 127. Geschwindigkeit und Aktivität bleiben unverändert; NULL wird ignoriert.

Anwendungsbeispiel

c
kq3d_body_set_mass(&temp,32); result[6]=temp.mass_q8; result[7]=temp.inv_mass_q8;
    kq3d_body_set_mass(&temp,0); result[8]=temp.inv_mass_q8;
    kq3d_body_set_mass(&temp,256);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_body_set_mass: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_body_set_mass: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:55

Deklarationshinweise im Original
Store the requested mass; nonpositive mass makes the body static.
For positive mass compute inverse weight as max(1,32767/max(mass,64)).
The stored mass retains the original input; this is a relative solver weight,
not an exact Q8 reciprocal. Null body is ignored.

kitaqgb/lib/physics3d.c:311

c
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8)
{
    if (body == 0) return;

    body->mass_q8 = mass_q8;
    if (mass_q8 <= 0)
    {
        body->inv_mass_q8 = 0;
        return;
    }

    if (mass_q8 < 64) mass_q8 = 64;
    body->inv_mass_q8 = (s16)(32767 / mass_q8);
    if (body->inv_mass_q8 <= 0) body->inv_mass_q8 = 1;
}
kq3d_dot_q8_8

Teilt jedes der drei vorzeichenbehafteten Produkte durch 256, schneidet jeden Term gegen null ab und addiert anschließend die Terme.

Syntax

c
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);

Parameter

x

Vorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.

y

Vorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.

z

Vorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.

ax

Vorzeichenbehafteter Bytekoeffizient für diese Achse (-128..127), mit Faktor 1/256 angewendet.

ay

Vorzeichenbehafteter Bytekoeffizient für diese Achse (-128..127), mit Faktor 1/256 angewendet.

az

Vorzeichenbehafteter Bytekoeffizient für diese Achse (-128..127), mit Faktor 1/256 angewendet.

Rückgabewert

Liefert die Summe dreier quantisierter Terme als s16.

Bedingungen und Grenzen

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Jeden Term zuerst gegen null abzuschneiden kann ein anderes Ergebnis liefern als die Gesamtsumme einmal zu schieben. Ein Koeffizient kann 1,0=256 nicht speichern. Die Endsumme wird nicht gesättigt.

Anwendungsbeispiel

c
result[13]=kq3d_dot_q8_8(256,128,0,64,-64,127);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_dot_q8_8: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_dot_q8_8: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:74

Deklarationshinweise im Original
Sum three signed products, shifting each by eight bits before addition.
Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.

kitaqgb/lib/physics3d.c:576

c
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az)
{
    return __sdot3_q8_8(x, y, z, ax, ay, az);
}
kq3d_integrate_body

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Setzt den Aufprallwert eines aktiven dynamischen Körpers zurück, addiert Weltschwerkraft und Körperbeschleunigung, begrenzt jede Geschwindigkeitsachse und aktualisiert die Position.

Syntax

c
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

body

Zeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Integration und Kollisionserkennung für Boxen verwenden gemeinsamen Arbeitsspeicher. Rufen Sie diese Physikroutinen nicht während ihrer Ausführung erneut aus einem Interrupt auf.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

last_impact_speed speichert die größte Annäherungsgeschwindigkeit entlang einer Kontaktachse. Die Integration setzt sie bei aktiven dynamischen Körpern zurück; statische und inaktive Körper behalten sie bei. Weder break_speed noch KQ3D_BODY_BROKEN löst automatisch eine Zerstörung aus. Das Spiel entscheidet darüber und ändert flags/active selbst.

ax/ay/az bleiben erhalten und wirken erneut bei der nächsten Integration. Diese Funktion allein löst keine Kontakte auf. NULL, inaktive und statische Körper werden nicht verändert.

Anwendungsbeispiel

c
kq3d_integrate_body(&world,&temp);
    result[9]=temp.x; result[10]=temp.y; result[11]=temp.z; result[12]=temp.last_impact_speed;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_integrate_body: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_integrate_body: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:66

Deklarationshinweise im Original
Reset impact for one active dynamic body, add gravity and persistent body
acceleration, clamp velocity per axis and advance position. Static/inactive
bodies retain impact state. Null inputs are ignored; no contacts are solved.
Use a nonnegative speed limit and avoid overflow before clamping.

kitaqgb/lib/physics3d.c:436

c
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body)
{
    if (world == 0) return;
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    body->last_impact_speed = 0;
    kq3d_asm_value = body->vx;
    kq3d_asm_operand = world->gravity_x;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->ax;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vx = kq3d_asm_value;

    kq3d_asm_value = body->vy;
    kq3d_asm_operand = world->gravity_y;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->ay;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vy = kq3d_asm_value;

    kq3d_asm_value = body->vz;
    kq3d_asm_operand = world->gravity_z;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->az;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vz = kq3d_asm_value;

    kq3d_asm_value = body->x;
    kq3d_asm_operand = body->vx;
    kq3d_add_s16_asm();
    body->x = kq3d_asm_value;

    kq3d_asm_value = body->y;
    kq3d_asm_operand = body->vy;
    kq3d_add_s16_asm();
    body->y = kq3d_asm_value;

    kq3d_asm_value = body->z;
    kq3d_asm_operand = body->vz;
    kq3d_add_s16_asm();
    body->z = kq3d_asm_value;
}
kq3d_overlap_aabb

Prüft zwei über ihren Mittelpunkt definierte Boxen auf echte Überlappung entlang aller drei Achsen.

Syntax

c
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);

Parameter

a

Gültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.

b

Gültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.

Rückgabewert

Liefert 1 bei Überlappung der Innenbereiche und 0 bei bloßer Berührung oder getrennten Formen.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Anwendungsbeispiel

c
result[14]=kq3d_overlap_aabb(&bodies[0],&bodies[1]);
    bodies[1].z=32; result[15]=kq3d_overlap_aabb(&bodies[0],&bodies[1]);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_overlap_aabb: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_overlap_aabb: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:70

Deklarationshinweise im Original
Test strict overlap on all three axes; face-only contact returns false.
Valid pointers are required and flags are ignored. Center differences and
extent sums must fit the signed 16-bit magnitude calculations.

kitaqgb/lib/physics3d.c:357

c
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b)
{
    s16 dx = kq3d__abs_s16((s16)(b->x - a->x));
    s16 dy = kq3d__abs_s16((s16)(b->y - a->y));
    s16 dz = kq3d__abs_s16((s16)(b->z - a->z));

    s16 sx = (s16)(a->half_x + b->half_x);
    s16 sy = (s16)(a->half_y + b->half_y);
    s16 sz = (s16)(a->half_z + b->half_z);

    if (dx >= sx) return 0;
    if (dy >= sy) return 0;
    if (dz >= sz) return 0;
    return 1;
}
kq3d_step

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Integriert aktive dynamische Körper und verarbeitet Kontaktkorrektur, Rückprall und Aufprallwerte zwischen aktiven Welteinträgen.

Syntax

c
void kq3d_step(KQWorld3D* world);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

Summen, Differenzen, addierte halbe Ausdehnungen und Produkte zur Kontaktkorrektur müssen im vorzeichenbehafteten 16-Bit-Bereich bleiben. Geschwindigkeitsgrenzen greifen erst nach der Addition und verhindern keinen Überlauf innerhalb dieser Addition.

Integration und Kollisionserkennung für Boxen verwenden gemeinsamen Arbeitsspeicher. Rufen Sie diese Physikroutinen nicht während ihrer Ausführung erneut aus einem Interrupt auf.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Kontakte nutzen die Achse mit der geringsten Eindringtiefe; bei Gleichstand gilt die Reihenfolge X, Y, Z. Nur eine Annäherung führt zum Abprallen. Dafür werden inverse Massen und der auf 0..256 begrenzte mittlere Rückprallkoeffizient verwendet. Schnelles Durchtunneln, Rotation, Drehimpuls und Reibung werden nicht behandelt.

last_impact_speed speichert die größte Annäherungsgeschwindigkeit entlang einer Kontaktachse. Die Integration setzt sie bei aktiven dynamischen Körpern zurück; statische und inaktive Körper behalten sie bei. Weder break_speed noch KQ3D_BODY_BROKEN löst automatisch eine Zerstörung aus. Das Spiel entscheidet darüber und ändert flags/active selbst.

Eine NULL-Welt oder ein NULL-Array wird ignoriert. Auch bei solver_iterations gleich null wird ein Kontaktdurchlauf ausgeführt.

Auch die Zwischenprodukte impact*(256+restitution) und correction*inverse-mass sind s16. Halten Sie die Produkte bei höchstens 32767; bei restitution 256 darf impact beispielsweise höchstens 63 betragen.

Anwendungsbeispiel

c
kq3d_step(&world);
    result[16]=bodies[0].x; result[17]=bodies[0].y; result[18]=bodies[0].z;
    result[19]=bodies[0].vx; result[20]=bodies[0].vz;
    result[21]=bodies[0].last_impact_speed; result[22]=bodies[0].flags;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_step: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_step: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:61

Deklarationshinweise im Original
Integrate active dynamic bodies and reset their impact values, then solve
each active unordered pair for the configured passes (zero means one).
Static bodies retain previous impact maxima until the game clears them.
Acceleration persists; flags and break thresholds remain game-owned.
This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.

kitaqgb/lib/physics3d.c:492

c
void kq3d_step(KQWorld3D* world)
{
    if (world == 0) return;
    if (world->bodies == 0) return;

    KQBody3D* bodies = world->bodies;
    u8 count = world->body_count;

    u8 i;
    for (i = 0; i < count; i++)
    {
        KQBody3D* b = &bodies[(__safe_index u8)i];
        if (b->active == 0) continue;
        if (b->inv_mass_q8 <= 0) continue;

        b->last_impact_speed = 0;
        kq3d_asm_value = b->vx;
        kq3d_asm_operand = world->gravity_x;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->ax;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vx = kq3d_asm_value;

        kq3d_asm_value = b->vy;
        kq3d_asm_operand = world->gravity_y;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->ay;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vy = kq3d_asm_value;

        kq3d_asm_value = b->vz;
        kq3d_asm_operand = world->gravity_z;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->az;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vz = kq3d_asm_value;

        kq3d_asm_value = b->x;
        kq3d_asm_operand = b->vx;
        kq3d_add_s16_asm();
        b->x = kq3d_asm_value;

        kq3d_asm_value = b->y;
        kq3d_asm_operand = b->vy;
        kq3d_add_s16_asm();
        b->y = kq3d_asm_value;

        kq3d_asm_value = b->z;
        kq3d_asm_operand = b->vz;
        kq3d_add_s16_asm();
        b->z = kq3d_asm_value;
    }

    u8 iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    u8 it;
    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQBody3D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;

            u8 j;
            for (j = (u8)(i + 1); j < count; j++)
            {
                KQBody3D* b = &bodies[(__safe_index u8)j];
                if (b->active == 0) continue;
                kq3d__resolve_pair(a, b);
            }
        }
    }
}
kq3d_world_init

Verknüpft ein Körperarray mit einer 3D-Welt mit Schwerkraft (0,24,0), vier Durchläufen und Geschwindigkeitsgrenze 512 pro Achse.

Syntax

c
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);

Parameter

world

Zeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.

bodies

Anfang eines vom aufrufenden Code gehaltenen Körperarrays mit body_count Elementen.

body_count

Anzahl der Arrayplätze von 0 bis 255, einschließlich inaktiver Einträge.

Rückgabewert

Kein Rückgabewert. Dieser Eintrag erläutert die geänderten Felder und den Zeitpunkt, zu dem die Änderungen wirksam werden.

Bedingungen und Grenzen

Verwenden Sie einheitliche ganzzahlige Einheiten für Positionen, Radien, halbe Ausdehnungen, Geschwindigkeiten und Schwerkraft. Ein Schritt entspricht einem Simulationstakt. Die Beispiele verwenden eine Einheit pro Pixel. Diese Routinen wandeln Positionen weder automatisch in Q8.8 um noch zeichnen sie diese.

Eine Welt nutzt ein vom aufrufenden Code bereitgestelltes Array. Dieser reserviert und besitzt den Speicher für die Körper und hält ihn gültig. Das Initialisieren der Welt initialisiert nicht die Arrayelemente.

physics3d.c liegt in ROM-Bank 2. Das Beispiel verwendet ein 128-KB-ROM mit MBC5, bindet diese Implementierung zuerst ein und legt main in Bank 0 ab. Ändern Sie während eines Aufrufs die ROM-Zuordnung nicht von außen.

Anwendungsbeispiel

c
kq3d_world_init(&world,bodies,2);
    result[0]=world.gravity_y; result[1]=world.solver_iterations; result[2]=world.max_speed;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

kq3d_world_init: DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
DMG — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
kq3d_world_init: CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.
CGB — Links ist die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Boxen zeigen (36,24,24) nach einem Takt, und blaue Flächen stellen das statische Hindernis dar. Die X-Geschwindigkeit springt beim Rückprall von 16 auf -14, während Z bei 8 bleibt. Der Aufprallwert beträgt 16, flags bleibt jedoch trotz break_speed=1 null. Die Panelursprünge liegen bei (8,48)/(88,48) auf dem Bildschirm. Auf dem DMG sind alle Markierungen schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/physics3d.h:46

Deklarationshinweise im Original
Borrow the body array without initializing it. Set gravity (0,24,0), four
contact passes and a per-axis speed limit of 512. Null world is ignored;
the caller retains ownership and must keep the array alive.

kitaqgb/lib/physics3d.c:294

c
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 24;
    world->gravity_z = 0;
    world->solver_iterations = 4;
    world->max_speed = 512;
}

raster.h — Scrolltabellen für Bildstreifen und Bildschirmzeilen

Die Raster-Bibliothek bietet eine Tabelle mit acht Bändern und einen LineX-Renderer, der X auf allen 144 sichtbaren Zeilen ändert. Bänder eignen sich für feste HUDs, Parallaxe, Fensteränderungen und CGB-Farbbereiche. LineX eignet sich für wellenförmige Titel und Bildschirmeffekte. Wählen Sie einen Treiber; betreiben Sie nicht beide gleichzeitig.

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Rasterzeilenwelle und animierte Titeleinblendung

Wird die X-Position des Hintergrunds für jede Bildschirmzeile verändert, verbiegen sich Säulen und Schrift wellenförmig. Das eignet sich für eine Teleportation, einen Bossauftritt oder eine Titelanimation. Die Vorschau unten zeigt acht Aufnahmen im Wechsel; in der ROM schreitet die Wellenphase mit jedem Frame fort.

Raster_Push-Operationen planen bis zu acht Bänder. Verwenden Sie Raster_LineXRunFrame für einen eigenen horizontalen Versatz je Rasterzeile. Sprites und Fenster werden nicht verbogen. Der Renderer belegt während aller 144 sichtbaren Zeilen die CPU und maskiert Interrupts; aktualisieren Sie Spiellogik und Audio daher zwischen den Aufrufen.

CGB-Aufnahme: Jede Bildschirmzeile versetzt die Kanten der Säulen. Eine Welle mit einer Länge von 64 Zeilen läuft durch die Szene; der Versatz beträgt bis zu 24 Pixel in beide Richtungen.
CGB-Aufnahme: Jede Bildschirmzeile versetzt die Kanten der Säulen. Eine Welle mit einer Länge von 64 Zeilen läuft durch die Szene; der Versatz beträgt bis zu 24 Pixel in beide Richtungen.

Beispiel einer fortlaufenden Welle

Beispiel einer Titeleinblendung

Der Titel kommt von rechts mit einer großen Welle ins Bild, wechselt zu einer kleinen Wellenbewegung und kommt dann zur Ruhe. Das Beispiel bindet raster_wave.c aus demselben Verzeichnis ein; halten Sie beide Quelldateien zusammen. Die API-Einträge unten enthalten Build-Befehle und individuelle Nutzungshinweise.

Die Raster-Bibliothek bietet eine Tabelle mit acht Bändern und einen LineX-Renderer, der X auf allen 144 sichtbaren Zeilen ändert. Bänder eignen sich für feste HUDs, Parallaxe, Fensteränderungen und CGB-Farbbereiche. LineX eignet sich für wellenförmige Titel und Bildschirmeffekte. Wählen Sie einen Treiber; betreiben Sie nicht beide gleichzeitig.

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Raster_BuildHudBottom

Erstellt ein scrollendes oberes Spielfeld und ein festes unteres HUD. LY=0 verwendet Kamerakoordinaten; hud_y schaltet den Hintergrund auf (0,0).

Syntax

c
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);

Parameter

hud_y

Teilungszeile in 1..143. Null oder Werte ab 144 liefern BAD_RANGE.

camera_x

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

camera_y

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Gültige Parameter stoppen bestehende Teilungen, leeren die Tabelle und fügen neue Bänder hinzu. Ungültige Parameter lassen Tabelle und Anzahl unverändert und speichern BAD_RANGE. Auch nach erfolgreichem Aufbau ist Raster_Commit erforderlich.

Anwendungsbeispiel

c
Raster_BuildHudBottom(96,8,8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeilen ab 96 bleiben fest. Kamera (8,8) setzt die oberen Rechtecke auf (24,8) und (24,72), während das untere bei (32,112) bleibt. FIXED BOTTOM HUD bleibt unten.

Raster_BuildHudBottom: DMG — Die Zeilen ab 96 bleiben fest. Kamera (8,8) setzt die oberen Rechtecke auf (24,8) und (24,72), während das untere bei (32,112) bleibt. FIXED BOTTOM HUD bleibt unten.
DMG — Die Zeilen ab 96 bleiben fest. Kamera (8,8) setzt die oberen Rechtecke auf (24,8) und (24,72), während das untere bei (32,112) bleibt. FIXED BOTTOM HUD bleibt unten.
Raster_BuildHudBottom: CGB — Die Zeilen ab 96 bleiben fest. Kamera (8,8) setzt die oberen Rechtecke auf (24,8) und (24,72), während das untere bei (32,112) bleibt. FIXED BOTTOM HUD bleibt unten.
CGB — Die Zeilen ab 96 bleiben fest. Kamera (8,8) setzt die oberen Rechtecke auf (24,8) und (24,72), während das untere bei (32,112) bleibt. FIXED BOTTOM HUD bleibt unten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_bottom.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:73

Deklarationshinweise im Original
Build a scrolling upper playfield and fixed bottom HUD after validating the split.

kitaqgb/lib/raster.c:183

c
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y)
{
    u8 r;

    if (hud_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (hud_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, camera_x, camera_y);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(hud_y, 0, 0);
}
Raster_BuildHudTop

Erstellt zwei Hintergrundbänder für ein festes oberes HUD: (0,0) bei LY=0, danach Kamerakoordinaten ab hud_height. Dies teilt den Hintergrundscroll und verwendet kein Fenster.

Syntax

c
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);

Parameter

hud_height

Teilungszeile in 1..143. Null oder Werte ab 144 liefern BAD_RANGE.

camera_x

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

camera_y

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Gültige Parameter stoppen bestehende Teilungen, leeren die Tabelle und fügen neue Bänder hinzu. Ungültige Parameter lassen Tabelle und Anzahl unverändert und speichern BAD_RANGE. Auch nach erfolgreichem Aufbau ist Raster_Commit erforderlich.

Anwendungsbeispiel

c
Raster_BuildHudTop(32,8,8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die oberen 32 Zeilen bleiben fest. Das obere Rechteck bleibt bei (32,16); Kamera (8,8) verschiebt die anderen beiden nach (24,72) und (24,104). FIXED TOP HUD bleibt oben.

Raster_BuildHudTop: DMG — Die oberen 32 Zeilen bleiben fest. Das obere Rechteck bleibt bei (32,16); Kamera (8,8) verschiebt die anderen beiden nach (24,72) und (24,104). FIXED TOP HUD bleibt oben.
DMG — Die oberen 32 Zeilen bleiben fest. Das obere Rechteck bleibt bei (32,16); Kamera (8,8) verschiebt die anderen beiden nach (24,72) und (24,104). FIXED TOP HUD bleibt oben.
Raster_BuildHudTop: CGB — Die oberen 32 Zeilen bleiben fest. Das obere Rechteck bleibt bei (32,16); Kamera (8,8) verschiebt die anderen beiden nach (24,72) und (24,104). FIXED TOP HUD bleibt oben.
CGB — Die oberen 32 Zeilen bleiben fest. Das obere Rechteck bleibt bei (32,16); Kamera (8,8) verschiebt die anderen beiden nach (24,72) und (24,104). FIXED TOP HUD bleibt oben.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_top.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:71

Deklarationshinweise im Original
Validate the HUD height, then replace pending splits with a fixed top band
and scrolling playfield. The new table still requires an explicit commit.

kitaqgb/lib/raster.c:169

c
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y)
{
    u8 r;

    if (hud_height == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (hud_height >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, 0, 0);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(hud_height, camera_x, camera_y);
}
Raster_BuildParallax2

Erstellt zwei Hintergrundbänder mit getrennten horizontalen Offsets: far_scx bei LY=0 und near_scx ab split_y, bei gemeinsamem Y-Scroll.

Syntax

c
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);

Parameter

split_y

Teilungszeile in 1..143. Null oder Werte ab 144 liefern BAD_RANGE.

far_scx

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

near_scx

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scy

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Gültige Parameter stoppen bestehende Teilungen, leeren die Tabelle und fügen neue Bänder hinzu. Ungültige Parameter lassen Tabelle und Anzahl unverändert und speichern BAD_RANGE. Auch nach erfolgreichem Aufbau ist Raster_Commit erforderlich.

Anwendungsbeispiel

c
Raster_BuildParallax2(64,0,16,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

X wechselt an der geplanten Zeile 64 von 0 auf 16. Rechtecke erscheinen bei (32,16), (16,80) und (16,112); nur der untere Bereich wird sechzehn Pixel nach links verschoben.

Raster_BuildParallax2: DMG — X wechselt an der geplanten Zeile 64 von 0 auf 16. Rechtecke erscheinen bei (32,16), (16,80) und (16,112); nur der untere Bereich wird sechzehn Pixel nach links verschoben.
DMG — X wechselt an der geplanten Zeile 64 von 0 auf 16. Rechtecke erscheinen bei (32,16), (16,80) und (16,112); nur der untere Bereich wird sechzehn Pixel nach links verschoben.
Raster_BuildParallax2: CGB — X wechselt an der geplanten Zeile 64 von 0 auf 16. Rechtecke erscheinen bei (32,16), (16,80) und (16,112); nur der untere Bereich wird sechzehn Pixel nach links verschoben.
CGB — X wechselt an der geplanten Zeile 64 von 0 auf 16. Rechtecke erscheinen bei (32,16), (16,80) und (16,112); nur der untere Bereich wird sechzehn Pixel nach links verschoben.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:76

Deklarationshinweise im Original
Build two horizontal-scroll bands sharing one vertical scroll value.

kitaqgb/lib/raster.c:197

c
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy)
{
    u8 r;

    if (split_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (split_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, far_scx, scy);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(split_y, near_scx, scy);
}
Raster_BuildParallax3

Trägt scx0, scx1 und scx2 für Bänder ab LY=0, y1 und y2 ein. Ferne, mittlere und nahe Ebenen erhalten verschiedene horizontale Offsets bei gemeinsamem Y-Scroll.

Syntax

c
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);

Parameter

y1

Teilungszeilen mit der Bedingung 1 <= y1 < y2 <= 143.

y2

Teilungszeilen mit der Bedingung 1 <= y1 < y2 <= 143.

scx0

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scx1

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scx2

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scy

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Gültige Parameter stoppen bestehende Teilungen, leeren die Tabelle und fügen neue Bänder hinzu. Ungültige Parameter lassen Tabelle und Anzahl unverändert und speichern BAD_RANGE. Auch nach erfolgreichem Aufbau ist Raster_Commit erforderlich.

Anwendungsbeispiel

c
Raster_BuildParallax3(64,104,0,8,16,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die geplanten Zeilen 64 und 104 begrenzen Bereiche mit X-Offsets 0, 8 und 16. Rechtecke bei (32,16), (24,80) und (16,112) zeigen die zunehmende Verschiebung über drei Bänder.

Raster_BuildParallax3: DMG — Die geplanten Zeilen 64 und 104 begrenzen Bereiche mit X-Offsets 0, 8 und 16. Rechtecke bei (32,16), (24,80) und (16,112) zeigen die zunehmende Verschiebung über drei Bänder.
DMG — Die geplanten Zeilen 64 und 104 begrenzen Bereiche mit X-Offsets 0, 8 und 16. Rechtecke bei (32,16), (24,80) und (16,112) zeigen die zunehmende Verschiebung über drei Bänder.
Raster_BuildParallax3: CGB — Die geplanten Zeilen 64 und 104 begrenzen Bereiche mit X-Offsets 0, 8 und 16. Rechtecke bei (32,16), (24,80) und (16,112) zeigen die zunehmende Verschiebung über drei Bänder.
CGB — Die geplanten Zeilen 64 und 104 begrenzen Bereiche mit X-Offsets 0, 8 und 16. Rechtecke bei (32,16), (24,80) und (16,112) zeigen die zunehmende Verschiebung über drei Bänder.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:79

Deklarationshinweise im Original
Build three horizontal-scroll bands at ordered visible split lines. Invalid
parameters leave the previous pending table intact and set the error status.

kitaqgb/lib/raster.c:212

c
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy)
{
    u8 r;

    if (y1 == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (y2 >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (y2 <= y1) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, scx0, scy);
    if (r != KQ_RASTER_OK) return r;
    r = Raster_Push(y1, scx1, scy);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(y2, scx2, scy);
}
Raster_Clear

Stoppt die Teilungsplanung sofort und setzt Anzahl, Reihenfolge und Fehlerzustand zurück, bevor die Tabelle in derselben Szene neu aufgebaut wird. Nicht jedes Byte des Tabellenspeichers wird auf null gesetzt.

Syntax

c
void Raster_Clear();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Das Stoppen der Teilungen setzt SCX, SCY, WX und WY nicht auf null. Stellen Sie den gewünschten Grundzustand mit normalen Setzfunktionen wie Scroll_SetBg her. Auch vorherige VBlank-/STAT-IE-Bits oder IME werden nicht wiederhergestellt.

Anwendungsbeispiel

c
Raster_Clear();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_Clear: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_Clear: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:39

Deklarationshinweise im Original
Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.

kitaqgb/lib/raster.c:65

c
void Raster_Clear()
{
    Scroll_SplitReset();
    Raster_CountValue = 0;
    Raster_LastLyValue = 0;
    Raster_HasLastLy = 0;
    Raster_LastErrorValue = KQ_RASTER_OK;
}
Raster_Commit

Aktiviert die aufgebaute gemeinsame Tabelle. Auch wenn ein Hinzufügen fehlschlug, werden zuvor erfolgreich eingetragene Bänder aktiviert. Der aufrufende Code muss jede Eintragung prüfen.

Syntax

c
u8 Raster_Commit();

Rückgabewert

Liefert den zuletzt gespeicherten Fehler. Null beweist nicht, dass alle vorherigen Eintragungen erfolgreich waren.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Eine nicht leere Tabelle setzt die VBlank-/STAT-IE-Bits und führt EI aus, um Interrupts zu aktivieren; andere IE-Bits bleiben erhalten. Eine leere Tabelle deaktiviert die Teilungsplanung, stellt aber die globale Interruptkonfiguration nicht wieder her.

Anwendungsbeispiel

c
result[2]=Raster_Commit();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_Commit: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_Commit: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:67

Deklarationshinweise im Original
Publish pending splits and return the stored status. This commits even if an
earlier append failed; callers should inspect errors while building the table.

kitaqgb/lib/raster.c:161

c
u8 Raster_Commit()
{
    Scroll_SplitCommit();
    return Raster_LastErrorValue;
}
Raster_Disable

Leert und aktiviert eine leere Tabelle, um Rasterbänder abzuschalten. Verwenden Sie dies als ausdrücklichen Stopp beim Wechsel in eine Szene ohne geteiltes Scrollen.

Syntax

c
void Raster_Disable();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Das Stoppen der Teilungen setzt SCX, SCY, WX und WY nicht auf null. Stellen Sie den gewünschten Grundzustand mit normalen Setzfunktionen wie Scroll_SetBg her. Auch vorherige VBlank-/STAT-IE-Bits oder IME werden nicht wiederhergestellt.

Anwendungsbeispiel

c
Raster_Disable();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_Disable: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_Disable: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:41

Deklarationshinweise im Original
Commit an empty split table so no raster bands remain active.

kitaqgb/lib/raster.c:75

c
void Raster_Disable()
{
    Raster_Clear();
    Scroll_SplitCommit();
}
Raster_GetCount

Liest die Anzahl der über den Raster-Wrapper eingetragenen Bänder. Clear/Disable setzt sie auf null; bloßes Aktivieren erhält sie.

Syntax

c
u8 Raster_GetCount();

Rückgabewert

Liefert die Anzahl der Einträge in 0..8. Acht minus dieser Wert ergibt die freie Kapazität. Das Lesen verändert keinen Zustand.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
result[0]=Raster_GetCount();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_GetCount: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_GetCount: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:44

Deklarationshinweise im Original
Read the number of bands currently recorded by this wrapper.

kitaqgb/lib/raster.c:82

c
u8 Raster_GetCount()
{
    return Raster_CountValue;
}
Raster_GetLastError

Liest den zuletzt gespeicherten Raster-Status, ohne ihn zu löschen. Er ist keine kumulative Aufzeichnung aller früheren Fehler.

Syntax

c
u8 Raster_GetLastError();

Rückgabewert

Liefert den gespeicherten Status in 0..4. Das Aktivieren gibt diesen Wert zurück, macht aber weder einen Fehler automatisch rückgängig noch verwirft es die Tabelle.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
result[1]=Raster_GetLastError();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_GetLastError: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_GetLastError: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:46

Deklarationshinweise im Original
Read the last stored status without clearing it.

kitaqgb/lib/raster.c:88

c
u8 Raster_GetLastError()
{
    return Raster_LastErrorValue;
}
Raster_Init

Leert die gemeinsame Bandtabelle, stoppt Teilungen und initialisiert Anzahl, Gültigkeit des letzten LY sowie Fehlerzustand. Anders als Scroll_Init initialisiert dies nicht die Hintergrund- und Fensterkoordinaten.

Syntax

c
void Raster_Init();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Das Stoppen der Teilungen setzt SCX, SCY, WX und WY nicht auf null. Stellen Sie den gewünschten Grundzustand mit normalen Setzfunktionen wie Scroll_SetBg her. Auch vorherige VBlank-/STAT-IE-Bits oder IME werden nicht wiederhergestellt.

Anwendungsbeispiel

c
Raster_Init();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_Init: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_Init: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:37

Deklarationshinweise im Original
Stop split scheduling, empty the shared table and clear error/count state.

kitaqgb/lib/raster.c:59

c
void Raster_Init()
{
    Raster_Clear();
}
Raster_LineXGetOffset

Berechnet SCX für die gewünschte Zeile, ohne Zustand, Anzeige oder Phase zu ändern.

Syntax

c
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);

Parameter

effect

Zeiger auf einen initialisierten RasterLineX, der während des gesamten Aufrufs gültig bleibt.

ly

Abzufragende Zeilenkoordinate (0..255); sichtbar sind Zeilen 0..143. Die Abfrage läuft mit der Wellenperiode um, statt einen Bereichsfehler zu melden.

Rückgabewert

Achtbit-SCX aus Basis-X plus Verschiebung der jeweiligen Zeile. Die Beispielabfrage bei Phase 8, Zeile 0 liefert 17.

Bedingungen und Grenzen

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
wave_lookup = Raster_LineXGetOffset(&wave, 0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Raster_LineXGetOffset: DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
Raster_LineXGetOffset: CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:91

Deklarationshinweise im Original
Look up the selected periodic profile at LY + phase and add base X modulo
256. An unknown profile returns the unmodified base X.

kitaqgb/lib/raster.c:264

c
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly)
{
    u8 index;

    if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
        index = (u8)((ly + effect->phase) & 15);
        return (u8)(effect->base_x + Raster_LineXXTitle[(__safe_index u8)index]);
    }

    if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
        index = (u8)((ly + effect->phase) & 63);
        return (u8)(effect->base_x + Raster_LineXTravelGate[(__safe_index u8)index]);
    }

    return effect->base_x;
}
Raster_LineXInit

Initialisiert Profil und Basis-X mit Phase null und einem Phasenschritt pro Frame. Der Aufruf zeichnet nichts und schreibt keine Scrollregister.

Syntax

c
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);

Parameter

effect

Zeiger auf beschreibbaren RasterLineX-Speicher; eine vorherige Initialisierung ist nicht nötig.

profile

0 (FLAT) erzeugt keine Verschiebung; 1 (X_TITLE) wiederholt Offsets von −4 bis +3 Pixeln alle 16 Zeilen; 2 (TRAVEL_GATE) wiederholt eine Welle von ±24 Pixeln alle 64 Zeilen. Andere Werte erzeugen keine Verschiebung.

base_x

Hintergrund-X, das zur Wellenverschiebung addiert wird, in Pixeln (0..255).

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
Raster_LineXInit(&wave, KQ_RASTER_LINE_TRAVEL_GATE, 0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Raster_LineXInit: DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
Raster_LineXInit: CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:82

Deklarationshinweise im Original
Initialize a scanline-wave state with phase zero and one phase step per frame.

kitaqgb/lib/raster.c:229

c
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x)
{
    effect->profile = profile;
    effect->base_x = base_x;
    effect->phase = 0;
    effect->phase_step = 1;
    effect->frame_divider = 1;
    effect->frame_counter = 0;
}
Raster_LineXRunFrame

Wartet auf VBlank und rendert die folgenden 144 sichtbaren Zeilen mit zeilenweisem Hintergrund-X. Anschließend wird der Teilerzähler erhöht und die Phase im gewählten Intervall aktualisiert.

Syntax

c
void Raster_LineXRunFrame(RasterLineX* effect);

Parameter

effect

Zeiger auf einen initialisierten RasterLineX, der während des gesamten Aufrufs gültig bleibt.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bei ausgeschaltetem LCD kehrt die Funktion sofort ohne Effektänderung zurück. Andernfalls blockiert sie, bis SCX für alle 144 Zeilen aktualisiert ist, stellt den Interrupt-Aktivierungszustand wieder her und synchronisiert die Scroll-Hilfe mit dem letzten SCX. Die Rückkehr garantiert keinen aktiven VBlank. Warten Sie vor direkten VRAM-Schreibzugriffen auf VBlank oder nutzen Sie eine Übertragungsroutine mit sicherem Zugriffstiming.

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
Raster_LineXRunFrame(&wave);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Raster_LineXRunFrame: DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
Raster_LineXRunFrame: CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:96

Deklarationshinweise im Original
Render all 144 visible lines with one SCX write per line, then advance phase.
This foreground renderer masks interrupts during the visible frame. Do game
and audio work between calls; do not combine it with a STAT raster driver.
Returns without changing the effect when the LCD is off.

kitaqgb/lib/raster.c:298

c
void Raster_LineXRunFrame(RasterLineX* effect)
{
    u8 interrupt_state;
    if ((Raster_LineXLcdc & 0x80) == 0) return;
    Raster_LineXTable = Raster_LineXFlat;
    Raster_LineXMask = 15;
    if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
        Raster_LineXTable = Raster_LineXXTitle;
    }
    if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
        Raster_LineXTable = Raster_LineXTravelGate;
        Raster_LineXMask = 63;
    }
    Raster_LineXPhase = effect->phase;
    Raster_LineXBase = effect->base_x;
    interrupt_state = __critical_enter();
    __asm {
        PUSH_AF
        PUSH_BC
        PUSH_DE
        PUSH_HL
        // Use the current VBlank when the preceding frame ended there.
        // Waiting for another VBlank edge would leave every second frame flat.
raster_linex_vblank:
        LDH_A_MEM 0x44
        CP_IMM 144
        JR_C raster_linex_vblank
        LD_B_IMM 0
        LD_A_MEM Raster_LineXPhase
        LD_C_A
        LD_A_MEM Raster_LineXMask
        LD_D_A
        LD_A_MEM Raster_LineXBase
        LD_E_A
raster_linex_line:
        LD_A_B
        ADD_C
        AND_D
        LD_L_A
        LD_H_IMM 0
        PUSH_DE
        LD_A_MEM Raster_LineXTable
        LD_E_A
        LD_A_MEM Raster_LineXTable+1
        LD_D_A
        ADD_HL_DE
        POP_DE
        LD_A_HL
        ADD_E
        PUSH_AF
raster_linex_wait:
        LDH_A_MEM 0x44
        CP_B
        JR_NZ raster_linex_wait
        POP_AF
        LDH_MEM_A 0x43
        INC_B
        LD_A_B
        CP_IMM 144
        JR_NZ raster_linex_line
        POP_HL
        POP_DE
        POP_BC
        POP_AF
    }
    // Synchronize the scroll helper's tracked state with the last hardware write.
    __scroll_bg_x_set(Raster_LineXScx);
    __critical_leave(interrupt_state);
    effect->frame_counter++;
    if (effect->frame_counter >= effect->frame_divider) {
        effect->frame_counter = 0;
        effect->phase = (u8)(effect->phase + effect->phase_step);
    }
}
Raster_LineXSetPhase

Setzt die Wellenposition direkt und erhält Basis-X, Geschwindigkeit und Teilerzähler.

Syntax

c
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);

Parameter

effect

Zeiger auf einen initialisierten RasterLineX, der während des gesamten Aufrufs gültig bleibt.

phase

Achtbit-Phasenwert; die gewählte Welle wiederholt sich alle 16 oder 64 Schritte.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
Raster_LineXSetPhase(&wave, 8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Raster_LineXSetPhase: DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
Raster_LineXSetPhase: CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:88

Deklarationshinweise im Original
Set the byte phase directly without resetting the frame-divider counter.

kitaqgb/lib/raster.c:257

c
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase)
{
    effect->phase = phase;
}
Raster_LineXSetProfile

Wählt ein Profil und setzt Phase und Frame-Teilerzähler auf null. Basis-X und Geschwindigkeit bleiben erhalten.

Syntax

c
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);

Parameter

effect

Zeiger auf einen initialisierten RasterLineX, der während des gesamten Aufrufs gültig bleibt.

profile

0 (FLAT) erzeugt keine Verschiebung; 1 (X_TITLE) wiederholt Offsets von −4 bis +3 Pixeln alle 16 Zeilen; 2 (TRAVEL_GATE) wiederholt eine Welle von ±24 Pixeln alle 64 Zeilen. Andere Werte erzeugen keine Verschiebung.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
Raster_LineXSetProfile(&wave, KQ_RASTER_LINE_X_TITLE);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.

Raster_LineXSetProfile: DMG / Frame 16 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
DMG / Frame 16 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
Raster_LineXSetProfile: DMG / Frame 60 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
DMG / Frame 60 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
Raster_LineXSetProfile: DMG / Frame 120 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
DMG / Frame 120 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
Raster_LineXSetProfile: CGB / Frame 16 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
CGB / Frame 16 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
Raster_LineXSetProfile: CGB / Frame 60 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
CGB / Frame 60 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
Raster_LineXSetProfile: CGB / Frame 120 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.
CGB / Frame 120 — Der eigenständig gestaltete Titel ORBIT GUARD kommt mit einer großen Welle von rechts ins Bild. Nach 48 gerenderten Frames geht sie in eine kleine Welle über; ab Frame 96 steht der Titel still. Nach 160 Frames wiederholt sich der Einlauf. Die Bilder zeigen nacheinander Einlauf, kleine Welle und ruhenden Titel.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_title_entry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_title_entry.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_title_entry.gb --hardware cgb --run-frames 120 --png .\out\raster_title_entry.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:84

Deklarationshinweise im Original
Change the wave profile and restart its phase/divider counter.

kitaqgb/lib/raster.c:240

c
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile)
{
    effect->profile = profile;
    effect->phase = 0;
    effect->frame_counter = 0;
}
Raster_LineXSetSpeed

Setzt Phasenzuwachs und Aktualisierungsintervall. Setzt den Teilerzähler zurück und erhält die aktuelle Phase.

Syntax

c
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);

Parameter

effect

Zeiger auf einen initialisierten RasterLineX, der während des gesamten Aufrufs gültig bleibt.

phase_step

Phasenzuwachs pro Aktualisierung (0..255). Null friert die Welle ein. 255 bewegt sie durch Achtbitumlauf um einen Schritt rückwärts.

frame_divider

Anzahl tatsächlich rendernder RunFrame-Aufrufe pro Phasenaktualisierung (1..255). Null wählt eins. Aufrufe, die wegen ausgeschaltetem LCD zurückkehren, zählen nicht.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

SCX ist ein Achtbitwert, und der Hintergrund läuft nach 256 Pixeln um. Negative Verschiebungen verwenden Bytewerte modulo 256. Füllen Sie die Karte auch außerhalb des sichtbaren Ausschnitts.

Der Effekt verändert den horizontalen Hintergrundscroll; Sprites und Fenster werden nicht gebogen. RunFrame belegt die CPU und sperrt Interrupts während aller 144 sichtbaren Zeilen. Aktualisieren Sie Spiellogik und Audio zwischen den Aufrufen und kombinieren Sie diesen Renderer nicht mit einem STAT-Rasterinterrupttreiber.

Die Bilder stammen aus DMG- und CGB-Läufen in KOKURA. Jedes Pixel der 160×144-Szene einschließlich Säulen und Text wird mit den erwarteten Koordinaten je Zeile verglichen. Das Timing auf echter Hardware wurde nicht getestet.

Legen Sie kitaqgb, kokura und kitaq-docs unter demselben übergeordneten Verzeichnis ab und öffnen Sie dort PowerShell. Das ROM unterstützt DMG und CGB; wählen Sie dmg oder cgb mit KOKURA --hardware.

Anwendungsbeispiel

c
Raster_LineXSetSpeed(&wave, 1, 1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Raster_LineXSetSpeed: DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
DMG / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
Raster_LineXSetSpeed: CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.
CGB / Frame 60 — Säulen und Buchstaben werden horizontal um bis zu 24 Pixel gebogen. Eine Welle umfasst 64 Rasterzeilen, ihre Phase rückt pro Frame um eine Zeile vor. Auf dem CGB sind Säulen und Schrift blau. Achten Sie auf unterschiedliche horizontale Offsets je Zeile statt auf eine einheitliche Bewegung des ganzen Bildes.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementierung und Quelltext

kitaqgb/lib/raster.h:86

Deklarationshinweise im Original
Configure the phase increment and frame interval; clamp a zero interval to one.

kitaqgb/lib/raster.c:248

c
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider)
{
    effect->phase_step = phase_step;
    if (frame_divider == 0) frame_divider = 1;
    effect->frame_divider = frame_divider;
    effect->frame_counter = 0;
}
Raster_Push

Fügt ein Band hinzu, das Hintergrund-SCX/SCY beim geplanten LY ändert. Diese reine Hintergrundoperation verändert weder Fenster noch Farben.

Syntax

c
u8 Raster_Push(u8 ly, u8 scx, u8 scy);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

scx

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scy

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
Raster_Push(0,0,0);Raster_Push(64,8,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_Push: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_Push: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:50

Deklarationshinweise im Original
Append a validated background-scroll band and advance the monotonic-LY
bookkeeping. A successful append clears the previous error.

kitaqgb/lib/raster.c:95

c
u8 Raster_Push(u8 ly, u8 scx, u8 scy)
{
    u8 r;

    r = Raster_CheckPush(ly);
    if (r != KQ_RASTER_OK) return r;

    Scroll_SplitPush(ly, scx, scy);

    Raster_LastLyValue = ly;
    Raster_HasLastLy = 1;
    Raster_CountValue++;
    Raster_LastErrorValue = KQ_RASTER_OK;
    return KQ_RASTER_OK;
}
Raster_PushBgColor0

Fügt ein Band hinzu, das während des Frames Farbe null der CGB-Hintergrundpalette null ändert. Es wählt keine andere Palette und ändert nicht deren drei weitere Farben. Eine Eintragung auf dem DMG erzeugt keinen Farbeffekt.

Syntax

c
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

rgb15

RGB15: Rot in Bits 0..4, Grün in 5..9, Blau in 10..14. 0x001F ist Rot, 0x03E0 Grün und 0x7C00 Blau. Der Eingabebereich wird nicht geprüft.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Farbänderungen nutzen BCPS/BCPD und erhalten den bisherigen BCPS-Index nicht. Setzen Sie den Index ausdrücklich, wenn auch der Hauptcode Paletten schreibt. Der Handler wartet auf einen zugänglichen LCD-Modus; die sichtbare Farbgrenze kann daher nach der geplanten LY-Zeile liegen.

Anwendungsbeispiel

c
Raster_PushBgColor0(0,0x7C00);Raster_PushBgColor0(64,0x001F);Raster_PushBgColor0(112,0x03E0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

In der geprüften CGB-Aufnahme bei normaler Geschwindigkeit sind Zeilen 0..65 blau, 66..113 rot und 114..143 grün. Geplant sind LY 0, 64 und 112; Interrupt- und Palettenzugriffslatenz beeinflussen die sichtbaren Grenzen. Eine DMG-Farbversion gibt es nicht.

Raster_PushBgColor0: CGB — In der geprüften CGB-Aufnahme bei normaler Geschwindigkeit sind Zeilen 0..65 blau, 66..113 rot und 114..143 grün. Geplant sind LY 0, 64 und 112; Interrupt- und Palettenzugriffslatenz beeinflussen die sichtbaren Grenzen. Eine DMG-Farbversion gibt es nicht.
CGB — In der geprüften CGB-Aufnahme bei normaler Geschwindigkeit sind Zeilen 0..65 blau, 66..113 rot und 114..143 grün. Geplant sind LY 0, 64 und 112; Interrupt- und Palettenzugriffslatenz beeinflussen die sichtbaren Grenzen. Eine DMG-Farbversion gibt es nicht.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:63

Deklarationshinweise im Original
Pack a 15-bit color into the extended band's two scroll-byte fields and select
the color-zero operation, which interprets those fields as color data.

kitaqgb/lib/raster.c:154

c
u8 Raster_PushBgColor0(u8 ly, u16 rgb15)
{
    return Raster_PushEx(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_RASTER_BG_COLOR0);
}
Raster_PushBgWindowScreen

Aktualisiert Hintergrundscroll und Fensterkoordinaten in einem Band. Der Wrapper ergänzt BG und WIN und wandelt Fenster-Bildschirm-X in WX um.

Syntax

c
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

scx

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scy

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

screen_x

Bildschirm-X-Koordinate des linken Fensterrands. Der Wrapper addiert sieben, um WX zu bilden. Verwenden Sie normalerweise 0..159. Werte ab 249 laufen bei der Byteaddition über; nutzen Sie sie nicht zum Verstecken des Fensters.

screen_y

Fenster-WY in Pixeln ab dem oberen Rand. Anders als bei X wird zu Y keine sieben addiert. WY-Werte ab 144 haben keine Startzeile im sichtbaren Bereich.

flags

Übergeben Sie normalerweise WIN_SHOW oder WIN_HIDE. Der Wrapper ergänzt WIN; null genügt daher zum Ändern der Koordinaten ohne Änderung der Sichtbarkeit. Andere unterstützte Bits werden weitergereicht. Vermeiden Sie unbeabsichtigte BG- oder Farboperationen.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
Raster_PushBgWindowScreen(0,8,0,24,48,KQ_RASTER_WIN_SHOW);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Hintergrund-X=8 verschiebt das rote Hintergrundrechteck nach (24,16). Der Fensterursprung bleibt bei (24,48), sein blaues Rechteck damit bei (32,56). Dies zeigt die unabhängigen Koordinatensysteme.

Raster_PushBgWindowScreen: DMG — Hintergrund-X=8 verschiebt das rote Hintergrundrechteck nach (24,16). Der Fensterursprung bleibt bei (24,48), sein blaues Rechteck damit bei (32,56). Dies zeigt die unabhängigen Koordinatensysteme.
DMG — Hintergrund-X=8 verschiebt das rote Hintergrundrechteck nach (24,16). Der Fensterursprung bleibt bei (24,48), sein blaues Rechteck damit bei (32,56). Dies zeigt die unabhängigen Koordinatensysteme.
Raster_PushBgWindowScreen: CGB — Hintergrund-X=8 verschiebt das rote Hintergrundrechteck nach (24,16). Der Fensterursprung bleibt bei (24,48), sein blaues Rechteck damit bei (32,56). Dies zeigt die unabhängigen Koordinatensysteme.
CGB — Hintergrund-X=8 verschiebt das rote Hintergrundrechteck nach (24,16). Der Fensterursprung bleibt bei (24,48), sein blaues Rechteck damit bei (32,56). Dies zeigt die unabhängigen Koordinatensysteme.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bg_window.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:60

Deklarationshinweise im Original
Queue both background and window updates, converting window screen X to WX.

kitaqgb/lib/raster.c:145

c
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags)
{
    flags = (u8)(flags | KQ_RASTER_BG | KQ_RASTER_WIN);
    return Raster_PushEx(ly, scx, scy, (u8)(screen_x + 7), screen_y, flags);
}
Raster_PushEx

Fügt ein erweitertes Band mit den durch Flags gewählten Hintergrund-, Fenster-, Sichtbarkeits- oder Farboperationen hinzu. Für reine Hintergrundänderungen nutzen Sie Raster_Push mit weniger Argumenten.

Syntax

c
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

scx

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

scy

Hintergrund-Scrollbyte in 0..255. SCX/SCY geben die Leseposition in der Hintergrundkarte an, keine Bildschirmposition. Die Koordinaten laufen innerhalb des 256-Pixel-Hintergrunds zyklisch um.

wx

Roher Hardwarewert WX. Addieren Sie sieben zur normalen Bildschirm-X-Koordinate; WX=7 setzt das Fenster an den linken Rand. Die Funktion begrenzt oder prüft WX nicht.

wy

Fenster-WY in Pixeln ab dem oberen Rand. Anders als bei X wird zu Y keine sieben addiert. WY-Werte ab 144 haben keine Startzeile im sichtbaren Bereich.

flags

Flags: BG=1 aktualisiert den Hintergrundscroll, WIN=2 WX/WY, WIN_SHOW=4 zeigt das Fenster, WIN_HIDE=8 verbirgt es, BG_COLOR0=16 aktualisiert CGB-Hintergrundfarbe null. Unbekannte obere Bits werden verworfen. Sind SHOW und HIDE gesetzt, wird SHOW zuletzt angewendet. Farbänderungen verwenden die Datenfelder SCX/SCY erneut; kombinieren Sie sie nicht mit normalem Hintergrundscrollen.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
Raster_PushEx(104,16,0,7,0,KQ_RASTER_BG|KQ_RASTER_WIN_HIDE);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Raster_PushEx: DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
DMG — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
Raster_PushEx: CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.
CGB — Rote Rechtecke von jeweils 24x16 Pixeln, auf DMG schwarz, erscheinen bei (32,16), (24,80) und (16,112). Tiefere Bänder werden weiter nach links verschoben. Intern werden Anzahl 3, Fehler 0 und Aktivierungsergebnis 0 gespeichert.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:52

Deklarationshinweise im Original
Append a validated extended band after masking flags to supported operations.

kitaqgb/lib/raster.c:112

c
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
    u8 r;

    r = Raster_CheckPush(ly);
    if (r != KQ_RASTER_OK) return r;

    // Masking removes unknown bits but does not reject conflicting supported operations.
    flags = (u8)(flags & KQ_RASTER_FLAG_MASK);
    Scroll_SplitPushEx(ly, scx, scy, wx, wy, flags);

    Raster_LastLyValue = ly;
    Raster_HasLastLy = 1;
    Raster_CountValue++;
    Raster_LastErrorValue = KQ_RASTER_OK;
    return KQ_RASTER_OK;
}
Raster_PushWindowRaw

Fügt ein Fensterband mit rohen Hardwarewerten WX/WY hinzu. Ergänzt automatisch WIN und übergibt null für beide Hintergrund-Datenbytes.

Syntax

c
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

wx

Roher Hardwarewert WX. Addieren Sie sieben zur normalen Bildschirm-X-Koordinate; WX=7 setzt das Fenster an den linken Rand. Die Funktion begrenzt oder prüft WX nicht.

wy

Fenster-WY in Pixeln ab dem oberen Rand. Anders als bei X wird zu Y keine sieben addiert. WY-Werte ab 144 haben keine Startzeile im sichtbaren Bereich.

flags

Übergeben Sie normalerweise WIN_SHOW oder WIN_HIDE. Der Wrapper ergänzt WIN; null genügt daher zum Ändern der Koordinaten ohne Änderung der Sichtbarkeit. Andere unterstützte Bits werden weitergereicht. Vermeiden Sie unbeabsichtigte BG- oder Farboperationen.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
Raster_PushWindowRaw(0,31,48,KQ_RASTER_WIN_SHOW);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

WX=31 und WY=48 legen den Fensterursprung auf Bildschirmposition (24,48). Das blaue 16x16-Rechteck an lokaler Position (8,8) erscheint bei (32,56). Das obere rote Hintergrundrechteck bleibt bei (32,16). Auf dem DMG sind beide schwarz.

Raster_PushWindowRaw: DMG — WX=31 und WY=48 legen den Fensterursprung auf Bildschirmposition (24,48). Das blaue 16x16-Rechteck an lokaler Position (8,8) erscheint bei (32,56). Das obere rote Hintergrundrechteck bleibt bei (32,16). Auf dem DMG sind beide schwarz.
DMG — WX=31 und WY=48 legen den Fensterursprung auf Bildschirmposition (24,48). Das blaue 16x16-Rechteck an lokaler Position (8,8) erscheint bei (32,56). Das obere rote Hintergrundrechteck bleibt bei (32,16). Auf dem DMG sind beide schwarz.
Raster_PushWindowRaw: CGB — WX=31 und WY=48 legen den Fensterursprung auf Bildschirmposition (24,48). Das blaue 16x16-Rechteck an lokaler Position (8,8) erscheint bei (32,56). Das obere rote Hintergrundrechteck bleibt bei (32,16). Auf dem DMG sind beide schwarz.
CGB — WX=31 und WY=48 legen den Fensterursprung auf Bildschirmposition (24,48). Das blaue 16x16-Rechteck an lokaler Position (8,8) erscheint bei (32,56). Das obere rote Hintergrundrechteck bleibt bei (32,16). Auf dem DMG sind beide schwarz.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_raw.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:55

Deklarationshinweise im Original
Enable window updates and pass hardware WX/WY values without coordinate conversion.

kitaqgb/lib/raster.c:131

c
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags)
{
    flags = (u8)(flags | KQ_RASTER_WIN);
    return Raster_PushEx(ly, 0, 0, wx, wy, flags);
}
Raster_PushWindowScreen

Fügt ein Fensterband in Bildschirmkoordinaten hinzu. Addiert vor dem Aufruf der Rohwertvariante sieben zu X, damit Bildschirm-X und WX beim Positionieren nicht verwechselt werden.

Syntax

c
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);

Parameter

ly

Geplante sichtbare Zeile in 0..143, strikt größer als die vorherige Tabellenzeile. Ein erster Eintrag bei LY=0 wird in der VBlank-Behandlung angewendet und legt den Zustand am Frameanfang fest.

screen_x

Bildschirm-X-Koordinate des linken Fensterrands. Der Wrapper addiert sieben, um WX zu bilden. Verwenden Sie normalerweise 0..159. Werte ab 249 laufen bei der Byteaddition über; nutzen Sie sie nicht zum Verstecken des Fensters.

screen_y

Fenster-WY in Pixeln ab dem oberen Rand. Anders als bei X wird zu Y keine sieben addiert. WY-Werte ab 144 haben keine Startzeile im sichtbaren Bereich.

flags

Übergeben Sie normalerweise WIN_SHOW oder WIN_HIDE. Der Wrapper ergänzt WIN; null genügt daher zum Ändern der Koordinaten ohne Änderung der Sichtbarkeit. Andere unterstützte Bits werden weitergereicht. Vermeiden Sie unbeabsichtigte BG- oder Farboperationen.

Rückgabewert

Liefert bei Erfolg KQ_RASTER_OK (0), sonst einen Fehlerstatus von 1 bis 4. Beachten Sie die Funktionsbedingungen und Raster_GetLastError.

Bedingungen und Grenzen

Binden Sie raster.h ein und kompilieren Sie raster.c zusammen mit scroll.c. Eine gemeinsame Tabelle fasst bis zu acht Bänder. Mischen Sie beim Aufbau mit Raster_* keine direkten Aufrufe von Scroll_Split* oder __scroll_split_* ein: Sie umgehen die Zählung und die Verwaltung der letzten Zeile im Wrapper.

Bauen Sie die Tabelle während VBlank oder in einem anderen Zeitraum mit kontrollierbarer Bildwirkung neu auf: leeren, Einträge hinzufügen, aktivieren. Das Leeren stoppt auch aktive Teilungen; es wird kein unabhängiger Hintergrundpuffer bearbeitet. LY plant einen Interrupt, Registerzugriffe benötigen zusätzliche Zeit. Für Wellen pro Rasterzeile verwenden Sie die separate Familie Raster_LineX*; betreiben Sie nicht beide Treiber gleichzeitig.

Die Statuscodes sind 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED und 4 BAD_RANGE. Beim Hinzufügen werden LY-Bereich, Kapazität und Reihenfolge in dieser Reihenfolge geprüft. Ein abgelehnter Eintrag vergrößert die Tabelle nicht. Ein späterer erfolgreicher Eintrag oder das Leeren setzt den Fehler auf null zurück; prüfen Sie daher jeden Rückgabewert unmittelbar.

Anwendungsbeispiel

c
Raster_PushWindowScreen(0,24,48,KQ_RASTER_WIN_SHOW);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die direkte Übergabe der Bildschirmkoordinaten (24,48) erzeugt dasselbe blaue Fensterrechteck bei (32,56) wie das Beispiel mit Rohwerten. Die Bibliothek addiert sieben zu X. Das obere rote Hintergrundrechteck liegt bei (32,16).

Raster_PushWindowScreen: DMG — Die direkte Übergabe der Bildschirmkoordinaten (24,48) erzeugt dasselbe blaue Fensterrechteck bei (32,56) wie das Beispiel mit Rohwerten. Die Bibliothek addiert sieben zu X. Das obere rote Hintergrundrechteck liegt bei (32,16).
DMG — Die direkte Übergabe der Bildschirmkoordinaten (24,48) erzeugt dasselbe blaue Fensterrechteck bei (32,56) wie das Beispiel mit Rohwerten. Die Bibliothek addiert sieben zu X. Das obere rote Hintergrundrechteck liegt bei (32,16).
Raster_PushWindowScreen: CGB — Die direkte Übergabe der Bildschirmkoordinaten (24,48) erzeugt dasselbe blaue Fensterrechteck bei (32,56) wie das Beispiel mit Rohwerten. Die Bibliothek addiert sieben zu X. Das obere rote Hintergrundrechteck liegt bei (32,16).
CGB — Die direkte Übergabe der Bildschirmkoordinaten (24,48) erzeugt dasselbe blaue Fensterrechteck bei (32,56) wie das Beispiel mit Rohwerten. Die Bibliothek addiert sieben zu X. Das obere rote Hintergrundrechteck liegt bei (32,16).

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_screen.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/raster.h:58

Deklarationshinweise im Original
Convert screen X to hardware WX by adding seven, then queue a window band.
The byte addition wraps if callers supply an excessive X coordinate.

kitaqgb/lib/raster.c:139

c
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags)
{
    return Raster_PushWindowRaw(ly, (u8)(screen_x + 7), screen_y, flags);
}

rpg.h — Zufallszahlen, Text, Karten, Spielstände und RPG-/ADV-/SLG-Funktionen

Die Texthelfer mit absoluten Positionen zeichnen direkt auf die Hintergrundkarte. text_window öffnet einen umrahmten Bereich, text_clear_rect füllt eine Region und text_print_xy schreibt Tile-Bytes ohne Steuercodeauswertung. text_print_u8, text_print_u16 und text_print_s16 wandeln Zahlen in Dezimaldarstellung um und belegen nur die nötigen Zellen. Reservieren und löschen Sie beim Ersetzen unterschiedlich langer Werte das gesamte Feld.

Die in rpg.h deklarierten RNG-Funktionen sind in lib/rng.c implementiert. Sie teilen den GB-Generator des Compilers: rng_seed setzt ihn zurück, rng8/rng_next8 verbrauchen ein Byte, rng16/rng_next16 zwei, und rand_range/rng_range, rng_chance sowie weighted_choice passen Ziehungen an Spielentscheidungen an. Kompilieren Sie rng.c mit dem Programm, wenn Sie diese Funktionen aufrufen. Reproduzierbare Tests benötigen festen Startwert und Aufrufreihenfolge; modulo-basierte Auswahlen garantieren keine exakten Wahrscheinlichkeiten.

RLE-Decodierung verwendet count/value-Bytepaare und count null als Abschluss. rle_decode liest einen normalen Zeiger und schreibt in RAM; rle_decode_far liest einen Zeiger mit ROM-Bankangabe nach RAM; __rle_decode_vram entpackt Bankdaten mit LCD-gerechten Schreibzugriffen direkt in VRAM. Die RAM-Funktionen liegen in lib/rle.c, die direkte VRAM-Operation wird vom Compiler erzeugt. Alle drei liefern die Anzahl ausgegebener Bytes und benötigen einen gültigen Strom sowie genügend Zielspeicher.

Den in rpg.h deklarierten Spielzustandsspeicher implementiert lib/flags.c. Die drei Flagfunktionen arbeiten auf 2048 unabhängigen booleschen Bits; quest_state und quest_set_state auf 64 unabhängigen Bytes für spieldefinierte Stufen. Kompilieren Sie flags.c bei der Nutzung, beachten Sie die ID-Grenzen und verwenden Sie ein separates Speichersystem, wenn Fortschritt das Ausschalten überdauern soll.

Fensterdialoge teilen sich ein aktives Rechteck, einen Cursor und eine Zeichengeschwindigkeit. text_open initialisiert den Bereich, text_close löscht ihn und text_set_speed setzt VBlank-Warten je Zeichen. text_print und text_print_far interpretieren Steuerströme; text_choice führt eine blockierende vertikale Auswahl aus. Laden Sie Kacheln, dimensionieren Sie den Bereich und planen Sie den Umgang mit blockierenden Aufrufen im Spiel.

Bietet Karten-/Metakachelzeichnung, Skripte, SRAM-Spielstände und Wegsuche. Gewöhnliche Zellen sind 8×8 Pixel groß, Metakacheln 16×16. Laden/Zeichnen, Bewegungs- und Angriffsmasken sind getrennte Operationen; das Spiel koordiniert Grafikladen und Ereignisausführung.

Die Suche verwendet etwa 4 KiB gemeinsamen, nicht reentranten Arbeitsspeicher. Begrenzen Sie Karten auf 1024 Zellen und untersuchte Entfernungen auf 254. Distanz 0xFF bedeutet „nicht erreicht“; eine Route mit 255 Schritten ist daher nicht darstellbar. Kosten- und Maskenausgaben benötigen width*height beschreibbare Bytes.

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Menüs unterstützen sowohl eine blockierende Auswahl als auch getrennte Eingabe- und Zeichenaufrufe aus der Spielschleife. Das Inventarmenü zeigt Gegenstandsnamen und Mengen an.

camera_center

Zentriert eine Zelle einer gewöhnlichen Karte in einem Ausschnitt von 20×18 Kacheln, begrenzt durch die Kartenränder.

Syntax

c
void camera_center(u8 x, u8 y);

Parameter

x

X-Koordinate der Zelle.

y

Y-Koordinate der Zelle.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Ursprung beginnt bei max(x−10,0), max(y−9,0), wird auf die Kartengrenzen begrenzt und schreibt dann die unteren Bytes von Ursprung*8 nach SCX/SCY. Im Metakachelmodus wird dies nicht angewandt. Neue Zeilen oder Spalten werden nicht in den VRAM nachgeladen.

Anwendungsbeispiel

c
camera_center(5,4);result[9]=*((u8*)0xFF43);result[10]=*((u8*)0xFF42);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

camera_center: DMG
DMG
camera_center: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:297

Deklarationshinweise im Original
Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp
the scroll origin to its edges. This adjusts scroll registers only; it does
not stream newly exposed map rows into VRAM.

kitaqgb/lib/map.c:105

c
void camera_center(u8 x, u8 y)
{
    u8 tile_x = 0;
    u8 tile_y = 0;
    u8 max_x = 0;
    u8 max_y = 0;

    map_camera_x = x;
    map_camera_y = y;

    if (map_loaded == 0) return;

    if (map_current.width > 20) max_x = (u8)(map_current.width - 20);
    if (map_current.height > 18) max_y = (u8)(map_current.height - 18);

    if (x > 10) tile_x = (u8)(x - 10);
    if (y > 9) tile_y = (u8)(y - 9);

    if (tile_x > max_x) tile_x = max_x;
    if (tile_y > max_y) tile_y = max_y;

    __scroll_bg_set((u8)(tile_x << 3), (u8)(tile_y << 3));
}
far_read16

Liest ein Little-Endian-Wort über einen Zeiger mit Bankangabe.

Syntax

c
#define far_read16(p) __farpeek16((p).bank, (p).ptr)

Parameter

p

far_ptr_t mit bank und ptr, wobei ptr eine CPU-sichtbare Adresse ist.

Rückgabewert

Das Wort als u16.

Bedingungen und Grenzen

Das Makro liest p.bank und p.ptr getrennt; übergeben Sie keinen Ausdruck mit Seiteneffekten. Die intrinsische Funktion wählt die ROM-Bank vorübergehend und stellt sie wieder her. Vermeiden Sie gleichzeitige Bankwechsel aus Interrupts.

Anwendungsbeispiel

c
result[1]=far_read16(far);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lesen Sie die Hexadezimalwerte 34 12 AB aus einer anderen ROM-Bank: erstes Byte 52, Little-Endian-Wort 4660 und letztes kopiertes Byte 171.

far_read16: DMG
DMG
far_read16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:172

far_read8

Liest ein Byte über einen Zeiger mit Bankangabe.

Syntax

c
#define far_read8(p) __farpeek8((p).bank, (p).ptr)

Parameter

p

far_ptr_t mit bank und ptr, wobei ptr eine CPU-sichtbare Adresse ist.

Rückgabewert

Das Byte als u8.

Bedingungen und Grenzen

Das Makro liest p.bank und p.ptr getrennt; übergeben Sie keinen Ausdruck mit Seiteneffekten. Die intrinsische Funktion wählt die ROM-Bank vorübergehend und stellt sie wieder her. Vermeiden Sie gleichzeitige Bankwechsel aus Interrupts.

Anwendungsbeispiel

c
far.bank=1;far.ptr=bank_bytes;result[0]=far_read8(far);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lesen Sie die Hexadezimalwerte 34 12 AB aus einer anderen ROM-Bank: erstes Byte 52, Little-Endian-Wort 4660 und letztes kopiertes Byte 171.

far_read8: DMG
DMG
far_read8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:171

far_read_block

Kopiert aufeinanderfolgende Bytes von einem Zeiger mit Bankangabe in den RAM.

Syntax

c
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))

Parameter

dst

Beginn von len beschreibbaren RAM-Bytes.

p

far_ptr_t mit bank und ptr, wobei ptr eine CPU-sichtbare Adresse ist.

len

Byte-Anzahl; der gesamte Quellbereich muss innerhalb seiner Bank bleiben.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Makro zur Weiterleitung an __farmemcpy. Überschreitet ROM-Bankgrenzen nicht automatisch und ist keine Verschiebeoperation für überlappende Speicherbereiche.

Anwendungsbeispiel

c
far_read_block(copy,far,3);result[2]=copy[2];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lesen Sie die Hexadezimalwerte 34 12 AB aus einer anderen ROM-Bank: erstes Byte 52, Little-Endian-Wort 4660 und letztes kopiertes Byte 171.

far_read_block: DMG
DMG
far_read_block: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:173

flag_clear

Löscht ein Spielflag auf 0, ohne benachbarte Flags zu löschen. Verwenden Sie dies beim Aufheben einer Ereignisbedingung oder zur ausdrücklichen Initialisierung eines Flags. Ein bereits gelöschtes Flag bleibt null.

Syntax

c
void flag_clear(u16 id);

Parameter

id

Flagnummer von 0 bis 2047, als u16 übergeben. Der Byteoffset ist id / 8, die Bitposition darin id % 8, beginnend beim niederwertigsten Bit. Der breitere Parametertyp vergrößert den festen Speicher für 2048 Flags nicht.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Die Funktion prüft die ID nicht. Halten Sie Flag-IDs unter 2048 und Aufgaben-IDs unter 64. Zugriffe außerhalb des Bereichs können fremde RAM-Inhalte lesen oder überschreiben. Die Beispiele initialisieren ausdrücklich, statt sich auf Anfangsinhalte zu verlassen.

flags.c besitzt 256 RAM-Bytes für Flags und weitere 64 Bytes für Aufgaben. Diese Funktionen greifen nicht auf Cartridge-Speicher-RAM zu und erhalten keine Daten über das Ausschalten hinweg. Für dauerhaften Fortschritt muss das Spiel Flag- und Aufgabenwerte über sein Speichersystem serialisieren und beim Laden wiederherstellen.

Binden Sie rpg.h ein und kompilieren Sie lib/flags.c mit dem Spiel. Die Arrays sind innerhalb dieser Quelldatei privat; verwenden Sie die Flag- und Aufgaben-APIs zum Zugriff. Alle Aufrufer teilen sich den Speicher. Koordinieren Sie daher Schreibzugriffe aus Hauptschleife und Interrupt-Handlern selbst.

Anwendungsbeispiel

c
flag_clear(9);flag_clear(9); // Mark it closed; clearing twice still leaves 0.
cleared=flag_get(9);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel löscht Türflag 9 nach dem Setzen. DOOR CLOSED zeigt 000, obwohl zweimal gelöscht wird. Der zuvor beobachtete Wert DOOR OPEN 001 bleibt sichtbar, sodass sich beide gespeicherten Beobachtungen vergleichen lassen.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: auf DMG mit schwarzem, auf CGB mit blauem Text. FAILED muss 000 sein. Die Aufnahmen zeigen nur das Verhalten der RAM-Zustände und belegen kein Speichern eines Spiels.

Die Prüfung im DMG-Emulator deckte alle Flag-IDs von 0 bis 2047, wiederholtes Setzen und Löschen, benachbarte Einträge sowie alle 256 Zustandswerte jeder der 64 Aufgaben ab. Ein abschließendes Muster aus 256 Flagbytes und 64 Aufgabenbytes wurde mit den erwarteten Daten verglichen. Beide Lehrbildschirme wurden nach 240 Frames geprüft. Echte Hardware und dauerhafte Speicherung wurden nicht getestet.

flag_clear: DMG
DMG
flag_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:372

Deklarationshinweise im Original
Clear a flag bit; id must be below 2048.

kitaqgb/lib/flags.c:21

c
void flag_clear(u16 id)
{
    __bit_clear(flags_bits, id);
}
flag_get

Liest ein Ein/Aus-Spielflag aus dem RAM-Bitarray der Bibliothek. Damit fragen Sie ab, ob eine Tür offen ist, ein Gegenstand gesammelt wurde oder ein anderes vom Spiel definiertes Ereignis eingetreten ist. Lesen verändert das Flag nicht.

Syntax

c
u8 flag_get(u16 id);

Parameter

id

Flagnummer von 0 bis 2047, als u16 übergeben. Der Byteoffset ist id / 8, die Bitposition darin id % 8, beginnend beim niederwertigsten Bit. Der breitere Parametertyp vergrößert den festen Speicher für 2048 Flags nicht.

Rückgabewert

Normalisierter boolescher u8-Wert: 0 bei gelöschtem, 1 bei gesetztem Flag. Diese GB-Bibliothek ruft das GB-Intrinsic __bit_test auf, das das Ergebnis normalisiert.

Bedingungen und Grenzen

Die Funktion prüft die ID nicht. Halten Sie Flag-IDs unter 2048 und Aufgaben-IDs unter 64. Zugriffe außerhalb des Bereichs können fremde RAM-Inhalte lesen oder überschreiben. Die Beispiele initialisieren ausdrücklich, statt sich auf Anfangsinhalte zu verlassen.

flags.c besitzt 256 RAM-Bytes für Flags und weitere 64 Bytes für Aufgaben. Diese Funktionen greifen nicht auf Cartridge-Speicher-RAM zu und erhalten keine Daten über das Ausschalten hinweg. Für dauerhaften Fortschritt muss das Spiel Flag- und Aufgabenwerte über sein Speichersystem serialisieren und beim Laden wiederherstellen.

Binden Sie rpg.h ein und kompilieren Sie lib/flags.c mit dem Spiel. Die Arrays sind innerhalb dieser Quelldatei privat; verwenden Sie die Flag- und Aufgaben-APIs zum Zugriff. Alle Aufrufer teilen sich den Speicher. Koordinieren Sie daher Schreibzugriffe aus Hauptschleife und Interrupt-Handlern selbst.

Anwendungsbeispiel

c
before=flag_get(9); // Door-open flag: 0 after explicit initialization.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel ordnet Flag 9 einer Tür zu. Nach ausdrücklichem Löschen zeigt BEFORE 000. Späteres Setzen und Löschen ergibt DOOR OPEN 001 und DOOR CLOSED 000 und zeigt damit, dass Abfragen den gespeicherten Zustand wiedergeben.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: auf DMG mit schwarzem, auf CGB mit blauem Text. FAILED muss 000 sein. Die Aufnahmen zeigen nur das Verhalten der RAM-Zustände und belegen kein Speichern eines Spiels.

Die Prüfung im DMG-Emulator deckte alle Flag-IDs von 0 bis 2047, wiederholtes Setzen und Löschen, benachbarte Einträge sowie alle 256 Zustandswerte jeder der 64 Aufgaben ab. Ein abschließendes Muster aus 256 Flagbytes und 64 Aufgabenbytes wurde mit den erwarteten Daten verglichen. Beide Lehrbildschirme wurden nach 240 Frames geprüft. Echte Hardware und dauerhafte Speicherung wurden nicht getestet.

flag_get: DMG
DMG
flag_get: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:368

Deklarationshinweise im Original
Read a bit from the flag array. Callers must keep id below 2048.

kitaqgb/lib/flags.c:9

c
u8 flag_get(u16 id)
{
    return __bit_test(flags_bits, id);
}
flag_set

Setzt ein Spielflag auf 1 und bewahrt die sieben anderen Flags desselben Bytes. Ein bereits gesetztes Flag bleibt gesetzt. Damit lassen sich einmalige Ereignisse wie das Öffnen einer Tür vermerken.

Syntax

c
void flag_set(u16 id);

Parameter

id

Flagnummer von 0 bis 2047, als u16 übergeben. Der Byteoffset ist id / 8, die Bitposition darin id % 8, beginnend beim niederwertigsten Bit. Der breitere Parametertyp vergrößert den festen Speicher für 2048 Flags nicht.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Die Funktion prüft die ID nicht. Halten Sie Flag-IDs unter 2048 und Aufgaben-IDs unter 64. Zugriffe außerhalb des Bereichs können fremde RAM-Inhalte lesen oder überschreiben. Die Beispiele initialisieren ausdrücklich, statt sich auf Anfangsinhalte zu verlassen.

flags.c besitzt 256 RAM-Bytes für Flags und weitere 64 Bytes für Aufgaben. Diese Funktionen greifen nicht auf Cartridge-Speicher-RAM zu und erhalten keine Daten über das Ausschalten hinweg. Für dauerhaften Fortschritt muss das Spiel Flag- und Aufgabenwerte über sein Speichersystem serialisieren und beim Laden wiederherstellen.

Binden Sie rpg.h ein und kompilieren Sie lib/flags.c mit dem Spiel. Die Arrays sind innerhalb dieser Quelldatei privat; verwenden Sie die Flag- und Aufgaben-APIs zum Zugriff. Alle Aufrufer teilen sich den Speicher. Koordinieren Sie daher Schreibzugriffe aus Hauptschleife und Interrupt-Handlern selbst.

Anwendungsbeispiel

c
flag_set(9); // Mark the door as open; setting an already set flag is harmless.
flag_set(9);
opened=flag_get(9);neighbor=flag_get(8); // 1 and 0: adjacent flag is unchanged.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel setzt Türflag 9 zweimal. DOOR OPEN zeigt 001, während das benachbarte Flag 8 bei NEIGHBOR 000 bleibt. Beide Flags liegen im selben Byte. Der Nachbarwert zeigt daher, dass das Setzen eines Flags das andere bewahrt.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: auf DMG mit schwarzem, auf CGB mit blauem Text. FAILED muss 000 sein. Die Aufnahmen zeigen nur das Verhalten der RAM-Zustände und belegen kein Speichern eines Spiels.

Die Prüfung im DMG-Emulator deckte alle Flag-IDs von 0 bis 2047, wiederholtes Setzen und Löschen, benachbarte Einträge sowie alle 256 Zustandswerte jeder der 64 Aufgaben ab. Ein abschließendes Muster aus 256 Flagbytes und 64 Aufgabenbytes wurde mit den erwarteten Daten verglichen. Beide Lehrbildschirme wurden nach 240 Frames geprüft. Echte Hardware und dauerhafte Speicherung wurden nicht getestet.

flag_set: DMG
DMG
flag_set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:370

Deklarationshinweise im Original
Set a flag bit without disturbing adjacent flags; id must be below 2048.

kitaqgb/lib/flags.c:15

c
void flag_set(u16 id)
{
    __bit_set(flags_bits, id);
}
map_current_height

Liest die Höhe der aktiven Karte.

Syntax

c
u8 map_current_height();

Rückgabewert

Gibt die Höhe in Zellen zurück oder null, wenn keine Karte geladen ist.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[1]=map_current_height();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

map_current_height: DMG
DMG
map_current_height: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:391

Deklarationshinweise im Original
Return the active map height in its own cell units, or zero when no map is loaded.

kitaqgb/lib/map.c:25

c
u8 map_current_height()
{
    if (map_meta_loaded != 0) return map_meta_current.height;
    if (map_loaded == 0) return 0;
    return map_current.height;
}
map_current_width

Liest die Breite der aktiven Karte.

Syntax

c
u8 map_current_width();

Rückgabewert

Gibt die Breite in Zellen zurück oder null, wenn keine Karte geladen ist.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[0]=map_current_width();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

map_current_width: DMG
DMG
map_current_width: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:389

Deklarationshinweise im Original
Return the active map width in its own cell units, or zero when no map is loaded.

kitaqgb/lib/map.c:17

c
u8 map_current_width()
{
    if (map_meta_loaded != 0) return map_meta_current.width;
    if (map_loaded == 0) return 0;
    return map_current.width;
}
map_draw_visible

Zeichnet 10×9 Metakacheln ab dem gewünschten Ursprung und merkt sich diese Kameraposition für Neuzeichnungen nach Änderungen.

Syntax

c
void map_draw_visible(u8 camera_tx, u8 camera_ty);

Parameter

camera_tx

X der äußersten linken Zelle; höchstens 246, um einen Byte-Überlauf beim Durchlaufen zu vermeiden.

camera_ty

Y der obersten Zelle; höchstens 247.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Zellen außerhalb zeichnen Metakachel-ID null; stellen Sie daher immer Definition null bereit. Der Aufruf lässt Zellen außerhalb des 20×18-Kachelausschnitts und CGB-Attribute unverändert.

Anwendungsbeispiel

c
map_draw_visible(1,0);result[9]=*((u8*)0x9800);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_draw_visible: DMG
DMG
map_draw_visible: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:304

Deklarationshinweise im Original
Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles.
Out-of-range cells use definition zero; palette attributes are not written.
Remember the camera and clear the dirty flag after the full redraw.

kitaqgb/lib/map.c:212

c
void map_draw_visible(u8 camera_tx, u8 camera_ty)
{
    u8 my;

    if (map_meta_loaded == 0) return;

    map_camera_x = camera_tx;
    map_camera_y = camera_ty;

    my = 0;
    while (my < 9) {
        u8 mx = 0;
        while (mx < 10) {
            u8 tx = (u8)(camera_tx + mx);
            u8 ty = (u8)(camera_ty + my);
            u8 sx = (u8)(mx << 1);
            u8 sy = (u8)(my << 1);
            metatile_t meta;
            u8 id = map_get_metatile(tx, ty);
            map_read_metatile(id, &meta);
            __settile_xy(sx, sy, meta.tile_tl);
            __settile_xy((u8)(sx + 1), sy, meta.tile_tr);
            __settile_xy(sx, (u8)(sy + 1), meta.tile_bl);
            __settile_xy((u8)(sx + 1), (u8)(sy + 1), meta.tile_br);
            mx++;
        }
        my++;
    }
    map_dirty = 0;
}
map_flush_dirty

Zeichnet bei gesetztem Änderungsflag den Ausschnitt am gespeicherten Kameraursprung neu und löscht das Flag.

Syntax

c
void map_flush_dirty();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Tut ohne Änderungsmarkierung nichts. Das Neuzeichnen umfasst alle 10×9 Metakacheln, nicht nur die geänderte Zelle.

Anwendungsbeispiel

c
map_flush_dirty();result[11]=*((u8*)0x9800);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_flush_dirty: DMG
DMG
map_flush_dirty: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:321

Deklarationshinweise im Original
Redraw the remembered metatile viewport only when the shared dirty flag is set.

kitaqgb/lib/map.c:254

c
void map_flush_dirty()
{
    if (map_dirty == 0) return;
    map_draw_visible(map_camera_x, map_camera_y);
}
map_get_attr

Liest Palettenmetadaten aus der Metakacheldefinition der Zelle.

Syntax

c
u8 map_get_attr(u8 tx, u8 ty);

Parameter

tx

Metakachel-X-Koordinate.

ty

Metakachel-Y-Koordinate.

Rückgabewert

Gibt das Palettenbyte zurück. Zellen außerhalb nutzen Definition null; ohne Metakachelmodus wird null zurückgegeben.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[3]=map_get_attr(0,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_get_attr: DMG
DMG
map_get_attr: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:310

Deklarationshinweise im Original
Return the selected definition's palette byte. An out-of-range coordinate
uses the metatile-zero fallback; this function does not write CGB attributes.

kitaqgb/lib/map.c:172

c
u8 map_get_attr(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return 0;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return meta.palette;
}
map_get_event

Liest eine Metakachel-Ereignis-ID; gewöhnliche Karten melden das Vorhandensein eines Ereignisses.

Syntax

c
u8 map_get_event(u8 tx, u8 ty);

Parameter

tx

Metakachel-X-Koordinate.

ty

Metakachel-Y-Koordinate.

Rückgabewert

Gibt das Metakachel-Ereignisbyte oder den booleschen Wert der gewöhnlichen Karte zurück; bei fehlender Karte oder Zellen außerhalb null.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[7]=map_get_event(0,0);result[8]=map_get_event(3,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_get_event: DMG
DMG
map_get_event: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:316

Deklarationshinweise im Original
Return a metatile event ID, or the ordinary-map Boolean trigger result.
Missing/out-of-range metatile cells have no event.

kitaqgb/lib/map.c:197

c
u8 map_get_event(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return map_trigger_at(tx, ty);
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return meta.event;
}
map_get_metatile

Liest die Metakachel-ID einer Zelle.

Syntax

c
u8 map_get_metatile(u8 tx, u8 ty);

Parameter

tx

Metakachel-X-Koordinate.

ty

Metakachel-Y-Koordinate.

Rückgabewert

Gibt die ID zurück, außerhalb der Karte oder ohne Metakachelmodus null.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[1]=map_get_metatile(0,0);result[2]=map_get_metatile(3,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_get_metatile: DMG
DMG
map_get_metatile: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:307

Deklarationshinweise im Original
Read a row-major metatile ID, returning ID zero for inactive or out-of-range
lookups. Callers must provide a usable definition for metatile zero.

kitaqgb/lib/map.c:159

c
u8 map_get_metatile(u8 tx, u8 ty)
{
    u16 index;

    if (map_meta_loaded == 0) return 0;
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;

    index = __map_index(tx, ty, map_meta_current.width);
    return __farpeek8(map_meta_data_bank(), map_meta_current.metatile_ids + index);
}
map_is_blocked

Prüft, ob eine Zielzelle die Bewegung blockiert; der Metakachelmodus nutzt das Feld collision der Definition.

Syntax

c
u8 map_is_blocked(u8 x, u8 y);

Parameter

x

X-Koordinate der Zelle.

y

Y-Koordinate der Zelle.

Rückgabewert

Gibt bei einer Wand, einer Koordinate außerhalb oder fehlender Karte 1 zurück, bei passierbaren Zellen 0. Ein NULL-Kollisionsarray einer gewöhnlichen Karte macht alle Zellen innerhalb der Karte passierbar.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[4]=map_is_blocked(2,2);result[5]=map_is_blocked(6,2);result[6]=map_is_blocked(1,2);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

map_is_blocked: DMG
DMG
map_is_blocked: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:290

Deklarationshinweise im Original
Use metatile collision when that mode is active; otherwise read one packed
collision bit. Missing maps/out-of-range cells block movement, but a valid
ordinary map without a collision array is entirely passable.

kitaqgb/lib/map.c:68

c
u8 map_is_blocked(u8 x, u8 y)
{
    u16 index;
    u8 value;

    if (map_meta_loaded != 0) return map_is_solid(x, y);
    if (map_loaded == 0) return 1;
    if (x >= map_current.width || y >= map_current.height) return 1;
    if (map_current.collision_bits == 0) return 0;

    index = __map_index(x, y, map_current.width);
    // Collision uses least-significant bit first within each row-major group of eight cells.
    value = __farpeek8(map_bank, map_current.collision_bits + (index >> 3));
    if ((value & (u8)(1 << (index & 7))) != 0) return 1;
    return 0;
}
map_is_solid

Prüft Solidität und verwendet im gewöhnlichen Kartenmodus die Kollisionsbits.

Syntax

c
u8 map_is_solid(u8 tx, u8 ty);

Parameter

tx

Metakachel-X-Koordinate.

ty

Metakachel-Y-Koordinate.

Rückgabewert

Gibt bei einem Kollisionswert ungleich null oder einer Zelle außerhalb 1 zurück, sonst 0.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[4]=map_is_solid(0,0);result[5]=map_is_solid(1,0);result[6]=map_is_solid(3,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_is_solid: DMG
DMG
map_is_solid: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:313

Deklarationshinweise im Original
Treat out-of-range metatile cells as solid; otherwise inspect the definition
collision flag. In ordinary-map mode, delegate to its packed collision bits.

kitaqgb/lib/map.c:184

c
u8 map_is_solid(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return map_is_blocked(tx, ty);
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 1;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return (u8)(meta.collision != 0);
}
map_load

Lädt einen Deskriptor für eine gewöhnliche Karte und zeichnet ab ihrer linken oberen Ecke bis zu 20×18 Kacheln in die gewählte Hintergrundkarte.

Syntax

c
void map_load(u8 bank, const map_t* map);

Parameter

bank

ROM-Bank für Deskriptor, Kollisionsbits und Ereignisse.

map

Gepacktes map_t mit neun Bytes. tiles enthält width*height Kachel-IDs; collision_bits packt Zellen beginnend beim niederwertigsten Bit; events speichert ein Byte je Zelle. Kachellesezugriffe verwenden bank_tiles.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Es gibt eine gemeinsame aktive Karte. Der Deskriptor wird kopiert, seine Arrays müssen jedoch während der gesamten Nutzung lesbar bleiben. Laden Sie Kachelgrafiken getrennt in den VRAM.

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Zellen außerhalb einer kleinen Karte werden nicht gelöscht. Bei gewöhnlichen Karten bedeutet bank_tiles=0 Bank null; die Bank des Deskriptors wird nicht übernommen.

Anwendungsbeispiel

c
map_load(0,maps);result[2]=map_current_width();result[3]=map_current_height();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

map_load: DMG
DMG
map_load: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:286

Deklarationshinweise im Original
Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles
from its top-left corner. Drawing does not upload tile graphics or clear
background cells beyond smaller map dimensions.

kitaqgb/lib/map.c:35

c
void map_load(u8 bank, const map_t* map)
{
    u8 row;
    u8 h;
    u8 w;

    // The literal copy size depends on the packed map_t layout; changing that layout requires updating this copy.
    __farmemcpy(&map_current, bank, map, 9);
    map_bank = bank;
    map_loaded = 1;
    map_meta_loaded = 0;

    w = map_current.width;
    h = map_current.height;
    if (w > 20) w = 20;
    if (h > 18) h = 18;

    row = 0;
    while (row < h) {
        u8 x = 0;
        u16 base_index = __map_index(0, row, map_current.width);
        while (x < w) {
            map_row[x] = __farpeek8(map_current.bank_tiles, map_current.tiles + base_index + x);
            x++;
        }
        __settile_row(0, row, map_row, w);
        row++;
    }
}
map_load_metatile

Wählt eine Metakachelkarte und erweitert einen Ausschnitt von 10×9 Zellen bei Kamera (0,0) zu 20×18 Kacheln.

Syntax

c
void map_load_metatile(u8 bank, const metatile_map_t* map);

Parameter

bank

ROM-Bank mit dem Deskriptor.

map

Zeiger auf metatile_map_t. Die Abmessungen zählen 16×16-Pixel-Zellen. Er verweist auf ein ID-Array und eine Tabelle aus sieben Byte großen metatile_t-Definitionen.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Es gibt eine gemeinsame aktive Karte. Der Deskriptor wird kopiert, seine Arrays müssen jedoch während der gesamten Nutzung lesbar bleiben. Laden Sie Kachelgrafiken getrennt in den VRAM.

bank_tiles=0 übernimmt die Bank des Deskriptors; ein Wert ungleich null wählt die Bank für IDs und Definitionen. Eine Definition speichert die Kacheln links oben, rechts oben, links unten und rechts unten sowie Kollision, Palette und Ereignis. Beim Zeichnen werden Palettenmetadaten nicht automatisch angewandt.

Anwendungsbeispiel

c
map_load_metatile(0,&level);result[0]=*((u8*)0x9800);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_load_metatile: DMG
DMG
map_load_metatile: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:300

Deklarationshinweise im Original
Select metatile mode, copy its descriptor and draw the initial viewport
with the camera at cell (0,0).

kitaqgb/lib/map.c:145

c
void map_load_metatile(u8 bank, const metatile_map_t* map)
{
    map_meta_bank = bank;
    __farmemcpy(&map_meta_current, bank, map, sizeof(metatile_map_t));
    map_meta_loaded = 1;
    map_loaded = 0;
    map_dirty = 0;
    map_camera_x = 0;
    map_camera_y = 0;
    map_draw_visible(0, 0);
}
map_mark_dirty

Markiert den Ausschnitt zum Neuzeichnen, wenn eine gültige Metakachelkoordinate übergeben wird.

Syntax

c
void map_mark_dirty(u8 tx, u8 ty);

Parameter

tx

Metakachel-X-Koordinate.

ty

Metakachel-Y-Koordinate.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Setzt ein gemeinsames Änderungsflag, statt Einzelzellenaktualisierungen einzureihen. Koordinaten außerhalb werden ignoriert. Der aufrufende Code ändert IDs oder Definitionen getrennt, bevor er die Änderung markiert.

Anwendungsbeispiel

c
ids[1]=1;map_mark_dirty(1,0);result[10]=*((u8*)0x9800);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie eine Metakachel-ID im RAM, markieren Sie die Änderung und übertragen Sie sie. Kamera (1,0) zeigt links oben ein grünes 16×16-Quadrat. Das Beispiel wendet Palettenmetadaten ausdrücklich auf CGB-Attribute an. Auf dem DMG erscheint ein schwarzes Quadrat.

map_mark_dirty: DMG
DMG
map_mark_dirty: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:319

Deklarationshinweise im Original
Mark the viewport for a full redraw when a valid metatile cell changes.
The coordinate is validated but no per-cell dirty list is retained.

kitaqgb/lib/map.c:246

c
void map_mark_dirty(u8 tx, u8 ty)
{
    if (map_meta_loaded == 0) return;
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return;
    map_dirty = 1;
}
map_trigger_at

Prüft, ob eine Zelle ein Ereignis hat, ohne es auszuführen.

Syntax

c
u8 map_trigger_at(u8 x, u8 y);

Parameter

x

X-Koordinate der Zelle.

y

Y-Koordinate der Zelle.

Rückgabewert

Gibt bei vorhandenem Ereignis 1 zurück, sonst 0; liefert weder das gespeicherte Ereignisbyte noch die Ereignis-ID einer Metakachel.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Anwendungsbeispiel

c
result[7]=map_trigger_at(5,4);result[8]=map_trigger_at(6,4);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

map_trigger_at: DMG
DMG
map_trigger_at: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:293

Deklarationshinweise im Original
Report whether an event exists at the cell. Ordinary maps expose a Boolean
byte-presence test; metatile maps reduce their event ID to a Boolean here.

kitaqgb/lib/map.c:87

c
u8 map_trigger_at(u8 x, u8 y)
{
    u16 index;
    u8 value;

    if (map_meta_loaded != 0) return (u8)(map_get_event(x, y) != 0);
    if (map_loaded == 0) return 0;
    if (x >= map_current.width || y >= map_current.height) return 0;
    if (map_current.events == 0) return 0;

    index = __map_index(x, y, map_current.width);
    value = __farpeek8(map_bank, ((const u8*)map_current.events) + index);
    return (u8)((value != 0) ? 1 : 0);
}
menu_draw

Zeichnet Rahmen, Eintragsbeschriftungen und aktuellen Cursor anhand des Menüzustands.

Syntax

c
void menu_draw(menu_state_t* state);

Parameter

state

Zeiger auf einen initialisierten Menüzustand.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bei einem Nullzeiger geschieht nichts. Jeder Aufruf öffnet das Fenster mit text_open() erneut und aktualisiert dabei auch den gemeinsamen Zustand des Textfensters. Eingaben werden nicht gelesen. Laden Sie die Kacheln für Rahmen, Cursor und Text vorher. Der aufrufende Code muss das Eintragsarray und die Zeichenketten vorhalten. Text wird weder automatisch umgebrochen noch abgeschnitten; wählen Sie Positionen, Eintragszahlen und Beschriftungslängen so, dass alles ins Fenster passt.

Anwendungsbeispiel

c
menu_draw(&menu_state);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel zeichnet das Menü zunächst einmal und nach Eingaben erneut. Nach DOWN steht der Cursor neben SHIELD.

menu_draw: DMG
DMG
menu_draw: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:273

Deklarationshinweise im Original
Draw the current menu and cursor without waiting or sampling input. The
caller schedules suitable display timing and keeps item text within bounds.

kitaqgb/lib/menu.c:94

c
void menu_draw(menu_state_t* state)
{
    u8 i;
    if (state == 0) return;

    text_open(state->x, state->y, state->w, state->h);
    i = 0;
    while (i < state->count) {
        u8 py = (u8)(state->y + 1 + i);
        const u8* s = state->items[i];
        u8 px = (u8)(state->x + 2);
        __settile_xy((u8)(state->x + 1), py, (i == state->cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
        while (*s != 0) {
            __settile_xy(px, py, *s);
            px++;
            s++;
        }
        i++;
    }
}
menu_get_selected

Liest die gespeicherte Auswahl eines schrittweise verarbeiteten Menüs.

Syntax

c
u8 menu_get_selected(menu_state_t* state);

Parameter

state

Zeiger auf einen initialisierten Menüzustand.

Rückgabewert

Gibt den gewählten Index ab null zurück; bei ausstehender Auswahl, Abbruch oder einem Nullzeiger 255.

Bedingungen und Grenzen

Das Lesen löscht das Ergebnis nicht. Beenden Sie nach Abschluss die Aktualisierung und rufen Sie vor einer neuen Interaktion menu_init_state() auf.

Anwendungsbeispiel

c
result[0]=menu_get_selected(&menu_state);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest für SHIELD den Auswahlwert 1 und prüft, dass ein Nullzeiger 255 ergibt.

menu_get_selected: DMG
DMG
menu_get_selected: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:279

Deklarationshinweise im Original
Read the latched selection without clearing it; null state returns 0xFF.

kitaqgb/lib/menu.c:148

c
u8 menu_get_selected(menu_state_t* state)
{
    if (state == 0) return 0xFF;
    return state->selected;
}
menu_init_state

Initialisiert ein Menü, das schrittweise von der Spielschleife verarbeitet wird.

Syntax

c
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count);

Parameter

state

Zu initialisierendes, beschreibbares menu_state_t; darf nicht null sein.

x

Kachelspalte am linken Fensterrand.

y

Kachelzeile am oberen Fensterrand.

w

Breite in Kacheln einschließlich Rahmen.

h

Höhe in Kacheln einschließlich Rahmen.

items

Array aus Zeigern auf nullterminierte Eintragsbeschriftungen.

count

Anzahl der Einträge, höchstens so viele wie verfügbare Zeilen im Fensterinneren.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Setzt Cursor und vorherigen Tastenzustand auf null, die Auswahl auf 255 und den Abbruchstatus auf null. Zeichnet nichts und wartet nicht auf eine Eingabe. Laden Sie die Kacheln für Rahmen, Cursor und Text vorher. Der aufrufende Code muss das Eintragsarray und die Zeichenketten vorhalten. Text wird weder automatisch umgebrochen noch abgeschnitten; wählen Sie Positionen, Eintragszahlen und Beschriftungslängen so, dass alles ins Fenster passt.

Anwendungsbeispiel

c
menu_init_state(&menu_state,1,2,18,5,choices,3);result[2]=menu_state.selected;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel bereitet ein Menü mit drei Einträgen bei (1,2) und einer Größe von 18×5 Kacheln vor. Der anfängliche Auswahlwert ist 255.

menu_init_state: DMG
DMG
menu_init_state: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:270

Deklarationshinweise im Original
Initialize a nonblocking menu state that borrows the item pointer table.
Selection starts unset (0xFF), and the cancellation flag starts clear.

kitaqgb/lib/menu.c:78

c
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count)
{
    state->x = x;
    state->y = y;
    state->w = w;
    state->h = h;
    state->items = items;
    state->count = count;
    state->cursor = 0;
    state->prev_keys = 0;
    state->selected = 0xFF;
    state->cancelled = 0;
}
menu_inventory

Zeigt die Namen der Inventargegenstände und ihre Mengen zweistellig an und lässt den Spieler einen Gegenstand wählen.

Syntax

c
u8 menu_inventory(const item_t* items, u8 count);

Parameter

items

Lesbares item_t-Array mit IDs, Mengen und Namen.

count

Anzahl der Gegenstände: 1–15 für eine sichtbare Liste, null für eine leere Liste.

Rückgabewert

Gibt den gewählten Array-Index zurück, nicht die Gegenstands-ID; bei Abbruch oder leerer Liste 255.

Bedingungen und Grenzen

Gegenstände und Mengen werden nicht verändert. Verwenden Sie Mengen von 0–99 und höchstens 15 sichtbare Einträge. Das Fenster liegt bei (1,1), ist 18 Kacheln breit und Anzahl+2 Kacheln hoch. Namen beginnen in Spalte 3, Mengen stehen in Spalte 15–16; lange Namen können die Mengen überschreiben. UP/DOWN läuft an den Listenenden um; bei gleichzeitigem Drücken hat A Vorrang vor B. Laden Sie die Kacheln für Rahmen, Cursor und Text vorher. Der aufrufende Code muss das Eintragsarray und die Zeichenketten vorhalten. Text wird weder automatisch umgebrochen noch abgeschnitten; wählen Sie Positionen, Eintragszahlen und Beschriftungslängen so, dass alles ins Fenster passt.

Anwendungsbeispiel

c
result[0]=menu_inventory(items,3);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Fenster zeigt SWORD 07, SHIELD 42 und POTION 99. Die Wahl von SHIELD liefert Index 1 zurück; seine Menge bleibt 42.

menu_inventory: DMG
DMG
menu_inventory: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_inventory.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_inventory.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:267

Deklarationshinweise im Original
Run a blocking item menu, drawing names and two-digit quantities. Return
the selected index or 0xFF on empty input/B; this does not consume an item.

kitaqgb/lib/menu.c:176

c
u8 menu_inventory(const item_t* items, u8 count)
{
    u8 cursor;
    u8 prev;
    u8 i;

    if (count == 0) return 0xFF;

    text_open(1, 1, 18, (u8)(count + 2));
    cursor = 0;
    prev = 0;

    while (1) {
        for (i = 0; i < count; i++) {
            u8 py = (u8)(2 + i);
            const u8* s = items[i].name;
            u8 px = 3;
            __settile_xy(2, py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            while (*s != 0) {
                __settile_xy(px, py, *s);
                px++;
                s++;
            }
            menu_draw_ascii_qty(15, py, items[i].qty);
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
menu_run

Zeigt ein Auswahlmenü an und wartet auf Bestätigung oder Abbruch.

Syntax

c
u8 menu_run(const menu_t* menu);

Parameter

menu

Nicht null gesetztes menu_t mit Position, Größe, Einträgen, Anzahl und Anfangsposition des Cursors. Liegt diese außerhalb des gültigen Bereichs, wird null verwendet.

Rückgabewert

Gibt den gewählten Index ab null zurück, bei Abbruch mit B oder leerer Liste 255.

Bedingungen und Grenzen

Neue UP/DOWN-Tastendrücke bewegen den Cursor mit Umlauf an den Listenenden, ohne Wiederholung bei gehaltener Taste. Bei gleichzeitigem Drücken hat A Vorrang vor B. Bereits beim Eintritt gehaltene Tasten gelten als neue Tastendrücke. menu->cursor liefert die Anfangsposition und wird nicht mit dem Ergebnis aktualisiert. Das Fenster bleibt nach der Rückkehr sichtbar. Laden Sie die Kacheln für Rahmen, Cursor und Text vorher. Der aufrufende Code muss das Eintragsarray und die Zeichenketten vorhalten. Text wird weder automatisch umgebrochen noch abgeschnitten; wählen Sie Positionen, Eintragszahlen und Beschriftungslängen so, dass alles ins Fenster passt.

Anwendungsbeispiel

c
result[0]=menu_run(&menu);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

In der Liste SWORD/SHIELD/POTION wählt DOWN gefolgt von A den Eintrag SHIELD mit Index 1. Die gespeicherte Anfangsposition des Cursors bleibt null.

menu_run: DMG
DMG
menu_run: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_run.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_run.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:262

Deklarationshinweise im Original
Run a blocking menu loop with wraparound up/down selection, A to accept
and B to cancel. Return 0xFF for an empty menu or cancellation. Item strings
and menu dimensions must fit the visible tile area.

kitaqgb/lib/menu.c:25

c
u8 menu_run(const menu_t* menu)
{
    u8 cursor;
    u8 prev;

    if (menu->count == 0) return 0xFF;

    text_open(menu->x, menu->y, menu->w, menu->h);
    cursor = menu->cursor;
    if (cursor >= menu->count) cursor = 0;
    prev = 0;

    while (1) {
        u8 i;
        for (i = 0; i < menu->count; i++) {
            u8 py = (u8)(menu->y + 1 + i);
            __settile_xy((u8)(menu->x + 1), py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            {
                const u8* s = menu->items[i];
                u8 px = (u8)(menu->x + 2);
                while (*s != 0) {
                    __settile_xy(px, py, *s);
                    px++;
                    s++;
                }
            }
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(menu->count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= menu->count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
menu_update

Liest einmal die Zustandsänderung der Controller-Tasten und aktualisiert Cursor, Auswahl und Abbruchstatus.

Syntax

c
void menu_update(menu_state_t* state);

Parameter

state

Initialisierter Menüzustand, dessen Eingabeverlauf und Ergebnisse aktualisiert werden.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bei einem Nullzeiger oder einer leeren Liste geschieht nichts. Die Funktion wartet weder auf einen Frame noch zeichnet sie; rufen Sie sie etwa einmal pro Frame der Spielschleife auf. UP/DOWN springt an den Listenenden zum jeweils anderen Ende, ohne Wiederholung bei gehaltener Taste. B wird nach A verarbeitet, daher bricht gleichzeitiges Drücken von A/B ab.

Anwendungsbeispiel

c
menu_update(&menu_state);menu_draw(&menu_state);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Schleife wartet auf VBlank, aktualisiert das Menü und zeichnet es, bis eine Auswahl oder ein Abbruch erfolgt. DOWN gefolgt von A ergibt Auswahl 1 und Abbruchflag 0.

menu_update: DMG
DMG
menu_update: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:277

Deklarationshinweise im Original
Sample new button presses and update cursor/selection state without drawing.
Selected and cancelled results remain latched; a B press in the same update
as A clears selection and leaves cancellation set.

kitaqgb/lib/menu.c:118

c
void menu_update(menu_state_t* state)
{
    u16 kt;
    u8 trigger;

    if (state == 0) return;
    if (state->count == 0) return;

    kt = __readpadex(state->prev_keys);
    state->prev_keys = (u8)kt;
    trigger = (u8)(kt >> 8);

    if ((trigger & PAD_KEY_UP) != 0) {
        if (state->cursor == 0) state->cursor = (u8)(state->count - 1);
        else state->cursor--;
    }
    if ((trigger & PAD_KEY_DOWN) != 0) {
        state->cursor++;
        if (state->cursor >= state->count) state->cursor = 0;
    }
    if ((trigger & PAD_KEY_A) != 0) {
        state->selected = state->cursor;
    }
    if ((trigger & PAD_KEY_B) != 0) {
        state->cancelled = 1;
        state->selected = 0xFF;
    }
}
menu_was_cancelled

Prüft, ob ein schrittweise verarbeitetes Menü mit B abgebrochen wurde.

Syntax

c
u8 menu_was_cancelled(menu_state_t* state);

Parameter

state

Zeiger auf einen initialisierten Menüzustand.

Rückgabewert

Gibt bei Abbruch 1 zurück, sonst 0, auch bei einem Nullzeiger.

Bedingungen und Grenzen

Das Lesen löscht das Flag nicht. Initialisieren Sie das Menü vor erneuter Verwendung. Prüfen Sie dieses Flag zusammen mit der Auswahl, da 255 allein nicht zwischen ausstehender Eingabe und Abbruch unterscheidet.

Anwendungsbeispiel

c
result[1]=menu_was_cancelled(&menu_state);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Bestätigung mit A lässt das Flag bei null. Eine separate Eingabeprüfung bricht mit B ab und prüft den Wert eins.

menu_was_cancelled: DMG
DMG
menu_was_cancelled: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:281

Deklarationshinweise im Original
Read the latched cancellation flag; null state returns false.

kitaqgb/lib/menu.c:155

c
u8 menu_was_cancelled(menu_state_t* state)
{
    if (state == 0) return 0;
    return state->cancelled;
}
menu_yesno

Zeigt ein YES/NO-Menü an einer festen Position und wartet auf eine Eingabe.

Syntax

c
u8 menu_yesno();

Rückgabewert

Gibt für YES 0 zurück, für NO 1 und bei Abbruch mit B 255.

Bedingungen und Grenzen

Das Fenster beginnt bei Kachel (6,10) und ist 8×4 Kacheln groß. Die Auswahl verwendet text_choice(). Nach der Rückkehr führt der aufrufende Code die gewählte Spielaktion aus. Laden Sie die Kacheln für Rahmen, Cursor und Text vorher. Der aufrufende Code muss das Eintragsarray und die Zeichenketten vorhalten. Text wird weder automatisch umgebrochen noch abgeschnitten; wählen Sie Positionen, Eintragszahlen und Beschriftungslängen so, dass alles ins Fenster passt.

Anwendungsbeispiel

c
result[0]=menu_yesno();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

DOWN gefolgt von A wählt NO. Der Cursor erscheint links neben NO, und SELECTED zeigt 00001 an.

menu_yesno: DMG
DMG
menu_yesno: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_yesno.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_yesno.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:264

Deklarationshinweise im Original
Open a two-choice dialog and return the text-choice result (YES first, NO second).

kitaqgb/lib/menu.c:162

c
u8 menu_yesno()
{
    const u8* items[2];

    items[0] = menu_yes;
    items[1] = menu_no;
    text_open(6, 10, 8, 4);
    return text_choice(items, 2);
}
path_find_bfs

Findet eine kürzeste orthogonale Route und schreibt ihre Richtungen in der Reihenfolge vom Start zum Ziel.

Syntax

c
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);

Parameter

sx

X der Startzelle innerhalb der Karte.

sy

Y der Startzelle.

gx

X der Zielzelle; ein blockiertes Ziel, das vom Ursprung abweicht, wird abgelehnt.

gy

Y der Zielzelle.

out_path

Beschreibbares Array mit mindestens max_len Bytes; 0=oben, 1=rechts, 2=unten, 3=links.

max_len

Ausgabekapazität; eine zu lange Route führt zu einem Fehlschlag, statt abgeschnitten zu werden.

Rückgabewert

Gibt die Routenlänge zurück; null bedeutet unerreichbar, ungültige Koordinaten, unzureichendes max_len oder bereits erreichtes Ziel.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Die Suche verwendet etwa 4 KiB gemeinsamen, nicht reentranten Arbeitsspeicher. Begrenzen Sie Karten auf 1024 Zellen und untersuchte Entfernungen auf 254. Distanz 0xFF bedeutet „nicht erreicht“; eine Route mit 255 Schritten ist daher nicht darstellbar. Kosten- und Maskenausgaben benötigen width*height beschreibbare Bytes.

max_len begrenzt die Ausgabe, nicht den Suchradius. Verwenden Sie die Ausgabe nach einem Fehlschlag nicht als neue Route.

Anwendungsbeispiel

c
result[49]=path_find_bfs(0,2,5,2,route,30);x=0;y=2;for(i=0;i<result[49];i++){if(route[i]==0)y--;if(route[i]==1)x++;if(route[i]==2)y++;if(route[i]==3)x--;}result[50]=x;result[51]=y;result[52]=path_find_bfs(0,2,5,2,route,2);result[53]=path_find_bfs(0,2,2,2,route,30);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

path_find_bfs: DMG
DMG
path_find_bfs: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:361

Deklarationshinweise im Original
Find a shortest cardinal path with BFS and write direction codes 0=up,
1=right, 2=down, 3=left. Return its byte length, or zero for failure or an
already-reached goal. The caller supplies max_len output bytes and respects
the shared workspace/distance limits; excessive paths are not truncated.

kitaqgb/lib/slg_path.c:78

c
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 head = 0;
    u16 tail = 0;
    u16 start;
    u16 goal;
    u8 found = 0;

    if (w == 0 || h == 0) return 0;
    if (sx >= w || sy >= h || gx >= w || gy >= h) return 0;
    if ((sx != gx || sy != gy) && map_is_blocked(gx, gy) != 0) return 0;

    total = (u16)((u16)w * (u16)h);
    __memset(path_dist, 0xFF, total);

    start = __map_index(sx, sy, w);
    goal = __map_index(gx, gy, w);

    path_dist[start] = 0;
    path_queue[tail++] = start;

    while (head < tail) {
        u16 cur = path_queue[head++];
        u8 cost = path_dist[cur];
        u8 y = (u8)(cur / w);
        u8 x = (u8)(cur - ((u16)y * (u16)w));

        if (cur == goal) {
            found = 1;
            break;
        }

        if (y > 0) {
            u16 next = (u16)(cur - w);
            if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(x + 1) < w) {
            u16 next = (u16)(cur + 1);
            if (path_dist[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(y + 1) < h) {
            u16 next = (u16)(cur + w);
            if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if (x > 0) {
            u16 next = (u16)(cur - 1);
            if (path_dist[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
    }

    // Reject unreachable or oversized paths before reconstructing output.
    if (found == 0) return 0;
    if (path_dist[goal] > max_len) return 0;

    {
        // Walk backward through decreasing costs, recording forward directions in
        // reverse order. The fixed neighbor order makes tied routes deterministic.
        u8 len = 0;
        u16 cur = goal;

        while (cur != start) {
            u8 cur_cost = path_dist[cur];
            u8 y = (u8)(cur / w);
            u8 x = (u8)(cur - ((u16)y * (u16)w));

            if (y > 0 && path_dist[(u16)(cur - w)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 2;
                cur = (u16)(cur - w);
                continue;
            }
            if ((u8)(x + 1) < w && path_dist[(u16)(cur + 1)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 3;
                cur = (u16)(cur + 1);
                continue;
            }
            if ((u8)(y + 1) < h && path_dist[(u16)(cur + w)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 0;
                cur = (u16)(cur + w);
                continue;
            }
            if (x > 0 && path_dist[(u16)(cur - 1)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 1;
                cur = (u16)(cur - 1);
                continue;
            }
            return 0;
        }

        // Reverse the recovered directions so the first output step starts at the origin.
        while (len != 0) {
            len--;
            out_path[path_dist[goal] - 1 - len] = path_rev[len];
        }

        return path_dist[goal];
    }
}
quest_set_state

Ersetzt das gesamte Zustandsbyte einer Aufgabe. Die Bedeutung jedes Werts bestimmt das Spiel, etwa 1 für angenommen und 3 für abgeschlossen. Die Funktion prüft nicht, ob der Übergang erlaubt ist, und löst weder Belohnungen noch Callbacks aus.

Syntax

c
void quest_set_state(u8 quest_id, u8 state);

Parameter

quest_id

Aufgabennummer von 0 bis 63, als u8 übergeben. Sie adressiert direkt eines der 64 Zustandsbytes und ist eine vom Spiel definierte ID, kein Zeiger und keine Anzahl abgeschlossener Aufgaben.

state

Neuer u8-Zustand von 0 bis 255. Alle acht Bits ersetzen den vorherigen Wert. Die Bibliothek weist den Werten keine feste Bedeutung zu und reserviert weder 0 noch 255.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Die Funktion prüft die ID nicht. Halten Sie Flag-IDs unter 2048 und Aufgaben-IDs unter 64. Zugriffe außerhalb des Bereichs können fremde RAM-Inhalte lesen oder überschreiben. Die Beispiele initialisieren ausdrücklich, statt sich auf Anfangsinhalte zu verlassen.

flags.c besitzt 256 RAM-Bytes für Flags und weitere 64 Bytes für Aufgaben. Diese Funktionen greifen nicht auf Cartridge-Speicher-RAM zu und erhalten keine Daten über das Ausschalten hinweg. Für dauerhaften Fortschritt muss das Spiel Flag- und Aufgabenwerte über sein Speichersystem serialisieren und beim Laden wiederherstellen.

Binden Sie rpg.h ein und kompilieren Sie lib/flags.c mit dem Spiel. Die Arrays sind innerhalb dieser Quelldatei privat; verwenden Sie die Flag- und Aufgaben-APIs zum Zugriff. Alle Aufrufer teilen sich den Speicher. Koordinieren Sie daher Schreibzugriffe aus Hauptschleife und Interrupt-Handlern selbst.

Anwendungsbeispiel

c
quest_set_state(2,1); // In this game, 1 means accepted.
started=quest_state(2);
quest_set_state(2,3); // In this game, 3 means completed; replace the whole byte.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel speichert für Aufgabe 2 zunächst 1 und überschreibt den Wert mit 3. ACCEPTED zeigt die erste Beobachtung 001, COMPLETED den Ersatzwert 003. LAST QUEST ist 255, nachdem 255 in Aufgaben-ID 63, dem letzten gültigen Eintrag, gespeichert wurde.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: auf DMG mit schwarzem, auf CGB mit blauem Text. FAILED muss 000 sein. Die Aufnahmen zeigen nur das Verhalten der RAM-Zustände und belegen kein Speichern eines Spiels.

Die Prüfung im DMG-Emulator deckte alle Flag-IDs von 0 bis 2047, wiederholtes Setzen und Löschen, benachbarte Einträge sowie alle 256 Zustandswerte jeder der 64 Aufgaben ab. Ein abschließendes Muster aus 256 Flagbytes und 64 Aufgabenbytes wurde mit den erwarteten Daten verglichen. Beide Lehrbildschirme wurden nach 240 Frames geprüft. Echte Hardware und dauerhafte Speicherung wurden nicht getestet.

quest_set_state: DMG
DMG
quest_set_state: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:377

Deklarationshinweise im Original
Replace a quest-state byte without validating its game-specific meaning.
The caller must keep quest_id below 64.

kitaqgb/lib/flags.c:34

c
void quest_set_state(u8 quest_id, u8 state)
{
    quest_states[quest_id] = state;
}
quest_state

Liest das gespeicherte Byte einer Aufgabe. Anders als ein Ein-Bit-Flag kann ein Aufgabenbyte mehrere Stufen wie nicht begonnen, angenommen und abgeschlossen unterscheiden. Die Funktion liest nur den Speicher, führt keine Aufgabenlogik aus und schaltet keine Stufe weiter.

Syntax

c
u8 quest_state(u8 quest_id);

Parameter

quest_id

Aufgabennummer von 0 bis 63, als u8 übergeben. Sie adressiert direkt eines der 64 Zustandsbytes und ist eine vom Spiel definierte ID, kein Zeiger und keine Anzahl abgeschlossener Aufgaben.

Rückgabewert

Gespeicherter u8-Wert von 0 bis 255. Dies ist ein vollständiges Zustandsbyte, kein normalisierter boolescher Wert. Vergleichen Sie ihn mit den vom Spiel definierten Stufenwerten.

Bedingungen und Grenzen

Die Funktion prüft die ID nicht. Halten Sie Flag-IDs unter 2048 und Aufgaben-IDs unter 64. Zugriffe außerhalb des Bereichs können fremde RAM-Inhalte lesen oder überschreiben. Die Beispiele initialisieren ausdrücklich, statt sich auf Anfangsinhalte zu verlassen.

flags.c besitzt 256 RAM-Bytes für Flags und weitere 64 Bytes für Aufgaben. Diese Funktionen greifen nicht auf Cartridge-Speicher-RAM zu und erhalten keine Daten über das Ausschalten hinweg. Für dauerhaften Fortschritt muss das Spiel Flag- und Aufgabenwerte über sein Speichersystem serialisieren und beim Laden wiederherstellen.

Binden Sie rpg.h ein und kompilieren Sie lib/flags.c mit dem Spiel. Die Arrays sind innerhalb dieser Quelldatei privat; verwenden Sie die Flag- und Aufgaben-APIs zum Zugriff. Alle Aufrufer teilen sich den Speicher. Koordinieren Sie daher Schreibzugriffe aus Hauptschleife und Interrupt-Handlern selbst.

Anwendungsbeispiel

c
finished=quest_state(2); // Read back 3 without advancing any quest logic.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest Aufgabe 2, nachdem das Spiel ihren Zustand ausdrücklich von 1 auf 3 geändert hat. ACCEPTED zeigt 001 und COMPLETED 003. Namen und Stufenbedeutungen legt das Beispiel fest, nicht die Bibliothek.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: auf DMG mit schwarzem, auf CGB mit blauem Text. FAILED muss 000 sein. Die Aufnahmen zeigen nur das Verhalten der RAM-Zustände und belegen kein Speichern eines Spiels.

Die Prüfung im DMG-Emulator deckte alle Flag-IDs von 0 bis 2047, wiederholtes Setzen und Löschen, benachbarte Einträge sowie alle 256 Zustandswerte jeder der 64 Aufgaben ab. Ein abschließendes Muster aus 256 Flagbytes und 64 Aufgabenbytes wurde mit den erwarteten Daten verglichen. Beide Lehrbildschirme wurden nach 240 Frames geprüft. Echte Hardware und dauerhafte Speicherung wurden nicht getestet.

quest_state: DMG
DMG
quest_state: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:374

Deklarationshinweise im Original
Read a quest-state byte; quest_id must be below 64.

kitaqgb/lib/flags.c:27

c
u8 quest_state(u8 quest_id)
{
    return quest_states[quest_id];
}
rand_range

Wählt mit rng8() % max einen Wert ab null und kleiner als max. Eine Grenze von 10 liefert beispielsweise einen Index von 0 bis 9. Bei Grenze null wird sofort null ohne Ziehung geliefert.

Syntax

c
u8 rand_range(u8 max);

Parameter

max

Ausgeschlossene Obergrenze als u8 (0–255). Für max > 0 ist das Ergebnis kleiner als max. Der Parameter kann 256 nicht darstellen; verwenden Sie rng8 für den gesamten Bytebereich ohne Modulo-Reduktion.

Rückgabewert

Für max > 0 ein u8 von 0 bis max−1 nach einer Ziehung. Für max == 0 null ohne Ziehung. Selbst max == 1 verbraucht eine Ziehung, obwohl das Ergebnis immer null ist.

Bedingungen und Grenzen

Modulo-Reduktion kann bestimmte Ergebnisse bevorzugen, wenn der Eingabebereich nicht durch die Grenze teilbar ist. Auch der zugrunde liegende Generator muss nicht gleichverteilt sein. Behandeln Sie begrenzte Ergebnisse und Chancenschwellen als Spielnäherungen statt als exakte Wahrscheinlichkeiten.

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
bounded=rand_range(10); // An index from 0 through 9; this seed yields 2.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel wählt einen Index unter 10. RANGE 10 zeigt 00002, weil das erste Byte nach Startwert 0x1234 gleich 2 ist. ZERO BOUND ist 00000 und das folgende NEXT BYTE weiterhin 00002; der Aufruf mit Grenze null hat somit keine Ziehung verbraucht.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rand_range: DMG
DMG
rand_range: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:199

Deklarationshinweise im Original
Reduce a random byte modulo max; zero returns zero without consuming randomness.
Modulo reduction is biased unless max divides the generator range.

kitaqgb/lib/rng.c:37

c
u8 rand_range(u8 max)
{
    if (max == 0) return 0;
    return (u8)(rng8() % max);
}
range_fill_move

Durchsucht orthogonale Nachbarzellen per Breitensuche mit Einheitskosten, um Bewegungskosten zu ermitteln.

Syntax

c
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);

Parameter

sx

X der Startzelle innerhalb der Karte.

sy

Y der Startzelle.

move

Bewegungsgrenze 0..254; null erreicht nur den Ursprung.

out_costmap

Beschreibbares Kostenarray mit width*height Einträgen: 255 für nicht erreicht, null am Ursprung.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Die Suche verwendet etwa 4 KiB gemeinsamen, nicht reentranten Arbeitsspeicher. Begrenzen Sie Karten auf 1024 Zellen und untersuchte Entfernungen auf 254. Distanz 0xFF bedeutet „nicht erreicht“; eine Route mit 255 Schritten ist daher nicht darstellbar. Kosten- und Maskenausgaben benötigen width*height beschreibbare Bytes.

Bei fehlender Karte oder ungültigem Ursprung bleibt die Ausgabe unverändert. Blockierte Zielzellen werden nicht betreten.

Anwendungsbeispiel

c
range_fill_move(0,2,3,costs);for(i=0;i<30;i++)result[13+i]=costs[i];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

range_fill_move: DMG
DMG
range_fill_move: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:365

Deklarationshinweise im Original
Flood cardinal neighbors at unit cost, stopping expansion at the movement
limit and rejecting blocked destinations. Initialize output to 0xFF only
after validating the map and origin; invalid input leaves output unchanged.

kitaqgb/lib/slg_path.c:14

c
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 head = 0;
    u16 tail = 0;
    u16 start;

    if (w == 0 || h == 0) return;
    if (sx >= w || sy >= h) return;

    total = (u16)((u16)w * (u16)h);
    __memset(out_costmap, 0xFF, total);

    start = __map_index(sx, sy, w);
    out_costmap[start] = 0;
    path_queue[tail++] = start;

    while (head < tail) {
        u16 cur = path_queue[head++];
        u8 cost = out_costmap[cur];
        u8 y = (u8)(cur / w);
        u8 x = (u8)(cur - ((u16)y * (u16)w));

        if (cost >= move) continue;

        if (y > 0) {
            u16 next = (u16)(cur - w);
            if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(x + 1) < w) {
            u16 next = (u16)(cur + 1);
            if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(y + 1) < h) {
            u16 next = (u16)(cur + w);
            if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if (x > 0) {
            u16 next = (u16)(cur - 1);
            if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
    }
}
rle_decode

Entpackt einen lauflängencodierten Bytestrom in normalen beschreibbaren RAM. Jedes Paar count/value wiederholt ein Byte count-mal; count gleich null beendet den Strom. Nutzen Sie diese Variante, wenn die codierten Daten über einen normalen Zeiger lesbar sind und Sie die entpackten Bytes vor dem Übertragen prüfen oder ändern möchten.

Syntax

c
u16 rle_decode(void* dst, const void* src);

Parameter

dst

Zeiger auf genügend beschreibbaren RAM für den gesamten entpackten Strom. Die Funktion erhält keine Kapazitätsangabe. Trennen Sie Ausgabe und codierte Quelle, damit Schreibzugriffe keine noch ungelesenen Paare überschreiben.

src

Lesbarer Zeiger auf count/value-Bytepaare mit count null als Abschluss. Normale Läufe haben count 1–255; value darf jedes Byte einschließlich null sein. Auf die abschließende null folgt kein Wertebyte. Der Zeiger muss während des gesamten Aufrufs in der aktuellen Zuordnung lesbar bleiben.

Rückgabewert

Anzahl geschriebener Bytes als u16. Ein sofortiger Nullzähler erzeugt keine Bytes und liefert 0. Der Abschluss wird nicht kopiert. Die entpackte Länge muss in u16 passen; der Rückgabewert enthält keinen separaten Fehlercode und ist keine Kachelanzahl.

Bedingungen und Grenzen

Die Codierung verarbeitet Bytes, keinen Text. Beispielsweise wird {3, 0x12, 2, 0xA5, 0} zu fünf Bytes: 12 12 12 A5 A5. Diese Ausgabeliste verwendet Hexadezimalwerte. Ein Nullwert bei einem Paar mit count ungleich null ist normales Datum, kein Endzeichen.

Es gibt keine Argumente für codierte Größe, Ausgabekapazität oder fehlerhafte Daten. Prüfen Sie Ressourcen beim Erstellen oder Laden, setzen Sie die abschließende null und berechnen Sie vor dem Decodieren die entpackte Größe. Ein ungültiger oder nicht abgeschlossener Strom kann über Quelle und Ziel hinaus lesen beziehungsweise schreiben.

Die RAM-Decoder verwenden normale Schreibzugriffe ohne Synchronisierung mit LCD-Zugriffsphasen. Ihre Ziele müssen im RAM liegen. Zum Anzeigen übertragen Sie das Ergebnis separat mit einer passenden VRAM-Kopierfunktion, wie im Beispiel bei gestopptem LCD.

Während eines Zugriffs mit Bankangabe dürfen Interruptroutinen weder die ROM-Zuordnung ändern noch die Far-Copy-Hilfe erneut verwenden; die Hilfen teilen ihre Bankverwaltung. Platzieren Sie den Decoder für normale Zeiger und seine Quelle in kompatiblen Zuordnungen. Ein Wechsel zur Funktionsbank darf einen normalen Quellzeiger nicht verdecken.

rle_decode und rle_decode_far sind in rpg.h deklariert und in lib/rle.c implementiert. Kompilieren Sie diese Implementierung einmal mit dem Spiel. Das vollständige Beispiel bindet rle.c nach #pragma bank 0 ein, damit Aufrufer und Decoder in der gemeinsamen Bank bleiben; übergeben Sie rle.c dafür nicht zusätzlich als eigene Eingabe. Die intrinsische Funktion __rle_decode_vram benötigt selbst keine Bibliotheksimplementierungsdatei.

Anwendungsbeispiel

c
near_count=rle_decode(near_buffer+1,local_rle); // 48 bytes in writable RAM.
__vram_copy(0x8800,near_buffer+1,near_count); // Upload those bytes while the LCD is off.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel entpackt neun codierte Bytes in einen RAM-Puffer mit Schutzbereichen und kopiert die 48 Ergebnisbytes an die Kacheldatenadresse 0x8800. RLE TO RAM zeigt 048. Die obere Reihe ist auf dem CGB rot und zeigt die drei über den normalen Zeiger decodierten Kacheln.

Jede Reihe enthält von links nach rechts ein gefülltes 8×8-Quadrat, einen 8×8-Rahmen mit einem Pixel Stärke und ein gefülltes 4×8-Rechteck in der linken Hälfte einer 8×8-Kachel. Die Kachelspalten sind 2, 5 und 8 (Pixel-x = 16, 40 und 64). Die drei Reihen beginnen bei Pixel-y = 32, 72 und 112. Auf dem DMG sind die Formen schwarz, auf dem CGB je Reihe rot, grün und blau. FAILED muss 000 sein. Die Zahlen zählen Bytes: Drei GB-Kacheln zu je 16 Bytes erfordern 48 entpackte Bytes.

Die Prüfmatrix umfasst 42 Fälle: leerer Strom, Einbyte-Lauf, Nullwertdaten, 255-Byte-Lauf, 510-Byte-Ausgabe über eine Zielseitengrenze und codierte Daten über eine Quellseitengrenze. Verglichen werden alle 528 beobachteten Ziel-/Schutzbytes, Ausgabelänge und wiederhergestellte ROM-Zuordnung. Direkte VRAM-Fälle umfassen LCD an/aus auf DMG und CGB sowie CGB-VBK 1. Die beiden Lehrbildschirme werden nach 240 Emulatorframes geprüft. Ungültige Ressourcen, gleichzeitige Interruptnutzung und echte Hardware sind nicht abgedeckt.

rle_decode: DMG
DMG
rle_decode: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:382

Deklarationshinweise im Original
Expand count/value byte pairs until a zero count terminates the stream.
The caller must provide a valid terminator and sufficient destination storage;
there are no source or destination bounds parameters. Return the 16-bit byte count.

kitaqgb/lib/rle.c:8

c
u16 rle_decode(void* dst, const void* src)
{
    const u8* in = (const u8*)src;
    u8* out = (u8*)dst;
    u16 total = 0;

    while (1) {
        u8 count = *in++;
        u8 value;
        if (count == 0) break;
        value = *in++;
        while (count != 0) {
            *out++ = value;
            total++;
            count--;
        }
    }

    return total;
}
rle_decode_far

Entpackt dasselbe count/value-Format in RAM, liest jedes codierte Byte aber über __farpeek8 aus der angegebenen ROM-Bank. Geeignet für komprimierte Ressourcen in einer umschaltbaren ROM-Bank. Das Ziel bleibt ein normaler RAM-Zeiger; das Bankargument beschreibt die Quelle.

Syntax

c
u16 rle_decode_far(void* dst, u8 bank, const void* src);

Parameter

dst

Zeiger auf genügend beschreibbaren RAM für den gesamten entpackten Strom. Die Funktion erhält keine Kapazitätsangabe. Trennen Sie Ausgabe und codierte Quelle, damit Schreibzugriffe keine noch ungelesenen Paare überschreiben.

bank

ROM-Quellbanknummer als u8. Bank und CPU-Adresse müssen zu Cartridge-Mapper und Ressourcenablage passen. Nach jedem codierten Byte wird die Bankauswahl wiederhergestellt. Das Argument wählt keine VRAM-Zielbank und kann keine Neunbit-MBC5-Banknummer darstellen.

src

CPU-Zeiger auf den codierten Strom in der angegebenen Bank. Die Adresse wird erhöht, die Banknummer bleibt jedoch fest. Halten Sie den gesamten Strom einschließlich Endnull in einer lesbaren Zuordnung; das Überschreiten von 0x7FFF setzt ihn nicht automatisch in der nächsten ROM-Bank fort.

Rückgabewert

Anzahl geschriebener Bytes als u16. Ein sofortiger Nullzähler erzeugt keine Bytes und liefert 0. Der Abschluss wird nicht kopiert. Die entpackte Länge muss in u16 passen; der Rückgabewert enthält keinen separaten Fehlercode und ist keine Kachelanzahl.

Bedingungen und Grenzen

Die Codierung verarbeitet Bytes, keinen Text. Beispielsweise wird {3, 0x12, 2, 0xA5, 0} zu fünf Bytes: 12 12 12 A5 A5. Diese Ausgabeliste verwendet Hexadezimalwerte. Ein Nullwert bei einem Paar mit count ungleich null ist normales Datum, kein Endzeichen.

Es gibt keine Argumente für codierte Größe, Ausgabekapazität oder fehlerhafte Daten. Prüfen Sie Ressourcen beim Erstellen oder Laden, setzen Sie die abschließende null und berechnen Sie vor dem Decodieren die entpackte Größe. Ein ungültiger oder nicht abgeschlossener Strom kann über Quelle und Ziel hinaus lesen beziehungsweise schreiben.

Die RAM-Decoder verwenden normale Schreibzugriffe ohne Synchronisierung mit LCD-Zugriffsphasen. Ihre Ziele müssen im RAM liegen. Zum Anzeigen übertragen Sie das Ergebnis separat mit einer passenden VRAM-Kopierfunktion, wie im Beispiel bei gestopptem LCD.

Während eines Zugriffs mit Bankangabe dürfen Interruptroutinen weder die ROM-Zuordnung ändern noch die Far-Copy-Hilfe erneut verwenden; die Hilfen teilen ihre Bankverwaltung. Platzieren Sie den Decoder für normale Zeiger und seine Quelle in kompatiblen Zuordnungen. Ein Wechsel zur Funktionsbank darf einen normalen Quellzeiger nicht verdecken.

rle_decode und rle_decode_far sind in rpg.h deklariert und in lib/rle.c implementiert. Kompilieren Sie diese Implementierung einmal mit dem Spiel. Das vollständige Beispiel bindet rle.c nach #pragma bank 0 ein, damit Aufrufer und Decoder in der gemeinsamen Bank bleiben; übergeben Sie rle.c dafür nicht zusätzlich als eigene Eingabe. Die intrinsische Funktion __rle_decode_vram benötigt selbst keine Bibliotheksimplementierungsdatei.

Anwendungsbeispiel

c
far_count=rle_decode_far(far_buffer+1,2,banked_rle); // Read encoded pairs from ROM bank 2.
if(*rle_bank_marker!=0xA1)failures++; // ROM bank 1 must be visible again.
__vram_copy(0x8830,far_buffer+1,far_count);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel liest den codierten Strom aus ROM-Bank 2, entpackt 48 Bytes in RAM und überträgt sie nach 0x8830. BANKED RAM zeigt 048. Die mittlere Reihe ist auf dem CGB grün. Ein Marker in ROM-Bank 1 prüft zusätzlich die Wiederherstellung der Zuordnung des Aufrufers.

Jede Reihe enthält von links nach rechts ein gefülltes 8×8-Quadrat, einen 8×8-Rahmen mit einem Pixel Stärke und ein gefülltes 4×8-Rechteck in der linken Hälfte einer 8×8-Kachel. Die Kachelspalten sind 2, 5 und 8 (Pixel-x = 16, 40 und 64). Die drei Reihen beginnen bei Pixel-y = 32, 72 und 112. Auf dem DMG sind die Formen schwarz, auf dem CGB je Reihe rot, grün und blau. FAILED muss 000 sein. Die Zahlen zählen Bytes: Drei GB-Kacheln zu je 16 Bytes erfordern 48 entpackte Bytes.

Die Prüfmatrix umfasst 42 Fälle: leerer Strom, Einbyte-Lauf, Nullwertdaten, 255-Byte-Lauf, 510-Byte-Ausgabe über eine Zielseitengrenze und codierte Daten über eine Quellseitengrenze. Verglichen werden alle 528 beobachteten Ziel-/Schutzbytes, Ausgabelänge und wiederhergestellte ROM-Zuordnung. Direkte VRAM-Fälle umfassen LCD an/aus auf DMG und CGB sowie CGB-VBK 1. Die beiden Lehrbildschirme werden nach 240 Emulatorframes geprüft. Ungültige Ressourcen, gleichzeitige Interruptnutzung und echte Hardware sind nicht abgedeckt.

rle_decode_far: DMG
DMG
rle_decode_far: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:386

Deklarationshinweise im Original
Decode the same count/value format using bank-qualified reads for every source
byte. Keep the encoded stream within the supplied bank/address mapping and
provide enough destination space; a zero count ends the stream.

kitaqgb/lib/rle.c:34

c
u16 rle_decode_far(void* dst, u8 bank, const void* src)
{
    const u8* p = (const u8*)src;
    u8* out = (u8*)dst;
    u16 total = 0;

    while (1) {
        u8 count = __farpeek8(bank, p);
        u8 value;
        p++;
        if (count == 0) break;
        value = __farpeek8(bank, p);
        p++;
        while (count != 0) {
            *out++ = value;
            total++;
            count--;
        }
    }

    return total;
}
rng16

Bildet einen vorzeichenlosen 16-Bit-Wert aus zwei aufeinanderfolgenden rng8-Ziehungen. Das erste Byte belegt Bits 15–8, das zweite Bits 7–0. Geeignet, wenn ein Byte den benötigten Wertebereich nicht abdeckt.

Syntax

c
u16 rng16();

Rückgabewert

Ein u16-Ergebnis (0–65535), gebildet als (first_byte << 8) | second_byte. Genau zwei Byteziehungen werden verbraucht; eine Gleichverteilung aller 65536 Werte ist damit nicht belegt.

Bedingungen und Grenzen

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
word=rng16(); // First draw 2 is high, second draw 34 is low: 0x0222 = 546.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel zeigt die Wortbildung. Nach erneutem Startwert 0x1234 bilden die Bytes 2 und 34 den Wert 0x0222, weshalb RNG16 00546 zeigt. FIRST und SECOND zeigen die zugehörigen Bytewerte einzeln.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng16: DMG
DMG
rng16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:196

Deklarationshinweise im Original
Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.

kitaqgb/lib/rng.c:22

c
u16 rng16()
{
    u16 hi = (u16)rng8();
    u16 lo = (u16)rng8();
    return (u16)((hi << 8) | lo);
}
rng8

Liefert ein Pseudozufallsbyte über die GB-Bibliothek. rng8 ruft __rng8 genau einmal auf und ist damit die grundlegende Ziehoperation der anderen rng.c-Hilfen.

Syntax

c
u8 rng8();

Rückgabewert

Ein u8-Ergebnis (0–255) nach einmaligem Fortschalten des gemeinsamen Generators. Dies beschreibt Typ und Grenzen, nicht gleiche Wahrscheinlichkeit für jedes Byte.

Bedingungen und Grenzen

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234); // Reset the same generator used by the intrinsics.
wrapped=rng8(); // One byte draw: 2 after the preceding seed.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel vergleicht die Byteziehung der Bibliothek mit der intrinsischen Funktion. Nach rng_seed(0x1234) zeigt RNG8 wie FIRST den Wert 00002. Das Setzen des Startwerts verbraucht die erste Ziehung nicht.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng8: DMG
DMG
rng8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:194

Deklarationshinweise im Original
Advance the compiler-provided pseudorandom generator and return one byte.

kitaqgb/lib/rng.c:4

c
u8 rng8()
{
    return __rng8();
}
rng_chance

Trifft mit rng_range(100) < percent eine Ja-/Nein-Entscheidung. Das eignet sich für ungefähre Spielchancen, etwa einen Gegenstandsdrop. Null liefert immer falsch, 100 oder mehr immer wahr; beide Randfälle verbrauchen keine Ziehung.

Syntax

c
u8 rng_chance(u8 percent);

Parameter

percent

Gewünschte Chance als u8. Werte 1–99 verwenden ein modulo-reduziertes Byte; 0 liefert falsch, 100–255 liefern wahr. Die Zwischenwerte sind ungefähre Schwellwerte, keine Garantie exakter Prozentsätze.

Rückgabewert

Normalisierter Wahrheitswert: 0 für falsch, 1 für wahr. Ein Schwellwert von 1 bis 99 verbraucht eine Byteziehung.

Bedingungen und Grenzen

Modulo-Reduktion kann bestimmte Ergebnisse bevorzugen, wenn der Eingabebereich nicht durch die Grenze teilbar ist. Auch der zugrunde liegende Generator muss nicht gleichverteilt sein. Behandeln Sie begrenzte Ergebnisse und Chancenschwellen als Spielnäherungen statt als exakte Wahrscheinlichkeiten.

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
chance=rng_chance(50); // Here 2 % 100 < 50, so the result is 1 (true).

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel führt eine ungefähre 50-Prozent-Entscheidung aus. Das gezogene Byte ist 2 und 2 % 100 < 50 wahr, daher zeigt CHANCE 50 den Wert 00001. Ein einzelner Erfolg belegt keine langfristige Erfolgsquote von 50 Prozent.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng_chance: DMG
DMG
rng_chance: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:214

Deklarationshinweise im Original
Return false for zero and true for values at least 100. Intermediate values
use the modulo-based range generator, so percentages are approximate.

kitaqgb/lib/rng.c:51

c
u8 rng_chance(u8 percent)
{
    if (percent == 0) return 0;
    if (percent >= 100) return 1;
    return (u8)(rng_range(100) < percent);
}
rng_next16

Liefert dasselbe Wort aus zwei Ziehungen wie rng16. Dieser Bibliotheksalias legt die erste Ziehung ins High-Byte und die zweite ins Low-Byte; er überspringt vorher keinen zusätzlichen Wert.

Syntax

c
u16 rng_next16();

Rückgabewert

Ein u16-Ergebnis (0–65535), gebildet als (first_byte << 8) | second_byte. Genau zwei Byteziehungen werden verbraucht; eine Gleichverteilung aller 65536 Werte ist damit nicht belegt.

Bedingungen und Grenzen

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
nextword=rng_next16(); // The same two-draw word: 546.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel vergleicht den Wortalias mit rng16 nach identischen Startwerten. NEXT16 und RNG16 zeigen jeweils 00546, zusammengesetzt aus zwei Byteziehungen in High-/Low-Reihenfolge.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng_next16: DMG
DMG
rng_next16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:209

Deklarationshinweise im Original
Alias the two-step 16-bit generator.

kitaqgb/lib/rng.c:30

c
u16 rng_next16()
{
    return rng16();
}
rng_next8

Zieht das nächste Byte mit derselben Operation wie rng8. Der Name betont das Fortschalten der Folge. Beide Namen nacheinander aufzurufen verbraucht zwei aufeinanderfolgende Ziehungen desselben gemeinsamen Generators.

Syntax

c
u8 rng_next8();

Rückgabewert

Ein u8-Ergebnis (0–255) nach einmaligem Fortschalten des gemeinsamen Generators. Dies beschreibt Typ und Grenzen, nicht gleiche Wahrscheinlichkeit für jedes Byte.

Bedingungen und Grenzen

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
nextbyte=rng_next8(); // One draw, just like rng8(): 2.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel prüft den Bytealias mit gleichem Startwert. NEXT8 und RNG8 zeigen jeweils 00002, da das Programm vor jedem Vergleich den Startwert erneut setzt. Ohne diese Rücksetzungen würden sie aufeinanderfolgende Werte verbrauchen.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng_next8: DMG
DMG
rng_next8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:207

Deklarationshinweise im Original
Alias the byte generator; this consumes one generator step.

kitaqgb/lib/rng.c:16

c
u8 rng_next8()
{
    return rng8();
}
rng_range

Ruft rand_range mit derselben ausgeschlossenen Obergrenze auf. Dieser Name ordnet die begrenzte Auswahl den anderen rng_-Funktionen zu. Byteziehung und Modulooperation sind identisch, einschließlich des Ergebnisses ohne Ziehung bei Grenze null.

Syntax

c
u8 rng_range(u8 max);

Parameter

max

Ausgeschlossene Obergrenze als u8 (0–255). Für max > 0 ist das Ergebnis kleiner als max. Der Parameter kann 256 nicht darstellen; verwenden Sie rng8 für den gesamten Bytebereich ohne Modulo-Reduktion.

Rückgabewert

Für max > 0 ein u8 von 0 bis max−1 nach einer Ziehung. Für max == 0 null ohne Ziehung. Selbst max == 1 verbraucht eine Ziehung, obwohl das Ergebnis immer null ist.

Bedingungen und Grenzen

Modulo-Reduktion kann bestimmte Ergebnisse bevorzugen, wenn der Eingabebereich nicht durch die Grenze teilbar ist. Auch der zugrunde liegende Generator muss nicht gleichverteilt sein. Behandeln Sie begrenzte Ergebnisse und Chancenschwellen als Spielnäherungen statt als exakte Wahrscheinlichkeiten.

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234);
alias=rng_range(10); // The same exclusive upper bound and result, 2.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel vergleicht zwei Namen der begrenzten Auswahl. Ein erneuter Startwert vor jedem Aufruf lässt ALIAS 10 und RANGE 10 jeweils 00002 anzeigen. Die Obergrenze 10 selbst ist ausgeschlossen.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng_range: DMG
DMG
rng_range: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:211

Deklarationshinweise im Original
Alias rand_range and return a value in [0,max), or zero when max is zero.

kitaqgb/lib/rng.c:44

c
u8 rng_range(u8 max)
{
    return rand_range(max);
}
rng_seed

Setzt den Startwert über die GB-Bibliotheksschnittstelle. Als Wrapper um __rng_seed setzt dies denselben Zustand zurück, den rng8, rng16 und Auswahlhilfen teilen; es wird kein separater Generator erzeugt.

Syntax

c
void rng_seed(u16 seed);

Parameter

seed

Vorzeichenloser 16-Bit-Startwert in 0–65535. Beide Bytes werden unverändert gespeichert. Wählen und notieren Sie den Startwert vor der Folge von Spielziehungen, die Sie reproduzieren möchten.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Zustand null ist zulässig. Bei der nächsten Byteziehung ersetzt ihn der GB-Generator vor dem Fortschalten durch 0x5AA5; __rng_seed(0) gefolgt von __rng8() liefert daher 122. Wiederholtes Setzen des Startwerts startet die Folge neu, statt Zufälligkeit hinzuzufügen.

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
rng_seed(0x1234); // Reset the same generator used by the intrinsics.
wrapped=rng8(); // One byte draw: 2 after the preceding seed.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel vergleicht die Byteziehung der Bibliothek mit der intrinsischen Funktion. Nach rng_seed(0x1234) zeigt RNG8 wie FIRST den Wert 00002. Das Setzen des Startwerts verbraucht die erste Ziehung nicht.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

rng_seed: DMG
DMG
rng_seed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:205

Deklarationshinweise im Original
Replace the generator seed so subsequent calls can reproduce a sequence.

kitaqgb/lib/rng.c:10

c
void rng_seed(u16 seed)
{
    __rng_seed(seed);
}
save_check

Führt dieselbe Integritätsprüfung wie save_exists aus, ohne Nutzdaten auszulesen.

Syntax

c
u8 save_check(u8 slot);

Parameter

slot

Slotnummer 0..3.

Rückgabewert

Gibt bei Gültigkeit 1 zurück, sonst 0. Auch ein Spielstand mit Länge null kann gültig sein.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Anwendungsbeispiel

c
result[4]=save_check(0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_check: DMG
DMG
save_check: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:341

Deklarationshinweise im Original
Alias save_exists, including its header and checksum validation.

kitaqgb/lib/save.c:175

c
u8 save_check(u8 slot)
{
    return save_exists(slot);
}
save_clear

Setzt alle 512 Bytes eines Slots auf null, um seinen Spielstand ungültig zu machen.

Syntax

c
void save_clear(u8 slot);

Parameter

slot

Slotnummer 0..3.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Ignoriert Slots außerhalb von 0..3 und lässt andere Slots unverändert.

Anwendungsbeispiel

c
save_clear(0);result[16]=save_check(0);result[17]=save_write(3,payload,0);result[18]=save_exists(3);save_clear(3);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_clear: DMG
DMG
save_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:344

Deklarationshinweise im Original
Zero the complete selected slot, including header and payload; invalid slot
IDs are ignored. Cartridge RAM is disabled when clearing finishes.

kitaqgb/lib/save.c:225

c
void save_clear(u8 slot)
{
    u16 base;
    u16 i;

    if (slot >= SAVE_SLOT_COUNT) return;

    base = save_slot_base(slot);
    save_enable();

    i = 0;
    while (i < SAVE_SLOT_SIZE) {
        save_write_abs((u16)(base + i), 0);
        i++;
    }

    save_disable();
}
save_exists

Prüft Header, Länge und Prüfsumme eines Slots auf einen verwendbaren Spielstand.

Syntax

c
u8 save_exists(u8 slot);

Parameter

slot

Slotnummer 0..3.

Rückgabewert

Gibt bei Gültigkeit 1 zurück, sonst 0. Auch ein Spielstand mit Länge null kann gültig sein.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Anwendungsbeispiel

c
result[0]=save_exists(0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_exists: DMG
DMG
save_exists: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:334

Deklarationshinweise im Original
Validate a slot's header, payload bounds and checksum without copying the
payload out. A nonzero result means the stored record passes these checks.

kitaqgb/lib/save.c:182

c
u8 save_exists(u8 slot)
{
    u16 base;
    u16 stored_len;
    u8 stored_sum;

    if (slot >= SAVE_SLOT_COUNT) return 0;

    base = save_slot_base(slot);
    save_enable();

    if (save_read_abs(base + 0) != SAVE_MAGIC0) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 1) != SAVE_MAGIC1) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 2) != SAVE_VERSION) {
        save_disable();
        return 0;
    }

    stored_len = (u16)save_read_abs(base + 3);
    stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
    stored_sum = save_read_abs(base + 5);

    if (stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
        save_disable();
        return 0;
    }
    if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
        save_disable();
        return 0;
    }

    save_disable();
    return 1;
}
save_init

Wählt RAM-Bank null, aktiviert sie kurz und deaktiviert sie anschließend.

Syntax

c
void save_init();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Löscht keine Spielstände, erkennt keine Modulhardware und formatiert keine Slots.

Anwendungsbeispiel

c
save_init();save_clear(0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_init: DMG
DMG
save_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:337

Deklarationshinweise im Original
Initialize the expected RAM access state and leave cartridge RAM disabled.
Existing slot contents are preserved.

kitaqgb/lib/save.c:70

c
void save_init()
{
    save_enable();
    save_disable();
}
save_load

Lädt gespeicherte Daten mit derselben Prüfung wie save_read.

Syntax

c
u8 save_load(u8 slot, void* data, u16 len);

Parameter

slot

Slotnummer 0..3.

data

Beschreibbares Ziel mit len Bytes.

len

Nutzdatenlänge 0..506 Bytes. Beim Lesen muss sie genau mit der gespeicherten Länge übereinstimmen.

Rückgabewert

Gibt bei erfolgreichem Laden 1 zurück, sonst 0; die angeforderte Länge muss der gespeicherten entsprechen.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Die additive 8-Bit-Prüfsumme erkennt nicht jede Beschädigung. Schreibvorgänge sind bei Stromausfall nicht atomar; eine Erfolgsmeldung allein garantiert daher keine dauerhafte physische Speicherung.

Anwendungsbeispiel

c
readback[1]=0;result[10]=save_load(0,readback,3);result[11]=readback[1];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_load: DMG
DMG
save_load: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:339

Deklarationshinweise im Original
Alias the checked save_read operation.

kitaqgb/lib/save.c:114

c
u8 save_load(u8 slot, void* data, u16 len)
{
    return save_read(slot, data, len);
}
save_read

Prüft Header, exakte Länge und Prüfsumme und kopiert Daten erst nach erfolgreicher Prüfung.

Syntax

c
u8 save_read(u8 slot, void* data, u16 len);

Parameter

slot

Slotnummer 0..3.

data

Beschreibbares Ziel mit len Bytes.

len

Nutzdatenlänge 0..506 Bytes. Beim Lesen muss sie genau mit der gespeicherten Länge übereinstimmen.

Rückgabewert

Gibt bei Erfolg 1 zurück, bei fehlgeschlagener Prüfung 0; ein Fehlschlag lässt das Ziel unverändert.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Die additive 8-Bit-Prüfsumme erkennt nicht jede Beschädigung. Schreibvorgänge sind bei Stromausfall nicht atomar; eine Erfolgsmeldung allein garantiert daher keine dauerhafte physische Speicherung.

Anwendungsbeispiel

c
readback[0]=99;result[5]=save_read(0,readback,2);result[6]=readback[0];result[7]=save_read(0,readback,3);result[8]=readback[0];result[9]=readback[2];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_read: DMG
DMG
save_read: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:331

Deklarationshinweise im Original
Require matching magic/version, exact requested length and a valid checksum
before copying data into the destination. Validation failure leaves the
destination unchanged. An invalid slot returns before touching RAM control;
validation failures after enabling RAM disable it before returning zero.

kitaqgb/lib/save.c:125

c
u8 save_read(u8 slot, void* data, u16 len)
{
    u8* dst = (u8*)data;
    u16 base;
    u16 stored_len;
    u8 stored_sum;
    u16 i;

    if (slot >= SAVE_SLOT_COUNT) return 0;

    base = save_slot_base(slot);
    save_enable();

    if (save_read_abs(base + 0) != SAVE_MAGIC0) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 1) != SAVE_MAGIC1) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 2) != SAVE_VERSION) {
        save_disable();
        return 0;
    }

    stored_len = (u16)save_read_abs(base + 3);
    stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
    stored_sum = save_read_abs(base + 5);

    if (stored_len != len || stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
        save_disable();
        return 0;
    }
    if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
        save_disable();
        return 0;
    }

    i = 0;
    while (i < stored_len) {
        dst[i] = save_read_abs((u16)(base + SAVE_HEADER_SIZE + i));
        i++;
    }

    save_disable();
    return 1;
}
save_write

Schreibt Daten, Länge und Prüfsumme in einen Slot.

Syntax

c
u8 save_write(u8 slot, const void* data, u16 len);

Parameter

slot

Slotnummer 0..3.

data

Lesbare Quelle mit len Bytes.

len

Nutzdatenlänge 0..506 Bytes. Beim Lesen muss sie genau mit der gespeicherten Länge übereinstimmen.

Rückgabewert

Gibt bei gültigen Argumenten 1 zurück, bei ungültigem Slot oder ungültiger Länge 0; führt keine Rückleseprüfung durch.

Bedingungen und Grenzen

Standardmäßig gibt es vier 512-Byte-Slots mit je sechs Headerbytes und bis zu 506 Nutzdatenbytes. Das Beispiel verwendet MBC5 mit 8 KiB SRAM. Aufrufe enden mit deaktiviertem RAM, ohne die vorherige Bank oder den Aktivierungszustand wiederherzustellen.

Die additive 8-Bit-Prüfsumme erkennt nicht jede Beschädigung. Schreibvorgänge sind bei Stromausfall nicht atomar; eine Erfolgsmeldung allein garantiert daher keine dauerhafte physische Speicherung.

Anwendungsbeispiel

c
payload[0]=7;payload[1]=42;payload[2]=255;result[1]=save_write(0,payload,3);result[2]=save_write(4,payload,3);result[3]=save_write(0,payload,507);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Speichern Sie drei Bytes, 7/42/255, und prüfen Sie falsche Länge, ungültigen Slot und beschädigte Prüfsumme. Erfolgreiches Laden ergibt das mittlere Byte 42; fehlgeschlagenes Lesen erhält Zielwert 77; die Prüfung nach dem Löschen liefert 0.

save_write: DMG
DMG
save_write: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementierung und Quelltext

kitaqgb/lib/rpg.h:326

Deklarationshinweise im Original
Validate slot and payload length, write payload bytes, then write the header
and checksum. Return one after completing the writes; interruption can leave
a partially replaced slot, so this is not transactional save storage.

kitaqgb/lib/save.c:81

c
u8 save_write(u8 slot, const void* data, u16 len)
{
    const u8* src = (const u8*)data;
    u16 base;
    u16 i;
    u8 sum = 0;

    if (slot >= SAVE_SLOT_COUNT) return 0;
    if (len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) return 0;

    base = save_slot_base(slot);
    save_enable();

    i = 0;
    while (i < len) {
        u8 v = src[i];
        save_write_abs((u16)(base + SAVE_HEADER_SIZE + i), v);
        sum = (u8)(sum + v);
        i++;
    }

    save_write_abs(base + 0, SAVE_MAGIC0);
    save_write_abs(base + 1, SAVE_MAGIC1);
    save_write_abs(base + 2, SAVE_VERSION);
    save_write_abs(base + 3, (u8)(len & 0xFF));
    save_write_abs(base + 4, (u8)(len >> 8));
    save_write_abs(base + 5, sum);

    save_disable();
    return 1;
}
script_run

Wählt ein Skript und setzt Wartezähler, Auswahlergebnis und gespeicherte Rücksprungposition zurück.

Syntax

c
void script_run(u8 bank, const u8* script);

Parameter

bank

ROM-Bank des Anweisungsstroms.

script

Beginn eines gültigen terminierten Datenstroms; dieser Aufruf bereitet ihn vor, ohne Befehle auszuführen.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Opcodes: 00 END; 01 TEXT(bank,ptr16); 02 SET_FLAG(id16); 03 CLEAR_FLAG(id16); 04 JUMP(bank,ptr16); 05 IF_FLAG(id16,bank,ptr16); 06 CHOICE(count,table16); 07 WAIT(n); 08 CALL_EVENT(bank,ptr16). Wörter sind Little-Endian. Halten Sie Zeichenketten, Zeigertabellen und Anweisungen lesbar und innerhalb ihrer eingeblendeten Banken.

Anwendungsbeispiel

c
flag_clear(19);script_run(1,(const u8*)&entry);result[0]=flag_get(19);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Springen Sie von Bank 1 zu Bank 2, setzen Sie Flag 19 und warten Sie. Die ersten beiden Warteaufrufe liefern 1; das Zielflag wird 1; der Abschluss nach WAIT liefert 2. Das Flag belegt, dass die Ausführung die andere Bank erreicht hat.

script_run: DMG
DMG
script_run: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:250

Deklarationshinweise im Original
Replace the active script and clear wait, choice and saved-return state.

kitaqgb/lib/script.c:105

c
void script_run(u8 bank, const u8* script)
{
    script_active = 1;
    script_bank = bank;
    script_pc = script;
    script_wait = 0;
    script_last_choice = 0xFF;
    script_return_active = 0;
}
script_step

Verarbeitet Befehle, bis Ausgabe, Auswahl, Warten oder Abschluss die Kontrolle zurückgibt.

Syntax

c
u8 script_step();

Rückgabewert

0=Kontrollrückgabe durch TEXT/CHOICE; 1=Warten; 2=beendet oder inaktiv. Unbekannte Opcodes beenden ebenfalls mit 2.

Bedingungen und Grenzen

Opcodes: 00 END; 01 TEXT(bank,ptr16); 02 SET_FLAG(id16); 03 CLEAR_FLAG(id16); 04 JUMP(bank,ptr16); 05 IF_FLAG(id16,bank,ptr16); 06 CHOICE(count,table16); 07 WAIT(n); 08 CALL_EVENT(bank,ptr16). Wörter sind Little-Endian. Halten Sie Zeichenketten, Zeigertabellen und Anweisungen lesbar und innerhalb ihrer eingeblendeten Banken.

WAIT n gibt beim Dekodieren 1 zurück und wartet danach weitere n Aufrufe. CALL_EVENT hat nur einen gespeicherten Rücksprungplatz. CHOICE benötigt eine Anzahl ungleich null und blockiert intern bis zur Auswahl. Eine Sprungschleife ohne Kontrollrückgabe blockiert die Spielschleife; stellen Sie sicher, dass ein Endbefehl oder ein Befehl zur Kontrollrückgabe erreicht wird.

Anwendungsbeispiel

c
result[3]=script_step();result[4]=flag_get(19);result[5]=script_step();result[6]=script_step();result[7]=script_step();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Springen Sie von Bank 1 zu Bank 2, setzen Sie Flag 19 und warten Sie. Die ersten beiden Warteaufrufe liefern 1; das Zielflag wird 1; der Abschluss nach WAIT liefert 2. Das Flag belegt, dass die Ausführung die andere Bank erreicht hat.

script_step: DMG
DMG
script_step: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:254

Deklarationshinweise im Original
Execute commands until an output/choice yields (0), a wait yields (1), or
execution ends (2). Control/flag commands continue within the same call, so
a script loop without a yielding command can block the game loop indefinitely.

kitaqgb/lib/script.c:125

c
u8 script_step()
{
    if (script_active == 0) return 2;
    if (script_wait != 0) {
        script_wait--;
        return 1;
    }

    while (script_active != 0) {
        u8 op = script_read8();

        // An END returns to the one saved caller when present; otherwise it ends the script.
        if (op == SCRIPT_OP_END) {
            if (script_return_active != 0) {
                script_bank = script_return_bank;
                script_pc = script_return_pc;
                script_return_active = 0;
                continue;
            }
            script_active = 0;
            return 2;
        }

        if (op == SCRIPT_OP_TEXT) {
            u8 bank = script_read8();
            u16 ptr = script_read16();
            text_print_far(bank, (const u8*)ptr);
            return 0;
        }

        if (op == SCRIPT_OP_SET_FLAG) {
            u16 id = script_read16();
            flag_set(id);
            continue;
        }

        if (op == SCRIPT_OP_CLEAR_FLAG) {
            u16 id = script_read16();
            flag_clear(id);
            continue;
        }

        if (op == SCRIPT_OP_JUMP) {
            // Read all operands in the source bank before installing the destination.
            u8 bank = script_read8();
            u16 ptr = script_read16();
            script_bank = bank;
            script_pc = (const u8*)ptr;
            continue;
        }

        // Read all branch operands before switching bank/address so an untaken branch
        // still consumes the full instruction.
        if (op == SCRIPT_OP_IF_FLAG) {
            u16 id = script_read16();
            u8 bank = script_read8();
            u16 ptr = script_read16();
            if (flag_get(id) != 0) {
                script_bank = bank;
                script_pc = (const u8*)ptr;
            }
            continue;
        }

        if (op == SCRIPT_OP_CHOICE) {
            u8 count = script_read8();
            u16 table = script_read16();
            script_last_choice = script_choice(script_bank, (const u8*)table, count);
            return 0;
        }

        if (op == SCRIPT_OP_WAIT) {
            script_wait = script_read8();
            return 1;
        }

        // Save the continuation only when the single return slot is empty. Nested
        // calls replace the current script but do not push another return address.
        if (op == SCRIPT_OP_CALL_EVENT) {
            u8 bank = script_read8();
            u16 ptr = script_read16();
            if (script_return_active == 0) {
                script_return_active = 1;
                script_return_bank = script_bank;
                script_return_pc = script_pc;
            }
            script_bank = bank;
            script_pc = (const u8*)ptr;
            continue;
        }

        // Unknown opcodes terminate with the same return code as END; there is no distinct malformed-stream error.
        script_active = 0;
        return 2;
    }

    return 2;
}
script_wait_frames

Lässt die angegebene Anzahl der nächsten script_step-Aufrufe warten.

Syntax

c
void script_wait_frames(u8 n);

Parameter

n

Anzahl wartender Aufrufe, 0..255; null hebt das Warten auf.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Dies entspricht nur dann einer Frame-Anzahl, wenn script_step einmal pro Frame aufgerufen wird; die Funktion wartet selbst nicht auf VBlank.

Anwendungsbeispiel

c
script_wait_frames(2);result[1]=script_step();result[2]=script_step();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Springen Sie von Bank 1 zu Bank 2, setzen Sie Flag 19 und warten Sie. Die ersten beiden Warteaufrufe liefern 1; das Zielflag wird 1; der Abschluss nach WAIT liefert 2. Das Flag belegt, dass die Ausführung die andere Bank erreicht hat.

script_wait_frames: DMG
DMG
script_wait_frames: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:257

Deklarationshinweise im Original
Set the number of subsequent script_step calls to spend waiting. Frame-based
timing requires the application to call script_step once per frame.

kitaqgb/lib/script.c:117

c
void script_wait_frames(u8 n)
{
    script_wait = n;
}
text_choice

Zeichnet eine vertikale Liste im aktiven Textbereich und wartet auf eine Auswahl. UP/DOWN bewegen den Cursor umlaufend, A bestätigt und B bricht ab. Die Schleife zeichnet die Auswahl neu und fragt nach einem VBlank-Wartevorgang einmal die Eingabe ab. Liefert einen Index ab null oder bei Abbruch beziehungsweise leerer Liste 255.

Syntax

c
u8 text_choice(const u8* const* choices, u8 count);

Parameter

choices

Zeiger auf ein Array mit count lesbaren Zeichenkettenzeigern. Jede Zeichenkette endet mit null und enthält rohe Kachel-IDs; Auswahltexte interpretieren keine Dialogsteuercodes. Halten Sie Zeigertabelle und Texte bis zum Auswahlende eingeblendet.

count

Anzahl der Auswahlmöglichkeiten. Null liefert sofort 255, ohne die Zeigertabelle zu lesen. Andernfalls benötigen Sie mindestens count Innenzeilen und genügend Breite für eine Cursorzelle plus den längsten Text. Es gibt weder Clipping noch Scrollen.

Rückgabewert

Index von 0 bis count−1 bei Bestätigung mit A. 255 bedeutet Abbruch mit B oder count gleich null; unterscheiden Sie dies bei Bedarf im aufrufenden Code. Die Funktion schließt den Textbereich nicht und löscht die Liste nicht.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Öffnen und dimensionieren Sie den Bereich vorher. Die Auswahlroutine nutzt seine gespeicherte Position, ohne den offenen Zustand zu prüfen. Texte beginnen zwei Spalten innerhalb der linken und eine Zeile unter der oberen Kante; der Cursor steht direkt links daneben. Die Auswahltexte verwenden nicht die Dialogzeichengeschwindigkeit.

Die Eingabeschleife reagiert auf neue Tastendrücke, UP vor DOWN und A vor B. Gehaltene Richtungen wiederholen die Bewegung nicht; lassen Sie los und drücken Sie erneut. Da die vorige Tastenmaske mit null beginnt, kann eine gehaltene Taste beim Eintritt sofort wirken. Gleichzeitige Bewegung und A liefern den neuen Index, obwohl der zuletzt gezeichnete Cursor noch die vorherige Position zeigen kann.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
selected=text_choice(dialogue_choices,3);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Drücken Sie einmal DOWN und dann A. In der Aufnahme steht der Rechtspfeilcursor neben SHIELD bei Kachel (2,4), und SELECTED zeigt 1. Die Texte beginnen bei (3,3), (3,4) und (3,5). Rahmen, Cursor und Texte sind auf CGB grün, auf DMG schwarz; Ergebnis und Hinweise bleiben schwarz.

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_choice: DMG
DMG
text_choice: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_choice.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_choice.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:231

Deklarationshinweise im Original
Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A
accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings
use raw tile bytes, and the caller must fit them inside the available rows.

kitaqgb/lib/text.c:316

c
u8 text_choice(const u8* const* choices, u8 count)
{
    u8 cursor;
    u8 prev;

    if (count == 0) return 0xFF;

    cursor = 0;
    prev = 0;
    while (1) {
        u8 i;
        for (i = 0; i < count; i++) {
            u8 py = (u8)(text_y + 1 + i);
            __settile_xy((u8)(text_x + 1), py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            text_draw_string_at((u8)(text_x + 2), py, choices[i]);
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
text_clear_rect

Füllt einen rechteckigen Bereich der Hintergrund-Tilemap mit TEXT_TILE_FILL. Damit können Sie eine Beschriftung, ein Zahlenfeld oder einen Teil eines Panels löschen. Der aktive Textcursor, der Öffnungszustand und die Abmessungen des Textbereichs bleiben unverändert.

Syntax

c
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

w

Breite in Tile-Zellen. Bei text_window sind beide Randspalten enthalten; innen bleiben max(w−2, 0) Spalten. Bei text_clear_rect ist dies die Anzahl der zu füllenden Zellen pro Zeile.

h

Höhe in Tile-Zellen. Bei text_window sind oberer und unterer Rand enthalten; innen bleiben max(h−2, 0) Zeilen. Bei text_clear_rect ist dies die Anzahl der zu füllenden Zeilen.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die öffentlichen Zahlenfunktionen verwenden genau die Breite des neuen Werts. Rechts verbleibende Zellen werden nicht gelöscht. Wird an derselben Position 7 über 12345 geschrieben, erscheint 72345. Löschen Sie das reservierte Fünf-Zellen-Feld vor der Ausgabe mit text_clear_rect, damit nur 7 erscheint. Für ein vorzeichenbehaftetes 16-Bit-Feld sind sechs Zellen nötig.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_clear_rect(7,5,5,1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Anfangs steht im Rahmen in Zeile 5 KEEP ERASE KEEP. Das Löschen von fünf Zellen ab (7,5) entfernt ERASE; beide KEEP-Beschriftungen und der Rahmen bleiben erhalten. Auch die Zeile CLEAN löscht vor der Ausgabe von 7 ein Zahlenfeld mit fünf Zellen.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_clear_rect: DMG
DMG
text_clear_rect: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:237

Deklarationshinweise im Original
Fill the supplied tile rectangle without changing the active text window or cursor.

kitaqgb/lib/text.c:220

c
void text_clear_rect(u8 x, u8 y, u8 w, u8 h)
{
    __settile_rect(x, y, w, h, TEXT_TILE_FILL);
}
text_close

Löscht den aktiven Textbereich einschließlich Rahmen mit TEXT_TILE_FILL und markiert ihn als geschlossen. Ein erneuter Aufruf im geschlossenen Zustand tut nichts. Die Hintergrundkacheln vor dem Öffnen werden nicht wiederhergestellt.

Syntax

c
void text_close();

Rückgabewert

Kein Rückgabewert. Zeichnen und blockierende Wartevorgänge erfolgen vor der Rückkehr.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Gewöhnliche Zeichen werden bei geschlossenem Bereich oder ohne nutzbaren Innenraum ignoriert. Steuerbytes werden weiterhin ausgewertet: WAIT kann blockieren, Seitenbefehle können warten oder den gespeicherten Bereich löschen. text_print auf einem geschlossenen Bereich ist daher nicht grundsätzlich wirkungslos.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
text_close();
text_print("HIDDEN"); // With the area closed, ordinary characters are not drawn.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel öffnet bei (1,9) einen Bereich von 18×3 Zellen, schreibt ERASE ME, schließt ihn und versucht HIDDEN zu schreiben. Unter CLOSED AREA müssen Zellen x=1–18 und y=9–11 leer sein; weder Text noch Rahmen dürfen bleiben. Der blaue Dialog darüber bleibt sichtbar.

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_close: DMG
DMG
text_close: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:220

Deklarationshinweise im Original
Erase the open window with the fill tile and disable windowed character output.

kitaqgb/lib/text.c:200

c
void text_close()
{
    if (text_opened == 0) return;
    __settile_rect(text_x, text_y, text_w, text_h, TEXT_TILE_FILL);
    text_opened = 0;
}
text_open

Öffnet einen softwareseitigen Textbereich auf der Hintergrundkarte. Speichert Position und Größe, setzt den Zeichencursor auf die erste Innenzelle, zeichnet den Rahmen und leert das Innere. Ein weiterer Bereich ersetzt den aktiven Bereich und Cursor, löscht aber keinen bereits an anderer Stelle gezeichneten Bereich.

Syntax

c
void text_open(u8 x, u8 y, u8 w, u8 h);

Parameter

x

Linke Spalte des Bereichs in 8×8-BG-Kartenzellen. Die gesamte Breite muss in Spalten 0–31 liegen.

y

Obere Zeile des Bereichs in 8×8-BG-Kartenzellen. Die gesamte Höhe muss in Zeilen 0–31 liegen.

w

Gesamtbreite in Zellen einschließlich linker und rechter Rahmenkante. Für eine innere Zeichenspalte sind mindestens drei Zellen nötig.

h

Gesamthöhe in Zellen einschließlich oberer und unterer Rahmenkante. Für eine innere Zeichenzeile sind mindestens drei Zellen nötig.

Rückgabewert

Kein Rückgabewert. Zeichnen und blockierende Wartevorgänge erfolgen vor der Rückkehr.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
text_open(1,2,18,5);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

DIALOGUE FLOW öffnet bei (1,2) einen Rahmen von 18×5 Zellen mit 16×3 Innenzellen. NEAR, READY und BANK 2 belegen die drei Zeilen. Sichtbare Rahmenlinien reichen von Pixel x=11 bis 147 und y=19 bis 51. Rahmen und Text sind auf CGB blau, auf DMG schwarz. Der später geöffnete Löschtestbereich lässt diesen Rahmen sichtbar.

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_open: DMG
DMG
text_open: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:218

Deklarationshinweise im Original
Set the tile-space window, reset its cursor and redraw it immediately.
Opening does not reset the existing character speed or load font tiles.

kitaqgb/lib/text.c:187

c
void text_open(u8 x, u8 y, u8 w, u8 h)
{
    text_x = x;
    text_y = y;
    text_w = w;
    text_h = h;
    text_opened = 1;
    text_reset_cursor();
    text_draw_frame();
    text_clear_inside();
}
text_print

Liest einen Steuerstrom über einen gewöhnlichen Zeiger und schreibt dessen Zeichenkacheln am aktiven Fenstercursor. Verarbeitet Zeilenumbrüche, Zeit- und Seitenwartebefehle und bricht an der Innenbreite um. Kehrt erst bei END zurück; Seitenwarten kann daher bis zu einem Tastendruck blockieren.

Syntax

c
void text_print(const u8* str);

Parameter

str

Lesbarer Zeiger auf einen mit TEXT_CTRL_END (0) terminierten Strom. Halten Sie ihn während blockierender Wartezeiten vollständig eingeblendet, einschließlich aller Operanden nach WAIT. Pufferlänge und Gültigkeit werden nicht geprüft.

Rückgabewert

Kein Rückgabewert. Zeichnen und blockierende Wartevorgänge erfolgen vor der Rückkehr.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Steuerbytes: 0x00 beendet den Strom; 0x0A wechselt zur nächsten Innenzeile; 0x01 liest das folgende Byte als Anzahl von VBlank-Wartevorgängen einschließlich null; 0x02 wartet auf Seitenwechsel, leert das Innere und setzt den Cursor zurück. Andere Bytes sind Kachel-IDs. Ein WAIT-Operand null ist kein END-Marker.

Ein Umbruch unter die letzte Innenzeile zeigt die Seitenwartemarkierung, wartet auf A, B oder START, leert das Innere und setzt in der ersten Zelle fort. Die Seite wird ersetzt, nicht zeilenweise gescrollt. Explizites 0x02 wartet ohne zusätzliche Markierung. Die Seitenabfrage beginnt ohne gespeicherte Tasten; eine schon beim Wartebeginn gehaltene Taste kann daher weiterschalten.

Gewöhnliche Zeichen werden bei geschlossenem Bereich oder ohne nutzbaren Innenraum ignoriert. Steuerbytes werden weiterhin ausgewertet: WAIT kann blockieren, Seitenbefehle können warten oder den gespeicherten Bereich löschen. text_print auf einem geschlossenen Bereich ist daher nicht grundsätzlich wirkungslos.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
text_print(dialogue_near);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Der gewöhnliche Strom schreibt NEAR, Zeilenumbruch, READY und einen Zwölffach-Wartebefehl vor END. NEAR beginnt bei Kachel (2,3), READY bei (2,4). Der folgende bankbezogene Strom nutzt denselben Cursor weiter; sein erster Umbruch setzt BANK 2 daher in die dritte Innenzeile.

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_print: DMG
DMG
text_print: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:224

Deklarationshinweise im Original
Decode an END-terminated stream of tile bytes and newline/wait/page controls.
WAIT consumes a following frame-count byte. The source must remain readable
through blocking waits; the routine does not validate stream length.

kitaqgb/lib/text.c:261

c
void text_print(const u8* str)
{
    while (*str != TEXT_CTRL_END) {
        u8 c = *str++;
        if (c == TEXT_CTRL_NEWLINE) {
            text_newline();
            continue;
        }
        if (c == TEXT_CTRL_WAIT) {
            u8 frames = *str++;
            text_delay_frames(frames);
            continue;
        }
        if (c == TEXT_CTRL_PAGE_WAIT) {
            text_wait_advance();
            text_clear_inside();
            text_reset_cursor();
            continue;
        }
        text_put_tile(c);
    }
}
text_print_far

Interpretiert denselben Dialogsteuerstrom, liest aber jedes Byte mit __farpeek8 aus der angegebenen ROM-Bank. Verwenden Sie dies für Dialoge außerhalb der aktuell eingeblendeten Quellbank. Zeichenplatzierung, Geschwindigkeit, Umbruch und Seitensteuerung entsprechen text_print.

Syntax

c
void text_print_far(u8 bank, const u8* str);

Parameter

bank

Vorzeichenlose 8-Bit-Nummer der ROM-Quellbank. Das Beispiel speichert den Strom in Bank 2 und prüft, dass der aufrufende Code nach der Ausgabe weiterhin eine Markierung in Bank 1 lesen kann.

str

CPU-Adresse des Stroms in der angegebenen Bank. Die Adresse schreitet fort, die Banknummer bleibt gleich; das Überschreiten des umschaltbaren ROM-Fensters setzt nicht automatisch in der nächsten Bank fort.

Rückgabewert

Kein Rückgabewert. Zeichnen und blockierende Wartevorgänge erfolgen vor der Rückkehr.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Steuerbytes: 0x00 beendet den Strom; 0x0A wechselt zur nächsten Innenzeile; 0x01 liest das folgende Byte als Anzahl von VBlank-Wartevorgängen einschließlich null; 0x02 wartet auf Seitenwechsel, leert das Innere und setzt den Cursor zurück. Andere Bytes sind Kachel-IDs. Ein WAIT-Operand null ist kein END-Marker.

Ein Umbruch unter die letzte Innenzeile zeigt die Seitenwartemarkierung, wartet auf A, B oder START, leert das Innere und setzt in der ersten Zelle fort. Die Seite wird ersetzt, nicht zeilenweise gescrollt. Explizites 0x02 wartet ohne zusätzliche Markierung. Die Seitenabfrage beginnt ohne gespeicherte Tasten; eine schon beim Wartebeginn gehaltene Taste kann daher weiterschalten.

Gewöhnliche Zeichen werden bei geschlossenem Bereich oder ohne nutzbaren Innenraum ignoriert. Steuerbytes werden weiterhin ausgewertet: WAIT kann blockieren, Seitenbefehle können warten oder den gespeicherten Bereich löschen. text_print auf einem geschlossenen Bereich ist daher nicht grundsätzlich wirkungslos.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
text_print_far(2,dialogue_far);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest Zeilenumbruch und BANK 2 aus ROM-Bank 2. BANK RESTORED zeigt durch anschließendes Lesen der Markierung in Bank 1 des Aufrufers den Wert 161. Die sichtbare BANK-2-Zeile beginnt bei Kachel (2,5), die Rückkehrbestätigung steht bei (16,14).

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_print_far: DMG
DMG
text_print_far: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:227

Deklarationshinweise im Original
Decode the same text controls while fetching each byte from the specified
ROM bank. The pointer advances within that bank; it does not roll into the next bank.

kitaqgb/lib/text.c:286

c
void text_print_far(u8 bank, const u8* str)
{
    const u8* p = str;
    while (1) {
        u8 c = __farpeek8(bank, p);
        p++;
        if (c == TEXT_CTRL_END) return;
        if (c == TEXT_CTRL_NEWLINE) {
            text_newline();
            continue;
        }
        if (c == TEXT_CTRL_WAIT) {
            u8 frames = __farpeek8(bank, p);
            p++;
            text_delay_frames(frames);
            continue;
        }
        if (c == TEXT_CTRL_PAGE_WAIT) {
            text_wait_advance();
            text_clear_inside();
            text_reset_cursor();
            continue;
        }
        text_put_tile(c);
    }
}
text_print_s16

Zeichnet einen vorzeichenbehafteten 16-Bit-Wert als Dezimalzahl. Negative Werte beginnen mit dem Minus-Tile, gefolgt vom Betrag; null und positive Werte erhalten kein Vorzeichen. Die längste Ausgabe ist -32768 mit sechs Zellen.

Syntax

c
void text_print_s16(u8 x, u8 y, s16 value);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

value

Vorzeichenbehafteter Wert von −32768 bis 32767. Das Beispiel castet das 16-Bit-Muster 32768 (0x8000) nach s16, um −32768 anzuzeigen.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die öffentlichen Zahlenfunktionen verwenden genau die Breite des neuen Werts. Rechts verbleibende Zellen werden nicht gelöscht. Wird an derselben Position 7 über 12345 geschrieben, erscheint 72345. Löschen Sie das reservierte Fünf-Zellen-Feld vor der Ausgabe mit text_clear_rect, damit nur 7 erscheint. Für ein vorzeichenbehaftetes 16-Bit-Feld sind sechs Zellen nötig.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_print_s16(11,12,(s16)32768);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile S16 zeigt -32768 ab (11,12) in sechs Zellen einschließlich Minuszeichen, auf CGB in Grün. Damit wird der kleinste vorzeichenbehaftete 16-Bit-Wert geprüft, dessen positiver Betrag nicht in s16 passt.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_print_s16: DMG
DMG
text_print_s16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:247

Deklarationshinweise im Original
Print a minus tile for negative values, followed by the unsigned magnitude.
Positive values use the unsigned decimal path; no plus sign is emitted.

kitaqgb/lib/text.c:246

c
void text_print_s16(u8 x, u8 y, s16 value)
{
    u16 magnitude;
    if (value < 0) {
        __settile_xy(x, y, (u8)'-');
        magnitude = (u16)((s16)0 - value);
        text_print_u16_width((u8)(x + 1), y, magnitude, text_dec_digits_u16(magnitude));
        return;
    }
    text_print_u16(x, y, (u16)value);
}
text_print_u16

Zeichnet einen vorzeichenlosen 16-Bit-Wert als Dezimalzahl ab der angegebenen Tile-Position. Die Ausgabe belegt eine bis fünf Zellen ohne führende Nullen. Verwenden Sie dies für Punktestände oder Objektanzahlen, die 255 überschreiten können.

Syntax

c
void text_print_u16(u8 x, u8 y, u16 value);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

value

Vorzeichenloser Wert von 0 bis 65535.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die öffentlichen Zahlenfunktionen verwenden genau die Breite des neuen Werts. Rechts verbleibende Zellen werden nicht gelöscht. Wird an derselben Position 7 über 12345 geschrieben, erscheint 72345. Löschen Sie das reservierte Fünf-Zellen-Feld vor der Ausgabe mit text_clear_rect, damit nur 7 erscheint. Für ein vorzeichenbehaftetes 16-Bit-Feld sind sechs Zellen nötig.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_print_u16(11,10,65535);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile U16 zeigt 65535 bei (11,10) in fünf Zellen, auf CGB in Blau. OVERWRITE zeigt 72345, nachdem 7 über 12345 geschrieben wurde, ohne das Fünf-Zellen-Feld vorher zu löschen.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_print_u16: DMG
DMG
text_print_u16: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:244

Deklarationshinweise im Original
Print an unsigned word in decimal using only the required number of cells.

kitaqgb/lib/text.c:239

c
void text_print_u16(u8 x, u8 y, u16 value)
{
    text_print_u16_width(x, y, value, text_dec_digits_u16(value));
}
text_print_u8

Zeichnet einen vorzeichenlosen 8-Bit-Wert als Dezimalzahl ab der angegebenen Tile-Position. Der Wert belegt eine bis drei Zellen ohne führende Nullen; null belegt eine Zelle. Geeignet für kleine Zähler wie Leben oder Munition.

Syntax

c
void text_print_u8(u8 x, u8 y, u8 value);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

value

Vorzeichenloser Wert von 0 bis 255. Ausdrücke mit größerer Bitbreite werden durch den Funktionsparameter in u8 umgewandelt.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die öffentlichen Zahlenfunktionen verwenden genau die Breite des neuen Werts. Rechts verbleibende Zellen werden nicht gelöscht. Wird an derselben Position 7 über 12345 geschrieben, erscheint 72345. Löschen Sie das reservierte Fünf-Zellen-Feld vor der Ausgabe mit text_clear_rect, damit nur 7 erscheint. Für ein vorzeichenbehaftetes 16-Bit-Feld sind sechs Zellen nötig.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_print_u8(11,8,255);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Zeile U8 zeigt 255 ab (11,8) in genau drei Zellen, auf CGB in Blau. OVERWRITE und CLEAN zeigen, warum das Feld beim Ersetzen durch einen kürzeren Wert ausdrücklich gelöscht werden muss.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_print_u8: DMG
DMG
text_print_u8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:242

Deklarationshinweise im Original
Print an unsigned byte in decimal using only the required number of cells.

kitaqgb/lib/text.c:233

c
void text_print_u8(u8 x, u8 y, u8 value)
{
    text_print_u16_width(x, y, (u16)value, text_dec_digits_u16((u16)value));
}
text_print_xy

Zeichnet eine nullterminierte Folge von Tile-Nummern waagerecht ab einer absoluten Position auf der Hintergrundkarte. Dabei gibt es weder Begrenzung auf das Textfenster noch Zeilenumbruch, Auswertung von Textsteuercodes oder Zeichenverzögerung. Der von text_print verwendete Cursor bleibt unverändert.

Syntax

c
void text_print_xy(u8 x, u8 y, const u8* str);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

str

Lesbarer Zeiger auf Tile-Bytes mit abschließender 0. Jedes Byte wird direkt als Tile-Nummer verwendet. Ein ASCII-String erscheint nur dann als Text, wenn die passenden Glyphen unter den entsprechenden Tile-IDs liegen. Die Quelle muss bis zur Rückkehr eingeblendet und lesbar bleiben. Diese Funktionen decodieren kein UTF-8 und laden keine Glyphen. Mehrbyte-Text benötigt vor der Anzeige eine vom Spiel definierte Codierung und passende Tile-Daten.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_print_xy(2,3,"HELLO!");

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

HELLO! beginnt bei Tile (2,3), Pixel (16,24), innerhalb des roten CGB-Rahmens. Die Position auf der BG-Karte ist absolut: Das Öffnen des Textbereichs addiert keinen Versatz zu x oder y.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_print_xy: DMG
DMG
text_print_xy: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:240

Deklarationshinweise im Original
Draw a zero-terminated tile string at absolute tile coordinates, without
window clipping, control codes or the windowed printing delay.

kitaqgb/lib/text.c:227

c
void text_print_xy(u8 x, u8 y, const u8* str)
{
    text_draw_string_at(x, y, str);
}
text_set_speed

Legt die Anzahl der VBlank-Wartevorgänge nach jedem gewöhnlichen Zeichen von text_print oder text_print_far fest. Null entfernt diese Wartezeiten pro Zeichen. Öffnen und Schließen setzen die Einstellung nicht zurück. Explizite WAIT-Befehle warten auch bei Zeichengeschwindigkeit null.

Syntax

c
void text_set_speed(u8 speed);

Parameter

speed

VBlank-Wartevorgänge nach jedem dargestellten Zeichen, 0–255. Dies zählt Wartevorgänge, nicht Millisekunden. Die Einstellung beeinflusst weder text_print_xy noch Zahlenhilfsfunktionen oder Auswahlliste.

Rückgabewert

Kein Rückgabewert. Zeichnen und blockierende Wartevorgänge erfolgen vor der Rückkehr.

Bedingungen und Grenzen

Verwenden Sie ein gültiges BG-Rechteck und laden Sie Schrift- und Rahmenkacheln vorher. Der Softwaretextbereich verwendet die durch LCDC-Bit 3 gewählte BG-Karte und aktiviert nicht die Hardware-Window-Ebene. Nutzen Sie auf CGB VBK 0 für Kachelnummern und setzen Sie Farbattribute getrennt. Die Beispiele liefern ASCII-zugeordnete Schrift sowie Rahmen-, Cursor- und Seitenmarkierungskacheln. Dialoge und Auswahltexte verwenden Byte-Kachel-IDs ohne UTF-8-Decodierung. Für andere Zeichen liefern Sie Glyphenkacheln und codieren Texte mit deren IDs; Dialogsteuerbytes müssen reserviert bleiben.

Diese Hilfsfunktionen blockieren: Während des Wartens rufen sie weder Spielaktualisierung noch Musikdienst oder Zeichenschleife auf. Bei ausgeschaltetem LCD kehrt __wait_vblank sofort zurück; Zeichengeschwindigkeit und WAIT erzeugen dann keine Frame-Verzögerung. Lassen Sie das LCD für zeitgesteuerte Dialoge und framegetaktete Eingaben eingeschaltet. Verwenden Sie eine spielseitige Zustandsmaschine, wenn während des Gesprächs andere Arbeit weiterlaufen muss.

Die zugrunde liegenden sicheren Kachelschreibzugriffe warten bei aktivem LCD auf beschreibbare Modi und verwenden DI/EI um die Schreibzugriffe. Sie können Interrupts aktivieren, statt einen anfänglich deaktivierten Zustand zu erhalten. Rufen Sie diese blockierenden Helfer nicht aus Interrupt-Handlern auf und verlassen Sie sich nicht auf die Erhaltung dieses Zustands.

Jedes vollständige Beispiel bindet text.c einmal ein. Bauen Sie mit den Include-Verzeichnissen der Bibliothek und Handbuchbeispiele; fügen Sie lib/text.c nicht zusätzlich als Quelldatei hinzu. Das Far-Stream-Beispiel nutzt MBC5 mit 64 KiB ROM, damit die Daten in Bank 2 enthalten sind.

Anwendungsbeispiel

c
text_set_speed(2);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Ablaufbeispiel nutzt Geschwindigkeit 2 für gewöhnliche und bankübergreifende Dialoge sowie WAIT-Operand 12. Das fertige Bild zeigt den Text nach dem Warten. Eine getrennte Frame-Aufzeichnung prüft Geschwindigkeit 3, einen expliziten Fünffach-Wartebefehl und vier Wartevorgänge bei geschlossenem Bereich. Das abschließende Bild allein dient nicht als Timingnachweis.

Die Emulatorprüfungen vergleichen die vollständige BG-Karte und vier Beispielbilder. Weitere Läufe decken Öffnen/Schließen, gewöhnliche und bankbezogene Steuerströme, Zeitwarten, explizites und automatisches Seitenwarten, A/B/START-Fortschaltung, gehaltene Tasten, umlaufende Auswahl, leere Listen und gleichzeitige Eingabeprioritäten ab. Prüfpunkte vor und nach geskripteten Eingaben belegen das tatsächliche Blockieren beim Seitenwarten. Physische Hardware und Interruptparallelität sind nicht getestet.

text_set_speed: DMG
DMG
text_set_speed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:233

Deklarationshinweise im Original
Set VBlank waits per windowed character; zero prints without character delays.

kitaqgb/lib/text.c:208

c
void text_set_speed(u8 speed)
{
    text_speed = speed;
}
text_window

Zeichnet einen umrahmten Textbereich auf die Hintergrund-Tilemap und aktiviert ihn für die Textausgabe im Fenster. Dieser Alias von text_open setzt den Fenstercursor auf die erste innere Zelle, zeichnet den Rahmen neu und löscht den Innenbereich. Die aktuelle Zeichenverzögerung bleibt erhalten.

Syntax

c
void text_window(u8 x, u8 y, u8 w, u8 h);

Parameter

x

Startspalte in 8×8-Zellen der Hintergrundkarte. Die gesamte Ausgabe muss innerhalb der Spalten 0–31 liegen. Ohne Hintergrund-Scrolling sind die Spalten 0–19 sichtbar.

y

Startzeile in 8×8-Zellen der Hintergrundkarte, 0–31. Ohne Hintergrund-Scrolling sind die Zeilen 0–17 sichtbar. Ein Rechteck muss auch in vertikaler Richtung vollständig in die Karte passen.

w

Breite in Tile-Zellen. Bei text_window sind beide Randspalten enthalten; innen bleiben max(w−2, 0) Spalten. Bei text_clear_rect ist dies die Anzahl der zu füllenden Zellen pro Zeile.

h

Höhe in Tile-Zellen. Bei text_window sind oberer und unterer Rand enthalten; innen bleiben max(h−2, 0) Zeilen. Bei text_clear_rect ist dies die Anzahl der zu füllenden Zeilen.

Rückgabewert

Kein Rückgabewert. Die Funktion beschreibt die Tilemap-Zellen vor der Rückkehr; sie liefert weder eine Zeichenanzahl noch einen Statuscode.

Bedingungen und Grenzen

Diese Funktionen zeichnen auf die durch LCDC-Bit 3 gewählte BG-Karte. Das Textfenster ist ein Softwarebereich auf dieser Karte, nicht die Hardware-Window-Ebene. Halten Sie CGB-VBK für Tile-Nummern auf 0; diese Aufrufe setzen weder Farbattribute noch Paletten oder Scrolling.

Laden Sie Schrift und Rahmengrafiken vor dem Zeichnen. Die Standard-Rahmen-IDs sind 1–6, das Füll-Tile ist 0 und die Dezimalziffern beginnen bei ASCII 0 (Tile 48). Das Minuszeichen verwendet ASCII - (Tile 45). Das Beispiel enthält sechs Rahmen-Tiles und die Schrift des Handbuchs mit zu ASCII passenden Glyphen-IDs.

Halten Sie Rechtecke und Text innerhalb der 32×32-Karte. Die Rechteckfüllung begrenzt Breite und Höhe nicht auf den Kartenrand. Bei Breite oder Höhe null wird nichts gefüllt; text_window merkt sich den Bereich trotzdem als geöffnet, jedoch ohne nutzbaren Innenraum.

Die Intrinsics für Tile-Schreibzugriffe prüfen den LCD-Zustand: Bei ausgeschaltetem LCD schreiben sie sofort; andernfalls warten sie auf beschreibbare LCD-Modi und umgeben die Zugriffe mit DI/EI. Dieser Pfad kann bei der Rückkehr Interrupts aktivieren. Verlassen Sie sich daher nicht darauf, dass ein deaktivierter Interruptzustand erhalten bleibt. Die Beispiele und Byte-Tests hier schreiben bei ausgeschaltetem LCD.

Das vollständige Beispiel bindet text.c genau einmal ein, damit die Bibliotheksimplementierung mit dem Programm kompiliert wird. Übergeben Sie lib/text.c für dieses Beispiel nicht zusätzlich als separate Eingabe. Definieren Sie angepasste TEXT_*-Tile-Konstanten vor dem Einbinden von rpg.h und der Implementierung. Verwenden Sie überall, wo die Bibliothek kompiliert wird, dieselben Definitionen.

Anwendungsbeispiel

c
text_window(1,2,18,5);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel öffnet bei (1,2) einen Bereich mit 18×5 Zellen und einem Innenraum von 16×3 Zellen. Der mitgelieferte Rahmen hat ein Pixel breite Linien; seine sichtbaren äußeren Linien reichen von x=11 bis 147 und y=19 bis 51 Pixel. Auf CGB ist er rot, auf DMG schwarz.

Die Prüfung vergleicht alle sichtbaren Pixel und sämtliche 1024 Bytes der BG-Karte in beiden Beispielbildern. Separate DMG/CGB-ROMs prüfen alle 256 vorzeichenlosen Byte-Werte, Dezimalstellenübergänge und vorzeichenbehaftete Extremwerte. Punkte neben jeder Zahl bleiben als Wächter erhalten. Die Layoutprüfungen umfassen leere und schmale Rechtecke, Platzierung am Kartenrand, rohe Tile-Bytes mit Steuercodewerten sowie den Fenstercursor nach absoluten Schreibzugriffen. Dies sind Emulatortests, keine Tests auf physischer Hardware.

text_window: DMG
DMG
text_window: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:235

Deklarationshinweise im Original
Open and redraw a window using the same tile-space arguments as text_open.

kitaqgb/lib/text.c:214

c
void text_window(u8 x, u8 y, u8 w, u8 h)
{
    text_open(x, y, w, h);
}
unit_attack_range

Markiert Zellen, deren Manhattan-Distanz einschließlich der Grenzen zwischen atk_min und atk_max liegt.

Syntax

c
u8 unit_attack_range(unit_t* u, u8* out_mask);

Parameter

u

Gültiges unit_t: Zellposition, move in Schritten, einschließlich geltender atk_min/atk_max-Bereich sowie hp und acted für die Handlungsberechtigung.

out_mask

width*height beschreibbare Bytes; erhält je Zelle null oder eins.

Rückgabewert

Gibt bei verfügbarer Karte 1 zurück, bei Abmessungen von null 0.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Ignoriert Hindernisse, Sichtlinien und verbündete Einheiten. Halten Sie ausgewertete Distanzen bei höchstens 255. Überschreitet die Mindestreichweite die Höchstreichweite, werden alle Zellen null.

Anwendungsbeispiel

c
result[46]=unit_attack_range(&hero,mask);result[47]=mask[12];result[48]=mask[14];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

unit_attack_range: DMG
DMG
unit_attack_range: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:352

Deklarationshinweise im Original
Mark cells whose Manhattan distance falls within the inclusive attack range.
This geometric mask does not test obstacles, line of sight or other units.

kitaqgb/lib/slg_unit.c:38

c
u8 unit_attack_range(unit_t* u, u8* out_mask)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u8 y;

    if (w == 0 || h == 0) return 0;

    __memset(out_mask, 0, (u16)((u16)w * (u16)h));
    y = 0;
    while (y < h) {
        u8 x = 0;
        while (x < w) {
            u8 dist = __manhattan(u->x, u->y, x, y);
            if (dist >= u->atk_min && dist <= u->atk_max) {
                out_mask[__map_index(x, y, w)] = 1;
            }
            x++;
        }
        y++;
    }
    return 1;
}
unit_can_act

Prüft, ob eine Einheit noch Trefferpunkte hat und noch nicht gehandelt hat.

Syntax

c
u8 unit_can_act(const unit_t* u);

Parameter

u

Gültiges unit_t: Zellposition, move in Schritten, einschließlich geltender atk_min/atk_max-Bereich sowie hp und acted für die Handlungsberechtigung.

Rückgabewert

Gibt 1 zurück, wenn hp ungleich null und acted gleich null ist, sonst 0. Verändert die Einheit nicht.

Anwendungsbeispiel

c
result[11]=unit_can_act(&hero);hero.acted=1;result[12]=unit_can_act(&hero);hero.acted=0;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

unit_can_act: DMG
DMG
unit_can_act: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:355

Deklarationshinweise im Original
A unit can act only while HP is nonzero and its acted flag is clear.
The unit pointer must refer to a valid record.

kitaqgb/lib/slg_unit.c:5

c
u8 unit_can_act(const unit_t* u)
{
    if (u->hp == 0) return 0;
    if (u->acted != 0) return 0;
    return 1;
}
unit_move_range

Erzeugt eine Maske der innerhalb des Bewegungsbudgets der Einheit erreichbaren Zellen.

Syntax

c
u8 unit_move_range(unit_t* u, u8* out_mask);

Parameter

u

Gültiges unit_t: Zellposition, move in Schritten, einschließlich geltender atk_min/atk_max-Bereich sowie hp und acted für die Handlungsberechtigung.

out_mask

width*height beschreibbare Bytes; erhält je Zelle null oder eins.

Rückgabewert

Gibt bei verfügbarer Karte 1 zurück, bei Abmessungen von null 0. Der Ursprung der Einheit muss innerhalb der Karte liegen.

Bedingungen und Grenzen

Koordinaten bezeichnen Zellen der aktuellen Karte: 8×8 Pixel bei gewöhnlichen Kacheln, 16×16 Pixel bei Metakacheln.

Die Suche verwendet etwa 4 KiB gemeinsamen, nicht reentranten Arbeitsspeicher. Begrenzen Sie Karten auf 1024 Zellen und untersuchte Entfernungen auf 254. Distanz 0xFF bedeutet „nicht erreicht“; eine Route mit 255 Schritten ist daher nicht darstellbar. Kosten- und Maskenausgaben benötigen width*height beschreibbare Bytes.

Der Ursprung wird auch bei Blockierung als erreichbar gesetzt. Trefferpunkte, acted und andere Einheiten beeinflussen die Bewegungsmaske nicht.

Anwendungsbeispiel

c
result[43]=unit_move_range(&hero,mask);result[44]=mask[12];result[45]=mask[14];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das linke Raster zeigt Bewegungskosten innerhalb von drei Schritten, das rechte eine kürzeste Route von S nach G. Grüne Sternchen markieren neun Schritte um eine rote Wand aus drei Zellen; blaue Ziffern zeigen Kosten. Auf dem DMG erscheint dieselbe Anordnung schwarz. RAM-Prüfungen zeigen außerdem, dass die Angriffsmaske Wände ignoriert.

unit_move_range: DMG
DMG
unit_move_range: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementierung und Quelltext

kitaqgb/lib/rpg.h:349

Deklarationshinweise im Original
Build movement costs, then convert reachable cells to one and unreachable
0xFF cells to zero. The caller provides one output byte per current-map cell
and a valid unit origin; path-search workspace limits also apply.

kitaqgb/lib/slg_unit.c:15

c
u8 unit_move_range(unit_t* u, u8* out_mask)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 i;

    if (w == 0 || h == 0) return 0;

    // A valid origin is required: the fill leaves storage unchanged on invalid origins, but this loop still converts it.
    range_fill_move(u->x, u->y, u->move, out_mask);
    total = (u16)((u16)w * (u16)h);
    i = 0;
    while (i < total) {
        out_mask[i] = (u8)((out_mask[i] == 0xFF) ? 0 : 1);
        i++;
    }
    return 1;
}
weighted_choice

Wählt einen Elementindex aus einer Liste relativer Bytegewichte. Die Funktion summiert die Gewichte, reduziert eine rng16-Ziehung modulo dieser Summe und sucht das erste kumulierte Intervall, das das Ergebnis enthält. Bei [1, 3, 6] gehören den Indizes 0, 1 und 2 die Intervalle 0, 1–3 und 4–9.

Syntax

c
u8 weighted_choice(const u8* weights, u8 count);

Parameter

weights

Zeiger auf count lesbare u8-Gewichte. Das Array wird nicht geändert. Bei positiver Summe werden Elemente mit Gewicht null übersprungen. Bei count == 0 wird der Zeiger nicht gelesen und darf null sein; andernfalls ist ein gültiges Array erforderlich.

count

Anzahl der Gewichte in 0–255. Höchstens 255 Gewichte zu je 255 ergeben 65025 und passen in den u16-Akkumulator. Die Funktion durchläuft die Liste zuerst zur Summierung und danach bis zum ausgewählten Intervall.

Rückgabewert

Bei positiver Summe ein Index von 0 bis count−1 nach zwei Byteziehungen. Ist count null oder sind alle Gewichte null, wird null ohne Ziehung geliefert. Dieser Ersatzwert ist von einer gültigen Auswahl des Index 0 nicht unterscheidbar. Prüfen Sie leere oder reine Nulllisten selbst, wenn dieser Unterschied wichtig ist.

Bedingungen und Grenzen

Gewichte bestimmen relative Intervallgrößen, keine garantierten beobachteten Prozentsätze. Sowohl die rng16-Verteilung als auch die Reduktion modulo der Summe beeinflussen tatsächliche Häufigkeiten. Eine positive Summe verbraucht stets zwei Byteziehungen, selbst wenn nur ein Element ein Gewicht ungleich null hat.

Diese Aufrufe teilen einen persistenten Zustand. Reproduktion erfordert dasselbe Zielsystem, denselben Startwert und dieselbe Aufrufreihenfolge einschließlich anderer Hilfsfunktionen. Führen Sie Startwertsetzung und Ziehungen in einem Ausführungskontext aus; die Prüfungen belegen keine sichere gleichzeitige Nutzung aus einem Interrupthandler.

GB und FC verwenden unterschiedliche Algorithmen und versprechen bei gleichem Startwert keine gleiche Folge. Dies sind deterministische Spielgeneratoren, keine Quellen kryptografischer Zufälligkeit. Die Tests prüfen Implementierungsverhalten, nicht statistische Qualität oder Periode.

Binden Sie rpg.h ein und kompilieren Sie lib/rng.c mit dem Spiel, wenn Sie die Bibliotheksfunktionen nutzen. __rng_seed und __rng8 werden als intrinsische Funktionen vom Compiler erzeugt; ein Programm mit nur diesen beiden benötigt kein rng.c-Objekt.

Anwendungsbeispiel

c
weights[0]=1;weights[1]=3;weights[2]=6;
rng_seed(0x1234);
chosen=weighted_choice(weights,3); // 546 % 10 = 6 selects index 2.
empty=weighted_choice((const u8*)0,0); // No items: 0 is a fallback, not a chosen item.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Dieses Beispiel gibt drei Elementen die Gewichte 1, 3 und 6. Das erzeugte Wort 546 ergibt Rest 6 im Intervall 4–9 des Index 2; WEIGHT INDEX zeigt 00002. EMPTY LIST zeigt 00000 als Ersatzwert für eine leere Liste, nicht als erfolgreiche Auswahl von Element 0.

Das vollständige Programm zeigt Dezimalergebnisse auf Weiß: schwarze Schrift auf DMG, blaue auf CGB. FAILED muss 00000 anzeigen. Die Bilder zeigen die tatsächliche Emulatorausgabe dieses Beispiels.

Die Prüfung verglich je Fall 32 Ausgaben und acht anschließende Byteziehungen mit einem unabhängigen Hostmodell: 93 GB- und 18 FC-Fälle, einschließlich konstanter und zur Laufzeit gesetzter Startwerte sowie GB-Grenzfällen für Bereiche, Chancen und Gewichte. Die Lehrbildschirme wurden nach 240 Emulatorframes geprüft. Echte Hardware und statistische Qualität wurden nicht getestet.

weighted_choice: DMG
DMG
weighted_choice: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/rpg.h:203

Deklarationshinweise im Original
Select an index from cumulative byte weights using a 16-bit random draw.
A zero total, including an empty list, returns zero; callers must distinguish
that case from a valid index. Modulo reduction can introduce a small bias.

kitaqgb/lib/rng.c:61

c
u8 weighted_choice(const u8* weights, u8 count)
{
    u8 i;
    u16 total;
    u16 pick;
    u16 acc;

    // At most 255 byte weights sum to 65025, so this accumulator fits u16.
    // A nonempty list requires count readable weight bytes.
    total = 0;
    i = 0;
    while (i < count) {
        total = (u16)(total + (u16)weights[i]);
        i++;
    }

    if (total == 0) return 0;

    pick = (u16)(rng16() % total);
    acc = 0;
    i = 0;
    while (i < count) {
        acc = (u16)(acc + (u16)weights[i]);
        if (pick < acc) return i;
        i++;
    }

    return (u8)(count - 1);
}

scene.h — Szenenregistrierung, -wechsel und -aktualisierung

Ruft die Handler enter, update, draw und exit einer Szenentabelle auf, um zwischen Bildschirmen wie Titelanzeige und Spiel zu wechseln.

scene_change

Verlässt die aktive Szene, sofern vorhanden, und betritt die angeforderte Szene.

Syntax

c
void scene_change(u8 scene_id);

Parameter

scene_id

Index der zu betretenden Szene, von 0 bis count−1.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

IDs außerhalb des gültigen Bereichs werden ignoriert. Ein gültiger Wechsel führt exit aus, speichert die neue ID und das Wechselflag und führt dann enter aus. Auch die Wahl derselben ID führt exit und enter aus. Die Szenentabelle gehört dem aufrufenden Code. Halten Sie die Tabelle und die Ziele ihrer gewöhnlichen Funktionszeiger während der gesamten Verwendung gültig. Null-Callbacks werden übersprungen. Wechseln Sie innerhalb von enter- oder exit-Callbacks nicht rekursiv die Szene und ersetzen Sie dort nicht die Tabelle.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
scene_change(0);scene_change(9);result[11]=events;result[12]=scene_was_changed();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Programm aktiviert Szene 0, ignoriert die ungültige ID 9, wechselt von 0→1 und betritt mit 1→1 dieselbe Szene erneut. Dabei prüft es die Reihenfolge der Callbacks.

scene_change: DMG
DMG
scene_change: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:20

Deklarationshinweise im Original
Ignore invalid IDs; otherwise exit the current scene and enter the requested one.
Selecting the current ID still performs exit/enter. Callbacks run synchronously.

kitaqgb/lib/scene.c:27

c
void scene_change(u8 scene_id)
{
    SceneFunc fn;

    if (scene_id >= scene_count) return;

    // Exit/enter handlers must not recursively change scenes or replace this shared table.
    if (scene_has_current != 0) {
        fn = scene_table[(__safe_index u8)scene_current].exit;
        if (fn != 0) fn();
    }

    scene_current = scene_id;
    scene_has_current = 1;
    scene_changed = 1;

    fn = scene_table[(__safe_index u8)scene_current].enter;
    if (fn != 0) fn();
}
scene_draw

Ruft den draw-Callback der aktiven Szene einmal auf.

Syntax

c
void scene_draw();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Ohne aktive Szene oder bei einem Null-Callback für draw bleibt der Aufruf ohne Wirkung. Das Wechselflag wird nicht gelöscht. Planen Sie Bildschirmübertragungen und Frame-Timing im Callback oder in der umgebenden Spielschleife. Die Szenentabelle gehört dem aufrufenden Code. Halten Sie die Tabelle und die Ziele ihrer gewöhnlichen Funktionszeiger während der gesamten Verwendung gültig. Null-Callbacks werden übersprungen. Wechseln Sie innerhalb von enter- oder exit-Callbacks nicht rekursiv die Szene und ersetzen Sie dort nicht die Tabelle.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
scene_draw();result[15]=events;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Ereignisfolge enthält die 12 aus dem draw-Aufruf von Szene 0 und die 22 aus dem draw-Aufruf von Szene 1.

scene_draw: DMG
DMG
scene_draw: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:25

Deklarationshinweise im Original
Call the active scene's draw handler if one exists; no current scene is a no-op.

kitaqgb/lib/scene.c:60

c
void scene_draw()
{
    SceneFunc fn;

    if (scene_has_current == 0) return;
    fn = scene_table[(__safe_index u8)scene_current].draw;
    if (fn != 0) fn();
}
scene_get_current

Liest die gespeicherte aktuelle Szenen-ID.

Syntax

c
u8 scene_get_current();

Rückgabewert

Gibt die gespeicherte 8-Bit-ID zurück; auch nach der Initialisierung ist sie null.

Bedingungen und Grenzen

Der Rückgabewert null allein belegt nicht, dass Szene 0 aktiv ist. Halten Sie fest, ob seit der Initialisierung bereits der erste Aufruf von scene_change() erfolgt ist.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
result[16]=scene_get_current();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest nach der Aktivierung von Szene 0 den Wert null und nach dem Wechsel zu Szene 1 den Wert eins.

scene_get_current: DMG
DMG
scene_get_current: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:27

Deklarationshinweise im Original
Return the stored scene ID; zero is also returned before the first transition.

kitaqgb/lib/scene.c:70

c
u8 scene_get_current()
{
    return scene_current;
}
scene_init

Registriert eine Szenentabelle, ohne eine Szene zu aktivieren.

Syntax

c
void scene_init(const SceneDef* scenes, u8 count);

Parameter

scenes

Array aus SceneDef-Einträgen mit den Callbacks enter, update, draw und exit.

count

Anzahl der Einträge; bei null gibt es keine gültigen Szenen-IDs.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Setzt die gespeicherte ID und das Wechselflag auf null zurück. enter wird nicht aufgerufen; aktivieren Sie eine Szene mit scene_change(). Die Szenentabelle gehört dem aufrufenden Code. Halten Sie die Tabelle und die Ziele ihrer gewöhnlichen Funktionszeiger während der gesamten Verwendung gültig. Null-Callbacks werden übersprungen. Wechseln Sie innerhalb von enter- oder exit-Callbacks nicht rekursiv die Szene und ersetzen Sie dort nicht die Tabelle.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
scene_init(scenes,2);scene_update();scene_draw();result[9]=events;result[10]=scene_was_changed();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel registriert zwei Szenen und prüft, dass Aufrufe von update und draw vor der Aktivierung keine Ereignisse auslösen.

scene_init: DMG
DMG
scene_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:15

Deklarationshinweise im Original
Attach the caller-owned scene table and clear current-scene state without invoking callbacks.

kitaqgb/lib/scene.c:10

c
void scene_init(const SceneDef* scenes, u8 count)
{
    scene_table = scenes;
    scene_count = count;
    scene_current = 0;
    scene_changed = 0;
    scene_has_current = 0;
}
scene_set_table

Ersetzt die Szenentabelle und lässt keine Szene aktiv.

Syntax

c
void scene_set_table(const SceneDef* scenes, u8 count);

Parameter

scenes

Array aus SceneDef-Einträgen mit den Callbacks enter, update, draw und exit.

count

Anzahl der Einträge; bei null gibt es keine gültigen Szenen-IDs.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Setzt den Zustand wie scene_init() zurück, ohne den bisherigen exit-Callback oder einen neuen enter-Callback aufzurufen. Die Szenentabelle gehört dem aufrufenden Code. Halten Sie die Tabelle und die Ziele ihrer gewöhnlichen Funktionszeiger während der gesamten Verwendung gültig. Null-Callbacks werden übersprungen. Wechseln Sie innerhalb von enter- oder exit-Callbacks nicht rekursiv die Szene und ersetzen Sie dort nicht die Tabelle.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
scene_set_table(scenes,2);result[23]=events;result[24]=scene_was_changed();scene_draw();result[25]=events;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach neun Ereignissen wird die Tabelle ersetzt: Der Zähler bleibt bei neun, das Wechselflag wird null, und der folgende draw-Aufruf bleibt ohne Wirkung.

scene_set_table: DMG
DMG
scene_set_table: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:17

Deklarationshinweise im Original
Replace the table by resetting scene state; this does not call the old scene's exit handler.

kitaqgb/lib/scene.c:20

c
void scene_set_table(const SceneDef* scenes, u8 count)
{
    scene_init(scenes, count);
}
scene_update

Ruft den update-Callback der aktiven Szene einmal auf.

Syntax

c
void scene_update();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Ohne aktive Szene bleibt der Aufruf ohne Wirkung. Andernfalls wird das Wechselflag vor dem Callback gelöscht, sodass ein innerhalb von update ausgelöster Wechsel anschließend weiterhin erkennbar ist. Die Szenentabelle gehört dem aufrufenden Code. Halten Sie die Tabelle und die Ziele ihrer gewöhnlichen Funktionszeiger während der gesamten Verwendung gültig. Null-Callbacks werden übersprungen. Wechseln Sie innerhalb von enter- oder exit-Callbacks nicht rekursiv die Szene und ersetzen Sie dort nicht die Tabelle.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
scene_update();result[13]=events;result[14]=scene_was_changed();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die update-Funktion von Szene 0 protokolliert Ereignis 11. Nach dieser regulären Aktualisierung wird das zuvor gesetzte Wechselflag von eins auf null zurückgesetzt.

scene_update: DMG
DMG
scene_update: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:23

Deklarationshinweise im Original
Clear the change flag before calling the active scene's update handler, so a
transition made during that handler is visible afterward.

kitaqgb/lib/scene.c:49

c
void scene_update()
{
    SceneFunc fn;

    if (scene_has_current == 0) return;
    scene_changed = 0;
    fn = scene_table[(__safe_index u8)scene_current].update;
    if (fn != 0) fn();
}
scene_was_changed

Prüft, ob derzeit ein Szenenwechsel vermerkt ist.

Syntax

c
u8 scene_was_changed();

Rückgabewert

Gibt bei gesetztem Wechselflag 1 zurück, andernfalls 0.

Bedingungen und Grenzen

Das Lesen löscht das Flag nicht. Initialisierung, Tabellenwechsel und der Beginn einer Aktualisierung der aktiven Szene löschen es. Eine ungültige Szenen-ID lässt es unverändert.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
result[17]=scene_was_changed();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Prüfungen erwarten eins unmittelbar nach einem Wechsel, null nach einer regulären Aktualisierung und null nach dem Ersetzen der Tabelle.

scene_was_changed: DMG
DMG
scene_was_changed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scene.h:29

Deklarationshinweise im Original
Read the transition flag, which is cleared at the start of an active scene update.

kitaqgb/lib/scene.c:76

c
u8 scene_was_changed()
{
    return scene_changed;
}

scroll.h — Hintergrund, Fenster und geteiltes Scrollen

Steuert sofortige und gepufferte Hintergrund-/Fensterverschiebung sowie bis zu acht Rasteraufteilungen. Unterscheiden Sie die von Lesefunktionen verwalteten aktuellen Werte, tatsächliche Hardwareregister und vorgemerkte Werte.

Scroll_BgAdd

Addiert vorzeichenbehaftete Verschiebungen zu den nachgeführten Hintergrundkoordinaten und wendet sie sofort an.

Syntax

c
void Scroll_BgAdd(s8 dx, s8 dy);

Parameter

dx

Vorzeichenbehaftete horizontale Pixelverschiebung, −128 bis 127.

dy

Vorzeichenbehaftete vertikale Pixelverschiebung, −128 bis 127.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Ergebnisse laufen modulo 256 um. Additionen gehen von den nachgeführten aktuellen Werten aus, nicht von vorgemerkten Werten oder temporären Rasterregisterwerten. Diese Funktion umhüllt __scroll_bg_add.

Anwendungsbeispiel

c
Scroll_BgAdd(-20,3);result[22]=M_SCX;result[23]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_BgAdd: DMG
DMG
Scroll_BgAdd: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_BgAdd: DMG
DMG
Scroll_BgAdd: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:73

Deklarationshinweise im Original
Apply signed deltas to the byte-sized background-scroll coordinates.

kitaqgb/lib/scroll.c:41

c
void Scroll_BgAdd(s8 dx, s8 dy) { __scroll_bg_add(dx, dy); }
Scroll_Flush

Überträgt geänderte Hintergrund- und Fensterkoordinaten in den nachgeführten Zustand und die Hardware und löscht anschließend ihre Vormerkflags.

Syntax

c
void Scroll_Flush();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ein unverändertes Koordinatenpaar bleibt unangetastet. Es werden weder Interrupts maskiert noch wird auf VBlank gewartet; der aufrufende Code muss den passenden Zeitpunkt sicherstellen. Diese Funktion umhüllt __scroll_flush.

Anwendungsbeispiel

c
Scroll_Flush();result[18]=M_SCX;result[19]=M_SCY;result[20]=M_WX;result[21]=M_WY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_Flush: DMG
DMG
Scroll_Flush: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_Flush: DMG
DMG
Scroll_Flush: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:70

Deklarationshinweise im Original
Apply the buffered scroll/window state through the compiler runtime.

kitaqgb/lib/scroll.c:38

c
void Scroll_Flush() { __scroll_flush(); }
Scroll_GetBgX

Liest den nachgeführten aktuellen Wert der horizontalen Hintergrundverschiebung.

Syntax

c
u8 Scroll_GetBgX();

Rückgabewert

Gibt den nachgeführten aktuellen Byte-Wert von 0–255 zurück. WX enthält den hardwarebedingten Versatz von sieben Pixeln.

Bedingungen und Grenzen

Dies liest kein Hardwareregister. Noch ausstehende Pufferwerte, direkte Registerzugriffe und temporäre Werte aus Rasteraufteilungen sind nicht enthalten. Diese Funktion umhüllt __scroll_bg_x_get.

Anwendungsbeispiel

c
result[6]=Scroll_GetBgX();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_GetBgX: DMG
DMG
Scroll_GetBgX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_GetBgX: DMG
DMG
Scroll_GetBgX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:50

Deklarationshinweise im Original
Read the tracked current background X; this is not a direct SCX register read.

kitaqgb/lib/scroll.c:18

c
u8 Scroll_GetBgX() { return __scroll_bg_x_get(); }
Scroll_GetBgY

Liest den nachgeführten aktuellen Wert der vertikalen Hintergrundverschiebung.

Syntax

c
u8 Scroll_GetBgY();

Rückgabewert

Gibt den nachgeführten aktuellen Byte-Wert von 0–255 zurück. WX enthält den hardwarebedingten Versatz von sieben Pixeln.

Bedingungen und Grenzen

Dies liest kein Hardwareregister. Noch ausstehende Pufferwerte, direkte Registerzugriffe und temporäre Werte aus Rasteraufteilungen sind nicht enthalten. Diese Funktion umhüllt __scroll_bg_y_get.

Anwendungsbeispiel

c
result[7]=Scroll_GetBgY();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_GetBgY: DMG
DMG
Scroll_GetBgY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_GetBgY: DMG
DMG
Scroll_GetBgY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:52

Deklarationshinweise im Original
Read the tracked current background Y; pending and raster-only values are excluded.

kitaqgb/lib/scroll.c:20

c
u8 Scroll_GetBgY() { return __scroll_bg_y_get(); }
Scroll_GetWindowX

Liest den nachgeführten aktuellen WX-Wert des Fensters.

Syntax

c
u8 Scroll_GetWindowX();

Rückgabewert

Gibt den nachgeführten aktuellen Byte-Wert von 0–255 zurück. WX enthält den hardwarebedingten Versatz von sieben Pixeln.

Bedingungen und Grenzen

Dies liest kein Hardwareregister. Noch ausstehende Pufferwerte, direkte Registerzugriffe und temporäre Werte aus Rasteraufteilungen sind nicht enthalten. Diese Funktion umhüllt __scroll_win_x_get.

Anwendungsbeispiel

c
result[12]=Scroll_GetWindowX();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_GetWindowX: DMG
DMG
Scroll_GetWindowX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_GetWindowX: DMG
DMG
Scroll_GetWindowX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:61

Deklarationshinweise im Original
Read tracked current WX, including its seven-pixel offset; not a live hardware read.

kitaqgb/lib/scroll.c:29

c
u8 Scroll_GetWindowX() { return __scroll_win_x_get(); }
Scroll_GetWindowY

Liest den nachgeführten aktuellen WY-Wert des Fensters.

Syntax

c
u8 Scroll_GetWindowY();

Rückgabewert

Gibt den nachgeführten aktuellen Byte-Wert von 0–255 zurück. WX enthält den hardwarebedingten Versatz von sieben Pixeln.

Bedingungen und Grenzen

Dies liest kein Hardwareregister. Noch ausstehende Pufferwerte, direkte Registerzugriffe und temporäre Werte aus Rasteraufteilungen sind nicht enthalten. Diese Funktion umhüllt __scroll_win_y_get.

Anwendungsbeispiel

c
result[13]=Scroll_GetWindowY();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_GetWindowY: DMG
DMG
Scroll_GetWindowY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_GetWindowY: DMG
DMG
Scroll_GetWindowY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:63

Deklarationshinweise im Original
Read tracked current WY; pending and raster-only values are excluded.

kitaqgb/lib/scroll.c:31

c
u8 Scroll_GetWindowY() { return __scroll_win_y_get(); }
Scroll_Init

Initialisiert die Hintergrundverschiebung mit (0,0) und die Fensterposition mit WX=7, WY=0.

Syntax

c
void Scroll_Init();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Synchronisiert aktuelle und vorgemerkte Koordinaten; setzt weder Fenstersichtbarkeit noch Aufteilungstabelle zurück.

Anwendungsbeispiel

c
Scroll_Init();result[0]=M_SCX;result[1]=M_SCY;result[2]=M_WX;result[3]=M_WY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_Init: DMG
DMG
Scroll_Init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_Init: DMG
DMG
Scroll_Init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:42

Deklarationshinweise im Original
Reset background scroll to zero and place the window at screen origin
using hardware WX=7 and WY=0.

kitaqgb/lib/scroll.c:5

c
void Scroll_Init()
{
    __scroll_bg_set(0, 0);
    __scroll_win_set(7, 0);
}
Scroll_SetBg

Setzt beide Hintergrund-Scrollkoordinaten sofort.

Syntax

c
void Scroll_SetBg(u8 scx, u8 scy);

Parameter

scx

Horizontale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach links.

scy

Vertikale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach oben.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Umhüllt __scroll_bg_set: Synchronisiert aktuelle, vorgemerkte und Hardwarewerte und löscht das BG-Änderungsflag, ohne auf VBlank zu warten.

Anwendungsbeispiel

c
Scroll_SetBg(8,16);result[28]=M_SCX;result[29]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetBg: DMG
DMG
Scroll_SetBg: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetBg: DMG
DMG
Scroll_SetBg: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:44

Deklarationshinweise im Original
Write both hardware background-scroll bytes immediately.

kitaqgb/lib/scroll.c:12

c
void Scroll_SetBg(u8 scx, u8 scy) { __scroll_bg_set(scx, scy); }
Scroll_SetBgBuffered

Merkt beide Hintergrund-Scrollkoordinaten zur späteren Übertragung vor.

Syntax

c
void Scroll_SetBgBuffered(u8 scx, u8 scy);

Parameter

scx

Horizontale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach links.

scy

Vertikale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach oben.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ändert weder nachgeführte aktuelle Werte noch Register. Übertragen Sie sie mit __scroll_flush oder Scroll_Flush; das Vormerken selbst wartet nicht auf VBlank. Diese Funktion umhüllt __scroll_bg_set_buffered.

Anwendungsbeispiel

c
Scroll_SetBgBuffered(16,24);result[14]=M_SCX;result[15]=Scroll_GetBgX();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetBgBuffered: DMG
DMG
Scroll_SetBgBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetBgBuffered: DMG
DMG
Scroll_SetBgBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:66

Deklarationshinweise im Original
Stage background-scroll values in the intrinsic buffer for a later flush.

kitaqgb/lib/scroll.c:34

c
void Scroll_SetBgBuffered(u8 scx, u8 scy) { __scroll_bg_set_buffered(scx, scy); }
Scroll_SetBgX

Setzt die horizontale Hintergrundverschiebung sofort.

Syntax

c
void Scroll_SetBgX(u8 scx);

Parameter

scx

Horizontale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach links.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Diese Funktion umhüllt __scroll_bg_x_set.

Anwendungsbeispiel

c
Scroll_SetBgX(250);result[4]=M_SCX;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetBgX: DMG
DMG
Scroll_SetBgX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetBgX: DMG
DMG
Scroll_SetBgX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:46

Deklarationshinweise im Original
Write horizontal background scroll while leaving vertical scroll unchanged.

kitaqgb/lib/scroll.c:14

c
void Scroll_SetBgX(u8 scx) { __scroll_bg_x_set(scx); }
Scroll_SetBgY

Setzt die vertikale Hintergrundverschiebung sofort.

Syntax

c
void Scroll_SetBgY(u8 scy);

Parameter

scy

Vertikale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach oben.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Diese Funktion umhüllt __scroll_bg_y_set.

Anwendungsbeispiel

c
Scroll_SetBgY(2);result[5]=M_SCY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetBgY: DMG
DMG
Scroll_SetBgY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetBgY: DMG
DMG
Scroll_SetBgY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:48

Deklarationshinweise im Original
Write vertical background scroll while leaving horizontal scroll unchanged.

kitaqgb/lib/scroll.c:16

c
void Scroll_SetBgY(u8 scy) { __scroll_bg_y_set(scy); }
Scroll_SetWindow

Setzt WX und WY des Fensters sofort.

Syntax

c
void Scroll_SetWindow(u8 wx, u8 wy);

Parameter

wx

Roher WX-Byte-Wert, 0–255: Addieren Sie 7 zur gewünschten Bildschirm-X-Koordinate; für den linken Rand verwenden Sie 7.

wy

Oberkante des Fensters in Bildschirm-Y-Pixeln, 0–255; sichtbar sind die Zeilen 0–143.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Diese Funktion umhüllt __scroll_win_set.

Anwendungsbeispiel

c
Scroll_SetWindow(15,8);result[8]=M_WX;result[9]=M_WY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetWindow: DMG
DMG
Scroll_SetWindow: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetWindow: DMG
DMG
Scroll_SetWindow: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:55

Deklarationshinweise im Original
Write raw hardware WX/WY values; callers add seven to a screen-space window X.

kitaqgb/lib/scroll.c:23

c
void Scroll_SetWindow(u8 wx, u8 wy) { __scroll_win_set(wx, wy); }
Scroll_SetWindowBuffered

Merkt beide Fensterkoordinaten zur späteren Übertragung vor.

Syntax

c
void Scroll_SetWindowBuffered(u8 wx, u8 wy);

Parameter

wx

Roher WX-Byte-Wert, 0–255: Addieren Sie 7 zur gewünschten Bildschirm-X-Koordinate; für den linken Rand verwenden Sie 7.

wy

Oberkante des Fensters in Bildschirm-Y-Pixeln, 0–255; sichtbar sind die Zeilen 0–143.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ändert weder nachgeführte aktuelle Werte noch Register. Übertragen Sie sie mit __scroll_flush oder Scroll_Flush; das Vormerken selbst wartet nicht auf VBlank. Diese Funktion umhüllt __scroll_win_set_buffered.

Anwendungsbeispiel

c
Scroll_SetWindowBuffered(39,32);result[16]=M_WX;result[17]=Scroll_GetWindowX();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetWindowBuffered: DMG
DMG
Scroll_SetWindowBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetWindowBuffered: DMG
DMG
Scroll_SetWindowBuffered: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:68

Deklarationshinweise im Original
Stage raw window-coordinate values for a later flush.

kitaqgb/lib/scroll.c:36

c
void Scroll_SetWindowBuffered(u8 wx, u8 wy) { __scroll_win_set_buffered(wx, wy); }
Scroll_SetWindowX

Setzt sofort nur die rohe WX-Koordinate des Fensters.

Syntax

c
void Scroll_SetWindowX(u8 wx);

Parameter

wx

Roher WX-Byte-Wert, 0–255: Addieren Sie 7 zur gewünschten Bildschirm-X-Koordinate; für den linken Rand verwenden Sie 7.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Diese Funktion umhüllt __scroll_win_x_set.

Anwendungsbeispiel

c
Scroll_SetWindowX(23);result[10]=M_WX;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetWindowX: DMG
DMG
Scroll_SetWindowX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetWindowX: DMG
DMG
Scroll_SetWindowX: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:57

Deklarationshinweise im Original
Write raw hardware WX without converting a screen-space X coordinate.

kitaqgb/lib/scroll.c:25

c
void Scroll_SetWindowX(u8 wx) { __scroll_win_x_set(wx); }
Scroll_SetWindowY

Setzt sofort nur die WY-Koordinate des Fensters.

Syntax

c
void Scroll_SetWindowY(u8 wy);

Parameter

wy

Oberkante des Fensters in Bildschirm-Y-Pixeln, 0–255; sichtbar sind die Zeilen 0–143.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Diese Funktion umhüllt __scroll_win_y_set.

Anwendungsbeispiel

c
Scroll_SetWindowY(16);result[11]=M_WY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_SetWindowY: DMG
DMG
Scroll_SetWindowY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_SetWindowY: DMG
DMG
Scroll_SetWindowY: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:59

Deklarationshinweise im Original
Write the window Y coordinate through the intrinsic.

kitaqgb/lib/scroll.c:27

c
void Scroll_SetWindowY(u8 wy) { __scroll_win_y_set(wy); }
Scroll_SplitCommit

Erfasst die grundlegende Fenstersichtbarkeit und aktiviert das erste Rasterzeilenereignis der Aufteilungstabelle.

Syntax

c
void Scroll_SplitCommit();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Die gemeinsame Tabelle enthält acht Einträge. Das Anhängen wendet sie weder an noch sortiert es sie; überzählige Einträge werden ignoriert. Bauen Sie die Tabelle an einer sicheren Frame-Grenze mit reset→push→commit neu auf und lassen Sie zwischen Ereignissen genügend Abstand für den Handler. Wegen der Interruptlatenz müssen die geplante Zeile und das erste betroffene Pixel nicht zusammenfallen. Eine nichtleere Tabelle aktiviert VBlank/STAT in IE und führt EI aus. Eine leere Tabelle deaktiviert die LYC-Quelle, stellt aber weder IE noch den CPU-Interruptzustand wieder her. Diese Funktion umhüllt __scroll_split_commit.

Anwendungsbeispiel

c
Scroll_SplitCommit();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verwenden Sie die Scroll-Hüllfunktionen für drei Hintergrund-Scrollstreifen. Ereignisse bei LY=64 und 104 setzen X auf 8 und 16, sodass 24×16-Rechtecke bei (32,16), (24,80) und (16,112) erscheinen. Das Bild zeigt den Versatz jedes Streifens.

Scroll_SplitCommit: DMG
DMG
Scroll_SplitCommit: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:92

Deklarationshinweise im Original
Publish the pending split configuration through the compiler runtime.

kitaqgb/lib/scroll.c:66

c
void Scroll_SplitCommit() { __scroll_split_commit(); }
Scroll_SplitPush

Fügt einen Eintrag hinzu, der die Hintergrundverschiebung beim gewünschten Rasterzeilenereignis ändert.

Syntax

c
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);

Parameter

ly

Rasterzeilennummer des Ereignisses; verwenden Sie 0–143 für sichtbare Ereignisse und fügen Sie sie aufsteigend hinzu. Ein erster Eintrag bei null wird während VBlank angewandt.

scx

Horizontale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach links.

scy

Vertikale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach oben.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Die gemeinsame Tabelle enthält acht Einträge. Das Anhängen wendet sie weder an noch sortiert es sie; überzählige Einträge werden ignoriert. Bauen Sie die Tabelle an einer sicheren Frame-Grenze mit reset→push→commit neu auf und lassen Sie zwischen Ereignissen genügend Abstand für den Handler. Wegen der Interruptlatenz müssen die geplante Zeile und das erste betroffene Pixel nicht zusammenfallen. Diese Funktion umhüllt __scroll_split_push.

Anwendungsbeispiel

c
Scroll_SplitPush(64,8,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verwenden Sie die Scroll-Hüllfunktionen für drei Hintergrund-Scrollstreifen. Ereignisse bei LY=64 und 104 setzen X auf 8 und 16, sodass 24×16-Rechtecke bei (32,16), (24,80) und (16,112) erscheinen. Das Bild zeigt den Versatz jedes Streifens.

Scroll_SplitPush: DMG
DMG
Scroll_SplitPush: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:85

Deklarationshinweise im Original
Append a background-scroll split directly. Use Raster_Push when caller-side
scanline ordering and capacity validation are desired.

kitaqgb/lib/scroll.c:53

c
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy) { __scroll_split_push(ly, scx, scy); }
Scroll_SplitPushBgColor0

Fügt ein Ereignis hinzu, das Farbe null der CGB-Hintergrundpalette null ändert.

Syntax

c
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);

Parameter

ly

Rasterzeilennummer des Ereignisses; verwenden Sie 0–143 für sichtbare Ereignisse und fügen Sie sie aufsteigend hinzu. Ein erster Eintrag bei null wird während VBlank angewandt.

rgb15

15-Bit-RGB555-Farbe: Rot in Bit 0–4, Grün in Bit 5–9, Blau in Bit 10–14.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Nur für CGB. Belegt über die erweiterte Aufteilungsoperation einen Eintrag der Tabelle mit acht Plätzen. Palettenschreibzugriffe warten auf ein zugängliches PPU-Zeitfenster. In diesem CGB-Beispiel mit Normalgeschwindigkeit werden Ereignisse bei LY=64/112 ab Zeile 66/114 sichtbar. Setzen Sie die Ereigniszeile nicht mit der ersten betroffenen Bildzeile gleich.

Anwendungsbeispiel

c
Scroll_SplitPushBgColor0(0,0x7C00);Scroll_SplitPushBgColor0(64,0x001F);Scroll_SplitPushBgColor0(112,0x03E0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Ändern Sie CGB-Hintergrundfarbe null innerhalb eines Frames. Bei Normalgeschwindigkeit zeichnet das Beispiel die Zeilen 0–65 blau, 66–113 rot und 114–143 grün. Die Ereignisse sind bei 0, 64 und 112 geplant; Interruptverarbeitung und Palettenzugriff verursachen Verzögerungen. Der DMG bietet diese Farbpaletten nicht.

Scroll_SplitPushBgColor0: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_color.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:90

Deklarationshinweise im Original
Reuse the two background-scroll fields to carry the low/high RGB15 bytes
for a split whose operation flag selects background color zero.

kitaqgb/lib/scroll.c:61

c
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15)
{
    __scroll_split_push_ex(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_SCROLL_SPLIT_BG_COLOR0);
}
Scroll_SplitPushEx

Fügt einen Aufteilungseintrag hinzu, dessen Flags Operationen für Hintergrund, Fenster, Sichtbarkeit oder Hintergrundfarbe null auswählen.

Syntax

c
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

Parameter

ly

Rasterzeilennummer des Ereignisses; verwenden Sie 0–143 für sichtbare Ereignisse und fügen Sie sie aufsteigend hinzu. Ein erster Eintrag bei null wird während VBlank angewandt.

scx

Horizontale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach links.

scy

Vertikale Hintergrundverschiebung, 0–255 Pixel; ein größerer Wert bewegt den Hintergrund nach oben.

wx

Roher WX-Byte-Wert, 0–255: Addieren Sie 7 zur gewünschten Bildschirm-X-Koordinate; für den linken Rand verwenden Sie 7.

wy

Oberkante des Fensters in Bildschirm-Y-Pixeln, 0–255; sichtbar sind die Zeilen 0–143.

flags

Operationsbits: BG=1, Fensterposition=2, Anzeigen=4, Ausblenden=8, CGB-Hintergrundpalette 0/Farbe 0=16. Unbekannte Bits werden verworfen. Der Modus für Farbe null nutzt scx/scy als niederwertiges/höherwertiges Byte des RGB15-Werts.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Die gemeinsame Tabelle enthält acht Einträge. Das Anhängen wendet sie weder an noch sortiert es sie; überzählige Einträge werden ignoriert. Bauen Sie die Tabelle an einer sicheren Frame-Grenze mit reset→push→commit neu auf und lassen Sie zwischen Ereignissen genügend Abstand für den Handler. Wegen der Interruptlatenz müssen die geplante Zeile und das erste betroffene Pixel nicht zusammenfallen. Sind beide Sichtbarkeitsbits gesetzt, hat Anzeigen Vorrang. Farbe null ist nur auf dem CGB verfügbar; bei Kombination mit BG-Bewegung dienen dieselben scx/scy-Bytes beiden Zwecken. Diese Funktion umhüllt __scroll_split_push_ex.

Anwendungsbeispiel

c
Scroll_SplitPushEx(104,16,0,7,0,KQ_SCROLL_SPLIT_USE_BG|KQ_SCROLL_SPLIT_WIN_HIDE);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verwenden Sie die Scroll-Hüllfunktionen für drei Hintergrund-Scrollstreifen. Ereignisse bei LY=64 und 104 setzen X auf 8 und 16, sodass 24×16-Rechtecke bei (32,16), (24,80) und (16,112) erscheinen. Das Bild zeigt den Versatz jedes Streifens.

Scroll_SplitPushEx: DMG
DMG
Scroll_SplitPushEx: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:87

Deklarationshinweise im Original
Append an extended split with raw background/window fields and operation flags.

kitaqgb/lib/scroll.c:55

c
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
    __scroll_split_push_ex(ly, scx, scy, wx, wy, flags);
}
Scroll_SplitReset

Löscht Anzahl und Index der Aufteilungen, deaktiviert ihre Verarbeitung und löscht das LYC-Interruptfreigabebit in STAT.

Syntax

c
void Scroll_SplitReset();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Die gemeinsame Tabelle enthält acht Einträge. Das Anhängen wendet sie weder an noch sortiert es sie; überzählige Einträge werden ignoriert. Bauen Sie die Tabelle an einer sicheren Frame-Grenze mit reset→push→commit neu auf und lassen Sie zwischen Ereignissen genügend Abstand für den Handler. Wegen der Interruptlatenz müssen die geplante Zeile und das erste betroffene Pixel nicht zusammenfallen. Löscht weder Tabellenbytes noch IE und deaktiviert keine CPU-Interrupts. Diese Funktion umhüllt __scroll_split_reset.

Anwendungsbeispiel

c
Scroll_SplitReset();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Verwenden Sie die Scroll-Hüllfunktionen für drei Hintergrund-Scrollstreifen. Ereignisse bei LY=64 und 104 setzen X auf 8 und 16, sodass 24×16-Rechtecke bei (32,16), (24,80) und (16,112) erscheinen. Das Bild zeigt den Versatz jedes Streifens.

Scroll_SplitReset: DMG
DMG
Scroll_SplitReset: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:82

Deklarationshinweise im Original
Clear the pending split table before building a new raster configuration.

kitaqgb/lib/scroll.c:50

c
void Scroll_SplitReset() { __scroll_split_reset(); }
Scroll_WindowAdd

Addiert vorzeichenbehaftete Verschiebungen zu den nachgeführten Fensterkoordinaten und wendet sie sofort an.

Syntax

c
void Scroll_WindowAdd(s8 dx, s8 dy);

Parameter

dx

Vorzeichenbehaftete horizontale Pixelverschiebung, −128 bis 127.

dy

Vorzeichenbehaftete vertikale Pixelverschiebung, −128 bis 127.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Es wird nicht gewartet. Sofortige Zuweisungen und Additionen gleichen das betroffene vorgemerkte Koordinatenpaar an die aktuellen Werte an und löschen dessen Änderungsflag. Auch das sofortige Setzen nur einer Achse verwirft den vorgemerkten Wert der anderen Achse desselben Paars. Ergebnisse laufen modulo 256 um. Additionen gehen von den nachgeführten aktuellen Werten aus, nicht von vorgemerkten Werten oder temporären Rasterregisterwerten. Diese Funktion umhüllt __scroll_win_add.

Anwendungsbeispiel

c
Scroll_WindowAdd(4,-40);result[24]=M_WX;result[25]=M_WY;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_WindowAdd: DMG
DMG
Scroll_WindowAdd: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_WindowAdd: DMG
DMG
Scroll_WindowAdd: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:75

Deklarationshinweise im Original
Apply signed deltas to the byte-sized hardware window coordinates.

kitaqgb/lib/scroll.c:43

c
void Scroll_WindowAdd(s8 dx, s8 dy) { __scroll_win_add(dx, dy); }
Scroll_WindowHide

Löscht das Fensterbit in LCDC und den nachgeführten Sichtbarkeitszustand des Fensters.

Syntax

c
void Scroll_WindowHide();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ändert weder Koordinaten noch Kartenauswahl. Sichtbarkeit setzt außerdem ein eingeschaltetes LCD, aktivierte Hintergrund-/Fensterfunktionen und eine Fensterposition im sichtbaren Bereich voraus. Diese Funktion umhüllt __scroll_win_hide.

Anwendungsbeispiel

c
Scroll_WindowHide();result[27]=M_LCDC&32;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_WindowHide: DMG
DMG
Scroll_WindowHide: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_WindowHide: DMG
DMG
Scroll_WindowHide: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:79

Deklarationshinweise im Original
Request that the window be hidden through the compiler intrinsic.

kitaqgb/lib/scroll.c:47

c
void Scroll_WindowHide() { __scroll_win_hide(); }
Scroll_WindowShow

Aktiviert das Fensterbit in LCDC und den nachgeführten Sichtbarkeitszustand des Fensters.

Syntax

c
void Scroll_WindowShow();

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Ändert weder Koordinaten noch Kartenauswahl. Sichtbarkeit setzt außerdem ein eingeschaltetes LCD, aktivierte Hintergrund-/Fensterfunktionen und eine Fensterposition im sichtbaren Bereich voraus. Diese Funktion umhüllt __scroll_win_show.

Anwendungsbeispiel

c
Scroll_WindowShow();result[26]=M_LCDC&32;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Lernen Sie mit den Scroll-Funktionen sofortige Aktualisierung, Vormerken, Übertragen, Addition und Sichtbarkeit. Die Übertragung ändert BG X von 250 auf 16 und WX von 23 auf 39. Das Fensterbit hat nach dem Anzeigen den Wert 32 und nach dem Ausblenden 0.

Scroll_WindowShow: DMG
DMG
Scroll_WindowShow: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k

Anwendungsbeispiel

c
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei einer Kamera an (8,16) erscheint das rote 32×24-Rechteck an Bildschirmposition (24,16). Das Fenster zeigt einen blauen 64×64-Rahmen bei (96,80) und ein grünes 16×16-Quadrat bei (112,96). Auf dem DMG sind alle Formen schwarz.

Scroll_WindowShow: DMG
DMG
Scroll_WindowShow: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/scroll.h:77

Deklarationshinweise im Original
Request window visibility through the compiler intrinsic.

kitaqgb/lib/scroll.c:45

c
void Scroll_WindowShow() { __scroll_win_show(); }

slg.h — Spielbretter, Zuglisten und Rücknahme

Bietet ein Brett mit Byte-Werten, eine begrenzte Zugliste und einen Rücknahmestapel. Das Spiel kombiniert diese Operationen, um Züge oder Rücknahmedatensätze auf sein Brett anzuwenden.

slg_board_clear

Füllt jede Zelle des Bretts mit dem gewünschten Wert.

Syntax

c
void slg_board_clear(SLGBoard* board, u8 value);

Parameter

board

Zu bearbeitendes SLGBoard; die Initialisierung benötigt Speicher, der nicht NULL ist.

value

Zu speichernder Byte-Wert; das Spiel legt seine Bedeutung fest, etwa Figuren- oder Geländetyp.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
slg_board_clear(&board,0);result[1]=cells[0];result[2]=cells[11];

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_board_clear: DMG
DMG
slg_board_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:33

Deklarationshinweise im Original
Fill every cell with value; a null board is ignored. A valid board must own
enough accessible cell storage for its declared dimensions.

kitaqgb/lib/slg_board.c:36

c
void slg_board_clear(SLGBoard* board, u8 value)
{
    u16 total;
    u16 i;
    u8* p;
    if (board == 0) return;
    total = (u16)((u16)board->width * (u16)board->height);
    i = 0;
    p = board->cells;
    while (i < total) {
        *p = value;
        p++;
        i++;
    }
}
slg_board_get

Liest eine Zelle; bei einem NULL-Brett oder Koordinaten außerhalb des Bereichs wird null zurückgegeben.

Syntax

c
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);

Parameter

board

Zu bearbeitendes SLGBoard; die Initialisierung benötigt Speicher, der nicht NULL ist.

x

Zellenspalte von links, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

y

Zellenzeile von oben, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

Rückgabewert

Byte-Wert der Zelle oder null bei ungültiger Abfrage. Null allein unterscheidet nicht zwischen einer leeren Zelle und einer ungültigen Koordinate.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
result[3]=slg_board_get(&board,1,1);result[4]=slg_board_get(&board,4,1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_board_get: DMG
DMG
slg_board_get: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:36

Deklarationshinweise im Original
Return zero for a null board or out-of-range coordinate; otherwise read the
cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.

kitaqgb/lib/slg_board.c:54

c
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y)
{
    u8* p;
    if (board == 0) return 0;
    if (x >= board->width || y >= board->height) return 0;
    p = slg_cell_ptr((SLGBoard*)board, x, y);
    return *p;
}
slg_board_init

Verknüpft Brettabmessungen und ein Zellenarray; der vorhandene Inhalt bleibt erhalten.

Syntax

c
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);

Parameter

board

Zu bearbeitendes SLGBoard; die Initialisierung benötigt Speicher, der nicht NULL ist.

width

Brettbreite in Zellen, zugleich der Abstand zwischen den Zeilenanfängen.

height

Anzahl der Brettzeilen.

cells

Beschreibbares, zeilenweise angeordnetes Array mit mindestens width*height Zellenbytes.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
cells[0]=9;slg_board_init(&board,4,3,cells);result[0]=slg_board_get(&board,0,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_board_init: DMG
DMG
slg_board_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:30

Deklarationshinweise im Original
Attach width * height bytes of caller-owned cell storage without clearing it.

kitaqgb/lib/slg_board.c:27

c
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells)
{
    board->width = width;
    board->height = height;
    board->cells = cells;
}
slg_board_set

Schreibt eine gültige Brettzelle; ein NULL-Brett oder Koordinaten außerhalb des Bereichs werden ignoriert.

Syntax

c
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);

Parameter

board

Zu bearbeitendes SLGBoard; die Initialisierung benötigt Speicher, der nicht NULL ist.

x

Zellenspalte von links, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

y

Zellenzeile von oben, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

value

Zu speichernder Byte-Wert; das Spiel legt seine Bedeutung fest, etwa Figuren- oder Geländetyp.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
slg_board_set(&board,1,1,7);slg_board_set(&board,4,1,9);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_board_set: DMG
DMG
slg_board_set: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:38

Deklarationshinweise im Original
Write a cell only when the board and coordinate are valid.

kitaqgb/lib/slg_board.c:64

c
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value)
{
    u8* p;
    if (board == 0) return;
    if (x >= board->width || y >= board->height) return;
    p = slg_cell_ptr(board, x, y);
    *p = value;
}
slg_move_list_clear

Setzt die Zuganzahl zurück, ohne die gespeicherten Datensätze zu löschen.

Syntax

c
void slg_move_list_clear(SLGMoveList* list);

Parameter

list

Zu bearbeitende Zugliste; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
slg_move_list_clear(&moves);result[10]=moves.count;result[11]=move_data[0].value;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_move_list_clear: DMG
DMG
slg_move_list_clear: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:42

Deklarationshinweise im Original
Forget the moves without erasing their storage; a null list is ignored.

kitaqgb/lib/slg_board.c:83

c
void slg_move_list_clear(SLGMoveList* list)
{
    if (list == 0) return;
    list->count = 0;
}
slg_move_list_init

Verknüpft Zugspeicher und Kapazität und setzt die Anzahl auf null.

Syntax

c
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);

Parameter

list

Zu bearbeitende Zugliste; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

items

Array des aufrufenden Codes mit Platz für mindestens capacity Datensätze vom Typ SLGMove.

capacity

Maximale Anzahl der Datensätze; null erlaubt keine Ergänzungen. Jeder Datensatz enthält drei Bytes: x, y und Wert.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
slg_move_list_init(&moves,move_data,2);result[5]=moves.count;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_move_list_init: DMG
DMG
slg_move_list_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:40

Deklarationshinweise im Original
Attach caller-owned move storage and reset the list length.

kitaqgb/lib/slg_board.c:75

c
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity)
{
    list->items = items;
    list->capacity = capacity;
    list->count = 0;
}
slg_move_list_push

Hängt Koordinaten und einen Wert an die Zugliste an, ohne das Brett zu verändern.

Syntax

c
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);

Parameter

list

Zu bearbeitende Zugliste; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

x

Zellenspalte von links, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

y

Zellenzeile von oben, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

value

Zu speichernder Byte-Wert; das Spiel legt seine Bedeutung fest, etwa Figuren- oder Geländetyp.

Rückgabewert

1 bei erfolgreichem Anhängen, 0 bei NULL oder vollem Speicher; ein Fehlschlag lässt Anzahl und vorhandene Datensätze unverändert.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
result[6]=slg_move_list_push(&moves,1,1,7);result[7]=slg_move_list_push(&moves,2,1,8);result[8]=slg_move_list_push(&moves,3,1,9);result[9]=moves.count;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_move_list_push: DMG
DMG
slg_move_list_push: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:45

Deklarationshinweise im Original
Append coordinates and a value to the bounded move list. Return zero on a
null/full list without replacing any existing move.

kitaqgb/lib/slg_board.c:91

c
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value)
{
    SLGMove* move;
    if (list == 0) return 0;
    if (list->count >= list->capacity) return 0;
    move = &list->items[(__safe_index u8)list->count];
    move->x = x;
    move->y = y;
    move->value = value;
    list->count++;
    return 1;
}
slg_undo_init

Verknüpft den Rücknahmespeicher und seine Kapazität und beginnt mit einem leeren Stapel.

Syntax

c
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);

Parameter

stack

Zu bearbeitender Rücknahmestapel; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

items

Array des aufrufenden Codes mit Platz für mindestens capacity Datensätze vom Typ SLGMove.

capacity

Maximale Anzahl der Datensätze; null erlaubt keine Ergänzungen. Jeder Datensatz enthält drei Bytes: x, y und Wert.

Rückgabewert

Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
slg_undo_init(&undo,undo_data,2);result[12]=undo.count;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_undo_init: DMG
DMG
slg_undo_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:47

Deklarationshinweise im Original
Attach caller-owned undo records and initialize an empty stack.

kitaqgb/lib/slg_board.c:106

c
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity)
{
    stack->items = items;
    stack->capacity = capacity;
    stack->count = 0;
}
slg_undo_pop

Entfernt und liefert den neuesten Rücknahmedatensatz; der aufrufende Code wendet ihn auf das Brett an.

Syntax

c
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);

Parameter

stack

Zu bearbeitender Rücknahmestapel; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

out_move

Ziel für den entnommenen Datensatz; NULL verwirft ihn ohne Kopie.

Rückgabewert

1, wenn ein Datensatz entnommen wurde, 0 bei einem NULL-Zeiger oder leeren Stapel; ein leerer Stapel lässt die Ausgabe unverändert.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
result[15]=slg_undo_pop(&undo,&old);result[16]=old.value;result[17]=slg_board_get(&board,1,1);slg_undo_pop(&undo,&old);slg_board_set(&board,old.x,old.y,old.value);result[18]=slg_board_get(&board,1,1);result[19]=slg_undo_pop(&undo,&old);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_undo_pop: DMG
DMG
slg_undo_pop: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:53

Deklarationshinweise im Original
Remove the newest undo record and optionally copy it out. A null output
still discards the record; a null or empty stack returns zero.

kitaqgb/lib/slg_board.c:128

c
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move)
{
    if (stack == 0) return 0;
    if (stack->count == 0) return 0;
    stack->count--;
    if (out_move != 0) {
        out_move->x = stack->items[stack->count].x;
        out_move->y = stack->items[stack->count].y;
        out_move->value = stack->items[stack->count].value;
    }
    return 1;
}
slg_undo_push

Legt den bisherigen Zellwert auf den Rücknahmestapel, ohne das Brett zu verändern.

Syntax

c
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);

Parameter

stack

Zu bearbeitender Rücknahmestapel; die Initialisierung benötigt einen Zeiger, der nicht NULL ist.

x

Zellenspalte von links, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

y

Zellenzeile von oben, beginnend bei null; das Aufzeichnen eines Zugs prüft die Brettgrenzen nicht.

old_value

Bisheriger Byte-Wert der Zelle; die Funktion liest ihn nicht automatisch vom Brett.

Rückgabewert

1 bei erfolgreichem Anhängen, 0 bei NULL oder vollem Speicher; ein Fehlschlag lässt Anzahl und vorhandene Datensätze unverändert.

Bedingungen und Grenzen

Der aufrufende Code stellt den Speicher bereit. Die Initialisierung reserviert und löscht ihn nicht. Brettkoordinaten werden in Zellen angegeben.

Anwendungsbeispiel

c
result[13]=slg_undo_push(&undo,1,1,slg_board_get(&board,1,1));slg_board_set(&board,1,1,8);slg_undo_push(&undo,1,1,8);result[14]=slg_undo_push(&undo,0,0,9);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel trennt die Aufgaben von Brett, Zugliste und Rücknahmedatensätzen. Die Brettinitialisierung behält 9 bei; ein dritter Eintrag in einer Liste mit zwei Plätzen liefert 0. Das Entnehmen allein lässt den Brettwert bei 8; erst das ausdrückliche Anwenden des Datensatzes stellt 7 wieder her.

slg_undo_push: DMG
DMG
slg_undo_push: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/slg.h:50

Deklarationshinweise im Original
Record a cell's previous value for later undo. Return zero if the stack is
null or full; this function does not change the board itself.

kitaqgb/lib/slg_board.c:115

c
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value)
{
    if (stack == 0) return 0;
    if (stack->count >= stack->capacity) return 0;
    stack->items[stack->count].x = x;
    stack->items[stack->count].y = y;
    stack->items[stack->count].value = old_value;
    stack->count++;
    return 1;
}

sprite.h — OBJ-Reservierung, Positionierung, Metasprites und Animation

Sprites sind bewegliche Hardwareobjekte, meist 8×8 oder 8×16 Pixel groß, die durch Einträge im Object Attribute Memory (OAM) beschrieben werden. Reservieren Sie Einträge, setzen Sie Position, Tile und Attribute im Arbeitspuffer und übertragen Sie ihn anschließend. Ein Metasprite fasst mehrere Einträge zu einem Objekt zusammen. GB bietet 40 Einträge mit höchstens 10 pro Zeile; FC bietet 64 mit höchstens 8 pro Zeile.

GB-Attribute: Bit 4 wählt OBP1 auf DMG, Bits 5/6 spiegeln X/Y, Bit 7 legt das Sprite hinter Hintergrundpixel mit Farbindex ungleich null. Auf CGB wählen Bits 0..2 die Objektpalette und Bit 3 die VRAM-Bank der Tile-Daten; das DMG-Palettenbit wählt keine nativen CGB-Farben.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

anim_update

Erhöht den SpriteAnim-Zähler und gibt die gewählte Tile-Nummer zurück. Nach ticks_per_frame Aufrufen folgt das nächste fortlaufende Tile; nach frame_count Bildern beginnt die Folge von vorn. Der Aufrufer übernimmt das Ergebnis mit sprite_set_tile.

Syntax

c
u8 anim_update(SpriteAnim* anim);

Parameter

anim

Beschreibbarer SpriteAnim-Zustand mit first_tile, frame_count, frame, ticks und ticks_per_frame. Bei Grenzen ungleich null muss frame kleiner als frame_count und ticks kleiner als ticks_per_frame sein.

Rückgabewert

Gewählte 8-Bit-Tile-Nummer; 0 bei einem Nullzeiger. Die Funktion schreibt nicht in das OAM.

Bedingungen und Grenzen

frame_count=0 liefert first_tile ohne Fortschritt; ticks_per_frame=0 hält das aktuelle Bild fest. Der Zähler zählt Aufrufe, keine Videobilder. Tile-Nummern laufen nach 255 über und steigen auch im 8×16-Modus jeweils nur um eins.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_example_animation.first_tile=128;sprite_example_animation.frame_count=2;
sprite_example_animation.frame=0;sprite_example_animation.ticks=0;
sprite_example_animation.ticks_per_frame=2;
sprite_example_expect(anim_update(&sprite_example_animation)==128);
tile=anim_update(&sprite_example_animation);
sprite_example_expect(tile==129);sprite_set_tile(5,tile);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei first_tile=128, zwei Bildern und zwei Aufrufen pro Bild liefert die erste Aktualisierung Pfeil-Tile 128 und die zweite Quadrat-Tile 129. Das Quadrat neben ANIMATION zeigt, dass das Ergebnis ins OAM übernommen wurde.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

anim_update: DMG
DMG
anim_update: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:86

Deklarationshinweise im Original
Advance animation ticks/frame with wrapping frame selection and return the
resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.

kitaqgb/lib/sprite.c:211

c
u8 anim_update(SpriteAnim* anim)
{
    if (anim == 0) return 0;
    if (anim->frame_count == 0) return anim->first_tile;
    if (anim->ticks_per_frame == 0) return (u8)(anim->first_tile + anim->frame);

    anim->ticks++;
    if (anim->ticks >= anim->ticks_per_frame) {
        anim->ticks = 0;
        anim->frame++;
        if (anim->frame >= anim->frame_count) anim->frame = 0;
    }
    return (u8)(anim->first_tile + anim->frame);
}
metasprite_draw

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Platziert eine angegebene Anzahl von Sprite-Teilen in aufeinanderfolgenden Einträgen. Jeder Teil enthält vorzeichenbehaftete Versätze, Tile und Attribute. Freie Einträge werden aktiviert, aktive überschrieben; am Eintragslimit endet die Ausgabe.

Syntax

c
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);

Parameter

first_id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

x

Horizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.

y

Y-Bildschirmkoordinate in Pixeln. Die GB-Funktion addiert vor dem Speichern im OAM den Wert 16.

parts

Lesbares Array mit mindestens count MetaSpritePart-Einträgen. Jeder vier Byte große Eintrag enthält vorzeichenbehaftete dx/dy-Werte, Tile und Attribute; es gibt keine Endmarkierung.

count

Anzahl der Teile als vorzeichenloses Byte. Null bewirkt keine Schreibzugriffe. Beim Erreichen von SPRITE_MAX werden nur die bis dahin passenden Teile geschrieben.

Rückgabewert

Zahl geschriebener Teile von 0 bis count. Daran lässt sich erkennen, ob die Ausgabe am Eintragslimit gekürzt wurde.

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Die vorzeichenbehafteten Byte-Versätze werden zur Basisposition addiert; das Ergebnis läuft auf acht Bit über. Das Teilearray muss während des Aufrufs lesbar bleiben. Aktive Einträge werden überschrieben, auch wenn sie zu einem anderen Objekt gehören.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_example_expect(metasprite_draw(10,88,SPRITE_EXAMPLE_Y(64),sprite_example_pair,2)==2);
sprite_example_expect(sprite_count_used()==9); // Sparse IDs count actual active slots.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

metasprite_draw: DMG
DMG
metasprite_draw: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:83

Deklarationshinweise im Original
Place consecutive parts, counting each newly activated slot once. Existing
active slots are overwritten without increasing the allocation count. Return
the number written; an invalid first slot or zero count writes nothing.

kitaqgb/lib/sprite.c:191

c
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count)
{
    u8 i = 0;
    while (i < count) {
        u8 id = (u8)(first_id + i);
        if (id >= SPRITE_MAX) return i;
        if (kq_sprite_active[id] == 0) {
            kq_sprite_active[id] = 1;
            kq_sprite_used = (u8)(kq_sprite_used + 1);
        }
        sprite_set_pos(id, (u8)(x + parts[i].dx), (u8)(y + parts[i].dy));
        sprite_set_tile(id, parts[i].tile);
        sprite_set_flags(id, parts[i].flags);
        i++;
    }
    return count;
}
sprite_alloc

Reserviert den ersten freien Sprite-Eintrag und blendet ihn bis zur Positionierung aus. Ein ausgeblendeter Eintrag bleibt reserviert. Legen Sie vor der Anzeige Tile und Attribute fest.

Syntax

c
u8 sprite_alloc();

Rückgabewert

ID des reservierten Eintrags oder 0xFF, wenn alle Einträge aktiv sind.

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
for(i=0;i<8;i++) sprite_example_expect(sprite_alloc()==i);
sprite_example_expect(sprite_count_used()==8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_alloc: DMG
DMG
sprite_alloc: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:53

Deklarationshinweise im Original
Claim the first free slot, hide it, and return its ID; return 0xFF when full.
Previously stored tile/flag bytes are retained until the caller replaces them.

kitaqgb/lib/sprite.c:60

c
u8 sprite_alloc()
{
    u8 i = 0;
    while (i < SPRITE_MAX) {
        if (kq_sprite_active[i] == 0) {
            kq_sprite_active[i] = 1;
            kq_sprite_used++;
            sprite_hide(i);
            return i;
        }
        i++;
    }
    return 0xFF;
}
sprite_count_used

Gibt die Zahl reservierter Einträge zurück, einschließlich ausgeblendeter Sprites und durch metasprite_draw aktivierter Einträge. Gezählt werden Reservierungen, keine sichtbaren Sprites.

Syntax

c
u8 sprite_count_used();

Rückgabewert

Vorzeichenloser Bytewert von 0 bis SPRITE_MAX.

Bedingungen und Grenzen

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_example_expect(sprite_count_used()==9); // After hiding, freeing and drawing the pair.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_count_used: DMG
DMG
sprite_count_used: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:73

Deklarationshinweise im Original
Return the number of active slots, including slots activated by metasprite_draw.
Hidden allocated slots remain active until sprite_free releases them.

kitaqgb/lib/sprite.c:148

c
u8 sprite_count_used()
{
    return kq_sprite_used;
}
sprite_flush_oam

Wartet auf VBlank und überträgt dann den OAM-Arbeitspuffer mit sprite_flush_oam_now.

Syntax

c
void sprite_flush_oam();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Die GB-Routine führt den DMA-Code im HRAM aus und kopiert 160 Byte aus dem ausgerichteten OAM-Puffer. Währenddessen sperrt sie Interrupts und aktiviert sie danach immer; ein zuvor gesperrter Zustand wird nicht wiederhergestellt.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
while(1) { sprite_flush_oam(); } // Transfer prepared sprites at the next frame boundary.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_flush_oam: DMG
DMG
sprite_flush_oam: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:70

Deklarationshinweise im Original
Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.

kitaqgb/lib/sprite.c:139

c
void sprite_flush_oam()
{
    __wait_vblank();
    sprite_flush_oam_now();
}
sprite_flush_oam_now

Überträgt den OAM-Arbeitspuffer sofort an die Hardware. Die Routine wartet nicht auf einen sicheren Anzeigezeitraum; der aufrufende Code bestimmt den Zeitpunkt.

Syntax

c
void sprite_flush_oam_now();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Die GB-Routine führt den DMA-Code im HRAM aus und kopiert 160 Byte aus dem ausgerichteten OAM-Puffer. Währenddessen sperrt sie Interrupts und aktiviert sie danach immer; ein zuvor gesperrter Zustand wird nicht wiederhergestellt.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
// Rendering is disabled here; all shadow entries have been prepared.
sprite_flush_oam_now();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_flush_oam_now: DMG
DMG
sprite_flush_oam_now: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:68

Deklarationshinweise im Original
Install the HRAM stub lazily and execute OAM DMA with interrupts disabled.
This routine does not wait for VBlank and always enables interrupts afterward;
it does not restore the caller's previous interrupt-enable state.

kitaqgb/lib/sprite.c:122

c
void sprite_flush_oam_now()
{
    SpriteDmaRoutine dma;
    if (kq_sprite_dma_ready == 0) {
        sprite_install_dma_stub();
    }
    dma = (SpriteDmaRoutine)kq_sprite_dma_stub;
    __asm {
        DI
    }
    dma();
    __asm {
        EI
    }
}
sprite_free

Gibt einen reservierten Eintrag frei, blendet ihn aus und verringert die Zahl aktiver Einträge um eins. Ungültige IDs und bereits freie Einträge bleiben ohne Wirkung.

Syntax

c
void sprite_free(u8 id);

Parameter

id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_free(7);sprite_free(7);
sprite_example_expect(sprite_count_used()==7); // Repeated release is ignored.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_free: DMG
DMG
sprite_free: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:55

Deklarationshinweise im Original
Release an allocated valid slot and hide it. Repeated frees do not decrement the count.

kitaqgb/lib/sprite.c:78

c
void sprite_free(u8 id)
{
    if (sprite_valid(id) == 0) return;
    if (kq_sprite_active[id] == 0) return;
    kq_sprite_active[id] = 0;
    if (kq_sprite_used != 0) kq_sprite_used--;
    sprite_hide(id);
}
sprite_hide

Blendet ein Sprite durch Änderung seiner Position im Arbeitspuffer aus. Reservierung, Tile und Attribute bleiben erhalten. Eine sichtbare Position blendet es ohne erneute Reservierung wieder ein.

Syntax

c
void sprite_hide(u8 id);

Parameter

id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_hide(6);
sprite_example_expect(sprite_count_used()==8); // Hiding retains allocation.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_hide: DMG
DMG
sprite_hide: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:64

Deklarationshinweise im Original
Move a valid shadow slot off screen without freeing it.

kitaqgb/lib/sprite.c:112

c
void sprite_hide(u8 id)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].y = 0;
    kq_sprite_oam[id].x = 0;
}
sprite_init

Setzt die Sprite-Verwaltung zurück und blendet alle Einträge im OAM-Arbeitspuffer aus. Die im Programm gespeicherte Höhe wird auf 8 Pixel gesetzt. Hardwaregröße und OAM-Übertragung werden separat eingerichtet.

Syntax

c
void sprite_init();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Auf GB werden alle vier Bytes jedes Eintrags gelöscht und die Installation der HRAM-DMA-Routine zurückgesetzt. Behalten Sie SPRITE_MAX=40 bei, sofern eine eigene DMA-Quelle nicht weiterhin volle 160 Byte bereitstellt.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_init();
sprite_example_expect(sprite_count_used()==0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach der Initialisierung sind null Einträge reserviert. Acht Reservierungen liefern 0..7. Ausblenden von Eintrag 6 belässt den Zähler bei 8; zweimalige Freigabe von 7 ergibt 7. Das Paar in Einträgen 10 und 11 erhöht ihn auf 9.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_init: DMG
DMG
sprite_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:50

Deklarationshinweise im Original
Clear allocation and shadow OAM state and reset the DMA-stub installation flag.
The default height is eight pixels; the hardware display mode is configured elsewhere.

kitaqgb/lib/sprite.c:22

c
void sprite_init()
{
    u8 i = 0;
    kq_sprite_used = 0;
    kq_sprite_height = 8;
    kq_sprite_dma_ready = 0;
    while (i < SPRITE_MAX) {
        kq_sprite_active[i] = 0;
        kq_sprite_oam[i].y = 0;
        kq_sprite_oam[i].x = 0;
        kq_sprite_oam[i].tile = 0;
        kq_sprite_oam[i].flags = 0;
        i++;
    }
}
sprite_max_scanline_count

Ermittelt aus den verwalteten Y-Positionen und kq_sprite_height die größte Zahl aktiver Sprites auf einer sichtbaren Bildschirmzeile.

Syntax

c
u8 sprite_max_scanline_count();

Rückgabewert

Vorzeichenloser Bytewert von 0 bis SPRITE_MAX.

Bedingungen und Grenzen

Setzen Sie kq_sprite_height auf die Hardwarehöhe 8 oder 16. Transparenz, horizontale Sichtbarkeit und Hardwarepriorität werden nicht berücksichtigt. FC verwendet die Bibliothekskoordinaten; direkte Änderungen durch OAM-Intrinsics gehen nicht in die Schätzung ein.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_example_expect(sprite_max_scanline_count()==SPRITE_EXAMPLE_LINE_COUNT);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

sprite_max_scanline_count: DMG
DMG
sprite_max_scanline_count: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:79

Deklarationshinweise im Original
Estimate the largest overlap of active, non-hidden shadow sprites across
visible scanlines using the configured sprite height. This is a software
overlap count, not a rendered-pixel or hardware-priority simulation.

kitaqgb/lib/sprite.c:158

c
u8 sprite_max_scanline_count()
{
    u8 line = 0;
    u8 best = 0;
    while (line < 144) {
        u8 i = 0;
        u8 count = 0;
        u8 ly_oam = (u8)(line + 16);
        while (i < SPRITE_MAX) {
            u8 sy = kq_sprite_oam[i].y;
            if (kq_sprite_active[i] != 0 && sy != 0) {
                if (ly_oam >= sy && ly_oam < (u8)(sy + kq_sprite_height)) {
                    count++;
                }
            }
            i++;
        }
        if (count > best) best = count;
        line++;
    }
    return best;
}
sprite_set_flags

Ersetzt das gesamte Attributbyte. Kombinieren Sie die Konstanten der Plattform für Spiegelung, Palette und Hintergrundpriorität. Nicht gesetzte Bits werden gelöscht.

Syntax

c
void sprite_set_flags(u8 id, u8 flags);

Parameter

id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

flags

Vollständiges Attributbyte aus den SPRITE_FLAG_*-Konstanten der Plattform. Mehrere Flags werden mit bitweisem ODER (|) kombiniert.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

GB-Attribute: Bit 4 wählt OBP1 auf DMG, Bits 5/6 spiegeln X/Y, Bit 7 legt das Sprite hinter Hintergrundpixel mit Farbindex ungleich null. Auf CGB wählen Bits 0..2 die Objektpalette und Bit 3 die VRAM-Bank der Tile-Daten; das DMG-Palettenbit wählt keine nativen CGB-Farben.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_set_flags(1,SPRITE_FLAG_XFLIP);
sprite_set_flags(2,SPRITE_FLAG_YFLIP);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_set_flags: DMG
DMG
sprite_set_flags: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:62

Deklarationshinweise im Original
Replace a valid shadow slot's complete hardware attribute byte.

kitaqgb/lib/sprite.c:105

c
void sprite_set_flags(u8 id, u8 flags)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].flags = flags;
}
sprite_set_pos

Verschiebt ein GB-Sprite im OAM-Arbeitspuffer anhand von Bildschirmkoordinaten in Pixeln. Die Funktion addiert die Hardwareversätze von 8 zu X und 16 zu Y.

Syntax

c
void sprite_set_pos(u8 id, u8 x, u8 y);

Parameter

id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

x

Horizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.

y

Y-Bildschirmkoordinate in Pixeln. Die GB-Funktion addiert vor dem Speichern im OAM den Wert 16.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Koordinaten werden mit acht Bit addiert und laufen modulo 256 über; die Bibliothek schneidet nicht am Bildschirmrand ab. Gültige Einträge sind auch ohne Reservierung bearbeitbar.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_set_pos(0,88,SPRITE_EXAMPLE_Y(16)); // Visible top-left: (88,16).

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_set_pos: DMG
DMG
sprite_set_pos: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:58

Deklarationshinweise im Original
Convert screen coordinates to OAM coordinates by adding X=8 and Y=16.
The byte additions wrap; this updates shadow storage even for an unallocated slot.

kitaqgb/lib/sprite.c:89

c
void sprite_set_pos(u8 id, u8 x, u8 y)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].x = (u8)(x + 8);
    kq_sprite_oam[id].y = (u8)(y + 16);
}
sprite_set_tile

Ersetzt die Tile-Nummer eines OAM-Eintrags. Damit werden bereits im Tile-Speicher liegende Grafiken ausgewählt; Grafikdaten werden weder geladen noch Sprite-Einträge reserviert.

Syntax

c
void sprite_set_tile(u8 id, u8 tile);

Parameter

id

Eintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.

tile

8-Bit-Tile-Nummer. Die Grafik muss vorher geladen werden. Die Hardware-Regeln für 8×16-Sprites gelten weiterhin; die Nummer wird nicht für Tile-Paare angepasst.

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

Position, Tile, Attribute und Ausblenden ändern nur den Arbeitspuffer. Sie reservieren keine Einträge und aktualisieren das Hardware-OAM nicht sofort. Übertragen Sie das vorbereitete Bild mit sprite_flush_oam.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_set_tile(5,129); // Select the green square beside ANIMATION.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Bei first_tile=128, zwei Bildern und zwei Aufrufen pro Bild liefert die erste Aktualisierung Pfeil-Tile 128 und die zweite Quadrat-Tile 129. Das Quadrat neben ANIMATION zeigt, dass das Ergebnis ins OAM übernommen wurde.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

sprite_set_tile: DMG
DMG
sprite_set_tile: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:60

Deklarationshinweise im Original
Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.

kitaqgb/lib/sprite.c:98

c
void sprite_set_tile(u8 id, u8 tile)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].tile = tile;
}
sprite_warn_scanline_overflow

Vergleicht sprite_max_scanline_count mit dem Zeilenlimit von 10 Sprites auf GB beziehungsweise 8 auf FC. Das Ergebnis ist eine Softwareschätzung; das Hardware-Überlaufbit wird nicht gelesen.

Syntax

c
u8 sprite_warn_scanline_overflow();

Rückgabewert

1 bei Überschreitung des Zeilenlimits, sonst 0.

Bedingungen und Grenzen

Setzen Sie kq_sprite_height auf die Hardwarehöhe 8 oder 16. Transparenz, horizontale Sichtbarkeit und Hardwarepriorität werden nicht berücksichtigt. FC verwendet die Bibliothekskoordinaten; direkte Änderungen durch OAM-Intrinsics gehen nicht in die Schätzung ein.

Das Beispiel nutzt die vollständige GB-Bibliothek. KQ_SPRITE_MINIMAL_RUNTIME entfernt sprite_free, sprite_set_pos, sprite_count_used, beide Zeilenabfragen, metasprite_draw und anim_update aus sprite.c. Definieren Sie es nicht, wenn Sie diese Funktionen verwenden.

Anwendungsbeispiel

c
sprite_example_expect(sprite_warn_scanline_overflow()==1);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Reihe unter SCAN LIMIT beginnt bei (8,128). Das Programm übergibt dort 11 GB- beziehungsweise 9 FC-Sprites, absichtlich eines zu viel. Sichtbar sein müssen 10 Pfeile auf GB und 8 auf FC; der zuletzt übergebene fehlt. Die Softwareprüfungen müssen trotzdem den Höchstwert 11/9 und das Warnsignal 1 liefern.

Das Programm zeigt Reservierung, Positionierung, Spiegelung, zusammengesetzte Objekte, Überlagerung, Animation und Zeilenlimit. Die beiden Ziffern oben rechts müssen 00 sein: Alle internen Prüfungen sind erfüllt. Jeder Pfeil und jedes Quadrat belegt ein 8×8-Tile.

NORMAL zeigt einen Rechtspfeil bei (88,16). FLIP X zeigt bei (88,32) nach links; FLIP Y spiegelt den Pfeil bei (88,48) vertikal. META setzt zwei Pfeile bei (88,64) und (96,64). Unter OVERLAP liegt der Pfeil bei (88,80) vor dem Quadrat bei (92,80), das durch transparente Pfeilpixel sichtbar bleibt. ANIMATION zeigt das Quadrat bei (88,96). Die Bereiche (120,16) und (120,32) bleiben nach Ausblenden und Freigabe leer.

Auf CGB und FC haben die Pfeile einen grünen Schaft, rote Konturen und blaue Details an der Spitze; das Quadrat ist grün. Transparente Pixel zeigen den weißen GB- beziehungsweise schwarzen FC-Hintergrund. DMG ersetzt Rot, Grün und Blau durch Hellgrau, Dunkelgrau und Schwarz.

sprite_warn_scanline_overflow: DMG
DMG
sprite_warn_scanline_overflow: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite.h:75

Deklarationshinweise im Original
Report whether the software overlap estimate exceeds ten sprites on a scanline.

kitaqgb/lib/sprite.c:182

c
u8 sprite_warn_scanline_overflow()
{
    return (u8)(sprite_max_scanline_count() > 10);
}

sprite_order.h — Spriteauswahl nach Priorität und Rotation

sprite_order setzt wichtige Objekte zuerst und rotiert die OAM-Reihenfolge bei gleicher Priorität. Es gibt bis zu 40 aus höchstens 255 Kandidaten aus und hilft bei der Zehnobjektgrenze je Zeile. sprite verwaltet Slots und DMA, sprite_order die Kandidatenauswahlreihenfolge.

Binden Sie sprite_order.h ein und kompilieren Sie sprite_order.c genau einmal. Nach der Initialisierung folgen je Frame begin, push für jeden Kandidaten und build. Die Ordnungsbibliothek selbst benötigt weder sprite.c noch globale Variablendefinitionen.

Die Hardware wählt je Rasterzeile die ersten zehn schneidenden Objekte in OAM-Reihenfolge. Niedrigere Prioritätswerte zuerst schützen wichtige Objekte auf vollen Zeilen. Rotation garantiert keine gleiche Anzeigehäufigkeit innerhalb einer Prioritätsstufe. Belegen wichtige Objekte alle zehn Plätze, bleiben niedrig priorisierte Objekte dieser Zeile unsichtbar.

SpriteOrderOamEntry enthält vier Bytes: Y, X, tile und flags. Für die OAM-Kopie aus sprite.h schreiben Sie nach (SpriteOrderOamEntry*)kq_sprite_oam. Behalten Sie SPRITE_MAX bei 40 und vermischen Sie keine vom Allocator verwalteten Slot-IDs mit umgeordneter Ausgabe: build aktualisiert dessen Verwaltung nicht.

sprite_order_begin

Leert die Kandidatenanzahl für den neuen Frame und erhält Speicher, Höhe und Phase. Anders als Neuinitialisierung je Frame bleibt die Rotation erhalten.

Syntax

c
void sprite_order_begin(SpriteOrder* order);

Parameter

order

Adresse eines vom Aufrufer gehaltenen SpriteOrder. Initialisieren Sie ihn vor Gebrauch und aktualisieren Sie ihn im Hauptcode.

Rückgabewert

Kein Rückgabewert. Null order wird ignoriert. Alte Eintragsbytes und bereits aufgebautes OAM werden nicht gelöscht.

Bedingungen und Grenzen

Binden Sie sprite_order.h ein und kompilieren Sie sprite_order.c genau einmal. Nach der Initialisierung folgen je Frame begin, push für jeden Kandidaten und build. Die Ordnungsbibliothek selbst benötigt weder sprite.c noch globale Variablendefinitionen.

Die Hardware wählt je Rasterzeile die ersten zehn schneidenden Objekte in OAM-Reihenfolge. Niedrigere Prioritätswerte zuerst schützen wichtige Objekte auf vollen Zeilen. Rotation garantiert keine gleiche Anzeigehäufigkeit innerhalb einer Prioritätsstufe. Belegen wichtige Objekte alle zehn Plätze, bleiben niedrig priorisierte Objekte dieser Zeile unsichtbar.

Anwendungsbeispiel

c
sprite_order_begin(&order_demo);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

sprite_order_begin: DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_begin: CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_begin: CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite_order.h:42

Deklarationshinweise im Original
Discard this frame's submissions while preserving storage, height and phase.
A null state is ignored. Call once before submitting the next frame's sprites.

kitaqgb/lib/sprite_order.c:24

c
void sprite_order_begin(SpriteOrder* order)
{
    if (order != 0) order->count = 0;
}
sprite_order_build

Baut 160 Bytes OAM-Kopie in Prioritäts- und zyklischer Reihenfolge auf. Unbenutzte Slots werden durch Nullsetzen verborgen, danach wird die Phase weitergeschaltet. Der Kandidatenspeicher wird nicht umgeordnet.

Syntax

c
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);

Parameter

order

Adresse eines vom Aufrufer gehaltenen SpriteOrder. Initialisieren Sie ihn vor Gebrauch und aktualisieren Sie ihn im Hauptcode.

output

Beschreibbares Array mit 40 SpriteOrderOamEntry. Alle 160 Bytes werden geschrieben, auch bei limit null oder kleiner als 40.

limit

Maximale Ausgabeanzahl 0..40; größere Werte werden auf 40 begrenzt. Gilt für das gesamte OAM, nicht je Zeile.

Rückgabewert

Liefert die Ausgabeanzahl 0..40. Eine gültige leere Warteschlange löscht alle Slots und setzt phase=0. Sonst wird phase modulo count normalisiert, dieser zyklische Start je aufsteigender Prioritätsstufe verwendet und phase danach erhöht und umgebrochen. Auch limit null schaltet die Phase weiter. Null order/output, deaktivierter Zustand, ungültige Höhe oder count>capacity liefert null ohne Änderung von Ausgabe oder Phase.

Bedingungen und Grenzen

Die Hardware wählt je Rasterzeile die ersten zehn schneidenden Objekte in OAM-Reihenfolge. Niedrigere Prioritätswerte zuerst schützen wichtige Objekte auf vollen Zeilen. Rotation garantiert keine gleiche Anzeigehäufigkeit innerhalb einer Prioritätsstufe. Belegen wichtige Objekte alle zehn Plätze, bleiben niedrig priorisierte Objekte dieser Zeile unsichtbar.

priority steuert die Auswahlreihenfolge unabhängig vom Attribut hinter dem Hintergrund. Auf DMG gewinnt bei ausgewählten überlappenden Objekten das kleinere X, bei Gleichstand die OAM-Reihenfolge. Normaler CGB-Farbmodus nutzt OAM, eine über OPRI gewählte DMG-Anordnung gilt jedoch weiterhin. Die Bibliothek ändert keine Hardwareprioritätsregeln.

SpriteOrderOamEntry enthält vier Bytes: Y, X, tile und flags. Für die OAM-Kopie aus sprite.h schreiben Sie nach (SpriteOrderOamEntry*)kq_sprite_oam. Behalten Sie SPRITE_MAX bei 40 und vermischen Sie keine vom Allocator verwalteten Slot-IDs mit umgeordneter Ausgabe: build aktualisiert dessen Verwaltung nicht.

build schreibt nur RAM. Stellen Sie ein 160-Byte-Ausgabearray ohne Überlappung mit Zustand oder Kandidatenspeicher bereit. OAM-DMA-Puffer müssen an einer 256-Byte-Grenze beginnen. Beenden Sie den Aufbau vor der VBlank-Übertragung; Interrupts dürfen keinen halbfertigen Puffer übertragen. Das Beispiel nutzt sprite_flush_oam.

Jede Einreichung hat begrenzten Aufwand. Der Aufbau löscht 160 Bytes OAM-Kopie und durchläuft das Kandidatenarray bis zu viermal, ohne es zu sortieren oder einen Sortierpuffer zu benötigen. Das garantiert nicht, dass 255 Kandidaten ins Framebudget passen; reichen Sie nur benötigte Kandidaten ein.

Anwendungsbeispiel

c
order_demo_state[1]=sprite_order_build(&order_demo,(SpriteOrderOamEntry*)kq_sprite_oam,40);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

sprite_order_build: DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_build: CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_build: CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite_order.h:62

Deklarationshinweise im Original
Write a complete 160-byte shadow OAM: ascending priority, then cyclic order
within each priority. Clamp limit to 40, return the number emitted and zero
all unused entries (including Y) so they cannot consume scanline slots.
Advance phase once for a nonempty valid queue, even when limit is zero.
Empty queues reset phase to zero. Null/disabled/corrupt state or null output
returns 0 without modifying output or phase.
Output must provide 40 entries and must not overlap item/state storage.
This only writes RAM. Build in foreground, then transfer during VBlank.
DMG overlap priority also depends on X: this cannot override that hardware
rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB.
It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.

kitaqgb/lib/sprite_order.c:57

c
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit)
{
    u8 i;
    u8 count;
    u8 phase;
    u8 priority;
    u8 visited;
    u8 written;
    SpriteOrderItem* item;
    if (order == 0 || output == 0) return 0;
    if (order->items == 0 || order->capacity == 0) return 0;
    if (order->count > order->capacity) return 0;
    if (order->height != 8 && order->height != 16) return 0;
    // Clear all hardware slots regardless of the requested emission limit.
    for (i = 0; i < SPRITE_ORDER_OAM_COUNT; i++) {
        output[i].y = 0;
        output[i].x = 0;
        output[i].tile = 0;
        output[i].flags = 0;
    }
    count = order->count;
    if (count == 0) {
        order->phase = 0;
        return 0;
    }
    if (limit > SPRITE_ORDER_OAM_COUNT) limit = SPRITE_ORDER_OAM_COUNT;
    phase = order->phase;
    while (phase >= count) phase = (u8)(phase - count);
    written = 0;
    for (priority = 0; priority < SPRITE_ORDER_LEVELS && written < limit; priority++) {
        i = phase;
        visited = 0;
        while (visited < count && written < limit) {
            item = &order->items[i];
            if (item->priority == priority) {
                output[written].y = item->oam.y;
                output[written].x = item->oam.x;
                output[written].tile = item->oam.tile;
                output[written].flags = item->oam.flags;
                written++;
            }
            visited++;
            i++;
            if (i >= count) i = 0;
        }
    }
    phase++;
    if (phase >= count) phase = 0;
    order->phase = phase;
    return written;
}
sprite_order_init

Bindet Kandidatenspeicher an den Ordnungszustand und setzt Anzahl sowie Rotationsphase zurück. Für Szenenbeginn oder Speicherwechsel.

Syntax

c
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);

Parameter

order

Adresse eines vom Aufrufer gehaltenen SpriteOrder. Initialisieren Sie ihn vor Gebrauch und aktualisieren Sie ihn im Hauptcode.

items

Beschreibbares SpriteOrderItem-Array mit fünf Bytes pro Eintrag. Reservieren Sie capacity Einträge und halten Sie den Speicher gültig.

capacity

Arraykapazität 1..255 Einträge, weder Byteanzahl noch Hardware-Slotzahl.

height

Alle Objekte teilen dieselbe Höhe. Übergeben Sie 8 oder 16 passend zu LCDCs 8×8-/8×16-Modus; die Bibliothek setzt LCDC nicht. Im 8×16-Modus ignoriert die Hardware das niederwertigste Bit der Kachelnummer.

Rückgabewert

Liefert bei Erfolg 1, sonst 0 für null items, Kapazität null, Höhe ungleich 8/16 oder null order. Bei gültigem order hinterlässt ein Fehler den deaktivierten Zustand items=NULL, capacity=count=phase=0, height=8. Das Eintragsarray bleibt unverändert.

Bedingungen und Grenzen

Binden Sie sprite_order.h ein und kompilieren Sie sprite_order.c genau einmal. Nach der Initialisierung folgen je Frame begin, push für jeden Kandidaten und build. Die Ordnungsbibliothek selbst benötigt weder sprite.c noch globale Variablendefinitionen.

Anwendungsbeispiel

c
sprite_init();sprite_order_init(&order_demo,order_demo_items,14,8);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

sprite_order_init: DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_init: CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_init: CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite_order.h:38

Deklarationshinweise im Original
Bind writable item storage and select the hardware sprite height (8 or 16).
Return 1 on success. Invalid storage, zero capacity or another height returns
0 and leaves a non-null state disabled. A null state returns 0 without writes.

kitaqgb/lib/sprite_order.c:6

c
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height)
{
    if (order == 0) return 0;
    order->items = 0;
    order->capacity = 0;
    order->count = 0;
    order->height = 8;
    order->phase = 0;
    if (items == 0 || capacity == 0) return 0;
    if (height != 8 && height != 16) return 0;
    order->items = items;
    order->capacity = capacity;
    order->height = height;
    return 1;
}
sprite_order_push

Reicht ein Sprite mit mindestens einem sichtbaren Pixel ein. Vollständig außerhalb liegende Kandidaten werden vor Verbrauch eines OAM-Auswahlplatzes abgelehnt.

Syntax

c
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);

Parameter

order

Adresse eines vom Aufrufer gehaltenen SpriteOrder. Initialisieren Sie ihn vor Gebrauch und aktualisieren Sie ihn im Hauptcode.

x

Vorzeichenbehaftetes Bildschirm-X ab links oben. Linke Kanten −7..159 sind zulässig; ≤−8 oder ≥160 liegt vollständig außerhalb. Für OAM-Koordinaten werden beim Speichern 8 addiert.

y

Vorzeichenbehaftetes Bildschirm-Y ab links oben. Zulässig: −7..143 bei Höhe 8, −15..143 bei Höhe 16. Beim Speichern werden für OAM 16 addiert.

tile

Kachelnummer 0..255, unverändert gespeichert. Für 8×16 siehe Höhenhinweise.

flags

Hardwareattributbyte, unverändert gespeichert: Spiegelung, Hintergrundpriorität, DMG-/CGB-Palette und CGB-VRAM-Bank behalten ihre Hardwarebedeutung.

priority

Softwareauswahlpriorität 0..3, null zuerst. Werte ab vier werden abgelehnt. Unabhängig vom Hardware-Flagsbyte.

Rückgabewert

Bei Annahme Rückgabe 1 und count-Erhöhung. Null/deaktivierter Zustand, ungültige Höhe, voller Speicher, ungültige Priorität oder vollständig unsichtbares Objekt ergeben 0 ohne Änderung von items oder count.

Bedingungen und Grenzen

Alle Objekte teilen dieselbe Höhe. Übergeben Sie 8 oder 16 passend zu LCDCs 8×8-/8×16-Modus; die Bibliothek setzt LCDC nicht. Im 8×16-Modus ignoriert die Hardware das niederwertigste Bit der Kachelnummer.

Die Hardware wählt je Rasterzeile die ersten zehn schneidenden Objekte in OAM-Reihenfolge. Niedrigere Prioritätswerte zuerst schützen wichtige Objekte auf vollen Zeilen. Rotation garantiert keine gleiche Anzeigehäufigkeit innerhalb einer Prioritätsstufe. Belegen wichtige Objekte alle zehn Plätze, bleiben niedrig priorisierte Objekte dieser Zeile unsichtbar.

priority steuert die Auswahlreihenfolge unabhängig vom Attribut hinter dem Hintergrund. Auf DMG gewinnt bei ausgewählten überlappenden Objekten das kleinere X, bei Gleichstand die OAM-Reihenfolge. Normaler CGB-Farbmodus nutzt OAM, eine über OPRI gewählte DMG-Anordnung gilt jedoch weiterhin. Die Bibliothek ändert keine Hardwareprioritätsregeln.

Anwendungsbeispiel

c
sprite_order_push(&order_demo,8,64,128,0,0);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

sprite_order_push: DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
DMG / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_push: CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 04 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
sprite_order_push: CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.
CGB / Phase 08 — Die Lektion zeigt vierzehn Objekte in einer Zeile. Zwei Rauten unter HIGH haben hohe, zwölf Quadrate unter NORMAL normale Priorität. CGB nutzt rote Rauten und blaue Quadrate, DMG Grau und Schwarz. Beide Rauten bleiben sichtbar, aber nur acht Quadrate erscheinen. 0..B bezeichnet ihre Positionen: PHASE 04 zeigt 4..B, PHASE 08 zeigt 8..B und 0..3. Der normale Build erhöht PHASE nach jeweils 60 Framewartezeiten. Die veröffentlichten Bilder fixieren die Phase desselben Programms; wechselnde Quadratauswahl wurde auch im laufenden Programm geprüft.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/sprite_order.h:49

Deklarationshinweise im Original
Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the
tile and attribute bytes; use priority 0 (first) through 3 (last). Fully
off-screen sprites, invalid priorities, disabled state and full storage return
0 without consuming a slot. Partly visible sprites are accepted. Return 1 on
acceptance. Hardware 8x16 mode still ignores the tile index's low bit.

kitaqgb/lib/sprite_order.c:31

c
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority)
{
    SpriteOrderItem* item;
    if (order == 0) return 0;
    if (order->items == 0 || order->capacity == 0) return 0;
    if (order->height != 8 && order->height != 16) return 0;
    if (order->count >= order->capacity || priority >= SPRITE_ORDER_LEVELS) return 0;
    if (x <= -8 || x >= 160 || y >= 144) return 0;
    if (order->height == 16) {
        if (y <= -16) return 0;
    } else {
        if (y <= -8) return 0;
    }
    item = &order->items[order->count];
    item->oam.y = (u8)(y + 16);
    item->oam.x = (u8)(x + 8);
    item->oam.tile = tile;
    item->oam.flags = flags;
    item->priority = priority;
    order->count++;
    return 1;
}

system.h — Start, Bildzähler, Wartefunktionen und Interrupts

Verwaltet Frame-Wartezähler, Callbacks nach dem Warten und die Steuerung maskierbarer CPU-Interrupts.

gb_disable_interrupts

gb_disable_interrupts ist ein Alias für system_disable_interrupts. Deaktiviert CPU-Interrupts auf dem GB.

Deaktiviert maskierbare CPU-Interrupts.

Syntax

c
void gb_disable_interrupts();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Halten Sie geschützte Aktualisierungen kurz und stellen Sie die Interrupts danach passend wieder her. Die Interruptsperre ist unabhängig von den Voraussetzungen einer Frame-Warteroutine.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_disable_interrupts

Anwendungsbeispiel

c
gb_disable_interrupts();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel kombiniert Deaktivierung und Aktivierung. Eigene Prüfprogramme kontrollieren zusätzlich den CPU-Interruptzustand.

gb_disable_interrupts: DMG
DMG
gb_disable_interrupts: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:32

c
#define gb_disable_interrupts system_disable_interrupts

kitaqgb/lib/system.c:52

c
void system_disable_interrupts()
{
    __asm {
        DI
        RET
    }
}
gb_enable_interrupts

gb_enable_interrupts ist ein Alias für system_enable_interrupts. Aktiviert CPU-Interrupts auf dem GB.

Aktiviert maskierbare CPU-Interrupts.

Syntax

c
void gb_enable_interrupts();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Bereiten Sie Interruptquellen und Handler vor der Aktivierung vor. Auf FC ist dies unabhängig davon, ob NMI aktiviert oder deaktiviert ist.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_enable_interrupts

Anwendungsbeispiel

c
gb_enable_interrupts();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel stellt die Interrupts wieder her. Das FC-Programm deaktiviert zuerst die APU-Frame- und DMC-IRQ-Quellen, damit eine nicht quittierte IRQ nicht wiederholt bearbeitet wird.

gb_enable_interrupts: DMG
DMG
gb_enable_interrupts: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:31

c
#define gb_enable_interrupts system_enable_interrupts

kitaqgb/lib/system.c:43

c
void system_enable_interrupts()
{
    __asm {
        EI
        RET
    }
}
gb_frame_count

gb_frame_count ist ein Alias für system_get_frame. Liest den 16-Bit-Softwarezähler der abgeschlossenen Warteaufrufe des Wrappers.

Liest den 16-Bit-Zähler der Frame-Wartefunktion.

Syntax

c
u16 gb_frame_count();

Rückgabewert

Gibt den aktuellen Zählerstand von 0 bis 65535 zurück.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Der Zähler zählt Wartevorgänge über diese Wrapper-Funktion, nicht automatisch die tatsächlich verstrichenen Hardware-Frames. Beim Überlauf nach 16 Bits beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_get_frame

Anwendungsbeispiel

c
result[3]=gb_frame_count();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest nach drei Wartevorgängen drei. Für den Überlauftest wird der Zähler ausdrücklich auf 65535 gesetzt und nach dem nächsten Wartevorgang auf null geprüft.

gb_frame_count: DMG
DMG
gb_frame_count: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:30

c
#define gb_frame_count system_get_frame

kitaqgb/lib/system.c:31

c
u16 system_get_frame()
{
    return kq_system_frame;
}
gb_init

gb_init ist ein Alias für system_init. Setzt den Software-Framezähler und die Callback-Registrierung zurück.

Initialisiert die Frame-Verwaltung, indem Zähler und registrierter Callback gelöscht werden.

Syntax

c
void gb_init();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Der Zähler zählt Wartevorgänge über diese Wrapper-Funktion, nicht automatisch die tatsächlich verstrichenen Hardware-Frames. Beim Überlauf nach 16 Bits beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_init

Anwendungsbeispiel

c
gb_init();result[0]=gb_frame_count();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel bestätigt vor dem Registrieren des Callbacks, dass die anfängliche Frame-Nummer null ist.

gb_init: DMG
DMG
gb_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:27

c
#define gb_init system_init

kitaqgb/lib/system.c:7

c
void system_init()
{
    kq_system_frame = 0;
    system_vblank_callback = 0;
}
gb_set_vblank_callback

gb_set_vblank_callback ist ein Alias für system_set_vblank_callback. Registriert oder entfernt den nach dem Framewarten synchron aufgerufenen Callback.

Registriert, ersetzt oder entfernt die nach einem Frame-Wartevorgang aufgerufene Funktion.

Syntax

c
void gb_set_vblank_callback(SystemCallback callback);

Parameter

callback

Aufzurufende Funktion; 0 entfernt den Callback.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Dies ist ein gewöhnlicher Zeiger auf eine Funktion ohne Parameter und Rückgabewert. Er enthält keine Banknummer; der Zielcode muss eingeblendet bleiben, solange Aufrufe möglich sind.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_set_vblank_callback

Anwendungsbeispiel

c
gb_set_vblank_callback(on_frame);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach drei Callback-Aufrufen deaktiviert die Registrierung von 0 den Aufruf. Der nächste Wartevorgang erhöht den Frame-Zähler auf vier, während die Callback-Anzahl drei bleibt.

gb_set_vblank_callback: DMG
DMG
gb_set_vblank_callback: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:29

c
#define gb_set_vblank_callback system_set_vblank_callback

kitaqgb/lib/system.c:25

c
void system_set_vblank_callback(SystemCallback callback)
{
    system_vblank_callback = callback;
}
gb_wait_vblank

gb_wait_vblank ist ein Alias für system_wait_vblank. Wartet auf die Framegrenze, erhöht den Software-Framezähler und ruft den registrierten Callback auf.

Wartet auf den nächsten Frame, erhöht den Zähler und ruft anschließend den registrierten Callback auf.

Syntax

c
void gb_wait_vblank();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Header definiert ein objektartiges Makro, das zum Implementierungsnamen expandiert. Argumente, Rückgabewerte und Zustandszugriffe entsprechen dem Ziel; der Alias fügt keinen eigenen Zustand oder Verarbeitungsschritt hinzu. Verwenden Sie wie im vollständigen Beispiel und Buildbefehl input.h/input.c für Eingaben oder system.h/system.c für Framedienste.

Der Callback läuft synchron innerhalb dieser Funktion; seine Registrierung installiert keinen Interrupt-Handler. Der Zähler zählt die Wartevorgänge dieses Wrappers und misst nicht automatisch die verstrichenen Hardware-Frames. Beim 16-Bit-Überlauf beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

system_wait_vblank

Anwendungsbeispiel

c
gb_wait_vblank();gb_wait_vblank();gb_wait_vblank();result[1]=frame_calls;result[2]=frame_seen;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Drei Wartevorgänge rufen den Callback dreimal auf; der zuletzt darin gelesene Zählerstand beträgt drei.

gb_wait_vblank: DMG
DMG
gb_wait_vblank: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:28

c
#define gb_wait_vblank system_wait_vblank

kitaqgb/lib/system.c:15

c
void system_wait_vblank()
{
    __wait_vblank();
    kq_system_frame++;
    if (system_vblank_callback != 0) {
        system_vblank_callback();
    }
}
system_disable_interrupts

Deaktiviert maskierbare CPU-Interrupts.

Syntax

c
void system_disable_interrupts();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Halten Sie geschützte Aktualisierungen kurz und stellen Sie die Interrupts danach passend wieder her. Die Interruptsperre ist unabhängig von den Voraussetzungen einer Frame-Warteroutine.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
system_disable_interrupts();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel kombiniert Deaktivierung und Aktivierung. Eigene Prüfprogramme kontrollieren zusätzlich den CPU-Interruptzustand.

system_disable_interrupts: DMG
DMG
system_disable_interrupts: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:25

Deklarationshinweise im Original
Disable CPU interrupts and return; callers must explicitly re-enable them later.

kitaqgb/lib/system.c:52

c
void system_disable_interrupts()
{
    __asm {
        DI
        RET
    }
}
system_enable_interrupts

Aktiviert maskierbare CPU-Interrupts.

Syntax

c
void system_enable_interrupts();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Bereiten Sie Interruptquellen und Handler vor der Aktivierung vor. Auf FC ist dies unabhängig davon, ob NMI aktiviert oder deaktiviert ist.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
system_enable_interrupts();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel stellt die Interrupts wieder her. Das FC-Programm deaktiviert zuerst die APU-Frame- und DMC-IRQ-Quellen, damit eine nicht quittierte IRQ nicht wiederholt bearbeitet wird.

system_enable_interrupts: DMG
DMG
system_enable_interrupts: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:23

Deklarationshinweise im Original
Enable CPU interrupts and return using the inline-assembly function body.

kitaqgb/lib/system.c:43

c
void system_enable_interrupts()
{
    __asm {
        EI
        RET
    }
}
system_get_frame

Liest den 16-Bit-Zähler der Frame-Wartefunktion.

Syntax

c
u16 system_get_frame();

Rückgabewert

Gibt den aktuellen Zählerstand von 0 bis 65535 zurück.

Bedingungen und Grenzen

Der Zähler zählt Wartevorgänge über diese Wrapper-Funktion, nicht automatisch die tatsächlich verstrichenen Hardware-Frames. Beim Überlauf nach 16 Bits beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
result[3]=system_get_frame();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest nach drei Wartevorgängen drei. Für den Überlauftest wird der Zähler ausdrücklich auf 65535 gesetzt und nach dem nächsten Wartevorgang auf null geprüft.

system_get_frame: DMG
DMG
system_get_frame: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:19

Deklarationshinweise im Original
Read the software count of completed system_wait_vblank calls.

kitaqgb/lib/system.c:31

c
u16 system_get_frame()
{
    return kq_system_frame;
}
system_get_frame8

Liest für kurze Wiederholungsintervalle die unteren acht Bits des Frame-Zählers.

Syntax

c
u8 system_get_frame8();

Rückgabewert

Gibt das niederwertige Byte von 0 bis 255 zurück.

Bedingungen und Grenzen

Der Zähler zählt Wartevorgänge über diese Wrapper-Funktion, nicht automatisch die tatsächlich verstrichenen Hardware-Frames. Beim Überlauf nach 16 Bits beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
result[4]=system_get_frame8();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel liest nach drei Wartevorgängen drei und beim Überlauf des 16-Bit-Zählers null.

system_get_frame8: DMG
DMG
system_get_frame8: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:21

Deklarationshinweise im Original
Return the low byte of the software frame counter for wrapping 8-bit timing.

kitaqgb/lib/system.c:37

c
u8 system_get_frame8()
{
    return (u8)kq_system_frame;
}
system_init

Initialisiert die Frame-Verwaltung, indem Zähler und registrierter Callback gelöscht werden.

Syntax

c
void system_init();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Zähler zählt Wartevorgänge über diese Wrapper-Funktion, nicht automatisch die tatsächlich verstrichenen Hardware-Frames. Beim Überlauf nach 16 Bits beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
system_init();result[0]=system_get_frame();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das Beispiel bestätigt vor dem Registrieren des Callbacks, dass die anfängliche Frame-Nummer null ist.

system_init: DMG
DMG
system_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:12

Deklarationshinweise im Original
Reset the software frame counter and remove any registered callback.

kitaqgb/lib/system.c:7

c
void system_init()
{
    kq_system_frame = 0;
    system_vblank_callback = 0;
}
system_set_vblank_callback

Registriert, ersetzt oder entfernt die nach einem Frame-Wartevorgang aufgerufene Funktion.

Syntax

c
void system_set_vblank_callback(SystemCallback callback);

Parameter

callback

Aufzurufende Funktion; 0 entfernt den Callback.

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Dies ist ein gewöhnlicher Zeiger auf eine Funktion ohne Parameter und Rückgabewert. Er enthält keine Banknummer; der Zielcode muss eingeblendet bleiben, solange Aufrufe möglich sind.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
system_set_vblank_callback(on_frame);

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Nach drei Callback-Aufrufen deaktiviert die Registrierung von 0 den Aufruf. Der nächste Wartevorgang erhöht den Frame-Zähler auf vier, während die Callback-Anzahl drei bleibt.

system_set_vblank_callback: DMG
DMG
system_set_vblank_callback: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:17

Deklarationshinweise im Original
Replace the callback used by system_wait_vblank; null disables the callback.

kitaqgb/lib/system.c:25

c
void system_set_vblank_callback(SystemCallback callback)
{
    system_vblank_callback = callback;
}
system_wait_vblank

Wartet auf den nächsten Frame, erhöht den Zähler und ruft anschließend den registrierten Callback auf.

Syntax

c
void system_wait_vblank();

Rückgabewert

Kein Rückgabewert.

Bedingungen und Grenzen

Der Callback läuft synchron innerhalb dieser Funktion; seine Registrierung installiert keinen Interrupt-Handler. Der Zähler zählt die Wartevorgänge dieses Wrappers und misst nicht automatisch die verstrichenen Hardware-Frames. Beim 16-Bit-Überlauf beginnt er wieder bei null.

Auf dem GB endet das Warten bei ausgeschaltetem LCD sofort. Die umgebende Funktion erhöht dennoch ihren Zähler und ruft ihren Callback auf. Die Initialisierung allein richtet weder das LCD noch die Interruptquellen ein.

Bauen Sie dieses vollständige Beispiel mit der standardmäßigen Legacy-ABI. Seine Callbacks verwenden Funktionszeigeraufrufe, die der Compiler mit --abi=stack als nicht unterstützt abweist. Dieselbe Einschränkung gilt bei Verwendung eines Alias.

Anwendungsbeispiel

c
system_wait_vblank();system_wait_vblank();system_wait_vblank();result[1]=frame_calls;result[2]=frame_seen;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Drei Wartevorgänge rufen den Callback dreimal auf; der zuletzt darin gelesene Zählerstand beträgt drei.

system_wait_vblank: DMG
DMG
system_wait_vblank: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementierung und Quelltext

kitaqgb/lib/system.h:15

Deklarationshinweise im Original
Wait for VBlank, count this wrapper call, then invoke the callback synchronously.
The counter wraps at 16 bits and is not an independent hardware frame clock.

kitaqgb/lib/system.c:15

c
void system_wait_vblank()
{
    __wait_vblank();
    kq_system_frame++;
    if (system_vblank_callback != 0) {
        system_vblank_callback();
    }
}

vram.h — VRAM-Aktualisierungen und Übertragung per Warteschlange

Initialisiert die Warteschlange für aufgeschobene VRAM-Schreibbefehle als leer und löscht die Überlaufmeldung. Löscht weder den Bildschirm noch lädt es Tile-Grafiken oder reserviert physischen VRAM.

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Wartet mit __wait_vblank und ruft anschließend vram_flush_now auf. Geeignet für einen überschaubaren Satz von Bildschirmänderungen. Einmaliges Warten begrenzt die Übertragungsmenge nicht und garantiert keinen Abschluss innerhalb eines VBlank.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

vram_clear_queue

Verwirft ausstehende VRAM-Befehle und löscht das Überlaufflag, ohne die Schreibvorgänge auszuführen.

Syntax

c
void vram_clear_queue();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
vram_clear_queue();
if (vram_get_queue_used()!=0 || vram_get_overflowed()!=0) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_clear_queue: DMG
DMG
vram_clear_queue: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:41

Deklarationshinweise im Original
Discard pending commands and clear the latched overflow flag without writing VRAM.

kitaqgb/lib/vram.c:41

c
void vram_clear_queue()
{
    kq_vram_queue_used = 0;
    kq_vram_queue_overflowed = 0;
}
vram_flush

Wartet mit __wait_vblank und ruft anschließend vram_flush_now auf. Geeignet für einen überschaubaren Satz von Bildschirmänderungen. Einmaliges Warten begrenzt die Übertragungsmenge nicht und garantiert keinen Abschluss innerhalb eines VBlank.

Syntax

c
void vram_flush();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Zieladresse in Bytes im VRAM (0x8000–0x9FFF), in der bei der Ausführung gewählten Bank. Die Übertragung ist fortlaufend, ohne Zeilenumbruch. Der gesamte Zielbereich muss gültig sein. Bei eingeschaltetem LCD können die sicheren Schreibpfade Interrupts einschalten; ein beim Aufruf gesperrter Interruptzustand bleibt nicht erhalten.

Anwendungsbeispiel

c
vram_flush(); // One small write through the VBlank/NMI path.

if (vram_get_queue_used()!=0) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_flush: DMG
DMG
vram_flush: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:64

Deklarationshinweise im Original
Wait for VBlank before executing the queue. Waiting once does not itself limit
the queued workload to the available VBlank duration.

kitaqgb/lib/vram.c:148

c
void vram_flush()
{
    __wait_vblank();
    vram_flush_now();
}
vram_flush_now

Führt alle Befehle in Einfügereihenfolge aus und setzt die belegte Anzahl auf 0. Wartet selbst nicht auf VBlank. Bei eingeschaltetem LCD warten die sicheren VRAM-Intrinsics auf beschreibbare Zeitfenster; eine große Warteschlange kann dennoch mehrere Zeilen oder Frames beanspruchen. Die Überlaufmeldung bleibt erhalten.

Syntax

c
void vram_flush_now();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Zieladresse in Bytes im VRAM (0x8000–0x9FFF), in der bei der Ausführung gewählten Bank. Die Übertragung ist fortlaufend, ohne Zeilenumbruch. Der gesamte Zielbereich muss gültig sein. Bei eingeschaltetem LCD können die sicheren Schreibpfade Interrupts einschalten; ein beim Aufruf gesperrter Interruptzustand bleibt nicht erhalten.

Anwendungsbeispiel

c
// Rendering is stopped here. On FC, commit readiness before direct execution.

vram_flush_now();
after_flush=vram_get_queue_used();
if (after_flush!=0) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_flush_now: DMG
DMG
vram_flush_now: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:61

Deklarationshinweise im Original
Execute pending commands in insertion order without waiting for VBlank here.
The caller must arrange suitable VRAM access timing and a sufficient transfer budget.
Only the used count is cleared; overflow stays latched until an explicit reset.

kitaqgb/lib/vram.c:125

c
void vram_flush_now()
{
    u8 i = 0;
    while (i < kq_vram_queue_used) {
        VramCommand* cmd = &kq_vram_queue[(__safe_index u8)i];
        if (cmd->kind == VRAM_CMD_BG_TILE) {
            __settile_xy(cmd->x, cmd->y, cmd->value);
        } else if (cmd->kind == VRAM_CMD_BG_RECT) {
            __settile_rect(cmd->x, cmd->y, cmd->w, cmd->h, cmd->value);
        } else if (cmd->kind == VRAM_CMD_BG_BLOCK) {
            __settilemap_rect(cmd->dst, cmd->x, cmd->y, cmd->w, cmd->h, cmd->src);
        } else if (cmd->kind == VRAM_CMD_MEMCPY) {
            __vram_copy(cmd->dst, cmd->src, cmd->len);
        } else if (cmd->kind == VRAM_CMD_MEMSET) {
            __vram_fill(cmd->dst, cmd->value, cmd->len);
        }
        i++;
    }
    kq_vram_queue_used = 0;
}
vram_get_overflowed

Liest das Überlaufflag, ohne es zu löschen; es kann einen früheren Fehler festhalten.

Syntax

c
u8 vram_get_overflowed();

Rückgabewert

0 ohne gespeicherten Überlauf; nach einem abgelehnten Eintrag 1 bis zum ausdrücklichen Zurücksetzen. Die Ausführung der Warteschlange löscht diese Meldung nicht.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
overflow_seen=vram_get_overflowed();
if (overflow_seen!=1) failures++;
// Reading the latch again does not clear it.
if (vram_get_overflowed()!=1) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_get_overflowed: DMG
DMG
vram_get_overflowed: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:73

Deklarationshinweise im Original
Read the overflow latch without clearing it.

kitaqgb/lib/vram.c:175

c
u8 vram_get_overflowed()
{
    return kq_vram_queue_overflowed;
}
vram_get_queue_capacity

Die lokalen Unterschiede dieser API stehen bei den Änderungen und Prüfungen vom 2026-10-03.

Gibt die Gesamtkapazität des Befehlspuffers unabhängig von seiner aktuellen Belegung zurück.

Syntax

c
u8 vram_get_queue_capacity();

Rückgabewert

Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
capacity=vram_get_queue_capacity();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_get_queue_capacity: DMG
DMG
vram_get_queue_capacity: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:69

Deklarationshinweise im Original
Return the total number of command slots, independent of queue usage.
This is command-buffer capacity, not free space in hardware VRAM.

kitaqgb/lib/vram.c:162

c
u8 vram_get_queue_capacity()
{
    return VRAM_QUEUE_MAX;
}
vram_get_queue_free

Gibt Gesamtkapazität minus aktuelle Belegung zurück. Prüfen Sie vor dem Einfügen, ob der nächste Eintrag oder ganze Stapel hineinpasst; diese Abfrage reserviert keinen Platz.

Syntax

c
u8 vram_get_queue_free();

Rückgabewert

Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
available=vram_get_queue_free();
if (used+available!=capacity) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_get_queue_free: DMG
DMG
vram_get_queue_free: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:71

Deklarationshinweise im Original
Return the remaining command-slot capacity.

kitaqgb/lib/vram.c:169

c
u8 vram_get_queue_free()
{
    return (u8)(VRAM_QUEUE_MAX - kq_vram_queue_used);
}
vram_get_queue_used

Gibt den von ausstehenden Befehlen belegten Pufferumfang zurück, nicht die Bytezahl der späteren Videodaten.

Syntax

c
u8 vram_get_queue_used();

Rückgabewert

Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
used=vram_get_queue_used();

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_get_queue_used: DMG
DMG
vram_get_queue_used: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:66

Deklarationshinweise im Original
Return the number of queued commands, not the number of transfer bytes.

kitaqgb/lib/vram.c:155

c
u8 vram_get_queue_used()
{
    return kq_vram_queue_used;
}
vram_init

Initialisiert die Warteschlange für aufgeschobene VRAM-Schreibbefehle als leer und löscht die Überlaufmeldung. Löscht weder den Bildschirm noch lädt es Tile-Grafiken oder reserviert physischen VRAM.

Syntax

c
void vram_init();

Rückgabewert

Keiner (void).

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
vram_init();
if (vram_get_queue_used()!=0 || vram_get_overflowed()!=0) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_init: DMG
DMG
vram_init: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:39

Deklarationshinweise im Original
Start with an empty command queue and a clear overflow flag.

kitaqgb/lib/vram.c:34

c
void vram_init()
{
    kq_vram_queue_used = 0;
    kq_vram_queue_overflowed = 0;
}
vram_queue_bg_block

Stellt ein Rechteck aus w × h Tile-Nummern von src für die Karte an base bereit. Quellzeilen enthalten jeweils w direkt aufeinanderfolgende Bytes; Zielzeilen haben 32 Bytes Abstand. Der Quellzeiger bleibt gespeichert, daher ändern spätere Quelldatenänderungen vor der Ausführung den sichtbaren Block.

Syntax

c
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);

Parameter

base

Kachel- und Rechteckbefehle wählen die Hintergrundkarte bei der Ausführung anhand von LCDC-Bit 3. Verwenden Sie auf dem CGB VRAM-Bank 0 für Kachelnummern. Blockübertragungen verwenden die angegebene Basisadresse, normalerweise 0x9800 oder 0x9C00. Der Zeilenabstand beträgt 32 Bytes; Koordinaten werden nicht automatisch begrenzt.

x, y

Linke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie x + w <= 32 und auf GB y + h <= 32, im Tile-Bereich einer FC-Nametable <= 30 ein. Ein einzelnes Tile hat Breite und Höhe 1.

w, h

Breite und Höhe in Tiles als vorzeichenlose Bytes. Der Quellblock enthält zeilenweise w * h Bytes. Nullabmessungen erzeugen keine sichtbaren Schreibzugriffe; der Platzbedarf folgt dennoch den Plattformregeln.

src

Nahzeiger auf lesbare Bytes, der bis zur Ausführung gespeichert bleibt. Daten und ihre Speicher- oder ROM-Bank müssen während der gesamten Verarbeitung gültig und eingeblendet bleiben; weder Banknummer noch Kopie werden gespeichert. Nichtleere Übertragungen benötigen eine gültige Quelle. Verwenden Sie kein abgelaufenes lokales Array.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Kachel- und Rechteckbefehle wählen die Hintergrundkarte bei der Ausführung anhand von LCDC-Bit 3. Verwenden Sie auf dem CGB VRAM-Bank 0 für Kachelnummern. Blockübertragungen verwenden die angegebene Basisadresse, normalerweise 0x9800 oder 0x9C00. Der Zeilenabstand beträgt 32 Bytes; Koordinaten werden nicht automatisch begrenzt.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_bg_block(MAP_BASE,10,4,3,2,block);
block[0]=1; // The queued pointer sees this change when the queue executes.
if (check_result!=1) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_bg_block: DMG
DMG
vram_queue_bg_block: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:50

Deklarationshinweise im Original
Queue a tile-map rectangle while retaining src rather than copying its bytes.
Keep the source data and its ROM bank accessible until the queue is flushed.

kitaqgb/lib/vram.c:79

c
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_BLOCK);
    if (cmd == 0) return 0;
    cmd->dst = base;
    cmd->x = x;
    cmd->y = y;
    cmd->w = w;
    cmd->h = h;
    cmd->src = src;
    return 1;
}
vram_queue_bg_rect

Stellt ein Hintergrundkartenrechteck aus derselben Tile-Nummer in die Warteschlange. Die linke obere Tile-Position ist (x, y), die Größe w × h Tiles. Ein einfarbiges Tile ergibt ein gefülltes Rechteck; ein gemustertes wiederholt sein Muster in jeder Zelle.

Syntax

c
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);

Parameter

x, y

Linke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie x + w <= 32 und auf GB y + h <= 32, im Tile-Bereich einer FC-Nametable <= 30 ein. Ein einzelnes Tile hat Breite und Höhe 1.

w, h

Breite und Höhe in Tiles als vorzeichenlose Bytes. Der Quellblock enthält zeilenweise w * h Bytes. Nullabmessungen erzeugen keine sichtbaren Schreibzugriffe; der Platzbedarf folgt dennoch den Plattformregeln.

tile

Tile-Kartenbyte von 0 bis 255. Laden Sie die Grafik separat und wählen Sie die passende Mustertabelle beziehungsweise Adressierungsart. Eine Tile-Nummer ist weder Zeiger noch Farbwert.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Kachel- und Rechteckbefehle wählen die Hintergrundkarte bei der Ausführung anhand von LCDC-Bit 3. Verwenden Sie auf dem CGB VRAM-Bank 0 für Kachelnummern. Blockübertragungen verwenden die angegebene Basisadresse, normalerweise 0x9800 oder 0x9C00. Der Zeilenabstand beträgt 32 Bytes; Koordinaten werden nicht automatisch begrenzt.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_bg_rect(2,4,4,3,1); // A filled 32x24 rectangle at (16,32).
if (check_result!=1) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_bg_rect: DMG
DMG
vram_queue_bg_rect: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:47

Deklarationshinweise im Original
Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.

kitaqgb/lib/vram.c:65

c
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_RECT);
    if (cmd == 0) return 0;
    cmd->x = x;
    cmd->y = y;
    cmd->w = w;
    cmd->h = h;
    cmd->value = tile;
    return 1;
}
vram_queue_bg_tile

Stellt einen Schreibbefehl für eine Hintergrund-Tile-Nummer an (x, y) in die Warteschlange. Sichtbar wird die Änderung bei deren Ausführung. Geschrieben wird ein Karteneintrag, weder Pixeldaten noch Palettenattribute.

Syntax

c
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);

Parameter

x, y

Linke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie x + w <= 32 und auf GB y + h <= 32, im Tile-Bereich einer FC-Nametable <= 30 ein. Ein einzelnes Tile hat Breite und Höhe 1.

tile

Tile-Kartenbyte von 0 bis 255. Laden Sie die Grafik separat und wählen Sie die passende Mustertabelle beziehungsweise Adressierungsart. Eine Tile-Nummer ist weder Zeiger noch Farbwert.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Kachel- und Rechteckbefehle wählen die Hintergrundkarte bei der Ausführung anhand von LCDC-Bit 3. Verwenden Sie auf dem CGB VRAM-Bank 0 für Kachelnummern. Blockübertragungen verwenden die angegebene Basisadresse, normalerweise 0x9800 oder 0x9C00. Der Zeilenabstand beträgt 32 Bytes; Koordinaten werden nicht automatisch begrenzt.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_bg_tile(2,2,1); // A solid 8x8 tile at pixel (16,16).
if (check_result!=1) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_bg_tile: DMG
DMG
vram_queue_bg_tile: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:43

Deklarationshinweise im Original
Queue a single background tile write; return zero if no command slot is available.

kitaqgb/lib/vram.c:48

c
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_TILE);
    if (cmd == 0) return 0;
    cmd->x = x;
    cmd->y = y;
    cmd->value = tile;
    return 1;
}
vram_queue_memcpy

Stellt eine Kopie von len aufeinanderfolgenden Bytes von src nach dst bereit. Beide Adressen steigen byteweise ohne Tile-Zeilensprung. Übertragbar sind Kartenbytes oder beschreibbare Musterdaten; Formate werden nicht umgewandelt und die Bytezahl eines Tiles wird nicht ermittelt.

Syntax

c
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);

Parameter

dst

Zieladresse in Bytes im VRAM (0x8000–0x9FFF), in der bei der Ausführung gewählten Bank. Die Übertragung ist fortlaufend, ohne Zeilenumbruch. Der gesamte Zielbereich muss gültig sein. Bei eingeschaltetem LCD können die sicheren Schreibpfade Interrupts einschalten; ein beim Aufruf gesperrter Interruptzustand bleibt nicht erhalten.

src

Nahzeiger auf lesbare Bytes, der bis zur Ausführung gespeichert bleibt. Daten und ihre Speicher- oder ROM-Bank müssen während der gesamten Verarbeitung gültig und eingeblendet bleiben; weder Banknummer noch Kopie werden gespeichert. Nichtleere Übertragungen benötigen eine gültige Quelle. Verwenden Sie kein abgelaufenes lokales Array.

len

Anzahl aufeinanderfolgender Bytes von 0 bis 65535, keine Tile-Anzahl. Der gesamte Bereich muss in gültiger Quelle und beschreibbarem Ziel liegen; die API prüft keine Grenzen und verhindert keinen 16-Bit-Adressüberlauf.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_memcpy(MAP_BASE+8*32+2,strip,3);
if (check_result!=1) failures++; // Copy three map bytes, not three tile patterns.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_memcpy: DMG
DMG
vram_queue_memcpy: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:53

Deklarationshinweise im Original
Queue a byte transfer and retain the source pointer. The source must remain
valid and visible until flush; len is measured in bytes, not tiles.

kitaqgb/lib/vram.c:94

c
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len)
{
    VramCommand* cmd = vram_push(VRAM_CMD_MEMCPY);
    if (cmd == 0) return 0;
    cmd->dst = dst;
    cmd->src = (const u8*)src;
    cmd->len = len;
    return 1;
}
vram_queue_memset

Stellt das Füllen von len aufeinanderfolgenden Bytes ab dst mit dem Byte value bereit. Wiederholt wird ein Byte, kein mehrteiliges Tile-Muster; ein Kartenzeilenabstand von 32 Bytes wird nicht eingefügt.

Syntax

c
u8 vram_queue_memset(u16 dst, u8 value, u16 len);

Parameter

dst

Zieladresse in Bytes im VRAM (0x8000–0x9FFF), in der bei der Ausführung gewählten Bank. Die Übertragung ist fortlaufend, ohne Zeilenumbruch. Der gesamte Zielbereich muss gültig sein. Bei eingeschaltetem LCD können die sicheren Schreibpfade Interrupts einschalten; ein beim Aufruf gesperrter Interruptzustand bleibt nicht erhalten.

value

Ein wiederholtes Byte von 0 bis 255. Seine sichtbare Wirkung hängt davon ab, ob das Ziel Tile-Indizes, Pixelebenen oder eine andere Bytestruktur enthält.

len

Anzahl aufeinanderfolgender Bytes von 0 bis 65535, keine Tile-Anzahl. Der gesamte Bereich muss in gültiger Quelle und beschreibbarem Ziel liegen; die API prüft keine Grenzen und verhindert keinen 16-Bit-Adressüberlauf.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_memset(MAP_BASE+8*32+10,1,5);
if (check_result!=1) failures++; // Five solid tiles form a 40x8 horizontal bar.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_memset: DMG
DMG
vram_queue_memset: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:57

Deklarationshinweise im Original
Queue a byte fill and return zero if the command queue is full.

kitaqgb/lib/vram.c:111

c
u8 vram_queue_memset(u16 dst, u8 value, u16 len)
{
    VramCommand* cmd = vram_push(VRAM_CMD_MEMSET);
    if (cmd == 0) return 0;
    cmd->dst = dst;
    cmd->value = value;
    cmd->len = len;
    return 1;
}
vram_queue_tile

vram_queue_tile ruft vram_queue_bg_tile direkt mit denselben Argumenten auf und gibt dessen Ergebnis zurück. Der Kurzname schreibt einen Hintergrundkarteneintrag; er bearbeitet keine Sprites und lädt keine Tile-Grafiken.

Syntax

c
u8 vram_queue_tile(u8 x, u8 y, u8 tile);

Parameter

x, y

Linke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie x + w <= 32 und auf GB y + h <= 32, im Tile-Bereich einer FC-Nametable <= 30 ein. Ein einzelnes Tile hat Breite und Höhe 1.

tile

Tile-Kartenbyte von 0 bis 255. Laden Sie die Grafik separat und wählen Sie die passende Mustertabelle beziehungsweise Adressierungsart. Eine Tile-Nummer ist weder Zeiger noch Farbwert.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Kachel- und Rechteckbefehle wählen die Hintergrundkarte bei der Ausführung anhand von LCDC-Bit 3. Verwenden Sie auf dem CGB VRAM-Bank 0 für Kachelnummern. Blockübertragungen verwenden die angegebene Basisadresse, normalerweise 0x9800 oder 0x9C00. Der Zeilenabstand beträgt 32 Bytes; Koordinaten werden nicht automatisch begrenzt.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_tile(4,2,1); // The short alias draws at pixel (32,16).
if (check_result!=1) failures++;

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_tile: DMG
DMG
vram_queue_tile: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:45

Deklarationshinweise im Original
Provide the short alias for a queued background tile write.

kitaqgb/lib/vram.c:59

c
u8 vram_queue_tile(u8 x, u8 y, u8 tile)
{
    return vram_queue_bg_tile(x, y, tile);
}
vram_queue_tiles

vram_queue_tiles ruft direkt vram_queue_memcpy auf. len zählt weiterhin Bytes statt Tiles. Quellzeiger, Warteschlangeneinträge, Rückgabewert und Ausführungszeitpunkt sind identisch.

Syntax

c
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);

Parameter

dst

Zieladresse in Bytes im VRAM (0x8000–0x9FFF), in der bei der Ausführung gewählten Bank. Die Übertragung ist fortlaufend, ohne Zeilenumbruch. Der gesamte Zielbereich muss gültig sein. Bei eingeschaltetem LCD können die sicheren Schreibpfade Interrupts einschalten; ein beim Aufruf gesperrter Interruptzustand bleibt nicht erhalten.

src

Nahzeiger auf lesbare Bytes, der bis zur Ausführung gespeichert bleibt. Daten und ihre Speicher- oder ROM-Bank müssen während der gesamten Verarbeitung gültig und eingeblendet bleiben; weder Banknummer noch Kopie werden gespeichert. Nichtleere Übertragungen benötigen eine gültige Quelle. Verwenden Sie kein abgelaufenes lokales Array.

len

Anzahl aufeinanderfolgender Bytes von 0 bis 65535, keine Tile-Anzahl. Der gesamte Bereich muss in gültiger Quelle und beschreibbarem Ziel liegen; die API prüft keine Grenzen und verhindert keinen 16-Bit-Adressüberlauf.

Rückgabewert

1, wenn dieser Befehl eingereiht wurde, oder 0 bei fehlendem Platz. Ein Fehler setzt die Überlaufmeldung und erhält vorhandene Befehle. Ein früherer Überlauf lässt einen später erfolgreichen Eintrag nicht automatisch 0 zurückgeben.

Bedingungen und Grenzen

GB zählt Befehlsplätze; die Standardkapazität beträgt 32. Jeder Einfügeaufruf belegt einen Platz, auch bei großen Übertragungen oder Länge null. Setzen Sie VRAM_QUEUE_MAX in allen Übersetzungseinheiten einheitlich auf 1 bis 255. Eine leere Warteschlange hat used=0 und free=capacity.

Koordinieren Sie Aufbau und Verarbeitung der Warteschlange. Fügen Sie während ihrer Interrupt-Ausführung nichts hinzu, ändern Sie die Verwaltung nicht direkt und überschreiben Sie gespeicherte Quelldaten nicht versehentlich. Diese APIs bieten weder Sperren noch Doppelpufferung. Die Kapazität betrifft den Befehlspuffer, nicht freie Bytes im Hardware-VRAM.

Anwendungsbeispiel

c
check_result=vram_queue_tiles(MAP_BASE+8*32+6,strip+1,2);
if (check_result!=1) failures++; // This alias also measures length in bytes.

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Das vollständige Programm zeigt aufgeschobene Schreibzugriffe, Kapazitätsverwaltung und die Behandlung eines Überlaufs. Sieben Zeichenaufrufe belegen auf dem GB 7 von 32 Plätzen, auf dem FC 52 von 128 Bytes: CAPACITY/USED/FREE zeigt 032/007/025 oder 128/052/076. AFTER FLUSH und FAILED CHECKS müssen 000 anzeigen, OVERFLOW SEEN dagegen 001. Ein absichtlicher Einfügeversuch in die volle Warteschlange prüft die Meldung: Lesen und Ausführen löschen sie nicht, das Leeren der Warteschlange schon. Auf dem FC muss eine direkte Ausführung ohne Freigabe die Warteschlange unverändert lassen.

Bildkoordinaten sind Pixelangaben ab der linken oberen Ecke. Erwartet werden ausgefüllte Quadrate von 8 × 8 bei (16,16) und (32,16), ein ausgefülltes Rechteck von 32 × 24 bei (16,32) sowie ein waagerechter Balken von 40 × 8 bei (80,64). Der letzte VBlank-Schreibzugriff ergänzt ein Quadrat von 8 × 8 bei (144,80). Die verworfene Schreibposition (144,24) muss leer bleiben. DMG zeigt schwarze Formen auf Weiß, CGB rote, blaue und grüne Formen auf Weiß und FC rote, blaue und grüne Formen auf Schwarz. Diese Emulatorbilder sind keine Prüfung auf echter Hardware.

Drei eigene Muster von 8 × 8 unterscheiden die Kopiervorgänge: Kachel 1 ist ausgefüllt, Kachel 2 füllt die vier linken Spalten, Kachel 3 bildet ein linksbündiges Dreieck mit einem Pixel Breite oben und acht unten. Der Block aus 3 × 2 Kacheln bei (80,32) muss [1,2,3] / [3,0,2] zeigen; 0 ist leer. Sein erstes Quellbyte ändert sich nach dem Einreihen. Die ausgefüllte Kachel oben links belegt deshalb, dass der Quellzeiger erhalten bleibt. Die Kopie bei (16,64) zeigt [1,2,3], der Alias tiles bei (48,64) zeigt [2,3]. Die Größen betragen entsprechend 24 × 16, 24 × 8 und 16 × 8 Pixel.

Im CGB-Modus sind die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat rot. Das Rechteck von 32 × 24 und die Kopie aus zwei Mustern sind blau. Der Block aus 3 × 2 Kacheln und der Balken von 40 × 8 sind grün. Text bleibt schwarz auf Weiß. Neben der Geometrie wird die Farbe jedes gezeichneten Pixels geprüft.

vram_queue_tiles: DMG
DMG
vram_queue_tiles: CGB
CGB

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/vram.h:55

Deklarationshinweise im Original
Alias the queued byte-copy operation; this does not convert a tile count to bytes.

kitaqgb/lib/vram.c:105

c
u8 vram_queue_tiles(u16 dst, const void* src, u16 len)
{
    return vram_queue_memcpy(dst, src, len);
}

wire3d.h — Drahtgitterdarstellung für DMG

Monochromes 3D-Linienzeichnen. Übergeben Sie Modelleckpunkte, Kanten und Flächen sowie Objektposition, Rotation und Skalierung. Verwenden Sie Initialisierung, Frame-Beginn, Zeichnen und Übertragung in dieser Reihenfolge. Physik ist getrennt. Winkel haben sechzehn Schritte pro Umdrehung; Modellskalierung 256 bedeutet Originalgröße.

Vec3 enthält x/y/z, Edge die Eckpunktindizes a/b und Face die Dreiecksindizes a/b/c. vertices, edges und faces in Model zeigen auf diese Arrays; die jeweilige Anzahl gibt ihre Länge an. edge_faces enthält die Nachbarflächenindizes f0/f1, bei fehlender Fläche FACE_NONE. MODEL_HIDDEN_LINES in flags fordert flächenbasierte Kantenauswahl an. Die vorzeichenbehaftete projizierte Fläche bestimmt die Ausrichtung; die Eckpunktreihenfolge ist daher wichtig.

Object speichert Modellreferenz, Position x/y/z, Winkel rx/ry/rz, scale_q8 und visible. Objekte können ein Modell teilen; Zeichnen kopiert aber keine Tabellen und schaltet deren ROM-Bänke nicht automatisch um. Referenzierte Daten müssen während des gesamten Zeichnens lesbar bleiben. CGB-Object besitzt zusätzlich einen Farbindex.

Model für Höhe 96 enthält außerdem edge_masks und edge_mask_count. Übergeben Sie eine RAM-Tabelle mit 16-Bit-Kantenmasken, die nach Objekt-Gierwinkel gewählt werden, oder setzen Sie beide Felder bei Nichtgebrauch auf null.

Wire3D_BeginFrame

Beginnt das Zeichnen eines Frames und deaktiviert die Verdeckungsprüfung.

Syntax

c
void Wire3D_BeginFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Löscht vorbereitete Pixel und Verdeckungsmaske und deaktiviert die Verdeckungsfilterung. Angezeigter VRAM-Frame und ausstehende BG-Tile-Warteschlange bleiben unverändert.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_BeginFrame: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_BeginFrame: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:34

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Clear staged pixels and occlusion mask and disable occlusion filtering.
This leaves the displayed VRAM frame and pending BG tile queue unchanged.

kitaqgb/lib/wire3d_dmg.c:2641

c
void Wire3DDMG_BeginFrame()
{

    w3ddmg_clear_stage_asm();
    w3ddmg_clear_occlusion_mask();




    w3ddmg_occlusion_active = 0;
}
Wire3D_DrawLine2D

Zeichnet eine vierfach zusammenhängende Bildschirmlinie einschließlich Endpunkten in den Staging-Bereich.

Syntax

c
void Wire3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Zeichnet eine zusammenhängende Linie einschließlich Endpunkten in den 128×96-Staging-Bereich. Während DrawScene wird die grobe Verdeckungsverwerfung mit fünf Abtastpunkten verwendet, sonst direkt gezeichnet. Verwenden Sie Viewport-Koordinaten. Nur EndFrame aktualisiert VRAM.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_DrawLine2D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_DrawLine2D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:35

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Draw a connected line into the 128x96 stage, including endpoints. During
DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly.
Supply viewport coordinates. VRAM is updated only by EndFrame.

kitaqgb/lib/wire3d_dmg.c:2685

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{




    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
Wire3D_DrawLine3D

Projiziert zwei Weltendpunkte und zeichnet eine Linie dazwischen.

Syntax

c
void Wire3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parameter

ax

X-Komponente des Startpunkts in Weltkoordinaten.

ay

Y-Komponente des Startpunkts in Weltkoordinaten.

az

Z-Komponente des Startpunkts in Weltkoordinaten.

bx

X-Komponente des Endpunkts in Weltkoordinaten.

by

Y-Komponente des Endpunkts in Weltkoordinaten.

bz

Z-Komponente des Endpunkts in Weltkoordinaten.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Projiziert beide Weltendpunkte und zeichnet nur, wenn beide den Tiefenbereich bestehen. Bildet keine Schnittpunkte eines kreuzenden Segments mit Nah- oder Fernebene; projizierte Endpunkte werden einzeln auf die Bildschirmränder begrenzt.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_DrawLine3D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_DrawLine3D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:36

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:2808

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3D_DrawModel

Zeichnet ein Eckpunkt-Kanten-Modell an der gewünschten Position und mit der gewünschten Rotation in Originalgröße.

Syntax

c
void Wire3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Zeichnet ein unskaliertes Modell, indem DrawModelScaled mit Skalierung 256 aufgerufen wird.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Wire3D_DrawModel: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
Wire3D_DrawModel: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:37

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:2825

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)



{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3D_DrawModelScaled

Skaliert ein Modell, dreht es in Y/X/Z-Reihenfolge, verschiebt und projiziert seine Eckpunkte und zeichnet die Kanten.

Syntax

c
void Wire3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Skaliert bis zu 24 Eckpunkte, dreht sie in Y/X/Z-Reihenfolge, verschiebt und projiziert sie; zeichnet danach bis zu 16 Kanten, gefiltert durch Giermasken und optional nach vorn gerichtete Flächen. Nichtpositive Skalierung wird zur Einheit (256). Nullzeiger für Modell, Eckpunkte oder Kanten werden ignoriert; referenzierte Tabellen müssen lesbar bleiben. Skalierungsprodukte und Verschiebungen müssen in den vorzeichenbehafteten 16-Bit-Bereich passen. Kanten über Tiefengrenzen werden verworfen, nicht zugeschnitten.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Wire3D_DrawModelScaled: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
Wire3D_DrawModelScaled: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:38

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Scale, rotate in Y/X/Z order, translate and project at most 24 vertices;
then draw up to 16 edges filtered by yaw masks and optional front-facing faces.
Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are
ignored; referenced tables must remain readable. Keep scale products and
translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.

kitaqgb/lib/wire3d_dmg.c:2965

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)








{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;

    if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
    w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);

    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&

                w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])



            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3D_DrawScene

Zeichnet bis zu acht Objekte von nah nach fern; nähere Flächen verdecken spätere Kanten.

Syntax

c
void Wire3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parameter

objects

Objektarray mit Positionen, Rotationen, Skalierungen und Sichtbarkeitsflags.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Verarbeitet höchstens die ersten acht Objekte, nach transformierter Ursprungstiefe von nah nach fern sortiert. Zeichnet sichtbare gültige Modelle und markiert anschließend die Begrenzungsrechtecke ihrer Vorderseiten, um spätere Linien zu verwerfen, deren sämtliche Abtastpunkte verdeckt sind. Dies nähert Verdeckung zwischen Objekten an und ist kein Tiefenpuffer. Löscht die eigene Maske, erhält aber vorhandene Staging-Pixel. Nullarrays werden ignoriert; Objekte und Daten müssen lesbar bleiben.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Wire3D_DrawScene: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
Wire3D_DrawScene: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:39

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Process at most the first eight objects, sorted near to far by transformed
origin depth. Draw visible valid models, then mark their front-face bounding
rectangles to reject fully sampled later lines. This approximates inter-object
occlusion, not a depth buffer. It clears its mask but retains existing staged
pixels. Null arrays are ignored; objects and their data must remain readable.

kitaqgb/lib/wire3d_dmg.c:2723

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;




    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];


            // Put the nearer origin first so its face bounds can suppress later lines.
            // The array itself stays in caller order; only the scratch index list is sorted.

            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();

    w3ddmg_occlusion_active = 1;




    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {

            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3ddmg_i8)obj->rx, (w3ddmg_i8)obj->ry, (w3ddmg_i8)obj->rz, obj->scale_q8);
            w3ddmg_mark_model_occluder(obj->model);








        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
Wire3D_EndFrame

Übergibt ausstehende Hintergrund-Schreibzugriffe und vorbereitete Zeichnungen an VRAM.

Syntax

c
void Wire3D_EndFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Wartet auf den nächsten VBlank, führt ausstehende BG-Kartenschreibzugriffe aus und kopiert Staging unter Abfrage der Zugriffsfenster ins VRAM. Das Kopieren verbraucht die vorbereiteten Pixel. Die Übertragung kann über VBlank hinausgehen; dies ist kein atomarer Frame-Wechsel.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_EndFrame: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_EndFrame: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:42

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Wait for the next VBlank, flush pending BG map writes, then copy the stage
to VRAM while polling access windows. Copying consumes the staged pixels.
The transfer may extend beyond VBlank; this is not an atomic frame swap.

kitaqgb/lib/wire3d_dmg.c:3081

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    w3ddmg_flush_bg_queue();

    w3ddmg_transfer_stage_asm();














}
Wire3D_EraseModelFaces

Projiziert nach vorn gerichtete Modelldreiecke und löscht vorbereitete Pixel in ihrem Inneren.

Syntax

c
void Wire3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Projiziert bis zu 24 Eckpunkte und löscht das Innere nach vorn gerichteter Dreiecke aus dem Staging-Bereich für ein Modell mit Verdeckungsflags und Flächendaten. Nichtpositive Skalierung bedeutet 256, also Originalgröße. Bis zu 16 Flächen werden betrachtet; Flächen über Tiefengrenzen werden übersprungen. Ersetzt auch gemeinsame Projektionscaches, aktualisiert aber kein VRAM.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
    for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
    Wire3D_EraseTriangle2D(12,12,28,12,12,28);
    Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Wire3D_EraseModelFaces: DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
Wire3D_EraseModelFaces: CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:43

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:2841

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)



{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3D_EraseSpan2D

Löscht einen waagerechten Span einschließlich Endpunkten in einer vorbereiteten Zeile.

Syntax

c
void Wire3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parameter

y

Pixel-Y-Koordinate der zu löschenden Zeile.

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Ordnet die X-Endpunkte und löscht den vorbereiteten Span einschließlich Endpunkten. Beide müssen in 0..127 liegen; ungültiges Y wird ignoriert. Die Routine begrenzt X nicht automatisch.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_EraseSpan2D: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_EraseSpan2D: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:44

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:2943

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
Wire3D_EraseTriangle2D

Löscht ein Bildschirmdreieck über waagerechte Rasterzeilen-Spans aus dem Staging-Bereich.

Syntax

c
void Wire3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

cx

X-Koordinate von Eckpunkt C in Viewport-Pixeln.

cy

Y-Koordinate von Eckpunkt C in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Löscht ein Dreieck aus vorbereiteten Pixeln über ganzzahlige Rasterzeilenschnittpunkte. Geben Sie Viewport-Koordinaten an. Entartete Dreiecke werden ignoriert; Verdeckungsmaske und VRAM bleiben unverändert.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
    for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
    Wire3D_EraseTriangle2D(12,12,28,12,12,28);
    Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Wire3D_EraseTriangle2D: DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
DMG — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
Wire3D_EraseTriangle2D: CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.
CGB — Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:45

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:2933

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3D_Init

Initialisiert LCD, Tiles und Hintergrundkarte für einen monochromen Drahtgitter-Viewport.

Syntax

c
void Wire3D_Init();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Übernimmt das LCD: Wartet auf VBlank, schaltet es aus, löscht 6144 Tile-Bytes und die BG-Karte, richtet HUD-Tiles und den 128×96-Viewport mit vorzeichenbehafteten Tile-Nummern ein und aktiviert BG mit Scrollwerten null und BGP=0xB4. Setzt Kamera, BG-Warteschlange und Staging-Bereich zurück. Reservieren Sie 0xD000..0xDFFF für Staging und erhalten Sie dessen WRAM-Bankeinblendung. Rufen Sie vor dem Zeichnen BeginFrame auf, um auch den Verdeckungszustand zu initialisieren.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_Init: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_Init: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:47

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and
the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable
BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage.
Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping.
Call BeginFrame before drawing to initialize the occlusion state as well.

kitaqgb/lib/wire3d_dmg.c:2572

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();

    w3ddmg_load_hud_tiles();

    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {

        off = (w3ddmg_u16)((w3ddmg_u16)row << 5);



        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }


    w3ddmg_reg_scx = 0;



    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;





    Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
    w3ddmg_clear_stage_asm();




}
Wire3D_ProjectPoint

Projiziert einen Weltpunkt durch die Kamera in Viewport-Koordinaten.

Syntax

c
w3ddmg_u8 Wire3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parameter

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

sx

Gültiger beschreibbarer u8-Zeiger für die projizierte X-Koordinate.

sy

Gültiger beschreibbarer u8-Zeiger für die projizierte Y-Koordinate.

Rückgabewert

Liefert 1 bei erfolgreicher Projektion oder 0 bei verworfener Tiefe.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Projiziert einen Weltpunkt mit der aktuellen Kamera. Verworfene Tiefe liefert null und lässt die Ausgabe unverändert; bei Erfolg werden auf 128×96 begrenzte Koordinaten geschrieben. Ausgabezeiger müssen gültig sein. Bildschirmbegrenzung ist kein geometrisches Clipping.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_ProjectPoint: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_ProjectPoint: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:50

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Project a world point with the current camera. Return zero for rejected
depth, leaving outputs unchanged; success writes clamped 128x96 coordinates.
Output pointers must be valid. Screen clamping is not geometric clipping.

kitaqgb/lib/wire3d_dmg.c:549

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
Wire3D_PutBgTile

Reiht einen Tile-Nummer-Schreibzugriff für eine Hintergrundkartenzelle ein.

Syntax

c
void Wire3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parameter

x

X-Tile-Koordinate in der 32×32-Hintergrundkarte.

y

Y-Tile-Koordinate in der 32×32-Hintergrundkarte.

tile

Acht-Bit-Tile-Nummer für die Hintergrundzelle.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Reiht einen Tile-Schreibzugriff auf die 32×32-Karte bei 0x9800 für EndFrame ein. Ungültige Kartenkoordinaten und Anfragen über 48 ausstehende Schreibzugriffe hinaus werden ohne Meldung ignoriert. Diese Warteschlange ist von der allgemeinen vram-Bibliothekswarteschlange getrennt.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_PutBgTile: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_PutBgTile: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:51

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:582

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
Wire3D_SelectEdgeMask

Wählt eine vorberechnete Kantensichtbarkeitsmaske für den Gierwinkel des Objekts.

Syntax

c
w3ddmg_u16 Wire3D_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

16-Bit-Kantensichtbarkeitsmaske oder 0xFFFF, wenn keine Tabelle übergeben wurde.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Wählt eine vorberechnete Maske aus den unteren vier Bits des Objekt-Gierwinkels; Nicken, Rollen und Kameraausrichtung werden ignoriert. Verwenden Sie 16, 8, 4 oder 2 Bereiche; andere positive Anzahlen wählen Eintrag null, wobei Anzahlen >=16 die ersten 16 verwenden. Fehlende Daten liefern 0xFFFF. Die Maskentabelle muss über die aktuelle Datenzeigereinblendung lesbar bleiben.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Wire3D_SelectEdgeMask: DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
DMG — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
Wire3D_SelectEdgeMask: CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.
CGB — Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:52

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Select a precomputed mask from the low four bits of object yaw; pitch,
roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
counts select entry zero (counts >=16 use the first 16). Missing data returns
0xFFFF. Keep the mask table readable through the current data-pointer mapping.

kitaqgb/lib/wire3d_dmg.c:1109

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
    w3ddmg_u8 count;
    w3ddmg_u8 bin;

    if (model == 0) return 0xFFFF;
    if (model->edge_masks == 0) return 0xFFFF;
    count = model->edge_mask_count;
    if (count == 0) return 0xFFFF;

    (void)rx;
    (void)rz;

    bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
    if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
    if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
    else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
    else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
    else bin = 0;

    if (bin >= count) bin = (w3ddmg_u8)(count - 1);
    return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}
Wire3D_SetCamera

Speichert Kameraposition und -ausrichtung für spätere Projektionen.

Syntax

c
void Wire3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);

Parameter

x

X-Komponente der Kamera in Weltkoordinaten.

y

Y-Komponente der Kamera in Weltkoordinaten.

z

Z-Komponente der Kamera in Weltkoordinaten.

pitch

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

yaw

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

roll

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Speichert Kameraposition und -winkel für späteres Zeichnen; 16 Winkelschritte ergeben eine Umdrehung. Vorhandene Zeichnungen werden nicht neu projiziert und Eingabebereiche nicht geprüft.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_SetCamera: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_SetCamera: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:53

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:2659

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)



{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
Wire3D_SetPalette

Schreibt die Zuordnung der vier Helligkeitsstufen ins monochrome Hintergrund-Palettenregister BGP.

Syntax

c
void Wire3D_SetPalette(w3ddmg_u8 bgp);

Parameter

bgp

BGP-Registerwert mit vier Zwei-Bit-Helligkeitszuordnungen.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96. Schreibt die rohe DMG-BGP-Palettencodierung sofort, ohne Frame-Synchronisierung.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Wire3D_SetPalette: DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
DMG — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
Wire3D_SetPalette: CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.
CGB — Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d.h:54

Deklarationshinweise im Original
WIRE3D_DMG_HEIGHT = 96.
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:597

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}

wire3d_cgb.h — Farbige Drahtgitterdarstellung für CGB

Verwendung der schnellen Renderingpfade

Der normale 128×96-Renderer schreibt Zeichenadressen schrittweise fort. Für unverdeckte Linien wählt er die Farbebene einmal pro Linie und hält Pixelzahl und Fehlerwert in CPU-Registern. Auch verdeckte Linien wählen die Farbebenen nur einmal pro Linie; Zeichen- und Maskenadressen werden gemeinsam schrittweise fortgeschrieben. Jedes Pixel prüft sein Maskenbit und wird nur geschrieben, wenn es nicht verdeckt ist. Der 160×144-Renderer und FastMap besitzen eigene Pfade. Drehungen um 0, 90, 180 und 270 Grad begrenzen zuerst die Eingaben und verwenden anschließend Koordinatentausch und Vorzeichenwechsel. Die Gesamtleistung hängt auch von Eckpunktzahl, Kantenlänge, Verdeckung und VRAM-Übertragungen ab. Messen Sie einzelne Operationen getrennt von der Zeit bis zum fertigen angezeigten Bild.

Farbige Drahtgitter für CGB. Der 128×96-Pixelrenderer, der 160×144-Tile-Allokator und FastMap mit Umriss-Tiles verwenden unterschiedliche Initialisierungs- und Übertragungsabläufe. Modelleckpunkte, Kanten und Dreiecksflächen gehören dem Aufrufer. Dieses Modul simuliert keine Physik.

Vec3 enthält x/y/z, Edge die Eckpunktindizes a/b und Face die Dreiecksindizes a/b/c. vertices, edges und faces in Model zeigen auf diese Arrays; die jeweilige Anzahl gibt ihre Länge an. edge_faces enthält die Nachbarflächenindizes f0/f1, bei fehlender Fläche FACE_NONE. MODEL_HIDDEN_LINES in flags fordert flächenbasierte Kantenauswahl an. Die vorzeichenbehaftete projizierte Fläche bestimmt die Ausrichtung; die Eckpunktreihenfolge ist daher wichtig.

Object speichert Modellreferenz, Position x/y/z, Winkel rx/ry/rz, scale_q8 und visible. Objekte können ein Modell teilen; Zeichnen kopiert aber keine Tabellen und schaltet deren ROM-Bänke nicht automatisch um. Referenzierte Daten müssen während des gesamten Zeichnens lesbar bleiben. CGB-Object besitzt zusätzlich einen Farbindex.

FastCube-x/y sind Versätze zur Bildschirmmitte; z wählt Größe oder Zeichenreihenfolge. FastCubes ignoriert Winkel, während FastCubeFrame mit rx/ry/rz vier Stempelvarianten wählt. Diese vereinfachten Anzeigen dienen anderen Zwecken als das kameraprojizierte DrawModel.

Wire3DCGB_BeginFrame

Beginnt einen neuen leeren Frame im gewählten Rendermodus.

Syntax

c
void Wire3DCGB_BeginFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wählt im normalen Modus die vollständige Staging-Übertragung, löscht alle vorbereiteten Pixel und die Bitmap-Maske, setzt Maskengrenzen zurück und deaktiviert Verdeckung. Im Vollbildmodus werden stattdessen dessen Allokator und Spans zurückgesetzt. Ausstehende BG-Schreibzugriffe bleiben in der Warteschlange. Erfordert einen Build mit vollständiger Laufzeitumgebung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:122

kitaqgb/lib/wire3d_cgb.c:8154

c
void Wire3DCGB_BeginFrame()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 1;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_occlusion_mask_asm();
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_BeginFrameFast

Beginnt einen gelöschten Frame und macht die bisherigen partiellen Bereiche ungültig, indem sie auf den gesamten Viewport erweitert werden.

Syntax

c
void Wire3DCGB_BeginFrameFast();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Führt denselben Frame-Reset für normalen oder Vollbildmodus wie BeginFrame aus, markiert aber zuerst beide bisherigen partiellen Verlaufsbereiche als den gesamten Viewport mit 192 Tiles. So verlässt sich eine spätere partielle Übertragung nicht auf veraltete Bankinhalte.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:123

kitaqgb/lib/wire3d_cgb.c:8175

c
void Wire3DCGB_BeginFrameFast()
{
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 1;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_occlusion_mask_asm();
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_BeginFrameSparse

Beginnt einen Frame für partielle Bereichsübertragung.

Syntax

c
void Wire3DCGB_BeginFrameSparse();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wählt partielle Übertragung und löscht den gesamten 128×96-Staging-Bereich, damit beim Vergrößern des Änderungsbereichs keine alten Pixel erscheinen. Setzt Maskengrenzen zurück und deaktiviert Verdeckung; PAINTER_ONLY-Builds überspringen das Löschen der ungenutzten Bitmap-Maske. Der Vollbildmodus verwendet stattdessen den Reset seines eigenen Allokators.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:124

kitaqgb/lib/wire3d_cgb.c:8200

c
void Wire3DCGB_BeginFrameSparse()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 0;
    w3dcgb_dirty_count = 0;
    /* One ASM pass is faster than repeated range-growth clears and guarantees
       that newly exposed dirty tiles can never copy stale stage pixels. */
    w3dcgb_clear_stage_asm();
#ifndef WIRE3DCGB_PAINTER_ONLY
    /* A Z-sorted painter erases silhouettes directly in the stage and never
       reads the separate front-to-back coverage mask. */
    w3dcgb_clear_occlusion_mask_asm();
#endif
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_ClearFrameTiles

Löscht die angezeigten 128×96-Frame-Tiles und den Staging-Bereich.

Syntax

c
void Wire3DCGB_ClearFrameTiles();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wartet beim 128×96-Renderer auf VBlank, deaktiviert das LCD, löscht den Staging-Bereich und die Frame-Tile-Bereiche beider Bänke, setzt Kartenattribute zurück und aktiviert anschließend LCDC 0x81. Löscht Änderungsflags und -zähler, aber nicht den Min/Max-Verlauf partieller Übertragungen. Setzt full_mode nicht zurück und initialisiert den Vollbildmodus nicht neu.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:121

kitaqgb/lib/wire3d_cgb.c:8240

c
void Wire3DCGB_ClearFrameTiles()
{
    w3dcgb_u8 i;

    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_frame_tiles_vram_asm();
    w3dcgb_fill_attr_map_asm();
    w3dcgb_reg_lcdc = 0x81;

    i = 0;
    while (i < W3DCGB_DIRTY_TILE_LIMIT)
    {
        w3dcgb_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
        w3dcgb_prev_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
}
Wire3DCGB_ClearOcclusionMask

Löscht die Verdeckungsbitmap oder den Vollbild-Span-Verlauf.

Syntax

c
void Wire3DCGB_ClearOcclusionMask();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Löscht bei gesetztem full_mode den Vollbild-Span-Verlauf, andernfalls die 128×96-Bitmap-Maske samt Grenzen. Löscht keine angezeigten oder vorbereiteten Pixel und ändert nicht, ob die Verdeckungsprüfung aktiviert ist.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein Dreieck verdeckt die Mitte roter Rasterzeilen; eine gepackte Silhouette verdeckt blaue Linien. Grüne Umrisse zeigen die Lage des verdeckenden Bereichs.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:148

kitaqgb/lib/wire3d_cgb.c:1962

c
void Wire3DCGB_ClearOcclusionMask()
{
    if (w3dcgb_full_mode != 0) w3dcgb_full_clear_spans_asm();
    else w3dcgb_clear_occlusion_mask();
}
Wire3DCGB_ClearSparseStageFast

Löscht den gesamten Staging-Bereich und markiert den vollständigen 128×96-Viewport zur Übertragung.

Syntax

c
void Wire3DCGB_ClearSparseStageFast();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Löscht den gesamten Staging-Bereich in Bank 2 und markiert den vollständigen 128×96-Viewport als geändert. Trotz des Namens ist dies kein partielles Löschen und erhält keine vorbereiteten Pixel. Weder der Verdeckungszustand noch der Übertragungsmodus wird dabei zurückgesetzt beziehungsweise gewählt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:125

kitaqgb/lib/wire3d_cgb.c:8227

c
void Wire3DCGB_ClearSparseStageFast()
{
    w3dcgb_clear_stage_asm();
    w3dcgb_mark_dirty_rect(0, 0,
                           (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1),
                           (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
}
Wire3DCGB_DrawEdgeList2D

Zeichnet bis zu 64 Kanten aus vorprojizierten vorzeichenbehafteten Byte-Eckpunktversätzen.

Syntax

c
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);

Parameter

edges

Eckpunktindizes je Kante im deklarierten Struct- oder Bytepaar-Format.

edge_count

Anzahl der Kanten.

vertex_x

Array vorprojizierter X-Eckpunktversätze.

vertex_y

Array vorprojizierter Y-Eckpunktversätze.

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet bis zu 64 indizierte Kanten aus vorzeichenbehafteten Byte-Versätzen um (cx,cy). Nullarrays werden ignoriert; Indizes müssen lesbare Eckpunkte adressieren. Halten Sie verschobene Endpunkte vor der umbrechenden Byte-Umwandlung im Viewport. Wählt den Pfad nach Modus und erhält die vorige Farbe; eine Prüfung der Eckpunktanzahl findet nicht statt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:183

kitaqgb/lib/wire3d_cgb.c:8524

c
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
                             const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                             w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 old_color;

    if (edges == 0) return;
    if (vertex_x == 0) return;
    if (vertex_y == 0) return;
    if (edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT) edge_count = WIRE3DCGB_MODEL_EDGE_LIMIT;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    if (w3dcgb_full_mode == 0)
    {
        w3dcgb_edge_list_ptr = edges;
        w3dcgb_edge_x_ptr = vertex_x;
        w3dcgb_edge_y_ptr = vertex_y;
        w3dcgb_edge_remaining = edge_count;
        w3dcgb_edge_center_x = x;
        w3dcgb_edge_center_y = y;
        w3dcgb_edge_list_asm();
        w3dcgb_line_color = old_color;
        return;
    }
    i = 0;
    while (i < edge_count)
    {
        a = edges[(__safe_index w3dcgb_u8)i].a;
        b = edges[(__safe_index w3dcgb_u8)i].b;
        w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
        w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
        w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
        w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
        if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
        else w3dcgb_line_stage_asm();
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawEdgeListClipped2D

Prüft vorzeichenbehaftete projizierte Eckpunkte und Kanten, begrenzt danach die Kantenliste und zeichnet sie.

Syntax

c
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count, w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);

Parameter

edges

Eckpunktindizes je Kante im deklarierten Struct- oder Bytepaar-Format.

edge_count

Anzahl der Kanten.

vx

Array vorzeichenbehafteter 16-Bit-X-Versätze vor dem Clipping.

vy

Array vorzeichenbehafteter 16-Bit-Y-Versätze vor dem Clipping.

vertex_count

Anzahl der Einträge im Eckpunktarray.

cx

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

cy

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Prüft vor dem Zeichnen Zeiger, 1..24 Eckpunkte, höchstens 64 Kanten, jeden Index sowie Eingabekoordinaten und Mittelpunkte im Bereich ±2047. Vollständig sichtbare Geometrie verwendet einen temporären Puffer mit vorzeichenbehafteten Bytes und den schnellen indizierten Pfad; andere Kanten nutzen den Clipper für vorzeichenbehaftete Linien. Dieser kann verschobene Endpunkte außerhalb von ±2047 verwerfen, auch wenn jede einzelne Eingabe gültig war. Ersetzt den gemeinsamen Bildschirm-Arbeitspuffer und erhält die vorherige Farbe über die aufgerufenen Linien-APIs.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:138

kitaqgb/lib/wire3d_cgb.c:9806

c
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
    const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
    w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 inside;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 min_x;
    w3dcgb_i16 min_y;
    w3dcgb_i16 max_x;
    w3dcgb_i16 max_y;
    if ((edges == 0) || (vx == 0) || (vy == 0)) return;
    if ((cx < -2047) || (cx > 2047) || (cy < -2047) || (cy > 2047)) return;
    if ((vertex_count == 0) || (vertex_count > WIRE3DCGB_MODEL_VERTEX_LIMIT) ||
        (edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT)) return;
    i = 0;
    while (i < edge_count)
    {
        if ((edges[(__safe_index w3dcgb_u8)i].a >= vertex_count) ||
            (edges[(__safe_index w3dcgb_u8)i].b >= vertex_count)) return;
        i = (w3dcgb_u8)(i + 1);
    }
    min_x = 32767;
    min_y = 32767;
    max_x = -32767;
    max_y = -32767;
    inside = 1;
    i = 0;
    while (i < vertex_count)
    {
        if ((vx[(__safe_index w3dcgb_u8)i] < -2047) ||
            (vx[(__safe_index w3dcgb_u8)i] > 2047) ||
            (vy[(__safe_index w3dcgb_u8)i] < -2047) ||
            (vy[(__safe_index w3dcgb_u8)i] > 2047)) return;
        x = (w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)i]);
        y = (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)i]);
        if (x < min_x) min_x = x;
        if (x > max_x) max_x = x;
        if (y < min_y) min_y = y;
        if (y > max_y) max_y = y;
        /* Reuse projected-vertex scratch; drawing is non-reentrant. */
        w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(x - 64);
        w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(y - 48);
        i = (w3dcgb_u8)(i + 1);
    }
    if ((w3dcgb_clip_outcode(min_x, min_y) | w3dcgb_clip_outcode(max_x, max_y)) != 0) inside = 0;
    if (inside != 0)
    {
        if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_rect((w3dcgb_u8)min_x,
            (w3dcgb_u8)min_y, (w3dcgb_u8)max_x, (w3dcgb_u8)max_y);
        Wire3DCGB_DrawEdgeList2D(edges, edge_count, (const w3dcgb_i8*)w3dcgb_screen_x,
            (const w3dcgb_i8*)w3dcgb_screen_y, 64, 48, color);
        return;
    }
    i = 0;
    while (i < edge_count)
    {
        a = edges[(__safe_index w3dcgb_u8)i].a;
        b = edges[(__safe_index w3dcgb_u8)i].b;
        Wire3DCGB_DrawLineClipped2D((w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)a]),
            (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)a]),
            (w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)b]),
            (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)b]), color);
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_DrawFastCubeFrame

Ersetzt den vorherigen Würfelstempel-Frame und überträgt bis zu drei Stempel samt Statusanzeigen.

Syntax

c
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parameter

cubes

Array mit Positionen, Winkeln und Farben für schnelles Würfelzeichnen.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

hidden_enabled

Null schließt verdeckte Kanten ein; ein Wert ungleich null wählt vereinfachtes Entfernen verdeckter Kanten.

selected

Index des ausgewählten Objekts im ursprünglichen Array; die Stempel-API verwendet ihn für eine Statusanzeige.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Bereitet die Karte vor, löscht vorherige Bereiche und Statuszellen, sortiert bis zu drei Würfelstempel nach unverändertem Z von fern nach nah und zeichnet und überträgt Nummern und Attribute im VBlank. Das Aufruferarray wird nicht umgeordnet. Ein Zeiger ungleich null mit count=0 löscht alte Stempel; ein Nullzeiger bewirkt gar nichts. selected & 3 wählt nur die Statuszelle, keine Würfelhervorhebung. Benötigt geladene Würfelstempel, die vollständige Laufzeitumgebung und konsistente FastMap-WRAM-Einblendung; diese werden nicht initialisiert.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// A complete cube-stamp frame removes the preceding stamp's old map cells.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cube[1];
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors();
    cube[0].x=-24;cube[0].y=0;cube[0].z=96;
    cube[0].rx=0;cube[0].ry=0;cube[0].rz=0;cube[0].color=1;
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
    cube[0].x=24;
    Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
    sample_svbk=bank;result[0]=cube[0].x;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Der alte Würfelstempel verschwindet. Ein roter 32×32-Würfel beginnt bei (72,32), darüber stehen grüne Statusanzeigen.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_stamp.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_stamp.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:158

kitaqgb/lib/wire3d_cgb.c:10800

c
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 i;
    w3dcgb_u8 scene_count;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
    w3dcgb_u8 x;

    if (cubes == 0) return;
    scene_count = count;
    if (scene_count > 3) scene_count = 3;

    w3dcgb_fast_map_prepare();

    i = 0;
    while (i < w3dcgb_fast_prev_count)
    {
        w3dcgb_fast_map_clear_rect(
            w3dcgb_fast_prev_x[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_y[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_w[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_h[(__safe_index w3dcgb_u8)i]);
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_fast_map_clear_rect(0, 0, 4, 1);
    w3dcgb_fast_map_clear_rect(14, 0, 2, 1);

    if (scene_count == 0)
    {
        w3dcgb_fast_prev_count = 0;
        w3dcgb_wait_vblank_start();
        w3dcgb_fast_map_flush_gdma_asm();
        return;
    }

    a = 0;
    b = 1;
    c = 2;
    if (scene_count == 1)
    {
        w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
        w3dcgb_fast_prev_count = 1;
    }
    else if (scene_count == 2)
    {
        if (cubes[0].z < cubes[1].z)
        {
            w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
            w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
        }
        else
        {
            w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
            w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
        }
        w3dcgb_fast_prev_count = 2;
    }
    else
    {
        if (cubes[a].z < cubes[b].z)
        {
            w3dcgb_u8 t;
            t = a;
            a = b;
            b = t;
        }
        if (cubes[b].z < cubes[c].z)
        {
            w3dcgb_u8 t;
            t = b;
            b = c;
            c = t;
        }
        if (cubes[a].z < cubes[b].z)
        {
            w3dcgb_u8 t;
            t = a;
            a = b;
            b = t;
        }
        w3dcgb_fast_map_draw_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a), a);
        w3dcgb_fast_map_draw_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b), b);
        w3dcgb_fast_map_draw_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c), c);
        w3dcgb_fast_prev_count = 3;
    }

    x = (w3dcgb_u8)(selected & 3);
    w3dcgb_fast_map_or_cell((w3dcgb_i16)x, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
    if (hidden_enabled != 0) w3dcgb_fast_map_or_cell((w3dcgb_i16)15, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
    else w3dcgb_fast_map_or_cell((w3dcgb_i16)14, (w3dcgb_i16)0, WIRE3DCGB_COLOR_LOW, 15);

    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_gdma_asm();
}
Wire3DCGB_DrawFastCubes

Zeichnet bis zu drei Würfel als 2D-Umrisse mit tiefenabhängiger Größe.

Syntax

c
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parameter

cubes

Array mit Positionen, Winkeln und Farben für schnelles Würfelzeichnen.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

hidden_enabled

Null schließt verdeckte Kanten ein; ein Wert ungleich null wählt vereinfachtes Entfernen verdeckter Kanten.

selected

Index des ausgewählten Objekts im ursprünglichen Array; die Stempel-API verwendet ihn für eine Statusanzeige.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet bis zu drei 2D-Würfelnäherungen, nach unverändertem Z von fern nach nah sortiert, ohne das Aufruferarray umzuordnen. Null oder leere Eingaben werden ignoriert. selected ist ein Index des ursprünglichen Arrays. Kamera und Rotation werden nicht verwendet; die Farbe wird nicht wiederhergestellt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
    u8 i;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
    cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
    cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
    Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
    Wire3DCGB_DrawFastCubes(cubes,2,1,0);
    Wire3DCGB_DrawFastStatus(1,0);
    result[0]=Wire3DCGB_GetLineColor();
    result[1]=cubes[0].z;result[2]=cubes[1].z;
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Der nahe rote Würfel links ist größer als der entfernte blaue Würfel rechts. Ein grünes Kreuz markiert den ausgewählten roten Würfel.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:156

kitaqgb/lib/wire3d_cgb.c:8765

c
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 scene_count;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
    w3dcgb_u8 x;

    if (cubes == 0) return;
    scene_count = count;
    if (scene_count == 0) return;
    if (scene_count > 3) scene_count = 3;

    a = 0;
    b = 1;
    c = 2;
    if (scene_count == 1)
    {
        w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
        return;
    }

    if (scene_count == 2)
    {
        if (cubes[0].z < cubes[1].z)
        {
            w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
            w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
        }
        else
        {
            w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
            w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
        }
        return;
    }

    if (cubes[a].z < cubes[b].z)
    {
        w3dcgb_u8 t;
        t = a;
        a = b;
        b = t;
    }
    if (cubes[b].z < cubes[c].z)
    {
        w3dcgb_u8 t;
        t = b;
        b = c;
        c = t;
    }
    if (cubes[a].z < cubes[b].z)
    {
        w3dcgb_u8 t;
        t = a;
        a = b;
        b = t;
    }

    w3dcgb_draw_fast_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a));
    w3dcgb_draw_fast_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b));
    w3dcgb_draw_fast_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c));
}
Wire3DCGB_DrawFastProjectile

Zeichnet ein Projektil mit sechs Kanten um einen bereits projizierten Mittelpunkt; Tiefe und Phase bestimmen Größe und Ausrichtung.

Syntax

c
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);

Parameter

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

z

Tiefe zur Größenauswahl oder Projektionsberechnung.

phase

Rotationsphase; alle acht Zählschritte folgt die nächste Ausrichtung.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet ein Projektil mit sechs Kanten um einen bereits projizierten Mittelpunkt, mit vier tiefenabhängigen Größenstufen und vier Phasenausrichtungen. Mittelpunkte außerhalb von X=10..117 oder Y=10..85 werden verworfen. Markiert Änderungsgrenzen und lässt die angeforderte Farbe ausgewählt. Verwendet den normalen Rasterisierer ohne Kameraanwendung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:159

kitaqgb/lib/wire3d_cgb.c:8833

c
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z,
                                  w3dcgb_u8 phase, w3dcgb_u8 color)
{
    w3dcgb_u8 radius;
    w3dcgb_u8 half;
    w3dcgb_u8 depth;
    w3dcgb_u8 ax;
    w3dcgb_u8 ay;
    w3dcgb_u8 bx;
    w3dcgb_u8 by;
    w3dcgb_u8 cx;
    w3dcgb_u8 cy;
    w3dcgb_u8 dx;
    w3dcgb_u8 dy;
    w3dcgb_u8 spin;

    if ((x < 10) || (x > 117) || (y < 10) || (y > 85)) return;
    radius = 3;
    depth = 1;
    if (z <= 160) { radius = 4; depth = 2; }
    if (z <= 112) { radius = 5; depth = 3; }
    if (z <= 64) { radius = 7; depth = 4; }
    half = (w3dcgb_u8)(radius >> 1);

    ax = x;
    ay = (w3dcgb_u8)(y - radius);
    bx = (w3dcgb_u8)(x - radius);
    by = (w3dcgb_u8)(y + half);
    cx = (w3dcgb_u8)(x + radius);
    cy = by;
    spin = (w3dcgb_u8)((phase >> 3) & 3);
    dx = (w3dcgb_u8)(x + depth);
    dy = (w3dcgb_u8)(y - depth);
    if (spin == 1) dy = (w3dcgb_u8)(y + depth);
    else if (spin == 2)
    {
        dx = (w3dcgb_u8)(x - depth);
        dy = (w3dcgb_u8)(y + depth);
    }
    else if (spin == 3) dx = (w3dcgb_u8)(x - depth);

    w3dcgb_mark_dirty_rect((w3dcgb_u8)(x - radius), (w3dcgb_u8)(y - radius),
                           (w3dcgb_u8)(x + radius), (w3dcgb_u8)(y + radius));
    w3dcgb_line_color = color;
    w3dcgb_draw_line_raw(ax, ay, bx, by);
    w3dcgb_draw_line_raw(bx, by, cx, cy);
    w3dcgb_draw_line_raw(cx, cy, ax, ay);
    w3dcgb_draw_line_raw(ax, ay, dx, dy);
    w3dcgb_draw_line_raw(bx, by, dx, dy);
    w3dcgb_draw_line_raw(cx, cy, dx, dy);
}
Wire3DCGB_DrawFastStatus

Zeichnet kleine Linienanzeigen für Objektauswahl und Verdeckungsmodus.

Syntax

c
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parameter

hidden_enabled

Null schließt verdeckte Kanten ein; ein Wert ungleich null wählt vereinfachtes Entfernen verdeckter Kanten.

selected

Index des ausgewählten Objekts im ursprünglichen Array; die Stempel-API verwendet ihn für eine Statusanzeige.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet kleine Auswahl- und Verdeckungsmodus-Anzeigen in Farbe 3 und markiert ihre Grenzen im normalen Modus als geändert. selected wird im Bereich 0..2 erwartet, aber nicht geprüft. Die Anzeigen verwenden Linien statt Schrift-Tiles; die vorherige Farbe wird nicht wiederhergestellt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
    u8 i;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
    cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
    cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
    Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
    Wire3DCGB_DrawFastCubes(cubes,2,1,0);
    Wire3DCGB_DrawFastStatus(1,0);
    result[0]=Wire3DCGB_GetLineColor();
    result[1]=cubes[0].z;result[2]=cubes[1].z;
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Der nahe rote Würfel links ist größer als der entfernte blaue Würfel rechts. Ein grünes Kreuz markiert den ausgewählten roten Würfel.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:157

kitaqgb/lib/wire3d_cgb.c:8888

c
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 x;

    w3dcgb_mark_dirty_rect(0, 0, 31, 7);
    w3dcgb_mark_dirty_rect(116, 0, 127, 7);

    x = (w3dcgb_u8)(4 + (selected * 8));
    w3dcgb_line_color = WIRE3DCGB_COLOR_HIGH;
    w3dcgb_draw_line_raw(x, 3, (w3dcgb_u8)(x + 5), 3);
    w3dcgb_draw_line_raw(x, 6, (w3dcgb_u8)(x + 5), 6);
    if (hidden_enabled != 0)
    {
        w3dcgb_draw_line_raw(118, 3, 124, 3);
        w3dcgb_draw_line_raw(118, 6, 124, 6);
    }
    else
    {
        w3dcgb_draw_line_raw(118, 3, 124, 6);
        w3dcgb_draw_line_raw(118, 6, 124, 3);
    }
}
Wire3DCGB_DrawLine2D

Zeichnet mit dem aktiven Renderer eine Bildschirmgerade einschließlich beider Endpunkte.

Syntax

c
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Speichert Byte-Endpunkte und ruft den normalen oder den Vollbild-Linienrasterisierer auf. Koordinaten müssen im gewählten Viewport liegen; verwenden Sie DrawLineClipped2D für vorzeichenbehaftete oder außerhalb liegende Geometrie. Normale Linien verknüpfen Farbebenen per OR und markieren keine partiellen Grenzen; verwenden Sie vor partieller Übertragung die Clipping-API oder InvalidateFrameHistory. Vollbildlinien ersetzen Farben und weisen Tiles zu. Beide aktiven Linienpfade behandeln Farbe null als 3, nicht als Löschen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:177

kitaqgb/lib/wire3d_cgb.c:8363

c
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by)
{
    w3dcgb_line_x0 = ax;
    w3dcgb_line_y0 = ay;
    w3dcgb_line_x1 = bx;
    w3dcgb_line_y1 = by;
    if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
    else w3dcgb_line_stage_asm();
}
Wire3DCGB_DrawLine2DColor

Zeichnet eine Bildschirm-Linie in einer temporären Farbe und erhält die ausgewählte Farbe.

Syntax

c
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Setzt für DrawLine2D color & 3 und stellt die vorige Farbe wieder her. Beachten Sie dessen Bedingungen für Koordinaten, Farbkombination und partielle Bereiche; null löscht in keinem der beiden aktiven Renderer eine Linie.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:178

kitaqgb/lib/wire3d_cgb.c:8376

c
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawLine2D(ax, ay, bx, by);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawLine3D

Projiziert Weltendpunkte durch die Kamera und zeichnet eine Linie in der aktuellen Farbe.

Syntax

c
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);

Parameter

ax

X-Komponente des Startpunkts in Weltkoordinaten.

ay

Y-Komponente des Startpunkts in Weltkoordinaten.

az

Z-Komponente des Startpunkts in Weltkoordinaten.

bx

X-Komponente des Endpunkts in Weltkoordinaten.

by

Y-Komponente des Endpunkts in Weltkoordinaten.

bz

Z-Komponente des Endpunkts in Weltkoordinaten.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Projiziert beide Endpunkte durch die Kamera in den 128×96-Viewport. Verwirft die gesamte Linie, wenn ein Endpunkt die Tiefenprüfung nicht besteht; schneidet keine Übergänge durch die nahe Ebene zu. DrawLine2D wählt den Pfad nach Modus, die Projektion bleibt aber 128×96. Normale Linien kombinieren Farbebenen und markieren keine partiellen Grenzen; verwenden Sie eine vollständige Übertragung oder invalidieren Sie den Frame-Verlauf vor einer partiellen Übertragung ausdrücklich.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:172

kitaqgb/lib/wire3d_cgb.c:8992

c
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz)
{
    w3dcgb_u8 sx0;
    w3dcgb_u8 sy0;
    w3dcgb_u8 sx1;
    w3dcgb_u8 sy1;

    if (w3dcgb_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3dcgb_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DCGB_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3DCGB_DrawLine3DColor

Zeichnet eine 3D-Linie in einer temporären Farbe.

Syntax

c
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);

Parameter

ax

X-Komponente des Startpunkts in Weltkoordinaten.

ay

Y-Komponente des Startpunkts in Weltkoordinaten.

az

Z-Komponente des Startpunkts in Weltkoordinaten.

bx

X-Komponente des Endpunkts in Weltkoordinaten.

by

Y-Komponente des Endpunkts in Weltkoordinaten.

bz

Z-Komponente des Endpunkts in Weltkoordinaten.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wählt vorübergehend color & 3 für DrawLine3D und stellt danach die vorige Farbe wieder her.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:173

kitaqgb/lib/wire3d_cgb.c:9005

c
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawLine3D(ax, ay, az, bx, by, bz);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawLineClipped2D

Begrenzt vorzeichenbehaftete Bildschirmkoordinaten auf den Viewport und zeichnet eine Linie in der angeforderten Farbe.

Syntax

c
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0, w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);

Parameter

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

y0

Unterer Y-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

y1

Oberer Y-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Vorzeichenbehaftete Endpunkte werden vor der Umwandlung in die u8-ABI des Rasterisierers begrenzt. Schneidet eine vorzeichenbehaftete 2D-Linie auf den gewählten Viewport zu und zeichnet sie in einer temporären Farbe. Eingaben außerhalb von ±2047 werden verworfen. Vollständig innerhalb von 128×96 liegende Linien verwenden einen schnellen Pfad; andere nutzen Bereichscodes und begrenzte ganzzahlige Schnittpunktberechnungen mit höchstens acht Iterationen. Akzeptierte Linien im normalen Modus markieren Änderungsgrenzen. Dies ist ausschließlich Bildschirm-Clipping ohne 3D-Projektion oder Tiefen-Clipping.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:136

Deklarationshinweise im Original
Signed endpoints, clipped before conversion to the rasterizer's u8 ABI.

kitaqgb/lib/wire3d_cgb.c:9745

c
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
                               w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color)
{
    w3dcgb_u8 c0;
    w3dcgb_u8 c1;
    w3dcgb_u8 outside;
    w3dcgb_u8 guard;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    c0 = 0;
    c1 = 0;
    if ((((x0 | y0 | x1 | y1) & 0xFF80) != 0) || (y0 >= WIRE3DCGB_SCREEN_H) || (y1 >= WIRE3DCGB_SCREEN_H))
    {
        if ((x0 < -2047) || (x0 > 2047) || (y0 < -2047) || (y0 > 2047) ||
            (x1 < -2047) || (x1 > 2047) || (y1 < -2047) || (y1 > 2047)) return;
        c0 = w3dcgb_clip_outcode(x0, y0);
        c1 = w3dcgb_clip_outcode(x1, y1);
    }
    guard = 0;
    while (guard < 8)
    {
        if ((c0 | c1) == 0)
        {
            /* The existing ASM rasterizer handles the hot, in-window path. */
            if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_line((w3dcgb_u8)x0, (w3dcgb_u8)y0,
                                  (w3dcgb_u8)x1, (w3dcgb_u8)y1);
            Wire3DCGB_DrawLine2DColor((w3dcgb_u8)x0, (w3dcgb_u8)y0,
                                    (w3dcgb_u8)x1, (w3dcgb_u8)y1, color);
            return;
        }
        if ((c0 & c1) != 0) return;
        outside = c0;
        if (outside == 0) outside = c1;
        if ((outside & 12) != 0)
        {
            y = 0;
            if ((outside & 8) != 0) y = WIRE3DCGB_SCREEN_H - 1;
            if (((outside & 8) != 0) && (w3dcgb_full_mode != 0)) y = WIRE3DCGB_FULL_SCREEN_H - 1;
            x = (w3dcgb_i16)(x0 + w3dcgb_clip_muldiv((w3dcgb_i16)(x1 - x0),
                (w3dcgb_i16)(y - y0), (w3dcgb_i16)(y1 - y0)));
        }
        else
        {
            x = 0;
            if ((outside & 2) != 0) x = WIRE3DCGB_SCREEN_W - 1;
            if (((outside & 2) != 0) && (w3dcgb_full_mode != 0)) x = WIRE3DCGB_FULL_SCREEN_W - 1;
            y = (w3dcgb_i16)(y0 + w3dcgb_clip_muldiv((w3dcgb_i16)(y1 - y0),
                (w3dcgb_i16)(x - x0), (w3dcgb_i16)(x1 - x0)));
        }
        if (outside == c0) { x0 = x; y0 = y; c0 = w3dcgb_clip_outcode(x0, y0); }
        else { x1 = x; y1 = y; c1 = w3dcgb_clip_outcode(x1, y1); }
        guard = (w3dcgb_u8)(guard + 1);
    }
}
Wire3DCGB_DrawLineList2DColor

Zeichnet eine Liste von Vier-Byte-Bildschirmlinien-Datensätzen in einer gewählten Farbe.

Syntax

c
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy, w3dcgb_u8 line_count, w3dcgb_u8 color);

Parameter

line_xy

Bytearray mit x0,y0,x1,y1-Datensätzen.

line_count

Anzahl der Liniendatensätze; höchstens 64 werden verarbeitet.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet bis zu 64 Vier-Byte-Datensätze (x0,y0,x1,y1) und ignoriert eine Nullliste. Endpunkte müssen im gewählten Viewport liegen. Erhält die vorige Farbe und übergibt jede Linie an den normalen oder Vollbildrasterisierer.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:186

kitaqgb/lib/wire3d_cgb.c:8571

c
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
                                  w3dcgb_u8 line_count, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 offset;
    w3dcgb_u8 old_color;
    if (line_xy == 0) return;
    if (line_count > WIRE3DCGB_MODEL_EDGE_LIMIT) line_count = WIRE3DCGB_MODEL_EDGE_LIMIT;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    i = 0;
    offset = 0;
    while (i < line_count)
    {
        w3dcgb_line_x0 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_y0 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_x1 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_y1 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
        else w3dcgb_line_stage_asm();
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawMaskedModel2D

Zeichnet aktivierte Modellkanten aus vorprojizierten Eckpunkten und einer Kantenbitmaske.

Syntax

c
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, const w3dcgb_u8* edge_mask, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

vertex_x

Array vorprojizierter X-Eckpunktversätze.

vertex_y

Array vorprojizierter Y-Eckpunktversätze.

edge_mask

Bytearray mit einem Sichtbarkeitsbit je Kante, niederwertigstes Bit zuerst.

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet aktivierte Modellkanten aus vorprojizierten vorzeichenbehafteten Byte-Versätzen um (x,y). Maskenbits beginnen mit dem niederwertigsten Bit, acht Kanten je Byte. Alle Zeiger und Eckpunktindizes müssen gültig sein; edge_mask[0] wird auch bei null Kanten gelesen. Keine Anzahl wird begrenzt. Verschobene Endpunkte müssen vor der Byte-Umwandlung im Viewport liegen; negative Werte würden umbrechen. Erhält die vorige Linienfarbe und wählt den Pfad nach aktivem Modus.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:179

kitaqgb/lib/wire3d_cgb.c:8392

c
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
                                 const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                                 const w3dcgb_u8* edge_mask,
                                 w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 bit;
    w3dcgb_u8 mask_index;
    w3dcgb_u8 mask;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 old_color;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    i = 0;
    bit = 1;
    mask_index = 0;
    mask = edge_mask[0];
    while (i < model->edge_count)
    {
        if ((mask & bit) != 0)
        {
            a = model->edges[(__safe_index w3dcgb_u8)i].a;
            b = model->edges[(__safe_index w3dcgb_u8)i].b;
            w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
            w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
            w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
            w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
            if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
            else w3dcgb_line_stage_asm();
        }
        i = (w3dcgb_u8)(i + 1);
        bit = (w3dcgb_u8)(bit << 1);
        if ((bit == 0) && (i < model->edge_count))
        {
            bit = 1;
            mask_index = (w3dcgb_u8)(mask_index + 1);
            mask = edge_mask[(__safe_index w3dcgb_u8)mask_index];
        }
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawModel

Zeichnet ein 3D-Modell an der angegebenen Position und mit der angegebenen Rotation in Originalgröße.

Syntax

c
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet ein Modell mit Q8-Einheitsskalierung (256) gemäß den Bedingungen von DrawModelScaled.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:128

kitaqgb/lib/wire3d_cgb.c:9015

c
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz)
{
    Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3DCGB_DrawModelColor

Zeichnet ein Modell in Originalgröße mit einer temporären Farbe.

Syntax

c
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet ein Modell mit Q8-Einheitsskalierung in einer temporären Farbe und stellt danach die vorherige Farbe wieder her.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:130

kitaqgb/lib/wire3d_cgb.c:9021

c
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color)
{
    Wire3DCGB_DrawModelScaledColor(model, x, y, z, rx, ry, rz, 256, color);
}
Wire3DCGB_DrawModelScaled

Skaliert, dreht und projiziert ein Modell und zeichnet danach dessen ausgewählte Kanten in der aktuellen Farbe.

Syntax

c
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Projiziert bis zu 24 Eckpunkte mit positiver Q8-Skalierung; nichtpositive Skalierung bedeutet Originalgröße. Multiplikation mit eins und Nullwinkelrotationen werden übersprungen. Zwischenwerte müssen in s16 passen. Wenn Nachbarschaftsfilterung verfügbar ist, werden bis zu 16 Vorderseitenflags erzeugt; anschließend werden Kanten mit gültiger Tiefe und gültigen Eckpunktindizes gezeichnet. Die Kantenzahl des Modells ist nicht auf 64 begrenzt. Es gibt kein Clipping an der nahen Ebene. Ersetzt den gemeinsamen Projektionscache und verknüpft Linienfarben per OR mit dem normalen 128×96-Staging-Bereich. Dieser Pfad markiert keine partiellen Grenzen; veranlassen Sie eine vollständige Übertragung oder machen Sie den Frame-Verlauf vor einer partiellen Übertragung ausdrücklich ungültig.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:129

kitaqgb/lib/wire3d_cgb.c:9396

c
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
    w3dcgb_u8 i;
    w3dcgb_u8 count;
    w3dcgb_u8 edge_count;
    w3dcgb_u8 face_count;
    w3dcgb_u8 camera_unrotated;
    w3dcgb_u8 unit_scale;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;
    unit_scale = 0;
    if (scale_q8 == 256) unit_scale = 1;
    camera_unrotated = 0;
    if ((w3dcgb_cam_yaw == 0) && (w3dcgb_cam_pitch == 0) && (w3dcgb_cam_roll == 0))
    {
        camera_unrotated = 1;
    }

    i = 0;
    while (i < count)
    {
        const Wire3DCGB_Vec3* v;
        w3dcgb_i16 vx;
        w3dcgb_i16 vy;
        w3dcgb_i16 vz;
        w3dcgb_u8 sx;
        w3dcgb_u8 sy;
        w3dcgb_u8 projected;

        v = &model->vertices[(__safe_index w3dcgb_u8)i];
        if (unit_scale != 0)
        {
            vx = v->x;
            vy = v->y;
            vz = v->z;
        }
        else
        {
            vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
            vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
            vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);
        }

        if (ry != 0) w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
        if (rx != 0) w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
        if (rz != 0) w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);

        vx = (w3dcgb_i16)(vx + x);
        vy = (w3dcgb_i16)(vy + y);
        vz = (w3dcgb_i16)(vz + z);

        if (camera_unrotated != 0)
        {
            vx = (w3dcgb_i16)(vx - w3dcgb_cam_x);
            vy = (w3dcgb_i16)(vy - w3dcgb_cam_y);
            vz = (w3dcgb_i16)(vz - w3dcgb_cam_z);
            projected = w3dcgb_project_camera_space(vx, vy, vz, &sx, &sy);
        }
        else
        {
            projected = w3dcgb_project_world(vx, vy, vz, &sx, &sy);
        }

        if (projected != 0)
        {
            w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
            w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
        }
        else
        {
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
        }
        i = (w3dcgb_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3dcgb_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;
    i = 0;
    while (i < edge_count)
    {
        const Wire3DCGB_Edge* e;
        e = &model->edges[(__safe_index w3dcgb_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->a] &&
                w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->b] &&
                w3dcgb_is_edge_visible(model, i, face_count))
            {
                w3dcgb_draw_model_line(
                    w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->a],
                    w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->a],
                    w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->b],
                    w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->b]);
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_DrawModelScaledColor

Zeichnet ein Modell mit gewählter Skalierung und temporärer Linienfarbe.

Syntax

c
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wählt für DrawModelScaled color & 3 und stellt anschließend die Farbe beim Eintritt wieder her.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:131

kitaqgb/lib/wire3d_cgb.c:9510

c
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, scale_q8);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawPoint2D

Schreibt ein Pixel in der aktuellen Farbe.

Syntax

c
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);

Parameter

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Verwirft im normalen Modus Koordinaten außerhalb von 128×96, markiert partielle Grenzen und ersetzt das vorbereitete Pixel durch die aktuelle Farbe einschließlich null. Im Vollbildmodus wird stattdessen eine schnelle Linie mit zusammenfallenden Endpunkten gezeichnet: Null bedeutet dort Farbe 3, und ungültige Koordinaten setzen das Overflow-Flag dieses Frames. Die Bildübertragung erfolgt später.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:174

kitaqgb/lib/wire3d_cgb.c:8283

c
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 tile;
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_line_x0 = x;
        w3dcgb_line_y0 = y;
        w3dcgb_line_x1 = x;
        w3dcgb_line_y1 = y;
        w3dcgb_full_line_fast_asm();
        return;
    }
    if (x >= WIRE3DCGB_SCREEN_W) return;
    if (y >= WIRE3DCGB_SCREEN_H) return;
    if (w3dcgb_full_frame_transfer == 0)
    {
        tile = (w3dcgb_u8)(((x >> 3) * W3DCGB_TILE_H) + (y >> 3));
        if (tile < w3dcgb_dirty_min_tile) w3dcgb_dirty_min_tile = tile;
        if (tile > w3dcgb_dirty_max_tile) w3dcgb_dirty_max_tile = tile;
    }
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = y;
    w3dcgb_plot_stage_asm();
}
Wire3DCGB_DrawScene

Zeichnet bis zu acht Objekte von nah nach fern; vorherige Modellflächen verdecken spätere Linien.

Syntax

c
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);

Parameter

objects

Objektarray mit Positionen, Rotationen, Skalierungen und Sichtbarkeitsflags.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Sortiert höchstens acht Objekte nach der Tiefe ihres Ursprungs im Kameraraum von nah nach fern, ohne das Aufruferarray zu ändern. Löscht die Maske, zeichnet sichtbare Modelle unter Berücksichtigung zuvor abgedeckter Bereiche und fügt danach ihre Flächen als Verdeckung hinzu. Modellarrays und Flächenindizes müssen gültig sein. Farbe null übernimmt die aktuelle Farbe, möglicherweise die des vorherigen Objekts. Am Ende werden die ursprüngliche Farbe wiederhergestellt und Verdeckung deaktiviert. Dieser Modellpfad verwendet den normalen 128×96-Staging-Bereich.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// A near square hides the middle of a farther blue line, regardless of array order.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
__prg_rom Wire3DCGB_Vec3 back_vertices[2]={{-96,0,0},{96,0,0}};
__prg_rom Wire3DCGB_Edge back_edges[1]={{0,1}};
Wire3DCGB_Model back;
Wire3DCGB_Object objects[2];
void main() {
    u8 i;
    wire_results_clear();wire_plane_setup();
    back.vertices=back_vertices;back.edges=back_edges;back.faces=0;back.edge_faces=0;
    back.vertex_count=2;back.edge_count=1;back.face_count=0;back.flags=0;
    for(i=0;i<2;i++) {
        objects[i].x=0;objects[i].y=0;objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256;objects[i].visible=1;
    }
    objects[0].model=&back;objects[0].z=128;objects[0].color=2;
    objects[1].model=&plane;objects[1].z=64;objects[1].color=1;
    Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawScene(objects,2);
    result[0]=objects[0].z;result[1]=objects[1].z;result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein nahes rotes Quadrat bei (46,30)..(82,66) verdeckt die Mitte einer weiter entfernten blauen waagerechten Linie; sichtbar bleiben nur deren linker und rechter Abschnitt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_scene.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_scene.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:155

kitaqgb/lib/wire3d_cgb.c:8918

c
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count)
{
    w3dcgb_u8 scene_count;
    w3dcgb_u8 i;
    w3dcgb_u8 old_color;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3DCGB_SCENE_OBJECT_LIMIT) scene_count = WIRE3DCGB_SCENE_OBJECT_LIMIT;

    i = 0;
    while (i < scene_count)
    {
        w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = i;
        w3dcgb_scene_depth[(__safe_index w3dcgb_u8)i] = w3dcgb_scene_object_depth(&objects[(__safe_index w3dcgb_u8)i]);
        i = (w3dcgb_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3dcgb_u8 j;
        j = (w3dcgb_u8)(i + 1);
        while (j < scene_count)
        {
            w3dcgb_u8 oi;
            w3dcgb_u8 oj;
            oi = w3dcgb_scene_order[(__safe_index w3dcgb_u8)i];
            oj = w3dcgb_scene_order[(__safe_index w3dcgb_u8)j];

            if (w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oj] < w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oi])
            {
                w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = oj;
                w3dcgb_scene_order[(__safe_index w3dcgb_u8)j] = oi;
            }
            j = (w3dcgb_u8)(j + 1);
        }
        i = (w3dcgb_u8)(i + 1);
    }

    old_color = w3dcgb_line_color;
    w3dcgb_clear_occlusion_mask();
    w3dcgb_occlusion_active = 0;

    i = 0;
    while (i < scene_count)
    {
        Wire3DCGB_Object* obj;
        obj = &objects[(__safe_index w3dcgb_u8)w3dcgb_scene_order[(__safe_index w3dcgb_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {
            if (i == 0) w3dcgb_occlusion_active = 0;
            else w3dcgb_occlusion_active = 1;
            if (obj->color != 0) Wire3DCGB_SetLineColor(obj->color);
            Wire3DCGB_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3dcgb_i8)obj->rx, (w3dcgb_i8)obj->ry, (w3dcgb_i8)obj->rz, obj->scale_q8);
            w3dcgb_occlusion_active = 0;
            w3dcgb_mark_model_occluder(obj->model);
        }
        i = (w3dcgb_u8)(i + 1);
    }

    w3dcgb_occlusion_active = 0;
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawTinyModel2D

Zeichnet eine Sechs-Pixel-Markierung, deren Kopf und Schwanz die Richtung anzeigen.

Syntax

c
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 turn, w3dcgb_u8 color);

Parameter

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

turn

Wert, dessen untere fünf Bits die Richtung der kleinen Markierung wählen.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Zeichnet eine Sechs-Pixel-Markierung über den 128×96-Punktzeichner und erhält die Linienfarbe. Mittelpunkte außerhalb von X=3..124 oder Y=3..92 werden ignoriert. Die unteren fünf turn-Bits wählen Kopf- und Schwanzversätze für links/gerade/rechts. Dies ist keine allgemeine 3D-Transformation und verwendet nicht den Vollbildrenderer.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:175

kitaqgb/lib/wire3d_cgb.c:8313

c
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
                               w3dcgb_u8 turn, w3dcgb_u8 color)
{
    w3dcgb_u8 nose_x;
    w3dcgb_u8 tail_x;
    w3dcgb_u8 old_color;
    if ((x < 3) || (x > 124) || (y < 3) || (y > (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 4))) return;

    nose_x = x;
    tail_x = x;
    turn = (w3dcgb_u8)(turn & 31);
    if (turn < 12)
    {
        nose_x = (w3dcgb_u8)(x + 1);
        tail_x = (w3dcgb_u8)(x - 1);
    }
    else if (turn >= 20)
    {
        nose_x = (w3dcgb_u8)(x - 1);
        tail_x = (w3dcgb_u8)(x + 1);
    }

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    w3dcgb_plot_x = nose_x;
    w3dcgb_plot_y = (w3dcgb_u8)(y - 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = (w3dcgb_u8)(y - 1);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = (w3dcgb_u8)(x - 2);
    w3dcgb_plot_y = (w3dcgb_u8)(y + 1);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = (w3dcgb_u8)(x + 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = y;
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = tail_x;
    w3dcgb_plot_y = (w3dcgb_u8)(y + 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawWhiteBorderFast

Zeichnet einen ein Pixel breiten Rand mit Farbindex 2 um den 128×96-Staging-Bereich.

Syntax

c
void Wire3DCGB_DrawWhiteBorderFast();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Schreibt einen ein Pixel breiten Rand in Farbe 2 um den normalen Staging-Bereich und erhält dabei innere Pixel sowie die WRAM-Bankauswahl. Die sichtbare Farbe hängt von der Palette ab. Kein Änderungsbereich wird markiert; bei partieller Übertragung muss der Aufrufer den Upload veranlassen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
    Wire3DCGB_EraseLeftGuard24Fast();
    // With this example's palette, color index 2 is blue rather than white.
    Wire3DCGB_DrawWhiteBorderFast();
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die linken 24 Spalten werden gelöscht, ein roter Streifen bleibt, und der äußere Rand mit Farbindex 2 ist blau.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:147

kitaqgb/lib/wire3d_cgb.c:9369

c
void Wire3DCGB_DrawWhiteBorderFast()
{
    w3dcgb_draw_white_border_asm();
}
Wire3DCGB_EnableAtomicMaps

Konfiguriert die 128×96-Ausgabe für den Wechsel zwischen zwei Hintergrundkarten.

Syntax

c
void Wire3DCGB_EnableAtomicMaps();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Nur beim Start: Reserviert beide BG-Karten; eingereihte HUD-Tiles werden in beide übernommen. Aktiviert den Kartenwechsel einmal während des 128×96-Starts; im Vollbildmodus oder bei bereits aktivierter Einstellung geschieht nichts. Bei eingeschaltetem LCD wird auf VBlank gewartet, das LCD ausgeschaltet, beide Bänke von 9800 nach 9C00 kopiert und den Viewport-Attributen jeweils Tile-Bank 0 beziehungsweise 1 zugewiesen. Stellt LCDC mit ausgewählter Karte 9C00 und VBK null wieder her. Beide BG-Karten sind reserviert; eingereihte HUD-Tile-Nummern werden in beide kopiert.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:144

Deklarationshinweise im Original
Startup-only: reserves both BG maps; queued HUD tiles are mirrored.

kitaqgb/lib/wire3d_cgb.c:7912

c
void Wire3DCGB_EnableAtomicMaps()
{
    if ((w3dcgb_full_mode != 0) || (w3dcgb_atomic_maps != 0)) return;
    __asm {
w3dam_wait:
        LDH_A_MEM 68
        CP_IMM 144
        JR_C w3dam_wait
        LDH_A_MEM 64
        PUSH_AF
        XOR_A
        LDH_MEM_A 64
        LDH_MEM_A 79
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 4
w3dam_copy_page:
        LD_C_IMM 0
w3dam_copy_byte:
        LD_A_HL
        INC_HL
        LD_DE_A
        INC_DE
        DEC_C
        JR_NZ w3dam_copy_byte
        DEC_B
        JR_NZ w3dam_copy_page
        LDH_A_MEM 79
        AND_IMM 1
        JR_NZ w3dam_attrs
        LD_A_IMM 1
        LDH_MEM_A 79
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 4
        JR w3dam_copy_page
w3dam_attrs:
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 12
w3dam_row:
        LD_C_IMM 16
w3dam_cell:
        XOR_A
        LDI_HL_A
        LD_A_IMM 8
        LD_DE_A
        INC_DE
        DEC_C
        JR_NZ w3dam_cell
        LD_A_L
        ADD_A_IMM 16
        LD_L_A
        JR_NC w3dam_hl_ready
        INC_H
w3dam_hl_ready:
        LD_A_E
        ADD_A_IMM 16
        LD_E_A
        JR_NC w3dam_de_ready
        INC_D
w3dam_de_ready:
        DEC_B
        JR_NZ w3dam_row
        LD_A_IMM 1
        LD_MEM_A w3dcgb_atomic_maps
        XOR_A
        LDH_MEM_A 79
        POP_AF
        OR_IMM 8
        LDH_MEM_A 64
        RET
    }
}
Wire3DCGB_EnableDoubleSpeed

Schaltet die CGB-CPU auf Doppeltakt um.

Syntax

c
void Wire3DCGB_EnableDoubleSpeed();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Kehrt auf CGB sofort zurück, wenn KEY1 bereits Doppeltakt meldet; andernfalls wird der Geschwindigkeitswechsel angefordert und der STOP-Helfer aufgerufen. Diese API setzt CGB-Hardware voraus und bietet keinen Ersatzpfad für monochrome Geräte.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:116

kitaqgb/lib/wire3d_cgb.c:1081

c
void Wire3DCGB_EnableDoubleSpeed()
{
    if ((w3dcgb_reg_key1 & 0x80) != 0) return;
    w3dcgb_reg_key1 = 1;
    w3dcgb_cgb_speed_switch_asm();
}
Wire3DCGB_EndFrame

Überträgt den fertigen Frame und zeigt ihn an.

Syntax

c
void Wire3DCGB_EndFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Im normalen Modus werden eingereihte BG-Schreibzugriffe ausgeführt, der gesamte Staging-Bereich übertragen und die fertige Tile-Bank angezeigt. Der Vollbildmodus überträgt und zeigt seine zugewiesenen Tiles, ohne die HUD-Warteschlange zu leeren. Erfordert aktiviertes LCD und die Bank-/Interruptbedingungen der Übertragungshelfer; kann mehrere Frames dauern.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:189

kitaqgb/lib/wire3d_cgb.c:9881

c
void Wire3DCGB_EndFrame()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    if (w3dcgb_bgq_count != 0)
    {
        w3dcgb_wait_vblank_start();
        w3dcgb_flush_bg_queue();
    }
    w3dcgb_transfer_stage_asm();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EndFrameFast

Überträgt und zeigt einen vollständigen Frame, ohne eingereihte Hintergrund-Schreibzugriffe auszuführen.

Syntax

c
void Wire3DCGB_EndFrameFast();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Überträgt und zeigt den vollständigen Frame des gewählten Modus, ohne die BG-Warteschlange zu leeren. Ausstehende HUD-Schreibzugriffe werden nicht verbraucht. Es gelten dieselben LCD-, Bank- und Interruptbedingungen wie bei EndFrame; benötigt einen Build mit vollständiger Laufzeitumgebung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:190

kitaqgb/lib/wire3d_cgb.c:9902

c
void Wire3DCGB_EndFrameFast()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    w3dcgb_transfer_stage_asm();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EndFrameSparse

Wartet auf einen neuen VBlank und überträgt und zeigt danach die erforderlichen partiellen Bereiche.

Syntax

c
void Wire3DCGB_EndFrameSparse();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wartet im normalen Modus auf einen neuen VBlank und ruft EndFrameSparseNow auf. Der Vollbildmodus verwendet stattdessen seine vollständige Übertragung und Anzeige. Benötigt die vollständige Laufzeitumgebung und aktiviertes LCD; Abschluss innerhalb eines Frames ist nicht garantiert.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:191

kitaqgb/lib/wire3d_cgb.c:9917

c
void Wire3DCGB_EndFrameSparse()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    w3dcgb_wait_vblank_start();
    Wire3DCGB_EndFrameSparseNow();
}
Wire3DCGB_EndFrameSparseNow

Übergibt Hintergrund-Schreibzugriffe und partielle Bereiche aktuell/N−2 ohne anfängliches Warten auf einen neuen VBlank.

Syntax

c
void Wire3DCGB_EndFrameSparseNow();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Führt eingereihte BG-Schreibzugriffe aus, überträgt den partiellen Tile-Bereich aktuell/N−2 in die hintere Bank und zeigt ihn an. Überspringt das anfängliche Warten auf einen neuen VBlank; der normale Kartenmodus wartet aber weiterhin beim Wiederherstellen des leeren HUD-Tiles. Auch DMA und Anzeige können warten. Der Vollbildmodus der vollständigen Laufzeitumgebung verwendet seinen eigenen Pfad. LCD muss aktiv sein; SVBK/VBK müssen während DMA stabil bleiben.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:192

kitaqgb/lib/wire3d_cgb.c:9935

c
void Wire3DCGB_EndFrameSparseNow()
{
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
#endif
    /* Atomic mode never writes a displayed tile and does not need a
       frame-long VBlank wait before starting an off-screen upload. */
    if (w3dcgb_atomic_maps == 0) w3dcgb_restore_hud_blank_tile_asm();
    if (w3dcgb_bgq_count != 0) w3dcgb_flush_bg_queue();
    w3dcgb_transfer_dirty_tiles();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EraseLeftGuard24Fast

Löscht die äußersten 24 linken Spalten des normalen Staging-Bereichs.

Syntax

c
void Wire3DCGB_EraseLeftGuard24Fast();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Löscht die äußersten 24 linken Spalten des Staging-Bereichs per ASM mit erhaltener Bankauswahl. Kein Änderungsbereich wird markiert; bei partieller Übertragung muss der Aufrufer die gelöschten Tiles einschließen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
    Wire3DCGB_EraseLeftGuard24Fast();
    // With this example's palette, color index 2 is blue rather than white.
    Wire3DCGB_DrawWhiteBorderFast();
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die linken 24 Spalten werden gelöscht, ein roter Streifen bleibt, und der äußere Rand mit Farbindex 2 ist blau.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:146

kitaqgb/lib/wire3d_cgb.c:9200

c
void Wire3DCGB_EraseLeftGuard24Fast()
{
    w3dcgb_erase_left_guard24_asm();
}
Wire3DCGB_EraseModelFaces

Löscht vorbereitete Pixel innerhalb der projizierten Vorderseiten des Modells.

Syntax

c
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Transformiert für ein Modell mit verdeckten Linien, Eckpunkten und Flächen höchstens 24 Eckpunkte und löscht die nach vorn gerichteten Dreiecke unter höchstens 16 Flächen. Nichtpositive Skalierung bedeutet Originalgröße; dieser Pfad multipliziert auch bei Einheitsskalierung und führt alle drei Rotationshelfer auch bei Nullwinkeln aus. Ungültige Flächen oder solche mit fehlgeschlagener Tiefenprüfung werden verworfen. Ersetzt den gemeinsamen Projektionscache und verwendet den normalen C-Staging-Löscher; der Aufrufer oder die Speicherzuweisung muss daher die richtige WRAM-Einblendung sicherstellen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Projected model faces erase a square opening; redraw its outline in green.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
void main() {
    u8 y;u8 bank;
    wire_results_clear();wire_plane_setup();Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=8;y<=88;y++) Wire3DCGB_DrawLine2D(24,y,104,y);
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_EraseModelFaces(&plane,0,0,64,0,0,0,256);
    sample_svbk=bank;
    Wire3DCGB_DrawModelColor(&plane,0,0,64,0,0,0,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_faces.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:132

kitaqgb/lib/wire3d_cgb.c:9033

c
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
    w3dcgb_u8 i;
    w3dcgb_u8 count;
    w3dcgb_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DCGB_Vec3* v;
        w3dcgb_i16 vx;
        w3dcgb_i16 vy;
        w3dcgb_i16 vz;
        w3dcgb_u8 sx;
        w3dcgb_u8 sy;

        v = &model->vertices[(__safe_index w3dcgb_u8)i];
        vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
        vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
        vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);

        w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
        w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
        w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);

        vx = (w3dcgb_i16)(vx + x);
        vy = (w3dcgb_i16)(vy + y);
        vz = (w3dcgb_i16)(vz + z);

        if (w3dcgb_project_world(vx, vy, vz, &sx, &sy))
        {
            w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
            w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
        }
        else
        {
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
        }
        i = (w3dcgb_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
    w3dcgb_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DCGB_Face* f;
        f = &model->faces[(__safe_index w3dcgb_u8)i];
        if (w3dcgb_face_visible[(__safe_index w3dcgb_u8)i] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->a] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->b] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->c])
        {
            w3dcgb_clear_triangle(
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->a],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->a],
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->b],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->b],
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->c],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->c]);
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_ErasePackedSilhouette2D

Löscht eine gepackte Silhouette aus beiden Farbebenen des normalen Staging-Bereichs.

Syntax

c
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);

Parameter

profile

Silhouettenarray mit einem Byte je Zeile; 0xFF überspringt eine Zeile.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

y0

Vorzeichenbehafteter Versatz vom Y-Mittelpunkt zur ersten Silhouettenzeile.

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Löscht bis zu 29 gepackte Silhouettenzeilen aus beiden vorbereiteten Bitebenen. Format, Platzierung, Zwei-Pixel-Schutzrand und Clipping entsprechen MarkPackedSilhouette2D; null wird ignoriert. Der ASM-Span-Schreiber wählt WRAM-Bank 2 und stellt die vorherige Auswahl wieder her, markiert aber keine geänderten Tiles. Im partiellen Modus muss der Aufrufer gelöschte Tiles in den Übertragungsbereich aufnehmen. Diese API betrifft den 128×96-Staging-Bereich.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dreiecke, waagerechte Spans, Rechtecke und gepackte Silhouetten schneiden schwarze Löcher in rot, blau und grün gefüllte Felder.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:153

kitaqgb/lib/wire3d_cgb.c:2038

c
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                      w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 i;
    w3dcgb_u8 packed;
    w3dcgb_u8 half_width;
    w3dcgb_i16 center;
    w3dcgb_i16 left;
    w3dcgb_i16 right;
    w3dcgb_i16 row;

    if (profile == 0) return;
    if (count > 29) count = 29;
    i = 0;
    while (i < count)
    {
        packed = profile[(__safe_index w3dcgb_u8)i];
        if (packed != 0xFF)
        {
            row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
            if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
            {
                center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
                half_width = (w3dcgb_u8)(packed & 15);
                left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
                right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
                if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
                {
                    if (left < 0) left = 0;
                    if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
                    w3dcgb_mask_span_y = (w3dcgb_u8)row;
                    w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
                    w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
                    w3dcgb_stage_clear_span_asm();
                }
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_EraseRect2D

Löscht ein Rechteck aus dem normalen Staging-Bereich.

Syntax

c
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);

Parameter

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

y0

Unterer Y-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

y1

Oberer Y-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Ordnet und begrenzt das Rechteck auf 128×96. Linke Streifen über die gesamte Höhe mit 16 oder 24 Pixeln Breite verwenden ASM-Löschen mit erhaltener Bankauswahl und Änderungsmarkierung. Andere Rechtecke verwenden zeilenweises Löschen in C und benötigen die richtige WRAM-Einblendung des Staging-Bereichs durch den Aufrufer.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dreiecke, waagerechte Spans, Rechtecke und gepackte Silhouetten schneiden schwarze Löcher in rot, blau und grün gefüllte Felder.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:145

kitaqgb/lib/wire3d_cgb.c:9146

c
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1)
{
    w3dcgb_u8 t;
    w3dcgb_u8 y;

    if (x0 > x1)
    {
        t = x0;
        x0 = x1;
        x1 = t;
    }
    if (y0 > y1)
    {
        t = y0;
        y0 = y1;
        y1 = t;
    }
    if (x0 >= WIRE3DCGB_SCREEN_W) return;
    if (y0 >= WIRE3DCGB_SCREEN_H) return;
    if (x1 >= WIRE3DCGB_SCREEN_W) x1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    if (y1 >= WIRE3DCGB_SCREEN_H) y1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);

    if ((x0 == 0) &&
        (x1 == 15) &&
        (y0 == 0) &&
        (y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
    {
        w3dcgb_erase_left_guard16_asm();
        w3dcgb_mark_dirty_rect(0, 0, 15, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
        return;
    }
    if ((x0 == 0) &&
        (x1 == 23) &&
        (y0 == 0) &&
        (y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
    {
        w3dcgb_erase_left_guard24_asm();
        w3dcgb_mark_dirty_rect(0, 0, 23, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
        return;
    }

    y = y0;
    while (y <= y1)
    {
        w3dcgb_stage_clear_span(y, x0, x1);
        if (y == y1) break;
        y = (w3dcgb_u8)(y + 1);
    }
}
Wire3DCGB_EraseSpan2D

Löscht einen waagerechten Span und sichert und restauriert dabei die WRAM-Bankauswahl.

Syntax

c
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);

Parameter

y

Pixel-Y-Koordinate der zu löschenden Zeile.

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Ordnet die X-Endpunkte, verwirft eine außerhalb liegende Zeile oder linke Grenze und begrenzt rechts auf 127. Markiert den Bereich als geändert und verwendet den ASM-Span-Löscher, der WRAM-Bank 2 auswählt und die vorherige Bankauswahl wiederherstellt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dreiecke, waagerechte Spans, Rechtecke und gepackte Silhouetten schneiden schwarze Löcher in rot, blau und grün gefüllte Felder.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:134

kitaqgb/lib/wire3d_cgb.c:9123

c
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1)
{
    w3dcgb_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    if ((y >= WIRE3DCGB_SCREEN_H) || (x0 >= WIRE3DCGB_SCREEN_W)) return;
    if (x1 >= WIRE3DCGB_SCREEN_W) x1 = WIRE3DCGB_SCREEN_W - 1;
    w3dcgb_mark_dirty_rect(x0, y, x1, y);
    w3dcgb_mask_span_y = y;
    w3dcgb_mask_span_min_x = x0;
    w3dcgb_mask_span_max_x = x1;
    w3dcgb_stage_clear_span_asm();
}
Wire3DCGB_EraseTriangle2D

Löscht ein Dreieck aus beiden Farbebenen des normalen Staging-Bereichs.

Syntax

c
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

cx

X-Koordinate von Eckpunkt C in Viewport-Pixeln.

cy

Y-Koordinate von Eckpunkt C in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Löscht ein Dreieck über den normalen C-Staging-Löscher. Die begrenzten Spans markieren berührte Tiles als geändert; Aufrufer oder Speicherzuweisung müssen die WRAM-Einblendung des Staging-Bereichs sicherstellen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dreiecke, waagerechte Spans, Rechtecke und gepackte Silhouetten schneiden schwarze Löcher in rot, blau und grün gefüllte Felder.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:133

kitaqgb/lib/wire3d_cgb.c:9113

c
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
    w3dcgb_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DCGB_FastMapBegin

Löscht Tile-Nummern und Attribute im 16×12-FastMap-Viewport.

Syntax

c
void Wire3DCGB_FastMapBegin();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert FastMap als vorbereitet und löscht Tile-Nummern und Attribute im 16×12-Viewport. Die Schattenspalten 16..31 bleiben erhalten, obwohl Flush je Zeile 32 Spalten kopiert. Benötigt die vollständige Laufzeitumgebung und stabile FastMap-WRAM-Einblendung; initialisiert keine Hardware und überträgt die Karte nicht.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:160

kitaqgb/lib/wire3d_cgb.c:10137

c
void Wire3DCGB_FastMapBegin()
{
    w3dcgb_fast_map_ready = 1;
    w3dcgb_fast_map_clear_rect(0, 0, 16, 12);
}
Wire3DCGB_FastMapBeginTilesOnly

Löscht nur die Tile-Nummern im 16×12-FastMap-Viewport.

Syntax

c
void Wire3DCGB_FastMapBeginTilesOnly();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert FastMap als vorbereitet und löscht nur die Tile-Nummern im 16×12-Viewport. Attribute und Spalten 16..31 bleiben erhalten. Benötigt die vollständige Laufzeitumgebung und die vorgesehene WRAM-Einblendung; Hardwareinitialisierung und Übertragung erfolgen separat.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:161

kitaqgb/lib/wire3d_cgb.c:10146

c
void Wire3DCGB_FastMapBeginTilesOnly()
{
    w3dcgb_fast_map_ready = 1;
    w3dcgb_fm_x0 = 0;
    w3dcgb_fm_y0 = 0;
    w3dcgb_fm_count_x = 16;
    w3dcgb_fm_count_y = 12;
    w3dcgb_fast_map_clear_rect_asm();
}
Wire3DCGB_FastMapCell

Fügt einer Kartenzelle die ausgewählten oberen, unteren, linken und rechten Umrissseiten hinzu.

Syntax

c
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);

Parameter

tx

X-Position in Tile-Koordinaten.

ty

Y-Position in Tile-Koordinaten.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

mask

Zellseitenmaske: 1=oben, 2=unten, 4=links, 8=rechts.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Fügt einer Zelle Umrissseiten hinzu: Bits 1/2/4/8 bedeuten oben/unten/links/rechts. Masken gleicher Farbe werden kombiniert; eine andere Farbe ersetzt die alte Maske. Maske null wird ignoriert, Farbe null bedeutet MAIN, und Farben über 3 werden auf 3 begrenzt. Betrifft den 16×12-Schattenpuffer bei stabiler WRAM-Einblendung; benötigt die vollständige Laufzeitumgebung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:162

kitaqgb/lib/wire3d_cgb.c:10160

c
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask)
{
    w3dcgb_fast_map_or_cell((w3dcgb_i16)tx, (w3dcgb_i16)ty, color, mask);
}
Wire3DCGB_FastMapFlush

Überträgt die ersten zwölf vollständigen Zeilen der Schatten-Tile-Nummern und -Attribute ins VRAM.

Syntax

c
void Wire3DCGB_FastMapFlush();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wartet bei aktiviertem LCD auf einen neuen VBlank und überträgt dann die ersten zwölf vollständigen Kartenzeilen mit Tile-Nummern und Attributen nach Karte 9800. Bei ausgeschaltetem LCD geht es sofort weiter. Benötigt die vollständige Laufzeitumgebung, stabile WRAM-Einblendung und genügend sichere Zeit für beide sofortigen GDMA-Übertragungen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:164

kitaqgb/lib/wire3d_cgb.c:10208

c
void Wire3DCGB_FastMapFlush()
{
    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_gdma_asm();
}
Wire3DCGB_FastMapFlushTilesOnly

Überträgt nur die Tile-Nummern der ersten zwölf vollständigen Schattenkartenzeilen.

Syntax

c
void Wire3DCGB_FastMapFlushTilesOnly();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Wartet bei aktiviertem LCD auf einen neuen VBlank und überträgt nur die Tile-Nummern der ersten zwölf vollständigen Zeilen nach Karte 9800. Attribute bleiben erhalten. Benötigt die vollständige Laufzeitumgebung, stabile WRAM-Einblendung und ein sicheres GDMA-Zeitfenster.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:165

kitaqgb/lib/wire3d_cgb.c:10217

c
void Wire3DCGB_FastMapFlushTilesOnly()
{
    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_tiles_gdma_asm();
}
Wire3DCGB_FastMapRect

Setzt die ausgewählten Umrissseiten um ein Rechteck in Tile-Koordinaten.

Syntax

c
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);

Parameter

tx0

X-Position in Tile-Koordinaten.

ty0

Y-Position in Tile-Koordinaten.

tx1

X-Position in Tile-Koordinaten.

ty1

Y-Position in Tile-Koordinaten.

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

sides

Rechteckseitenmaske: 1=oben, 2=unten, 4=links, 8=rechts.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Ordnet die Byte-Tile-Koordinaten, begrenzt sie auf 16×12 und ersetzt die ausgewählten Randzellen. Seitenbits 1/2/4/8 bedeuten oben/unten/links/rechts. Farbe null bedeutet MAIN; Werte über 3 werden auf 3 begrenzt. Attribute und innere Zellen bleiben erhalten. Verwenden Sie mindestens zwei Zeilen und Spalten für getrennte Ecken; zusammenfallende Ecken werden nacheinander überschrieben. Benötigt die vollständige Laufzeitumgebung und stabile WRAM-Einblendung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:163

kitaqgb/lib/wire3d_cgb.c:10170

c
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides)
{
    w3dcgb_u8 t;

    if (tx0 > tx1)
    {
        t = tx0;
        tx0 = tx1;
        tx1 = t;
    }
    if (ty0 > ty1)
    {
        t = ty0;
        ty0 = ty1;
        ty1 = t;
    }
    if (tx0 >= 16) return;
    if (ty0 >= 12) return;
    if (tx1 >= 16) tx1 = 15;
    if (ty1 >= 12) ty1 = 11;
    if (color == 0) color = WIRE3DCGB_COLOR_MAIN;
    if (color > 3) color = 3;

    w3dcgb_fm_x0 = tx0;
    w3dcgb_fm_y0 = ty0;
    w3dcgb_fm_x1 = tx1;
    w3dcgb_fm_y1 = ty1;
    w3dcgb_fm_count_x = (w3dcgb_u8)(tx1 - tx0 + 1);
    w3dcgb_fm_count_y = (w3dcgb_u8)(ty1 - ty0 + 1);
    w3dcgb_fm_tile_base = (w3dcgb_u8)(W3DCGB_FAST_TILE_BASE + ((color - 1) << 4));
    w3dcgb_fm_sides = (w3dcgb_u8)(sides & 15);
    w3dcgb_fast_map_rect_asm();
}
Wire3DCGB_GetFullScreenOverflow

Meldet eine ungültige Koordinate oder erschöpfte Tile-Zuweisung beim Vollbildzeichnen.

Syntax

c
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow();

Rückgabewert

Null ohne Fehler, eins nach erschöpfter Zuweisung oder ungültiger Koordinate.

Bedingungen und Grenzen

Liefert das Fehlerflag des Vollbildframes: Der schnelle Linienpfad setzt es bei erschöpfter Tile-Zuweisung oder ungültiger Koordinate. Danach werden weitere Pixelzugriffe des schnellen Pfads unterdrückt, bis BeginFrame das Flag zurücksetzt. Dies ist kein allgemeines Hardwarestatusflag; der Getter benötigt die vollständige Laufzeitumgebung.

Die Vollbild-Zuweisung erfolgt, bevor Verdeckung und Overflow Pixelschreibzugriffe unterdrücken. Zugewiesene Tiles können schwarz bleiben; weiteres Zeichnen nach einem Fehler kann die Tile-Anzahl weiterhin erhöhen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
    u8 i;
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
    for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

127 rote Punkte belegen unterschiedliche Tiles. Der Versuch einer 128. Zuweisung lässt die Anzahl bei 127 und setzt overflow auf eins.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:194

kitaqgb/lib/wire3d_cgb.c:9965

c
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow()
{
    return w3dcgb_full_overflow;
}
Wire3DCGB_GetFullScreenTileCount

Liefert die Anzahl der im aktuellen Frame zugewiesenen Vollbild-Tiles.

Syntax

c
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount();

Rückgabewert

Anzahl zugewiesener Tiles, 0..127.

Bedingungen und Grenzen

Liefert die aktuelle Vollbild-Zuweisungsanzahl bis 127. Dies ist weder eine Byteanzahl noch die Anzahl sichtbarer oder von null verschiedener Pixel. Nur mit vollständiger Laufzeitumgebung.

Die Vollbild-Zuweisung erfolgt, bevor Verdeckung und Overflow Pixelschreibzugriffe unterdrücken. Zugewiesene Tiles können schwarz bleiben; weiteres Zeichnen nach einem Fehler kann die Tile-Anzahl weiterhin erhöhen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
    u8 i;
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
    for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

127 rote Punkte belegen unterschiedliche Tiles. Der Versuch einer 128. Zuweisung lässt die Anzahl bei 127 und setzt overflow auf eins.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:193

kitaqgb/lib/wire3d_cgb.c:9956

c
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount()
{
    return w3dcgb_full_tile_count;
}
Wire3DCGB_GetLineColor

Liest den aktuell gespeicherten Linienfarbindex.

Syntax

c
w3dcgb_u8 Wire3DCGB_GetLineColor();

Rückgabewert

Aktuell gespeicherter Linienfarbwert.

Bedingungen und Grenzen

Liefert die aktuell gespeicherte Zwei-Bit-Linienfarbe, ohne den Zeichenzustand zu ändern.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:120

kitaqgb/lib/wire3d_cgb.c:1147

c
w3dcgb_u8 Wire3DCGB_GetLineColor()
{
    return w3dcgb_line_color;
}
Wire3DCGB_Init

Initialisiert den CGB-Pixelrenderer für 128×96.

Syntax

c
void Wire3DCGB_Init();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Initialisiert den CGB-exklusiven 128×96-Renderer: Aktiviert den Doppeltakt, schaltet das LCD im VBlank aus, löscht beide Tile-Bänke, lädt HUD- und erzeugte Tiles und richtet einen spaltenweise angeordneten 16×12-Viewport ein. Der Startzustand verwendet die leere Tile-Bank 1, Scrollwerte null, Standard-BG-Paletten, Farbe 2 und eine auf null gesetzte Kamera. Setzt Warteschlangen zurück und löscht den Staging-Bereich in Bank 2. Rufen Sie vor dem Zeichnen BeginFrame auf, um den Verdeckungszustand zu initialisieren. Die Initialisierung ersetzt den LCD-, Tile- und Kartenzustand global.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:113

kitaqgb/lib/wire3d_cgb.c:7994

c
void Wire3DCGB_Init()
{
    w3dcgb_u8 row;
    w3dcgb_u8 col;
    w3dcgb_u8 tid;
    w3dcgb_u8 tile_index;
    w3dcgb_u16 off;

    w3dcgb_full_mode = 0;
    w3dcgb_atomic_maps = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_load_hud_tiles();
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
    w3dcgb_load_fast_map_tiles();
    w3dcgb_load_fast_stamp_tiles();
#endif
    w3dcgb_fill_bg_map_asm();
    w3dcgb_fill_attr_map_asm();

    row = 0;
    while (row < W3DCGB_TILE_H)
    {
        off = (w3dcgb_u16)((w3dcgb_u16)row << 5);
        tile_index = row;
        col = 0;
        while (col < W3DCGB_TILE_W)
        {
            if (tile_index < 112) tid = (w3dcgb_u8)(0x90 + tile_index);
            else tid = (w3dcgb_u8)(tile_index - 112);
            w3dcgb_bg_map_9800[(w3dcgb_u16)(off + (w3dcgb_u16)col)] = tid;
            tile_index = (w3dcgb_u8)(tile_index + W3DCGB_TILE_H);
            col = (w3dcgb_u8)(col + 1);
        }
        row = (w3dcgb_u8)(row + 1);
    }

    w3dcgb_select_blank_render_bank_asm();

    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_reg_lcdc = 0x81;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_dirty_min_tile = 0xFF;
    w3dcgb_dirty_max_tile = 0;
    // Both back banks may contain generated fast-map/stamp tiles. Refresh
    // the whole pixel viewport on their first sparse use, including empty rows.
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_display_tile_bank = 1;
    w3dcgb_pending_tile_bank = 1;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_clear_stage_asm();
}
Wire3DCGB_InitFastMapLite

Initialisiert das FastMap-Rendering mit vorberechneten Umriss-Tiles.

Syntax

c
void Wire3DCGB_InitFastMapLite();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Initialisiert einen CGB-Tilemap-Renderer mit HUD und 48 vorberechneten Umriss-Tiles. Löscht Tile-VRAM und Karten, setzt Scrolling, Paletten und Kamera zurück und wählt den normalen Modus. Das übliche Kartenlayout des Pixel-Viewports und erzeugte Würfelstempel entfallen; verwenden Sie in diesem Modus die FastMap-APIs. Löscht den Staging-Bereich in Bank 2 und markiert die FastMap-Vorbereitung als ausstehend. Ein Build mit vollständiger Laufzeitumgebung ist erforderlich.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Eine rote Ecke, ein großes blaues Rechteck und ein grüner Rahmen von einem Tile zeigen die Umrisszellen. Die anfängliche rote Zelle oben links verschwindet; beim reinen Tile-Update bleiben die Attribute erhalten.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:115

kitaqgb/lib/wire3d_cgb.c:8108

c
void Wire3DCGB_InitFastMapLite()
{
    w3dcgb_atomic_maps = 0;
    w3dcgb_full_mode = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_load_hud_tiles();
    w3dcgb_load_fast_map_tiles_lite_asm();
    w3dcgb_fill_bg_map_asm();
    w3dcgb_fill_attr_map_asm();

    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_reg_lcdc = 0x81;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_dirty_min_tile = 0xFF;
    w3dcgb_dirty_max_tile = 0;
    w3dcgb_prev_dirty_min_tile = 0xFF;
    w3dcgb_prev_dirty_max_tile = 0;
    w3dcgb_fast_map_ready = 0;
    w3dcgb_display_tile_bank = 0;
    w3dcgb_pending_tile_bank = 0;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_clear_stage_asm();
}
Wire3DCGB_InitFullScreen

Initialisiert einen 160×144-Renderer, der beim Zeichnen von Pixeln Tiles zuweist.

Syntax

c
void Wire3DCGB_InitFullScreen();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Initialisiert den CGB-exklusiven Tile-Allokator für 160×144. Löscht beide Tile-Bänke und Karte 9800, setzt Scrolling, Paletten, Farbe und Kamera, setzt Tile-Zähler sowie Lookup- und Span-Zustand zurück und aktiviert die vorzeichenlose BG-Tile-Adressierung. HUD-Tiles werden nicht geladen. Reservieren Sie die festen WRAM-Bereiche für Lookup, Nutzdaten und Adresslisten. Lassen Sie beim gesamten Vollbild-Rendering dieselbe WRAM-Bank eingeblendet.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// A large frame demonstrates the 160x144 renderer and its allocated-tile count.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,151,8);
    Wire3DCGB_DrawLine2D(8,8,8,135);
    Wire3DCGB_DrawLine2DColor(8,135,151,135,2);
    Wire3DCGB_DrawLine2DColor(151,8,151,135,3);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrameFast();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein großer Rahmen reicht von (8,8) bis (151,135): oben und links rot, unten blau, rechts grün. Er verwendet 64 Tiles bei overflow null.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_full.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_full.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:114

kitaqgb/lib/wire3d_cgb.c:8070

c
void Wire3DCGB_InitFullScreen()
{
    w3dcgb_atomic_maps = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_full_clear_map_asm();
    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_display_tile_bank = 0;
    w3dcgb_pending_tile_bank = 0;
    w3dcgb_full_tile_count = 0;
    w3dcgb_full_prev_tile_count = 0;
    w3dcgb_full_overflow = 0;
    w3dcgb_full_mode = 1;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_full_begin_asm();
    w3dcgb_reg_lcdc = 0x91;
}
Wire3DCGB_InvalidateFrameHistory

Erweitert den aktuellen und die beiden vorherigen Übertragungsbereiche auf alle 192 Tiles des normalen Modus.

Syntax

c
void Wire3DCGB_InvalidateFrameHistory();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert den aktuellen und beide vorherigen partiellen Bereiche als alle 192 Tiles des normalen Modus. Pixeldaten werden nicht gelöscht; spätere Übertragungen können sich nicht mehr auf alte Bereiche verlassen.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:142

kitaqgb/lib/wire3d_cgb.c:9712

c
void Wire3DCGB_InvalidateFrameHistory()
{
    w3dcgb_dirty_min_tile = 0;
    w3dcgb_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
}
Wire3DCGB_MarkDirtyRect2D

Fügt dem später zu übertragenden Bereich ein Pixelrechteck hinzu.

Syntax

c
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);

Parameter

min_x

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

min_y

Unterer Y-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

max_x

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

max_y

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert ein Pixelrechteck einschließlich seiner Endpunkte zur späteren Übertragung, ohne es zu zeichnen. Geben Sie die Endpunkte geordnet an; Werte oberhalb von 127/95 werden auf den Rand begrenzt. Dies erfasst die 128×96-Tiles, nicht den Vollbild-Tile-Allokator.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Die zuvor gezeichneten roten und blauen Rahmen verschwinden; nur der letzte grüne Rahmen bei (80,8)..(112,32) bleibt. Dies zeigt partielle Übertragung und Verlaufsverwaltung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:126

kitaqgb/lib/wire3d_cgb.c:1288

c
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y)
{
    w3dcgb_mark_dirty_rect(min_x, min_y, max_x, max_y);
}
Wire3DCGB_MarkPackedSilhouette2D

Markiert eine zeilenweise gepackte Silhouette in der 128×96-Verdeckungsbitmap.

Syntax

c
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);

Parameter

profile

Silhouettenarray mit einem Byte je Zeile; 0xFF überspringt eine Zeile.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

y0

Vorzeichenbehafteter Versatz vom Y-Mittelpunkt zur ersten Silhouettenzeile.

x

X-Koordinate des Mittelpunkts in Viewport-Pixeln.

y

Y-Koordinate des Mittelpunkts in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert bis zu 29 Silhouettenzeilen in der 128×96-Bitmap-Maske. Das obere Nibble jedes gepackten Bytes beschreibt den Mittenversatz (nibble−7), das untere die halbe Breite; 0xFF überspringt eine Zeile. Die Zeilen liegen bei y+y0+i; ihre Spans werden um zwei Pixel erweitert und auf den Viewport begrenzt. profile muss count lesbare Bytes enthalten; null wird ignoriert. Aktualisiert weder Vollbild-Spans noch aktiviert es Verdeckung.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein Dreieck verdeckt die Mitte roter Rasterzeilen; eine gepackte Silhouette verdeckt blaue Linien. Grüne Umrisse zeigen die Lage des verdeckenden Bereichs.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:151

kitaqgb/lib/wire3d_cgb.c:1991

c
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                     w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 i;
    w3dcgb_u8 packed;
    w3dcgb_u8 half_width;
    w3dcgb_i16 center;
    w3dcgb_i16 left;
    w3dcgb_i16 right;
    w3dcgb_i16 row;

    if (profile == 0) return;
    if (count > 29) count = 29;
    i = 0;
    while (i < count)
    {
        packed = profile[(__safe_index w3dcgb_u8)i];
        if (packed != 0xFF)
        {
            row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
            if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
            {
                center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
                half_width = (w3dcgb_u8)(packed & 15);
                /* Two-pixel guard covers rasterized endpoints at 22.5-degree views. */
                left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
                right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
                if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
                {
                    if (left < 0) left = 0;
                    if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
                    w3dcgb_mask_span_y = (w3dcgb_u8)row;
                    w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
                    w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
                    w3dcgb_mask_set_span_asm();
                }
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_MarkTriangle2D

Registriert ein Dreieck als Bereich, der anschließend gezeichnete Linien verdecken kann.

Syntax

c
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

cx

X-Koordinate von Eckpunkt C in Viewport-Pixeln.

cy

Y-Koordinate von Eckpunkt C in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Markiert ein Dreieck in Bildschirmkoordinaten, ohne Pixel zu zeichnen oder Verdeckung zu aktivieren. Die Eckpunkte müssen im gewählten Viewport liegen. Der verwendete ASM-Code ergänzt einen Schutzrand von einem Pixel in X, begrenzt auf 0..127 im Modus 128×96 beziehungsweise 0..159 im Modus 160×144. Beliebige außerhalb liegende Dreiecke werden nicht zugeschnitten.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein Dreieck verdeckt die Mitte roter Rasterzeilen; eine gepackte Silhouette verdeckt blaue Linien. Grüne Umrisse zeigen die Lage des verdeckenden Bereichs.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:150

kitaqgb/lib/wire3d_cgb.c:1980

c
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
    w3dcgb_mark_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DCGB_ProjectAxis48

Nähert einen projizierten Versatz mit Brennweite 48 an.

Syntax

c
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);

Parameter

value

Zu projizierende vorzeichenbehaftete 16-Bit-Komponente.

z

Tiefe zur Größenauswahl oder Projektionsberechnung.

Rückgabewert

Angenäherter vorzeichenbehafteter 16-Bit-Projektionsversatz.

Bedingungen und Grenzen

Nähert value*48/z ohne Kamera- oder Bildschirmmittenversatz an. Negative oder sehr kleine Z-Werte werden zu 4. Bei Z über 255 werden Tiefe und Betrag gemeinsam nach rechts geschoben, bis die Tiefe in ein Byte passt; danach wird der Betrag auf 160 begrenzt. Liefert einen vorzeichenbehafteten Versatz; der Helfer verwirft keine nahen oder fernen Tiefenwerte.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Zwei rote waagerechte Kanten, ein blaues Quadrat, ein begrenzter grüner Rahmen, eine grüne Sechs-Pixel-Markierung und ein rotes Projektil vergleichen die Listenformate.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:141

kitaqgb/lib/wire3d_cgb.c:9702

c
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z)
{
    w3dcgb_projection_value = value;
    w3dcgb_projection_z = z;
    w3dcgb_project_axis48_asm();
    return w3dcgb_projection_result;
}
Wire3DCGB_ProjectPoint

Projiziert einen Weltpunkt durch die Kamera in den 128×96-Viewport.

Syntax

c
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parameter

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

sx

Gültiger beschreibbarer u8-Zeiger für die projizierte X-Koordinate.

sy

Gültiger beschreibbarer u8-Zeiger für die projizierte Y-Koordinate.

Rückgabewert

Liefert 1 bei erfolgreicher Projektion oder 0 bei verworfener Tiefe.

Bedingungen und Grenzen

Projiziert einen Weltpunkt durch die aktuelle Kamera in den 128×96-Viewport. Bei verworfener Tiefe wird null zurückgegeben und die Ausgabe bleibt unverändert; andernfalls werden begrenzte Byte-Koordinaten geschrieben. Gültige beschreibbare Zeiger sind erforderlich. Dies ist nicht der 160×144-Vollbildprojektor. In MINIMAL_RUNTIME-Builds nicht enthalten.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:169

kitaqgb/lib/wire3d_cgb.c:589

c
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy)
{
    return w3dcgb_project_world(x, y, z, sx, sy);
}
Wire3DCGB_ProjectPointNoRotation

Projiziert einen Punkt nach Abzug der Kameraposition ohne Kamerarotation.

Syntax

c
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parameter

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

sx

Gültiger beschreibbarer u8-Zeiger für die projizierte X-Koordinate.

sy

Gültiger beschreibbarer u8-Zeiger für die projizierte Y-Koordinate.

Rückgabewert

Liefert 1 bei erfolgreicher Projektion oder 0 bei verworfener Tiefe.

Bedingungen und Grenzen

Schneller Pfad für Spiele, deren Kamerawinkel für Nicken, Gieren und Rollen null bleiben. Zieht die Kameraposition ab und projiziert nach 128×96, wobei alle Kamerawinkel ignoriert werden. Nur bei drei Nullwinkeln verwenden. Ungültige Tiefe wird ohne Änderung der Ausgabeziele verworfen; erfolgreiche Koordinaten werden auf den Viewport begrenzt. In MINIMAL_RUNTIME-Builds nicht enthalten.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:171

Deklarationshinweise im Original
Fast path for games whose camera pitch, yaw, and roll stay at zero.

kitaqgb/lib/wire3d_cgb.c:598

c
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z,
                                            w3dcgb_u8* sx, w3dcgb_u8* sy)
{
    return w3dcgb_project_camera_space((w3dcgb_i16)(x - w3dcgb_cam_x),
                                        (w3dcgb_i16)(y - w3dcgb_cam_y),
                                        (w3dcgb_i16)(z - w3dcgb_cam_z), sx, sy);
}
Wire3DCGB_PutBgTile

Reiht eine Änderung der Hintergrund-Tile-Nummer für EndFrame ein.

Syntax

c
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);

Parameter

x

X-Tile-Koordinate in der 32×32-Hintergrundkarte.

y

Y-Tile-Koordinate in der 32×32-Hintergrundkarte.

tile

Acht-Bit-Tile-Nummer für die Hintergrundzelle.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Reiht einen Tile-Nummer-Schreibzugriff für eine 32×32-BG-Karte ein. Ungültige Koordinaten und weitere Einträge nach 48 ausstehenden Schreibzugriffen werden ignoriert. EndFrame leert diese private Warteschlange; im atomic-map-Modus werden Schreibzugriffe in beide BG-Karten übernommen. Attribute werden nicht eingereiht.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:188

kitaqgb/lib/wire3d_cgb.c:1067

c
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3dcgb_bgq_count >= W3DCGB_BG_QUEUE_LIMIT) return;
    w3dcgb_bgq_x[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = x;
    w3dcgb_bgq_y[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = y;
    w3dcgb_bgq_tile[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = tile;
    w3dcgb_bgq_count = (w3dcgb_u8)(w3dcgb_bgq_count + 1);
}
WIRE3DCGB_RGB15

Packt rote, grüne und blaue Fünf-Bit-Kanäle in eine CGB-15-Bit-Farbe.

Syntax

c
#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))

Parameter

r5

Rotkanal, 0..31.

g5

Grünkanal, 0..31.

b5

Blaukanal, 0..31.

Rückgabewert

Gepackter RGB15-Wert als u16.

Bedingungen und Grenzen

Packt die unteren fünf Bits jedes Kanals in RGB15; jedes Argument wird genau einmal ausgewertet.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:50

Wire3DCGB_SetCamera

Speichert Kameraposition und -ausrichtung für die Projektion mit 16 Winkelschritten pro Umdrehung.

Syntax

c
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);

Parameter

x

X-Komponente der Kamera in Weltkoordinaten.

y

Y-Komponente der Kamera in Weltkoordinaten.

z

Z-Komponente der Kamera in Weltkoordinaten.

pitch

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

yaw

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

roll

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Speichert Kameraposition und -winkel, ohne vorhandene Pixel zu ändern. Rotationshelfer verwenden die unteren vier Winkelbits, also 16 Schritte pro Umdrehung. Bildschirmversätze liegen in separaten LCD-Registern und werden durch diesen Aufruf nicht geändert.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Vergleicht Modelle in Originalgröße und skalierte Modelle in Rot, Blau und Grün sowie sich kreuzende 3D-Linien. RAM-Werte prüfen zusätzlich die Kameraprojektion und deren Variante ohne Rotation.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:127

kitaqgb/lib/wire3d_cgb.c:8266

c
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll)
{
    w3dcgb_cam_x = x;
    w3dcgb_cam_y = y;
    w3dcgb_cam_z = z;
    w3dcgb_cam_pitch = pitch;
    w3dcgb_cam_yaw = yaw;
    w3dcgb_cam_roll = roll;
}
Wire3DCGB_SetLineColor

Wählt den Farbindex für anschließend gezeichnete Linien.

Syntax

c
void Wire3DCGB_SetLineColor(w3dcgb_u8 color);

Parameter

color

Zeichenfarbindex; die Beispielpaletten verwenden 1=Rot, 2=Blau und 3=Grün.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Speichert color & 3. Verwenden Sie die benannten Linienfarben 1..3: Normale Linien verknüpfen ihre Bitebenen mit OR, sodass sich Farben an Schnittpunkten kombinieren; schnelle Vollbildlinien ersetzen dagegen die Pixelfarbe. Linienfarbe null wird als 3 behandelt und löscht nicht. Beim Zeichnen von Punkten im normalen Modus wird Farbe null unabhängig davon zum Löschen unterstützt.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:119

kitaqgb/lib/wire3d_cgb.c:1140

c
void Wire3DCGB_SetLineColor(w3dcgb_u8 color)
{
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
}
Wire3DCGB_SetOcclusionActive

Aktiviert oder deaktiviert die Verdeckungsprüfung für nachfolgende Linien.

Syntax

c
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);

Parameter

active

Null deaktiviert die Verdeckungsprüfung; jeder andere Wert aktiviert sie.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Normalisiert active auf null oder eins und speichert es als Verdeckungsschalter. Es werden weder Masken gelöscht noch Geometrie markiert.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Ein Dreieck verdeckt die Mitte roter Rasterzeilen; eine gepackte Silhouette verdeckt blaue Linien. Grüne Umrisse zeigen die Lage des verdeckenden Bereichs.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:149

kitaqgb/lib/wire3d_cgb.c:1970

c
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active)
{
    if (active == 0) w3dcgb_occlusion_active = 0;
    else w3dcgb_occlusion_active = 1;
}
Wire3DCGB_SetPaletteRGB15

Setzt die vier Zeichenfarben und die Hintergrundpaletten zum Einfärben der Stempel.

Syntax

c
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);

Parameter

color0

RGB15-Farbe in Paletteneintrag 0.

color1

RGB15-Farbe in Paletteneintrag 1.

color2

RGB15-Farbe in Paletteneintrag 2.

color3

RGB15-Farbe in Paletteneintrag 3.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Setzt BG-Palette 0 auf die vier übergebenen RGB15-Farben. Die Paletten 1..3 teilen sich color0 und wiederholen ihre jeweilige Farbe mit Index ungleich null in den Einträgen 1..3. So lassen sich monochrome Stempel-Tiles über Attribute umfärben. Rufen Sie die Funktion in einem zulässigen Zeitfenster für Palettenzugriffe auf, üblicherweise beim Einrichten mit ausgeschaltetem LCD oder im VBlank.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:118

kitaqgb/lib/wire3d_cgb.c:1112

c
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3)
{
    w3dcgb_write_bg_color(0, color0);
    w3dcgb_write_bg_color(1, color1);
    w3dcgb_write_bg_color(2, color2);
    w3dcgb_write_bg_color(3, color3);

    w3dcgb_write_bg_color(4, color0);
    w3dcgb_write_bg_color(5, color1);
    w3dcgb_write_bg_color(6, color1);
    w3dcgb_write_bg_color(7, color1);

    w3dcgb_write_bg_color(8, color0);
    w3dcgb_write_bg_color(9, color2);
    w3dcgb_write_bg_color(10, color2);
    w3dcgb_write_bg_color(11, color2);

    w3dcgb_write_bg_color(12, color0);
    w3dcgb_write_bg_color(13, color3);
    w3dcgb_write_bg_color(14, color3);
    w3dcgb_write_bg_color(15, color3);
}
Wire3DCGB_SetScreenOffset

Setzt die LCD-Scrollregister SCX und SCY direkt.

Syntax

c
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);

Parameter

scx

In SCX geschriebener Scrollversatz in Pixeln.

scy

In SCY geschriebener Scrollversatz in Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

Schreibt SCX/SCY sofort, ohne auf VBlank zu warten oder projizierte Koordinaten zu ändern. Der Aufrufer bestimmt, wann eine sichtbare Scrolländerung akzeptabel ist.

Nur CGB. Das normale Staging reserviert D300..DEFF in WRAM-Bank 2. Wegen des gemeinsam genutzten Zustands sind diese Routinen nicht reentrant; rufen Sie sie nicht rekursiv aus Interrupts auf. Die Beispiele verwenden einen festen Stack und die vollständige Laufzeitumgebung.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt einfache Linien, Punkte, Löschen und Projektion in einem Frame. Ein roter Rahmen enthält eine blaue Diagonale, einen grünen Punkt und eine grüne waagerechte Linie, ein blaues L sowie eine grüne Null oben rechts.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:117

kitaqgb/lib/wire3d_cgb.c:1091

c
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy)
{
    w3dcgb_reg_scx = scx;
    w3dcgb_reg_scy = scy;
}

Wire3D-Zeitmessung, Profile mit 88 Zeilen und unabhängige Takte

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Ein vollständiger Transfer mit 88 Zeilen liest bei DMG 1.408 Byte und bei CGB 2.816 Byte. Gegenüber DMG 120 sinkt die Datenmenge um 26,67 %, gegenüber 96 Zeilen um 8,33 %; daraus folgt keine entsprechende fps-Steigerung. DMG behält 256-Byte-Spaltenabstände, CGB packt Spalten mit 11 Kacheln. CGB reserviert weiterhin 3.072 Byte für die Kompatibilität zum Vollbildmodus.

ProjectCameraPoint projiziert Kamerakoordinaten ohne Kamerasubtraktion oder -rotation. Außerhalb Z=8..255 liefert es 0 und lässt die Ausgaben unverändert. X/Y werden auf ±120 begrenzt; Produkte der inversen Tiefentabelle werden vorzeichenbehaftet mit Abrundung durch 32 geteilt und danach auf den Bildschirm begrenzt. Dies ist kein geometrisches Abschneiden von Linien. Das allgemeine CGB ProjectPoint behält die Rotationsgrenzen ±220 auch bei Nullwinkeln.

DMG EndFrameNow überspringt nur das anfängliche Warten auf einen neuen VBlank und verarbeitet BG-Warteschlange, Transfermodi und dirty-Historie. CGB EndFrameSparseNow arbeitet ebenfalls synchron. Now wartet weiterhin auf STAT-Zugriff, DMA-Ende und sichere Anzeige. DMG-Aktualisierungen sind nicht atomar. Beim CGB-sparse-Löschen zählen der aktuelle Bereich und der zwei Bilder alte Bereich der Zielbank. Niedrige CGB-Linienfunktionen brauchen dirty-Markierungen.

Beim CGB-Sparse-Start aktualisiert die erste Nutzung jeder Zielbank (die ersten zwei Bilder) den gesamten Ausschnitt und entfernt Initialisierungskacheln. Diese Startkosten sind enthalten. DrawLine2D erfasst keine Sparse-Bereiche: DrawLineClipped2D oder ausdrücklich MarkDirtyRect2D verwenden.

Die Beispiele verwenden einen unabhängig erstellten bewegten Quader, eine Balkenanzeige und vier BGM-Töne. Die Bewegung nutzt verstrichene audio_vblank-Ticks; eine kurze sichere VBlank-Routine aktualisiert die Anzeige. Rufen Sie den Renderer mit gemeinsamem Zustand nie aus einer ISR auf. wire3d_audio_vblank.c legt die 80-Byte-Warteschlange in festen WRAM und Steuerfunktionen in ROM-Bank 5. Kompilieren Sie nicht zusätzlich audio_vblank.c. CGB-Beispiele nutzen WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lesen Sie die Differenz eines 8-Bit-Ticks innerhalb von 255 Bildern.

Das Messwerkzeug zählt Marker nach abgeschlossenem Transfer und Anzeigenwechsel. PPU-Dots (4.194.304/s; 70.224/Bild) erfassen Löschen, Projektion, Rasterung, Transfer samt Anzeige und äußere Wartezeit. Berichtet werden Mittelwert, Median, größtes Intervall und überschrittene Fristen. Transfer samt Anzeige umfasst interne STAT/DMA/VBlank-Wartezeiten. Vergleichen Sie rohe CGB-CPU-Zyklen bei doppeltem Takt nicht direkt mit DMG. Gleiche mittlere fps belegen keine Einhaltung aller Fristen. Reale Hardware ist nicht geprüft.

Sieben eigene Beispielkonfigurationen führten je 48 Transfers aus: 336 Stage/VRAM-Vergleiche und 84 Leerbilder zur Löschprüfung. Fünf Profile bestanden 25.700 Projektionsgrenzfälle. Fünf Rust-Builds beendeten ebenfalls 48 Bilder mit BGM-Ausgabe. Einige Intervalle überschreiten vier PPU-Bilder: Durchschnitts-fps beweisen keinen Betrieb ohne Verzögerung. Emulatorprüfung, keine Hardwareverifikation.

KOKURA führte die eigenen DMG/CGB-Beispiele je 400 Bilder aus; SARAKURA-Analyse und strenge Schemavalidierung bestanden. Jeweils bleiben null Fehler, eine Warnung für wiederholten PC in der Warteschleife und drei Hinweise, darunter DAC/Mixer-Knackrisiken. Audiotreue und Hardwareverhalten sind damit nicht bestätigt.

Veröffentlichte Beispiele, Bilder und Prüfdaten verwenden ausschließlich unabhängig erstellte Geometrie, Anzeigen und Tonfolgen. Sie enthalten keine kommerziellen Spiel-ROMs, extrahierten Code, Spielgeometrie, Bildschirmbilder, Musik oder Zustandsdateien.

Prüfergebnisse und Beispiele · C / BGM / HUD

ProfilfpsMedian / Maximum (PPU-Bilder)Fristüberschreitungen / 47
clocked_dmg_88_sparse13.8524.449 / 4.73235
clocked_dmg_96_sparse13.1864.669 / 4.89139
clocked_dmg_120_sparse13.4344.453 / 7.17635
clocked_cgb_88_sparse15.0124.000 / 5.00028
clocked_cgb_96_sparse15.0924.000 / 5.00026
clocked_cgb_88_full12.5325.000 / 6.00041
clocked_cgb_96_full12.5885.000 / 5.02041
Original DMG box and bar gauge
DMG 128×88 · Veröffentlichte Beispiele, Bilder und Prüfdaten verwenden ausschließlich unabhängig erstellte Geometrie, Anzeigen und Tonfolgen. Sie enthalten keine kommerziellen Spiel-ROMs, extrahierten Code, Spielgeometrie, Bildschirmbilder, Musik oder Zustandsdateien.
Original CGB box and bar gauge
CGB 128×88 · Veröffentlichte Beispiele, Bilder und Prüfdaten verwenden ausschließlich unabhängig erstellte Geometrie, Anzeigen und Tonfolgen. Sie enthalten keine kommerziellen Spiel-ROMs, extrahierten Code, Spielgeometrie, Bildschirmbilder, Musik oder Zustandsdateien.
Wire3DDMG_ProjectCameraPoint

ProjectCameraPoint projiziert Kamerakoordinaten ohne Kamerasubtraktion oder -rotation. Außerhalb Z=8..255 liefert es 0 und lässt die Ausgaben unverändert. X/Y werden auf ±120 begrenzt; Produkte der inversen Tiefentabelle werden vorzeichenbehaftet mit Abrundung durch 32 geteilt und danach auf den Bildschirm begrenzt. Dies ist kein geometrisches Abschneiden von Linien. Das allgemeine CGB ProjectPoint behält die Rotationsgrenzen ±220 auch bei Nullwinkeln.

Syntax

c
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);

Parameter

x

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

y

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

z

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

sx

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

sy

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

Rückgabewert

Liefert bei erfolgreicher Projektion 1, bei verworfener Tiefe 0. Ein Verwerfen lässt sx und sy unverändert.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Die Beispiele verwenden einen unabhängig erstellten bewegten Quader, eine Balkenanzeige und vier BGM-Töne. Die Bewegung nutzt verstrichene audio_vblank-Ticks; eine kurze sichere VBlank-Routine aktualisiert die Anzeige. Rufen Sie den Renderer mit gemeinsamem Zustand nie aus einer ISR auf. wire3d_audio_vblank.c legt die 80-Byte-Warteschlange in festen WRAM und Steuerfunktionen in ROM-Bank 5. Kompilieren Sie nicht zusätzlich audio_vblank.c. CGB-Beispiele nutzen WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lesen Sie die Differenz eines 8-Bit-Ticks innerhalb von 255 Bildern.

Das Messwerkzeug zählt Marker nach abgeschlossenem Transfer und Anzeigenwechsel. PPU-Dots (4.194.304/s; 70.224/Bild) erfassen Löschen, Projektion, Rasterung, Transfer samt Anzeige und äußere Wartezeit. Berichtet werden Mittelwert, Median, größtes Intervall und überschrittene Fristen. Transfer samt Anzeige umfasst interne STAT/DMA/VBlank-Wartezeiten. Vergleichen Sie rohe CGB-CPU-Zyklen bei doppeltem Takt nicht direkt mit DMG. Gleiche mittlere fps belegen keine Einhaltung aller Fristen. Reale Hardware ist nicht geprüft.

Anwendungsbeispiel

c
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void project_one() {
    u8 sx; u8 sy;
    if (Wire3DDMG_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
        // Use the projected coordinates in a main-thread drawing routine.
    }
}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Sieben eigene Beispielkonfigurationen führten je 48 Transfers aus: 336 Stage/VRAM-Vergleiche und 84 Leerbilder zur Löschprüfung. Fünf Profile bestanden 25.700 Projektionsgrenzfälle. Fünf Rust-Builds beendeten ebenfalls 48 Bilder mit BGM-Ausgabe. Einige Intervalle überschreiten vier PPU-Bilder: Durchschnitts-fps beweisen keinen Betrieb ohne Verzögerung. Emulatorprüfung, keine Hardwareverifikation.

Vollständiges Beispielprogramm

renderer_dmg_88.c

hardware.c

audio_glue.c

README.md

Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:146

Deklarationshinweise im Original
Validate depth and project coordinates already in camera space.

kitaqgb/lib/wire3d_dmg.c:720

c
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy)
{
 return w3ddmg_project_camera_space(x,y,z,sx,sy);
}
Wire3DCGB_ProjectCameraPoint

ProjectCameraPoint projiziert Kamerakoordinaten ohne Kamerasubtraktion oder -rotation. Außerhalb Z=8..255 liefert es 0 und lässt die Ausgaben unverändert. X/Y werden auf ±120 begrenzt; Produkte der inversen Tiefentabelle werden vorzeichenbehaftet mit Abrundung durch 32 geteilt und danach auf den Bildschirm begrenzt. Dies ist kein geometrisches Abschneiden von Linien. Das allgemeine CGB ProjectPoint behält die Rotationsgrenzen ±220 auch bei Nullwinkeln.

Syntax

c
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parameter

x

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

y

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

z

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

sx

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

sy

Vorzeichenbehaftete 16-Bit-Kamerakoordinaten X/Y/Z. sx und sy müssen gültige beschreibbare u8-Zeiger sein.

Rückgabewert

Liefert bei erfolgreicher Projektion 1, bei verworfener Tiefe 0. Ein Verwerfen lässt sx und sy unverändert.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Die Beispiele verwenden einen unabhängig erstellten bewegten Quader, eine Balkenanzeige und vier BGM-Töne. Die Bewegung nutzt verstrichene audio_vblank-Ticks; eine kurze sichere VBlank-Routine aktualisiert die Anzeige. Rufen Sie den Renderer mit gemeinsamem Zustand nie aus einer ISR auf. wire3d_audio_vblank.c legt die 80-Byte-Warteschlange in festen WRAM und Steuerfunktionen in ROM-Bank 5. Kompilieren Sie nicht zusätzlich audio_vblank.c. CGB-Beispiele nutzen WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lesen Sie die Differenz eines 8-Bit-Ticks innerhalb von 255 Bildern.

Das Messwerkzeug zählt Marker nach abgeschlossenem Transfer und Anzeigenwechsel. PPU-Dots (4.194.304/s; 70.224/Bild) erfassen Löschen, Projektion, Rasterung, Transfer samt Anzeige und äußere Wartezeit. Berichtet werden Mittelwert, Median, größtes Intervall und überschrittene Fristen. Transfer samt Anzeige umfasst interne STAT/DMA/VBlank-Wartezeiten. Vergleichen Sie rohe CGB-CPU-Zyklen bei doppeltem Takt nicht direkt mit DMG. Gleiche mittlere fps belegen keine Einhaltung aller Fristen. Reale Hardware ist nicht geprüft.

Anwendungsbeispiel

c
#define WIRE3DCGB_HEIGHT 88
#include "wire3d_cgb.h"
void project_one() {
    u8 sx; u8 sy;
    if (Wire3DCGB_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
        // Use the projected coordinates in a main-thread drawing routine.
    }
}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Sieben eigene Beispielkonfigurationen führten je 48 Transfers aus: 336 Stage/VRAM-Vergleiche und 84 Leerbilder zur Löschprüfung. Fünf Profile bestanden 25.700 Projektionsgrenzfälle. Fünf Rust-Builds beendeten ebenfalls 48 Bilder mit BGM-Ausgabe. Einige Intervalle überschreiten vier PPU-Bilder: Durchschnitts-fps beweisen keinen Betrieb ohne Verzögerung. Emulatorprüfung, keine Hardwareverifikation.

Vollständiges Beispielprogramm

renderer_cgb_88.c

hardware.c

audio_glue.c

README.md

Implementierung und Quelltext

kitaqgb/lib/wire3d_cgb.h:168

Deklarationshinweise im Original
Project camera-space coordinates without subtracting/rotating the camera.
Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.

kitaqgb/lib/wire3d_cgb.c:552

c
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x,w3dcgb_i16 y,w3dcgb_i16 z,w3dcgb_u8* sx,w3dcgb_u8* sy)
{
    return w3dcgb_project_camera_space(x,y,z,sx,sy);
}
Wire3DDMG_EndFrameNow

DMG EndFrameNow überspringt nur das anfängliche Warten auf einen neuen VBlank und verarbeitet BG-Warteschlange, Transfermodi und dirty-Historie. CGB EndFrameSparseNow arbeitet ebenfalls synchron. Now wartet weiterhin auf STAT-Zugriff, DMA-Ende und sichere Anzeige. DMG-Aktualisierungen sind nicht atomar. Beim CGB-sparse-Löschen zählen der aktuelle Bereich und der zwei Bilder alte Bereich der Zielbank. Niedrige CGB-Linienfunktionen brauchen dirty-Markierungen.

Syntax

c
void Wire3DDMG_EndFrameNow();

Rückgabewert

Kein Rückgabewert; kehrt nach Transfer und erforderlicher Synchronisierung zurück.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Die Beispiele verwenden einen unabhängig erstellten bewegten Quader, eine Balkenanzeige und vier BGM-Töne. Die Bewegung nutzt verstrichene audio_vblank-Ticks; eine kurze sichere VBlank-Routine aktualisiert die Anzeige. Rufen Sie den Renderer mit gemeinsamem Zustand nie aus einer ISR auf. wire3d_audio_vblank.c legt die 80-Byte-Warteschlange in festen WRAM und Steuerfunktionen in ROM-Bank 5. Kompilieren Sie nicht zusätzlich audio_vblank.c. CGB-Beispiele nutzen WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lesen Sie die Differenz eines 8-Bit-Ticks innerhalb von 255 Bildern.

Das Messwerkzeug zählt Marker nach abgeschlossenem Transfer und Anzeigenwechsel. PPU-Dots (4.194.304/s; 70.224/Bild) erfassen Löschen, Projektion, Rasterung, Transfer samt Anzeige und äußere Wartezeit. Berichtet werden Mittelwert, Median, größtes Intervall und überschrittene Fristen. Transfer samt Anzeige umfasst interne STAT/DMA/VBlank-Wartezeiten. Vergleichen Sie rohe CGB-CPU-Zyklen bei doppeltem Takt nicht direkt mit DMG. Gleiche mittlere fps belegen keine Einhaltung aller Fristen. Reale Hardware ist nicht geprüft.

Anwendungsbeispiel

c
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void draw_one() {
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,32,32);
    Wire3DDMG_PutBgTile(18,16,128);
    Wire3DDMG_EndFrameNow();
}

Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.

Erwartetes Ergebnis

Sieben eigene Beispielkonfigurationen führten je 48 Transfers aus: 336 Stage/VRAM-Vergleiche und 84 Leerbilder zur Löschprüfung. Fünf Profile bestanden 25.700 Projektionsgrenzfälle. Fünf Rust-Builds beendeten ebenfalls 48 Bilder mit BGM-Ausgabe. Einige Intervalle überschreiten vier PPU-Bilder: Durchschnitts-fps beweisen keinen Betrieb ohne Verzögerung. Emulatorprüfung, keine Hardwareverifikation.

Vollständiges Beispielprogramm

renderer_dmg_88.c

hardware.c

audio_glue.c

README.md

Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:289

Deklarationshinweise im Original
Same queue/gate/history lifecycle, without the initial fresh-VBlank wait.
Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.

kitaqgb/lib/wire3d_dmg.c:3826

c
void Wire3DDMG_EndFrameNow()
{
    w3ddmg_flush_bg_queue();



    if (w3ddmg_aux_transfer_enabled)
    {
        w3ddmg_transfer_stage_aux_asm();
    }
    if (w3ddmg_dirty_transfer_enabled)
    {
        w3ddmg_transfer_dirty_stage();
    }
    else
    {
        w3ddmg_transfer_stage_asm();
    }

}

wire3d_dmg.h — Drahtgitterdarstellung für DMG

Verwendung der schnellen Renderingpfade

Bei Linien innerhalb des Darstellungsbereichs werden Zeichenadresse und Pixelbit schrittweise fortgeschrieben; verbleibende Pixelzahl und Fehlerwert bleiben in CPU-Registern. Dadurch entfallen Tile-Koordinatenberechnungen pro Pixel; zusätzliche Verbindungspixel schließen diagonale Übergänge. Bei aktivierter Verdeckung entscheiden fünf Abtastpunkte entlang der Linie, ob sie gezeichnet werden muss. Akzeptierte Linien verwenden denselben schnellen Pfad. Maskenzeilen werden byteweise gefüllt, wobei partielle Randbits erhalten bleiben. Flächenbegrenzungsrechtecke und Fünfpunktverwerfung sind Näherungen, keine pixelgenaue Dreiecks- oder Linienverdeckung. Drehungen um 0, 90, 180 und 270 Grad begrenzen zuerst die Eingaben und verwenden anschließend Koordinatentausch und Vorzeichenwechsel. Die Gesamtleistung hängt auch von Eckpunktzahl, Kantenlänge, Verdeckung und VRAM-Übertragungen ab. Messen Sie einzelne Operationen getrennt von der Zeit bis zum fertigen angezeigten Bild.

Monochromes 3D-Linienzeichnen. Übergeben Sie Modelleckpunkte, Kanten und Flächen sowie Objektposition, Rotation und Skalierung. Verwenden Sie Initialisierung, Frame-Beginn, Zeichnen und Übertragung in dieser Reihenfolge. Physik ist getrennt. Winkel haben sechzehn Schritte pro Umdrehung; Modellskalierung 256 bedeutet Originalgröße.

Vec3 enthält x/y/z, Edge die Eckpunktindizes a/b und Face die Dreiecksindizes a/b/c. vertices, edges und faces in Model zeigen auf diese Arrays; die jeweilige Anzahl gibt ihre Länge an. edge_faces enthält die Nachbarflächenindizes f0/f1, bei fehlender Fläche FACE_NONE. MODEL_HIDDEN_LINES in flags fordert flächenbasierte Kantenauswahl an. Die vorzeichenbehaftete projizierte Fläche bestimmt die Ausrichtung; die Eckpunktreihenfolge ist daher wichtig.

Object speichert Modellreferenz, Position x/y/z, Winkel rx/ry/rz, scale_q8 und visible. Objekte können ein Modell teilen; Zeichnen kopiert aber keine Tabellen und schaltet deren ROM-Bänke nicht automatisch um. Referenzierte Daten müssen während des gesamten Zeichnens lesbar bleiben. CGB-Object besitzt zusätzlich einen Farbindex.

Model für Höhe 96 enthält außerdem edge_masks und edge_mask_count. Übergeben Sie eine RAM-Tabelle mit 16-Bit-Kantenmasken, die nach Objekt-Gierwinkel gewählt werden, oder setzen Sie beide Felder bei Nichtgebrauch auf null.

Wire3DDMG_BeginFrame

Beginnt das Zeichnen eines Frames und deaktiviert die Verdeckungsprüfung.

Syntax

c
void Wire3DDMG_BeginFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_BeginFrame(); Löscht vorbereitete Pixel und Verdeckungsmaske und deaktiviert die Verdeckungsfilterung. Angezeigter VRAM-Frame und ausstehende BG-Tile-Warteschlange bleiben unverändert. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_BeginFrame(); Deaktiviert nur die Verdeckungsfilterung. Staging wird normalerweise während der Übertragung gelöscht; Init liefert den ersten leeren Bereich. Verwirft keinen ungesendeten Frame, löscht keine Maske und setzt weder ausstehende BG-Schreibzugriffe noch Änderungsflags zurück.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:144

Deklarationshinweise im Original
Disable occlusion filtering only. Stage clearing normally happens during
transfer, and Init supplies the first clean stage. This does not discard an
unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.

kitaqgb/lib/wire3d_dmg.c:3379

c
void Wire3DDMG_BeginFrame()
{




    /* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
       resets draw state. Wire3DDMG_Init supplies the first clean buffer. */

    w3ddmg_occlusion_active = 0;
}
Wire3DDMG_DrawIndexedEdges

Zeichnet ein ganzzahlig skaliertes Linienmodell aus Eckpunkten und Zwei-Byte-Kantenindexpaaren.

Syntax

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);

Parameter

vertices

Array von 3D-Eckpunkten.

vertex_count

Anzahl der Einträge im Eckpunktarray.

edges

Eckpunktindizes je Kante im deklarierten Struct- oder Bytepaar-Format.

edge_count

Anzahl der Kanten.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

scale

Ganzzahlige Skalierung; null wird als eins behandelt.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale); Zeichnet per Bytepaar indizierte Kanten nach ganzzahliger Skalierung und Verschiebung; Skalierung null bedeutet eins, ohne Objektrotation oder Flächenfilterung. Projiziert höchstens 24 Eckpunkte. Übergeben Sie höchstens 128 Kantenpaare, da Byte-Offsets nach 255 umbrechen. Ungültige Eckpunkt-IDs und tiefenbedingt verworfene Endpunkte werden übersprungen; Nullarrays werden ignoriert. Koordinatenprodukte und -summen müssen als s16 darstellbar sein.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:253

Deklarationshinweise im Original
Draw byte-pair edge indices after integer scaling and translation; scale
zero means one, and there is no object rotation or face filtering. Project at
most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
are ignored. Keep coordinate products/sums representable as s16.

kitaqgb/lib/wire3d_dmg.c:4568

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
    w3ddmg_u8 i;
    w3ddmg_u8 count;

    if (vertices == 0) return;
    if (edges == 0) return;

    count = vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
    if (scale == 0) scale = 1;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
        vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
        vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }

        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < edge_count)
    {
        w3ddmg_u8 a;
        w3ddmg_u8 b;

        a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
        b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
        if ((a < count) && (b < count) &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
        {
            Wire3DDMG_DrawLine2D(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
        }

        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_DrawLine2D

Zeichnet eine vierfach zusammenhängende Bildschirmlinie einschließlich Endpunkten in den Staging-Bereich.

Syntax

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by); Zeichnet eine zusammenhängende Linie einschließlich Endpunkten in den 128×96-Staging-Bereich. Während DrawScene wird die grobe Verdeckungsverwerfung mit fünf Abtastpunkten verwendet, sonst direkt gezeichnet. Verwenden Sie Viewport-Koordinaten. Nur EndFrame aktualisiert VRAM. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by); Bei aktivierter Änderungsübertragung wird das umschließende Tile-Rechteck markiert und danach eine zusammenhängende Staging-Linie gezeichnet. Szenenzeichnen kann sie anhand von fünf Maskenabtastungen verwerfen. Geben Sie Endpunkte im 128×120-Viewport an; niedrige Pixelgrenzprüfungen schneiden das Segment nicht geometrisch zu.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:237

Deklarationshinweise im Original
Mark the bounding tile rectangle when dirty transfer is enabled, then draw
a connected staged line. Scene drawing may reject it using five mask samples.
Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
the segment geometrically.

kitaqgb/lib/wire3d_dmg.c:3423

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{

    w3ddmg_mark_line_dirty(ax, ay, bx, by);


    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
Wire3DDMG_DrawLine3D

Projiziert zwei Weltendpunkte und zeichnet eine Linie dazwischen.

Syntax

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parameter

ax

X-Komponente des Startpunkts in Weltkoordinaten.

ay

Y-Komponente des Startpunkts in Weltkoordinaten.

az

Z-Komponente des Startpunkts in Weltkoordinaten.

bx

X-Komponente des Endpunkts in Weltkoordinaten.

by

Y-Komponente des Endpunkts in Weltkoordinaten.

bz

Z-Komponente des Endpunkts in Weltkoordinaten.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz); Projiziert beide Weltendpunkte und zeichnet nur, wenn beide den Tiefenbereich bestehen. Bildet keine Schnittpunkte eines kreuzenden Segments mit Nah- oder Fernebene; projizierte Endpunkte werden einzeln auf die Bildschirmränder begrenzt. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz); Projiziert beide Weltendpunkte und zeichnet nur, wenn beide den Tiefenbereich bestehen. Bildet keine Schnittpunkte eines kreuzenden Segments mit Nah- oder Fernebene; projizierte Endpunkte werden einzeln auf die Bildschirmränder begrenzt.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:226

Deklarationshinweise im Original
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:3546

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3DDMG_DrawModel

Zeichnet ein Eckpunkt-Kanten-Modell an der gewünschten Position und mit der gewünschten Rotation in Originalgröße.

Syntax

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz); Zeichnet ein unskaliertes Modell, indem DrawModelScaled mit Skalierung 256 aufgerufen wird. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz); Zeichnet ein unskaliertes Modell, indem DrawModelScaled mit Skalierung 256 aufgerufen wird.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:164

Deklarationshinweise im Original
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:3565

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)

{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}

kitaqgb/lib/wire3d_dmg.c:3563

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)



{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3DDMG_DrawModelScaled

Skaliert ein Modell, dreht es in Y/X/Z-Reihenfolge, verschiebt und projiziert seine Eckpunkte und zeichnet die Kanten.

Syntax

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8); Skaliert bis zu 24 Eckpunkte, dreht sie in Y/X/Z-Reihenfolge, verschiebt und projiziert sie; zeichnet danach bis zu 16 Kanten, gefiltert durch Giermasken und optional nach vorn gerichtete Flächen. Nichtpositive Skalierung wird zur Einheit (256). Nullzeiger für Modell, Eckpunkte oder Kanten werden ignoriert; referenzierte Tabellen müssen lesbar bleiben. Skalierungsprodukte und Verschiebungen müssen in den vorzeichenbehafteten 16-Bit-Bereich passen. Kanten über Tiefengrenzen werden verworfen, nicht zugeschnitten. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8); Skaliert bis zu 24 Eckpunkte, dreht Y/X/Z, verschiebt und projiziert sie und durchläuft dann alle edge_count-Einträge mit optionaler Nachbarflächenfilterung. edge_count ist ein Byte-Zähler. Der Flächen-Arbeitspuffer ist auf 16 begrenzt; Kantentabellen müssen alle deklarierten Einträge enthalten. Nichtpositive Skalierung bedeutet 256. Nullzeiger für Modell, Eckpunkte oder Kanten werden ignoriert. Produkte und Verschiebungen müssen in vorzeichenbehaftete 16 Bit passen; Kanten über Tiefengrenzen werden verworfen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:170

Deklarationshinweise im Original
Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
all edge_count entries (a byte count) with optional adjacent-face filtering.
Face scratch is capped at 16; edge tables must contain all declared entries.
Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.

kitaqgb/lib/wire3d_dmg.c:3710

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;




    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&



                w3ddmg_is_edge_visible(model, i, face_count))

            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}

kitaqgb/lib/wire3d_dmg.c:3703

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)








{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;

    if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
    w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);

    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&

                w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])



            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_DrawScene

Zeichnet bis zu acht Objekte von nah nach fern; nähere Flächen verdecken spätere Kanten.

Syntax

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parameter

objects

Objektarray mit Positionen, Rotationen, Skalierungen und Sichtbarkeitsflags.

count

Anzahl der übergebenen Arrayeinträge; beachten Sie die Verarbeitungsgrenze der jeweiligen Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count); Verarbeitet höchstens die ersten acht Objekte, nach transformierter Ursprungstiefe von nah nach fern sortiert. Zeichnet sichtbare gültige Modelle und markiert anschließend die Begrenzungsrechtecke ihrer Vorderseiten, um spätere Linien zu verwerfen, deren sämtliche Abtastpunkte verdeckt sind. Dies nähert Verdeckung zwischen Objekten an und ist kein Tiefenpuffer. Löscht die eigene Maske, erhält aber vorhandene Staging-Pixel. Nullarrays werden ignoriert; Objekte und Daten müssen lesbar bleiben. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count); Sortiert bis zu acht Objektursprünge nach Kameratiefe von nah nach fern. Zeichnet sichtbare gültige Modelle und markiert Vorderseiten-Begrenzungsrechtecke für spätere Objekte. Der erste sortierte Platz überspringt Maskentests; der letzte benötigt keinen neuen Verdeckungsbereich. Dies ist grobes Linienverwerfen, kein Tiefenpuffer. Null oder leere Eingaben werden ignoriert; Aufruferdaten und aktueller Projektionscache müssen während des Durchlaufs gültig bleiben.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:201

Deklarationshinweise im Original
Sort at most eight object origins by camera depth, near to far. Draw visible
valid models and mark front-face bounding rectangles for later objects. The
first sorted slot bypasses mask tests and the last needs no new occluder.
This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
caller data and the current projection cache must remain valid during traversal.

kitaqgb/lib/wire3d_dmg.c:3461

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;

    if (scene_count == 0) return;


    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];





            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();



    w3ddmg_occlusion_active = 0;


    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {




            w3ddmg_occlusion_active = i == 0 ? 0 : 1;
            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
            if ((w3ddmg_u8)(i + 1) < scene_count)
            {
                w3ddmg_mark_model_occluder(obj->model);
            }

        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
Wire3DDMG_EndFrame

Übergibt ausstehende Hintergrund-Schreibzugriffe und vorbereitete Zeichnungen an VRAM.

Syntax

c
void Wire3DDMG_EndFrame();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EndFrame(); Wartet auf den nächsten VBlank, führt ausstehende BG-Kartenschreibzugriffe aus und kopiert Staging unter Abfrage der Zugriffsfenster ins VRAM. Das Kopieren verbraucht die vorbereiteten Pixel. Die Übertragung kann über VBlank hinausgehen; dies ist kein atomarer Frame-Wechsel. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EndFrame(); Wartet auf den nächsten VBlank und führt BG-Schreibzugriffe aus. Verbraucht dann optional zuerst die Hilfsstreifen, bevor geänderte Tiles oder das gesamte Haupt-Staging übertragen werden. Wegen überlappender Hilfs- und Hauptquellen ist diese Reihenfolge wichtig. STAT wird über Zugriffsfenster hinweg weiter abgefragt; die Aktualisierung muss nicht in einen VBlank passen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:286

Deklarationshinweise im Original
Wait for the next VBlank and flush BG writes, then optionally consume the
auxiliary strips before uploading either dirty tiles or the entire main stage.
Auxiliary/main source overlap makes that ordering significant. STAT polling
continues across access windows; the update need not fit one VBlank.

kitaqgb/lib/wire3d_dmg.c:3819

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    Wire3DDMG_EndFrameNow();
}
Wire3DDMG_EraseModelFaces

Projiziert nach vorn gerichtete Modelldreiecke und löscht vorbereitete Pixel in ihrem Inneren.

Syntax

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

scale_q8

Skalierung mit 256 als Einheit; nichtpositive Werte bedeuten ebenfalls Originalgröße.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8); Projiziert bis zu 24 Eckpunkte und löscht das Innere nach vorn gerichteter Dreiecke aus dem Staging-Bereich für ein Modell mit Verdeckungsflags und Flächendaten. Nichtpositive Skalierung bedeutet 256, also Originalgröße. Bis zu 16 Flächen werden betrachtet; Flächen über Tiefengrenzen werden übersprungen. Ersetzt auch gemeinsame Projektionscaches, aktualisiert aber kein VRAM. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8); Projiziert bis zu 24 Eckpunkte und löscht das Innere nach vorn gerichteter Dreiecke aus dem Staging-Bereich für ein Modell mit Verdeckungsflags und Flächendaten. Nichtpositive Skalierung bedeutet 256, also Originalgröße. Bis zu 16 Flächen werden betrachtet; Flächen über Tiefengrenzen werden übersprungen. Ersetzt auch gemeinsame Projektionscaches, aktualisiert aber kein VRAM.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    Wire3DDMG_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
    Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
    Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:179

Deklarationshinweise im Original
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:3581

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}

kitaqgb/lib/wire3d_dmg.c:3579

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)



{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_EraseSpan2D

Löscht einen waagerechten Span einschließlich Endpunkten in einer vorbereiteten Zeile.

Syntax

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parameter

y

Pixel-Y-Koordinate der zu löschenden Zeile.

x0

Unterer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

x1

Oberer X-Endpunkt in Viewport-Pixeln; Reihenfolge und Begrenzung richten sich nach den Hinweisen zu dieser Operation.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1); Ordnet die X-Endpunkte und löscht den vorbereiteten Span einschließlich Endpunkten. Beide müssen in 0..127 liegen; ungültiges Y wird ignoriert. Die Routine begrenzt X nicht automatisch. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1); Ordnet die X-Endpunkte und löscht den vorbereiteten Span einschließlich Endpunkten. Beide müssen in 0..127 liegen; ungültiges Y wird ignoriert. Die Routine begrenzt X nicht automatisch.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:187

Deklarationshinweise im Original
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:3681

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
Wire3DDMG_EraseTriangle2D

Löscht ein Bildschirmdreieck über waagerechte Rasterzeilen-Spans aus dem Staging-Bereich.

Syntax

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parameter

ax

X-Koordinate von Eckpunkt A in Viewport-Pixeln.

ay

Y-Koordinate von Eckpunkt A in Viewport-Pixeln.

bx

X-Koordinate von Eckpunkt B in Viewport-Pixeln.

by

Y-Koordinate von Eckpunkt B in Viewport-Pixeln.

cx

X-Koordinate von Eckpunkt C in Viewport-Pixeln.

cy

Y-Koordinate von Eckpunkt C in Viewport-Pixeln.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy); Löscht ein Dreieck aus vorbereiteten Pixeln über ganzzahlige Rasterzeilenschnittpunkte. Geben Sie Viewport-Koordinaten an. Entartete Dreiecke werden ignoriert; Verdeckungsmaske und VRAM bleiben unverändert. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy); Löscht ein Dreieck aus vorbereiteten Pixeln über ganzzahlige Rasterzeilenschnittpunkte. Geben Sie Viewport-Koordinaten an. Entartete Dreiecke werden ignoriert; Verdeckungsmaske und VRAM bleiben unverändert.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    Wire3DDMG_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
    Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
    Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Projizierte Flächen löschen einen gefüllten Bereich, sodass erhaltene und gelöschte Bereiche sichtbar werden.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:184

Deklarationshinweise im Original
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:3671

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DDMG_Init

Initialisiert LCD, Tiles und Hintergrundkarte für einen monochromen Drahtgitter-Viewport.

Syntax

c
void Wire3DDMG_Init();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_Init(); Übernimmt das LCD: Wartet auf VBlank, schaltet es aus, löscht 6144 Tile-Bytes und die BG-Karte, richtet HUD-Tiles und den 128×96-Viewport mit vorzeichenbehafteten Tile-Nummern ein und aktiviert BG mit Scrollwerten null und BGP=0xB4. Setzt Kamera, BG-Warteschlange und Staging-Bereich zurück. Reservieren Sie 0xD000..0xDFFF für Staging und erhalten Sie dessen WRAM-Bankeinblendung. Rufen Sie vor dem Zeichnen BeginFrame auf, um auch den Verdeckungszustand zu initialisieren. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_Init(); Übernimmt den LCD-Zustand, löscht Tile-VRAM und BG-Karte und richtet einen 16×15-Viewport ab Kartentile (3,1) ein. Setzt Scrolling (8,0), BGP=0xB4 und BG-Anzeige. Setzt Kamera, Warteschlangen, Übertragungsmodi, beide Änderungstabellen und Staging zurück. Reservieren Sie 0xD000..0xDFFF und erhalten Sie die WRAM-Einblendung; Hilfsspeicher verwendet dieselben Adressen. Rufen Sie vor dem Zeichnen BeginFrame auf, um den Verdeckungszustand herzustellen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:135

Deklarationshinweise im Original
Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
Call BeginFrame before drawing to establish occlusion state.

kitaqgb/lib/wire3d_dmg.c:3310

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();



    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {



        off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));

        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }




    w3ddmg_reg_scx = 8;

    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;

    w3ddmg_aux_transfer_enabled = 0;
    w3ddmg_dirty_transfer_enabled = 0;


    Wire3DDMG_SetCamera((w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_u8)0, (w3ddmg_u8)0, (w3ddmg_u8)0);
    w3ddmg_clear_stage_asm();

    w3ddmg_clear_stage_aux_asm();
    w3ddmg_clear_dirty_tables();

}
Wire3DDMG_ProjectPoint

Projiziert einen Weltpunkt durch die Kamera in Viewport-Koordinaten.

Syntax

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parameter

x

X-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

y

Y-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

z

Z-Komponente des Punkts oder Objektursprungs in Weltkoordinaten.

sx

Gültiger beschreibbarer u8-Zeiger für die projizierte X-Koordinate.

sy

Gültiger beschreibbarer u8-Zeiger für die projizierte Y-Koordinate.

Rückgabewert

Liefert 1 bei erfolgreicher Projektion oder 0 bei verworfener Tiefe.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy); Projiziert einen Weltpunkt mit der aktuellen Kamera. Verworfene Tiefe liefert null und lässt die Ausgabe unverändert; bei Erfolg werden auf 128×96 begrenzte Koordinaten geschrieben. Ausgabezeiger müssen gültig sein. Bildschirmbegrenzung ist kein geometrisches Clipping. WIRE3D_DMG_HEIGHT = 120 w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy); Projiziert einen Weltpunkt mit der aktuellen Kamera. Ungültige Tiefe liefert null ohne Ausgabeänderung; bei Erfolg werden auf 128×120 begrenzte Koordinaten geschrieben. Beide Ausgabezeiger müssen gültig sein. Koordinatendifferenzen müssen in s16 passen.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:216

Deklarationshinweise im Original
Project a world point with the current camera. Return zero for invalid
depth without changing outputs; success writes clamped 128x120 coordinates.
Both output pointers must be valid. Coordinate differences must fit s16.

kitaqgb/lib/wire3d_dmg.c:688

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
Wire3DDMG_PutBgTile

Reiht einen Tile-Nummer-Schreibzugriff für eine Hintergrundkartenzelle ein.

Syntax

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parameter

x

X-Tile-Koordinate in der 32×32-Hintergrundkarte.

y

Y-Tile-Koordinate in der 32×32-Hintergrundkarte.

tile

Acht-Bit-Tile-Nummer für die Hintergrundzelle.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile); Reiht einen Tile-Schreibzugriff auf die 32×32-Karte bei 0x9800 für EndFrame ein. Ungültige Kartenkoordinaten und Anfragen über 48 ausstehende Schreibzugriffe hinaus werden ohne Meldung ignoriert. Diese Warteschlange ist von der allgemeinen vram-Bibliothekswarteschlange getrennt. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile); Reiht einen Tile-Schreibzugriff auf die 32×32-Karte bei 0x9800 für EndFrame ein. Ungültige Kartenkoordinaten und Anfragen über 48 ausstehende Schreibzugriffe hinaus werden ohne Meldung ignoriert. Diese Warteschlange ist von der allgemeinen vram-Bibliothekswarteschlange getrennt.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:258

Deklarationshinweise im Original
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:731

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
Wire3DDMG_RotatePoint

Dreht einen Punkt mit den angegebenen Winkeln direkt in seinen Variablen.

Syntax

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parameter

x

Separater beschreibbarer s16-Zeiger für die X-Komponente.

y

Separater beschreibbarer s16-Zeiger für die Y-Komponente.

z

Separater beschreibbarer s16-Zeiger für die Z-Komponente.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz); Dreht direkt in den Variablen in Y/X/Z-Reihenfolge mit 16 Schritten pro Umdrehung. Ein Nullzeiger für eine Komponente macht den gesamten Aufruf wirkungslos; verwenden Sie getrennte Zeiger. Jede Achsrotation begrenzt ihre Eingaben auf ±220.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:221

Deklarationshinweise im Original
Rotate in place in Y/X/Z order using 16 steps per full turn. A null
component pointer makes the whole call a no-op; use distinct pointers.
Each axis rotation clamps its inputs to +/-220.

kitaqgb/lib/wire3d_dmg.c:3865

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
    if (x == 0) return;
    if (y == 0) return;
    if (z == 0) return;

    w3ddmg_rotate_y(x, z, ry);
    w3ddmg_rotate_x(y, z, rx);
    w3ddmg_rotate_z(x, y, rz);
}
Wire3DDMG_SelectEdgeMask

Wählt eine vorberechnete Kantensichtbarkeitsmaske für den Gierwinkel des Objekts.

Syntax

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parameter

model

Modell mit Arrays und Anzahlen für Eckpunkte, Kanten und Flächen; seine Tabellen müssen während des Aufrufs lesbar bleiben.

rx

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

ry

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

rz

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

16-Bit-Kantensichtbarkeitsmaske oder 0xFFFF, wenn keine Tabelle übergeben wurde.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz); Wählt eine vorberechnete Maske aus den unteren vier Bits des Objekt-Gierwinkels; Nicken, Rollen und Kameraausrichtung werden ignoriert. Verwenden Sie 16, 8, 4 oder 2 Bereiche; andere positive Anzahlen wählen Eintrag null, wobei Anzahlen >=16 die ersten 16 verwenden. Fehlende Daten liefern 0xFFFF. Die Maskentabelle muss über die aktuelle Datenzeigereinblendung lesbar bleiben.

Dieses Beispiel verwendet das 128×96-Profil; sein Viewport beginnt auf dem Bildschirm bei (0,0). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3DDMG_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3DDMG_SelectEdgeMask(&cube,0,8,0);
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Modelle in Originalgröße und halber Größe erscheinen über einer Szene aus einem Objektarray mit denselben Skalierungen und zeigen Projektion und Skalierung.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg96_models.c .\kitaqgb\lib\wire3d_dmg_96.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg96_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:207

Deklarationshinweise im Original
Select a precomputed mask from the low four bits of object yaw; pitch,
roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
counts select entry zero (counts >=16 use the first 16). Missing data returns
0xFFFF. Keep the mask table readable through the current data-pointer mapping.

kitaqgb/lib/wire3d_dmg.c:1258

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
    w3ddmg_u8 count;
    w3ddmg_u8 bin;

    if (model == 0) return 0xFFFF;
    if (model->edge_masks == 0) return 0xFFFF;
    count = model->edge_mask_count;
    if (count == 0) return 0xFFFF;

    (void)rx;
    (void)rz;

    bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
    if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
    if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
    else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
    else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
    else bin = 0;

    if (bin >= count) bin = (w3ddmg_u8)(count - 1);
    return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}
Wire3DDMG_SetAuxTransfer

Wählt, ob EndFrame auch die Hilfsstreifen überträgt.

Syntax

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);

Parameter

flag

Null deaktiviert die Übertragungsfunktion; jeder andere Wert aktiviert sie.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag); Speichert die Hilfsübertragungsfreigabe für EndFrame; jeder Wert ungleich null aktiviert sie. Hier werden keine Daten kopiert oder gelöscht. Hilfsquellbytes teilen sich die Adressen mit dem Haupt-Staging-Bereich.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(1);
    Wire3DDMG_BeginFrame();
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    // Auxiliary upload consumes this source before the dirty main tile is sent.

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Die Hilfsübertragung verbraucht einen Teil des Haupt-Staging-Bereichs; dadurch entsteht bei Bildschirmkoordinate (80,24) ein schwarzer 8×8-Block.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_aux_gate.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:268

Deklarationshinweise im Original
Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
No data is copied or cleared here. Auxiliary source bytes alias the main stage.

kitaqgb/lib/wire3d_dmg.c:4639

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
    w3ddmg_aux_transfer_enabled = flag;
}
Wire3DDMG_SetCamera

Speichert Kameraposition und -ausrichtung für spätere Projektionen.

Syntax

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);

Parameter

x

X-Komponente der Kamera in Weltkoordinaten.

y

Y-Komponente der Kamera in Weltkoordinaten.

z

Z-Komponente der Kamera in Weltkoordinaten.

pitch

Drehung um X; sechzehn Schritte ergeben eine volle Umdrehung.

yaw

Drehung um Y; sechzehn Schritte ergeben eine volle Umdrehung.

roll

Drehung um Z; sechzehn Schritte ergeben eine volle Umdrehung.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll); Speichert Kameraposition und -winkel für späteres Zeichnen; 16 Winkelschritte ergeben eine Umdrehung. Vorhandene Zeichnungen werden nicht neu projiziert und Eingabebereiche nicht geprüft. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll); Speichert Kameraposition und -winkel für späteres Zeichnen; 16 Winkelschritte ergeben eine Umdrehung. Vorhandene Zeichnungen werden nicht neu projiziert und Eingabebereiche nicht geprüft.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:152

Deklarationshinweise im Original
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:3399

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)

{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}

kitaqgb/lib/wire3d_dmg.c:3397

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)



{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
Wire3DDMG_SetDirtyTransfer

Wählt die Übertragung geänderter Tiles für den Haupt-Viewport mit 120 Zeilen.

Syntax

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);

Parameter

flag

Null deaktiviert die Übertragungsfunktion; jeder andere Wert aktiviert sie.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag); Speichert die Freigabe für Änderungsübertragung und löscht beide Änderungsverläufe sowie den Haupt-Staging-Bereich, selbst bei unverändertem Wert. VRAM bleibt erhalten; beim Aktivieren über einem alten Bild können unmarkierte alte Tiles zurückbleiben. Sorgen Sie daher für einen sauberen angezeigten Ausgangszustand.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,24,8); Wire3DDMG_DrawLine2D(24,8,24,24);
    Wire3DDMG_DrawLine2D(24,24,8,24); Wire3DDMG_DrawLine2D(8,24,8,8);
    Wire3DDMG_EndFrame();
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(80,80,104,80); Wire3DDMG_DrawLine2D(104,80,104,104);
    Wire3DDMG_DrawLine2D(104,104,80,104); Wire3DDMG_DrawLine2D(80,104,80,80);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Der vorherige Rahmen links oben verschwindet; nur ein neuer Rahmen bei Bildschirmkoordinaten (96,88)..(120,112) bleibt.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_dirty.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:272

Deklarationshinweise im Original
Store the dirty-transfer gate and clear both dirty histories and the main
stage, even if the value is unchanged. VRAM is retained; enabling this over an
old image can leave unmarked old tiles, so arrange a clean displayed baseline.

kitaqgb/lib/wire3d_dmg.c:4699

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
    w3ddmg_dirty_transfer_enabled = flag;
    w3ddmg_clear_dirty_tables();
    w3ddmg_clear_stage_asm();
}
Wire3DDMG_SetPalette

Schreibt die Zuordnung der vier Helligkeitsstufen ins monochrome Hintergrund-Palettenregister BGP.

Syntax

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);

Parameter

bgp

BGP-Registerwert mit vier Zwei-Bit-Helligkeitszuordnungen.

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_SetPalette(w3ddmg_u8 bgp); Schreibt die rohe DMG-BGP-Palettencodierung sofort, ohne Frame-Synchronisierung. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetPalette(w3ddmg_u8 bgp); Schreibt die rohe DMG-BGP-Palettencodierung sofort, ohne Frame-Synchronisierung.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

Erwartetes Ergebnis

Dieses Beispiel zeigt Linien, Punkte, Löschen und Projektion in einem Frame. Die Mitte der oberen Kante des Rahmens links oben wird gelöscht; nahe der Bildmitte wird eine Diagonale projiziert. Eine verworfene Projektion erhält die Ausgabewerte 91 und 92.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:260

Deklarationshinweise im Original
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:746

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}
Wire3DDMG_TransferAuxNow

Überträgt sechs Hilfsstreifen sofort und löscht ihre Quellbytes.

Syntax

c
void Wire3DDMG_TransferAuxNow();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_TransferAuxNow(); Überträgt und verbraucht die Hilfsquellstreifen sofort, unabhängig von der Hilfsfreigabe. Wartet nicht auf den VBlank-Start und aktualisiert weder Änderungsverlauf noch BG-Warteschlange. Die Quelle überlappt den Haupt-Staging-Bereich; stimmen Sie die Übertragungen aufeinander ab.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:280

Deklarationshinweise im Original
Upload and consume auxiliary source strips immediately, independent of the
auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
The source overlaps the main stage and must be coordinated with its upload.

kitaqgb/lib/wire3d_dmg.c:4727

c
void Wire3DDMG_TransferAuxNow()
{
    w3ddmg_transfer_stage_aux_asm();
}
Wire3DDMG_TransferMainNow

Überträgt den gesamten Haupt-Staging-Bereich sofort und löscht die verbrauchten Quellpixel.

Syntax

c
void Wire3DDMG_TransferMainNow();

Rückgabewert

Kein Rückgabewert; geänderter Zustand und Anzeige-Timing sind oben beschrieben.

Bedingungen und Grenzen

WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_TransferMainNow(); Überträgt und verbraucht den gesamten Haupt-Staging-Bereich sofort, fragt dabei STAT ab, wartet aber nicht auf den nächsten VBlank. Ignoriert Übertragungsfreigaben und erhält Änderungsverläufe sowie BG-Tile-Warteschlange; der Aufrufer koordiniert den Frame-Ablauf.

Dieses Beispiel verwendet das 128×120-Profil; sein Viewport beginnt auf dem Bildschirm bei (16,8). Reservieren Sie WRAM D000..DFFF und halten Sie dessen Bankeinblendung auch auf CGB stabil. Der gemeinsame Zustand ist nicht reentrant.

WIRE3D_DMG_HEIGHT ist standardmäßig 120. Verwenden Sie für Höhe 96 wire3d_dmg_96.c. SelectEdgeMask ist bei Höhe 96 verfügbar; RotatePoint, DrawIndexedEdges, Übertragungsfreigaben und direkte Übertragungen benötigen Höhe 120.

WIRE3D_DMG_HEIGHT erlaubt 88, 96 oder 120; WIRE3DCGB_HEIGHT erlaubt 88 oder 96. Die Vorgaben bleiben DMG 120 und CGB 96. Das 88-Zeilen-Profil hat 128×88 Pixel mit Mittelpunkt Y=44. Bibliothek und Aufrufer benötigen denselben Wert; kompilieren Sie wire3d_dmg_88.c / wire3d_cgb_88.c statt des normalen Einstiegspunkts. DMG 88 verwendet die Modellstruktur des 96-Zeilen-Profils und dessen Grenze von 16 Kanten. CGB 160×144 bleibt unverändert.

Anwendungsbeispiel

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

Erwartetes Ergebnis

Eine projizierte waagerechte Linie und ein zusätzlicher 8×8-Block zeigen direkte Übertragungen; ein Quellbyte wechselt beim Verbrauch von 255 auf 0.

Vollständiges Beispielprogramm

Build-Befehl

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementierung und Quelltext

kitaqgb/lib/wire3d_dmg.h:276

Deklarationshinweise im Original
Upload and consume the full main stage immediately, polling STAT but not
waiting for the next VBlank. Ignore transfer gates and leave dirty histories
and BG tile queue unchanged; the caller coordinates the frame lifecycle.

kitaqgb/lib/wire3d_dmg.c:4714

c
void Wire3DDMG_TransferMainNow()
{
    w3ddmg_transfer_stage_asm();
}

Strukturen, Konstanten und vollständige Header

Diese Header enthalten auch Makros ohne Funktionsform, Strukturen, Arraygrenzen, Aufzählungen und Aliase. Sie geben die erfassten Quellen einschließlich der ursprünglichen Kommentare unverändert wieder.

asset.h — Ressourcen-IDs und Datenbeschreibungen
c
#pragma once

#define ASSET_TYPE_RAW   ((u8)0)
#define ASSET_TYPE_TILES ((u8)1)
#define ASSET_TYPE_MAP   ((u8)2)
#define ASSET_TYPE_SONG  ((u8)3)

// Packed ROM descriptor: type tag, payload bank, bank-window address and byte length.
// The table itself may live in a different bank from the payload.
typedef __packed struct {
    u8 type;
    u8 bank;
    const u8* ptr;
    u16 len;
} AssetDesc;

void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __vram_copy(u16 dst, const void* src, u16 len);

// Retain the descriptor table address, bank and count; the table is not copied.
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);
// Copy one descriptor from its ROM bank into caller storage. Return zero for a
// null destination or an out-of-range ID; table validity is the caller's responsibility.
u8 asset_get(u8 asset_id, AssetDesc* out_desc);
// Copy at most max_len bytes using the asset's bank. Success means the ID was
// valid, even when the payload was truncated to fit the supplied limit.
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);
// Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes
// the descriptor pointer directly; callers must arrange the correct visible ROM bank.
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);
// Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.
u8 asset_get_bank(u8 asset_id);
// Return the stored address without switching banks. Use the descriptor bank
// with far-data helpers before dereferencing banked assets; failure returns null.
const u8* asset_get_ptr(u8 asset_id);
// Return the descriptor byte length, or zero if its ID cannot be resolved.
u16 asset_get_len(u8 asset_id);

kitaqgb/lib/asset.h

audio.h — Musik, Soundeffekte und Audiosteuerung
c
#pragma once

// Shared Game Boy audio driver for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before audio.c so NR10..NR52 and
//   WAVE0..WAVE15 are already declared.
// - Call Audio_Init() once during startup.
// - Call Audio_Update() once per frame, ideally from your VBlank-driven main loop.
// - audio.c is intended to stay in bank 0.
// - Music streams are banked explicitly with Audio_PlayMusic(bank, song).
// - Audio_PlaySFX(sfx, priority) captures the currently visible ROM bank.
// - Audio_PlaySFXBanked(bank, sfx, priority) safely classifies CH1/CH3 data
//   after switching to the requested bank, so banked SFX can be started from
//   any currently visible ROM bank.
// - GBDAW-Stream v1.2 extends the legacy command set with explicit per-channel
//   automation commands that map more directly from GUI and Python tooling.

// Physical APIs and music-stream commands share zero-based CH1..CH4 IDs.
#define AUDIO_CHANNEL_CH1 ((u8)0)
#define AUDIO_CHANNEL_CH2 ((u8)1)
#define AUDIO_CHANNEL_CH3 ((u8)2)
#define AUDIO_CHANNEL_CH4 ((u8)3)

// Music-stream IDs used by NOTE, SET_INST and STOP_CHANNEL.
#define AUDIO_STREAM_CHANNEL_CH1 AUDIO_CHANNEL_CH1
#define AUDIO_STREAM_CHANNEL_CH2 AUDIO_CHANNEL_CH2
#define AUDIO_STREAM_CHANNEL_CH3 AUDIO_CHANNEL_CH3
#define AUDIO_STREAM_CHANNEL_CH4 AUDIO_CHANNEL_CH4

#define AUDIO_PAN_CENTER ((u8)0)
#define AUDIO_PAN_LEFT ((u8)1)
#define AUDIO_PAN_RIGHT ((u8)2)
#define AUDIO_PAN_MUTE ((u8)3)
#define AUDIO_PAN_INHERIT ((u8)0xFF)

#define AUDIO_WAVE_TRIANGLE ((u8)0)
#define AUDIO_WAVE_SAW ((u8)1)
#define AUDIO_WAVE_VOWEL_A ((u8)2)
#define AUDIO_WAVE_VOWEL_I ((u8)3)
#define AUDIO_WAVE_VOWEL_U ((u8)4)
#define AUDIO_WAVE_VOWEL_E ((u8)5)
#define AUDIO_WAVE_VOWEL_O ((u8)6)
#define AUDIO_WAVE_CUSTOM ((u8)7)

#define AUDIO_CH3_LEVEL_MUTE ((u8)0x00)
#define AUDIO_CH3_LEVEL_100 ((u8)0x20)
#define AUDIO_CH3_LEVEL_50 ((u8)0x40)
#define AUDIO_CH3_LEVEL_25 ((u8)0x60)

#define AUDIO_VOLUME_MIN ((u8)0)
#define AUDIO_VOLUME_MAX ((u8)7)
#define AUDIO_NOTE_MAX ((u8)67)

#define AUDIO_CMD_WAIT ((u8)0x00)
#define AUDIO_CMD_NOTE ((u8)0x10)
#define AUDIO_CMD_SET_INST ((u8)0x11)
#define AUDIO_CMD_SET_PAN ((u8)0x12)
#define AUDIO_CMD_SET_SWEEP ((u8)0x13)
#define AUDIO_CMD_SET_WAVE ((u8)0x14)
#define AUDIO_CMD_SET_CH3_CUSTOM_WAVE ((u8)0x15)
#define AUDIO_CMD_SET_CH4_PARAM ((u8)0x16)
#define AUDIO_CMD_SET_MASTER_VOLUME ((u8)0x17)
#define AUDIO_CMD_SET_CH1_DUTY ((u8)0x18)
#define AUDIO_CMD_SET_CH2_DUTY ((u8)0x19)
#define AUDIO_CMD_SET_CH3_LEVEL ((u8)0x1A)
#define AUDIO_CMD_STOP_CHANNEL ((u8)0x20)
#define AUDIO_CMD_LOOP ((u8)0x30)
#define AUDIO_CMD_STOP ((u8)0x40)

#define AUDIO_SFX_CH3_MARKER ((u8)0xFF)

// Enable the APU and reset software streams, instruments, mix and fade state.
// Load the initial triangle wave, then leave every channel silent. Call at startup
// before concurrent interrupt-driven audio service can access these shared fields.
void Audio_Init();
// Advance the master fade first. Unless paused, service both effect streams
// then the optional legacy music decoder. Call once per frame for frame-based timing.
void Audio_Update();
// Retain the bank and song pointer, reset legacy instruments/cursors, and arm
// playback from the beginning. Supply a valid, persistent song; no bytes are copied
// and null is not checked. Existing effect streams remain active.
void __stackcall Audio_PlayMusic(u8 bank, u8 *song);
// Stop legacy music and clear its resume mask, then silence all physical channels.
// Effect pointers remain active and may produce sound on a later update.
void Audio_StopMusic();
// On pause entry, silence hardware while retaining cursors. On resume, retrigger
// eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still
// advance master fades while paused, and effect playback resumes on a later update.
void __stackcall Audio_SetPaused(u8 on);
// Capture the currently mapped ROM bank and start an effect with inherited pan.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority);
// Start a banked effect with the channel's base pan, subject to priority arbitration.
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority);
// Capture the currently mapped ROM bank and request an effect with a pan override.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan);
// Retain a banked effect stream if its priority equals or exceeds the current
// owner's priority, or that slot is empty. A leading CH3 marker selects the wave
// slot and is skipped; other streams use the pulse slot. Paused requests are ignored.
// Keep stream storage valid until completion; acceptance does not trigger a note.
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan);
// Clear both effect streams and their pan overrides. When not paused, release
// borrowed channels through the configured legacy or VBlank recovery path.
void Audio_StopSfx();
// Stop a physical channel and clear its legacy resume bit. CH1 also clears the
// pulse effect stream; CH3 clears the wave effect stream. This is the legacy
// channel API and does not clear a VBlank driver's independently latched notes.
void __stackcall Audio_StopChannel(u8 ch);

// Set the music-processing gate. This does not silence notes already playing
// or stop the legacy stream cursor from consuming commands.
void __stackcall Audio_SetMusicEnabled(u8 on);
// Enable effect note writes, or disable them and release both effect streams.
// Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.
void __stackcall Audio_SetSfxEnabled(u8 on);

// Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.
void __stackcall Audio_SetMasterVolume(u8 left, u8 right);
// Move left/right volume toward clamped targets at the requested Audio_Update
// call interval. An interval of zero applies the levels immediately.
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames);
// Cancel further volume steps, retaining the current cached levels and hardware output.
void Audio_CancelMasterVolumeFade();

// Update the base pan for a physical channel and reapply active effect overrides.
// Unknown channel IDs select CH4; unsupported pan values mute the selected channel.
void __stackcall Audio_SetPan(u8 ch, u8 pan);
// Two bits per channel (CH1 in bits 0-1): center, left, right, mute.
// Applies all four positions with one NR51 update for sequencer automation.
void __stackcall Audio_SetPanPacked(u8 packed);
// Install a named preset or the cached custom wave. Unknown IDs are ignored.
// This does not update Audio_Ch3Wave or trigger a new note.
void __stackcall Audio_LoadWave(u8 wave_id);
// Copy 16 packed sample bytes into the persistent custom cache and wave RAM.
// A null pointer is ignored; the source is needed only for this call.
void __stackcall Audio_LoadCustomWave(const u8 *wave16);

// Cache the low two duty bits for the next CH1 note; do not change the active register.
void __stackcall Audio_SetCh1Duty(u8 duty);
// Cache the low two duty bits for the next CH2 note; do not change the active register.
void __stackcall Audio_SetCh2Duty(u8 duty);
// Cache the raw NR32 level encoding for the next CH3 note without writing hardware.
void __stackcall Audio_SetCh3Level(u8 level);
// Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.
void __stackcall Audio_SetCh4Param(u8 param);

// Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the
// note index; duty values 0, 1 and 3 select their encodings, and all others use 2.
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2);
// Trigger CH2 with the supplied raw envelope and a clamped note index. Duty
// values 0, 1 and 3 select their encodings; all other values use duty 2.
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2);
// Clamp the note index, program the raw NR32 output level, and trigger CH3.
// Wave RAM must already contain the desired waveform; this does not load one.
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level);
// Cache the supplied noise parameter, program the raw envelope and polynomial
// registers, then trigger CH4 with the length-enable bit clear.
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env);

kitaqgb/lib/audio.h

audio_vblank.h — Musikwiedergabe im VBlank-Interrupt
c
#pragma once

// Fixed-bank VBlank BGM driver.
//
// Stream format:
//   delay, ch1_note, ch2_note, ch3_note, ch4_noise_param
//   IMMEDIATE, ch1_note, ch2_note, ch3_note, ch4_noise_param
//   CONTROL, command, arg0, arg1, arg2
//
// Notes are 0..67. To stay inside the useful CGB register range, C6..G6
// (60..67) alias C5..G5 (48..55) in the fixed pitch table. REST leaves a
// channel unchanged, while STOP silences it. END stops either playback mode.
// LOOP jumps to MusicLoopPoint only in direct-pointer mode; a queue producer
// must expand loops itself. IMMEDIATE is recognized only in queue mode.
// Direct streams treat 0xFB as an ordinary delay, and queues treat 0xFE as one.

#define AUDIO_VBLANK_REST ((u8)0xFF)
#define AUDIO_VBLANK_END  ((u8)0xFF)
#define AUDIO_VBLANK_LOOP ((u8)0xFE)
#define AUDIO_VBLANK_STOP ((u8)0xFD)
#define AUDIO_VBLANK_CONTROL ((u8)0xFC)
#define AUDIO_VBLANK_IMMEDIATE ((u8)0xFB)
#define AUDIO_VBLANK_CONTROL_RESET ((u8)0x01)

#define AUDIO_VBLANK_W8 ((u8)15)
#define AUDIO_VBLANK_WQ ((u8)30)
#define AUDIO_VBLANK_WH ((u8)60)

#define AUDIO_VBLANK_QUEUE_RECORDS 16
#define AUDIO_VBLANK_QUEUE_BYTES 80

typedef void (*AudioVBlankFrameHook)();

extern __wram u8 AudioVBlank_MusicPlaying;
extern __wram u8 AudioVBlank_MusicEnabled;
extern __wram u8 AudioVBlank_MusicDelay;
extern __wram u8 *AudioVBlank_MusicStart;
extern __wram u8 *AudioVBlank_MusicPointer;
extern __wram u8 *AudioVBlank_MusicLoopPoint;
extern __wram u8 AudioVBlank_Step;
extern __wram u8 AudioVBlank_Ch2Note;
extern __wram u8 AudioVBlank_Ch1Note;
extern __wram u8 AudioVBlank_Ch3Note;
extern __wram u8 AudioVBlank_Ch2LatchedNote;
extern __wram u8 AudioVBlank_Ch1LatchedNote;
extern __wram u8 AudioVBlank_Ch3LatchedNote;
// Sound effects temporarily own CH1/CH2/CH3.  A pending value of 1 means a BGM
// note/stop event was suppressed and must be applied once the effect ends;
// value 2 means release the effect channel without retriggering an old note.
extern __wram u8 AudioVBlank_RestoreCh1Pending;
extern __wram u8 AudioVBlank_RestoreCh3Pending;
extern __wram u8 AudioVBlank_Ch4Param;
extern __wram u8 AudioVBlank_Ch1Envelope;
extern __wram u8 AudioVBlank_Ch2Envelope;
extern __wram u8 AudioVBlank_Ch4Envelope;
extern __wram u8 AudioVBlank_Ch1Duty;
extern __wram u8 AudioVBlank_Ch2Duty;
extern __wram u8 AudioVBlank_Ch1Sweep;
extern __wram u8 AudioVBlank_Ch3Level;
extern __wram u8 AudioVBlank_ControlCommand;
extern __wram u8 AudioVBlank_ControlArg0;
extern __wram u8 AudioVBlank_ControlArg1;
extern __wram u8 AudioVBlank_ControlArg2;
// QueueReset/QueueRefill/QueuePlay provide the foreground producer. The ISR owns
// ReadIndex and decreases Count; use the producer APIs instead of editing the
// indices/count while playback is running. Records contain exactly five bytes.
// MusicPlaying and all enable/pause gates still apply in queue mode.
extern __wram u8 AudioVBlank_QueueMode;
extern __wram u8 AudioVBlank_QueueReadIndex;
extern __wram u8 AudioVBlank_QueueWriteIndex;
extern __wram u8 AudioVBlank_QueueCount;
extern __wram u8 AudioVBlank_QueueUnderruns;
// Queue bytes reside in WRAM bank 1. A producer must select that bank while
// writing and restore the caller bank; publish the record only after all bytes
// are complete. The ISR selects bank 1 itself and restores SVBK before returning.
extern __wramx_bank(1) u8 AudioVBlank_QueueBuffer[AUDIO_VBLANK_QUEUE_BYTES];
// The ISR invokes this hook even when music processing is gated off. It runs
// with SVBK=1 using a direct-address call; keep hook code/data accessible in that
// context and synchronize pointer changes with interrupt execution.
extern __wram AudioVBlankFrameHook AudioVBlank_FrameHook;

// Reset software playback state, queue counters, instruments and the frame hook.
// Call before enabling this ISR; the routine does not mask interrupts or
// initialize the APU registers and cannot synchronize with an active handler.
void AudioVBlank_Init();
// Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.
void AudioVBlank_QueueReset();
// Copy complete records from the currently mapped source; return records accepted.
// Each call attempts at most 16 records and stops when full. Null/zero returns 0.
// Supports ROM and RAM sources, restores SVBK and IE, and never changes IME.
// Single foreground producer only: do not call from an ISR or frame hook.
// LOOP must be expanded by the producer. END occupies a full five-byte record.
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count);
// Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode.
// Does not enable the interrupt, music gate or clear pause. Queue before starting.
u8 AudioVBlank_QueuePlay();
// Select a directly addressed song and reset its cursors, leaving the playing
// flag unchanged. Song storage must remain accessible to the fixed-bank ISR;
// coordinate this multi-field update with interrupt execution.
void __stackcall AudioVBlank_SetMusic(u8 *song);
// Restart the selected direct song at its beginning, leaving queue mode.
// A null song invokes Stop; this does not enable the music or IRQ gates.
void AudioVBlank_Play();
// Select and restart a directly addressed song. This is not the banked WRAM-queue path.
void __stackcall AudioVBlank_PlayMusic(u8 *song);
// Stop software playback and silence pulse/noise envelopes and the wave DAC.
// Song pointers and the IRQ enable remain unchanged; the routine writes the
// physical channels directly, so coordinate ownership with sound effects.
void AudioVBlank_Stop();
// Gate music processing and clear pending CH1/CH3 recovery on disable.
// No audio register is written here: disabling does not itself silence a note
// already playing or disable the VBlank interrupt.
void __stackcall AudioVBlank_SetEnabled(u8 on);
// Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally.
// Install the correct interrupt vector and initialize driver state first.
void AudioVBlank_EnableIrq();
// Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.
void AudioVBlank_DisableIrq();
// Recover the borrowed pulse channel (CH1 or CH2) from its latched music event.
// Pending value 2, disabled music, or a non-note latch silences it instead.
// The caller must first establish that the effect has released the channel.
void AudioVBlank_RestoreCh1();
// Recover a latched wave-channel music event after effect release, or disable
// the DAC for a release-only request, disabled music, or a non-note latch.
// The caller owns effect arbitration and clearing the pending flag.
void AudioVBlank_RestoreCh3();
// Request deferred pulse-channel release only when no recovery is pending.
// Preserve value 1, which records a music event suppressed while an effect owned it.
void AudioVBlank_RequestRestoreCh1();
// Request a deferred wave-channel release only if no recovery is pending.
// Preserve value 1, which records a new music event suppressed by the effect.
void AudioVBlank_RequestRestoreCh3();

kitaqgb/lib/audio_vblank.h

bank.h — Bankabhängiger Zugriff auf Code und Daten
c
#pragma once

// A bank byte accompanies the CPU-visible ROM address; the pointer alone is not a far address.
typedef __packed struct {
    u8 bank;
    const u8* ptr;
} BankPtr;

extern u8 kq_bank_current;

void __bankswitch(u8 bank);
u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __farcall_ptr(u8 bank, const void* func);

// Update both the library bank record and the compiler shadow used by far
// reads and calls. Invoke this permanent bank change from fixed-bank code.
void bank_switch(u8 bank);
// Return the last bank recorded by bank_switch; this does not read cartridge hardware.
u8 bank_get_current();
// Read one byte through the compiler intrinsic that accepts an explicit ROM bank.
u8 far_data_read8(u8 bank, const void* addr);
// Read a 16-bit value from the supplied bank and address through the far-read intrinsic.
u16 far_data_read16(u8 bank, const void* addr);
// Copy len bytes from banked ROM into caller-owned writable storage.
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);
// Invoke a no-argument callback in its ROM bank, then restore the caller
// bank. The pointer must identify executable code; no arguments are forwarded.
void far_call(u8 bank, const void* func);
// Store a bank/address pair without accessing ROM; a null output pointer is ignored.
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);
// Read one byte using both components of the bank-qualified pointer.
u8 farptr_read8(BankPtr ptr);
// Read a 16-bit value using both components of the bank-qualified pointer.
u16 farptr_read16(BankPtr ptr);
// Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.
void farptr_read(BankPtr ptr, void* dst, u16 len);

kitaqgb/lib/bank.h

camera.h — Weltkoordinaten und sichtbare Bereiche
c
#pragma once

#include "scroll.h"

// All position, target and bound fields use signed Q8.8 (-128 to just below 128 pixels).
// Pass initialized, non-null storage; world/screen conversion arguments use integer pixels.
typedef struct Camera8_8 {
    s16 fx;
    s16 fy;
    s16 target_fx;
    s16 target_fy;
    s16 min_fx;
    s16 min_fy;
    s16 max_fx;
    s16 max_fy;
    u8 use_target;
    u8 use_bounds;
} Camera8_8;

// Zero all position/target/bound fields and disable targeting and bounds.
void Camera_Init(Camera8_8* cam);
// Replace the current Q8.8 position and immediately apply enabled bounds.
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);
// Store a Q8.8 target and enable subsequent step-toward-target updates.
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);
// Disable target following without moving the camera or erasing the stored target.
void Camera_ClearTarget(Camera8_8* cam);
// Install ordered Q8.8 bounds, enable them and clamp the current position immediately.
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);
// Disable clamping while retaining the stored bounds and current position.
void Camera_ClearBounds(Camera8_8* cam);
// Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16;
// clamping cannot repair arithmetic that already overflowed.
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);
// Move by the signed target delta shifted by 0..7 bits, then apply bounds.
// Quantization can make a small delta produce no movement; only exact equality
// clears targeting, and a target outside the bounds may remain active indefinitely.
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);
// Discard fractional bits and write the low eight integer bits to background scroll registers.
void Camera_ApplyBg(const Camera8_8* cam);
// Convert the Q8.8 position to byte scroll values and stage them for a later flush.
void Camera_ApplyBgBuffered(const Camera8_8* cam);
// Derive nonnegative camera extents from world minus screen size, then convert
// them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does
// not imply support for arbitrary large worlds.
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Convert an integer-pixel world X by subtracting the camera's integer X component.
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);
// Convert an integer-pixel world Y by subtracting the camera's integer Y component.
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);
// Convert integer-pixel screen X back to world X using the camera's integer component.
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);
// Convert integer-pixel screen Y back to world Y using the camera's integer component.
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);

// Set the shared camera from integer pixels, converting to the representable Q8.8 range.
void camera_set(s16 x, s16 y);
// Position the shared camera so the world point appears at the requested screen
// anchor. This is an immediate move, not the smoothed target-following path.
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);
// Derive and apply world/screen bounds to the shared convenience camera.
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Write the shared camera's current integer position to background scroll registers.
void camera_apply();
// Convert integer-pixel world X using the shared convenience camera.
s16 camera_world_to_screen_x(s16 world_x);
// Convert integer-pixel world Y using the shared convenience camera.
s16 camera_world_to_screen_y(s16 world_y);

kitaqgb/lib/camera.h

cgb_palette.h — CGB-Paletten für BG und OBJ
c
#pragma once

// High-level CGB palette helpers for KITAQGB.
// Palette writes no-op on DMG; RGB packing works on either hardware model.

// Safe here means CGB hardware gating. Palette data writes still require an accessible
// PPU phase (for example LCD off or a sufficiently short VBlank update).
u8 __cgb_is_cgb();
void __cgb_safe_set_bcps(u8 value);
void __cgb_safe_set_bcpd(u8 value);
void __cgb_safe_set_ocps(u8 value);
void __cgb_safe_set_ocpd(u8 value);

// Mask each component to five bits: red in 0..4, green in 5..9, blue in 10..14.
// These macros wrap oversized components rather than saturating them.
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))

// Pack the red, green and blue components using the public RGB15 macro.
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);

// Set one background color through the indexed palette wrapper.
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);
// Set one object color through the indexed palette wrapper.
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);
// Pack component values and write one background color.
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);
// Pack component values and write one object color.
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

// Write background colors starting at the indexed slot. The range may cross
// palette boundaries and is clamped only at the end of all 32 slots.
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);
// Write object colors from the indexed slot, potentially crossing into later palettes.
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

// Write four consecutive colors for one background palette.
void cgb_bg_palette(u8 palette_index, const u16* colors);
// Write four consecutive colors for one object palette.
void cgb_obj_palette(u8 palette_index, const u16* colors);

// Expose sequential background writes using an absolute color-slot index.
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);
// Expose sequential object writes using an absolute color-slot index.
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

kitaqgb/lib/cgb_palette.h

cgb_tile.h — CGB-Kachelnummern und -attribute
c
#pragma once

// Declarations for compiler-intrinsic CGB tile helpers.
// Canonical intrinsic entry points use the "__" prefix.
// Attr writes no-op on DMG. Combined tile+attr writes still write the tile on DMG.

// These helpers emit compiler code; cgb_tile.c has no runtime bodies. Scalar coordinates address 32x32 maps.
// Safe write paths poll VRAM access; LCD-on paths can enable interrupts after writing.
// Use _unsafe/_fast only with caller-managed writable VRAM timing, especially inside an ISR.
// Tile writes use the selected VRAM bank; choose bank zero before combined tile/attribute operations.
#define KQ_CGB_ATTR_PAL_MASK 0x07
#define KQ_CGB_ATTR_BANK1 0x08
#define KQ_CGB_ATTR_XFLIP 0x20
#define KQ_CGB_ATTR_YFLIP 0x40
#define KQ_CGB_ATTR_PRIORITY 0x80

#define KQ_CGB_ATTR_NONE ((u8)0)
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))

// Return the compiler/runtime CGB mode test as a byte Boolean.
u8 __cgb_is_cgb();
// Write the VRAM bank selection only on CGB. Safe here means hardware-mode guarded, not PPU-timed.
void __cgb_safe_set_vbk(u8 value);

// Write a tile number to map 9800, waiting for VRAM access when necessary.
void __settile(u8 x, u8 y, u8 tile);
// Write a tile number to map 9800 without waiting for writable VRAM.
void __settile_unsafe(u8 x, u8 y, u8 tile);
// Write at base+32*y+x with VRAM access checks; supply a valid tile-map base.
void __settileat(u16 base, u8 x, u8 y, u8 tile);
// Use an explicit map base without waiting for VRAM access.
void __settileat_unsafe(u16 base, u8 x, u8 y, u8 tile);
// Select the window map from LCDC bit 6, then write a tile with access checks.
void __settilewin(u8 x, u8 y, u8 tile);
// Select the LCDC window map and write without access waits.
void __settilewin_unsafe(u8 x, u8 y, u8 tile);
// Select the background map from LCDC bit 3, then write with access checks.
void __settilebg(u8 x, u8 y, u8 tile);
// Select the LCDC background map and write without access waits.
void __settilebg_unsafe(u8 x, u8 y, u8 tile);

// Copy count sequential bytes to dest using the current VRAM bank and access-checked transfer.
void __settile_bulk(u16 dest, const u8* src, u8 count);
// Copy count sequential bytes to dest without VRAM access waits; retain source-bank visibility.
void __settile_bulk_fast(u16 dest, const u8* src, u8 count);

// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. Use the access-checked write path.
void __settilecgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilecgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileatattr(u16 base, u8 x, u8 y, u8 attr);
// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileatattr_unsafe(u16 base, u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. Use the access-checked write path.
void __settileatcgb(u16 base, u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. No VRAM access waits are inserted.
void __settileatcgb_unsafe(u16 base, u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilewinattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilewinattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. Use the access-checked write path.
void __settilewincgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilewincgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilebgattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilebgattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. Use the access-checked write path.
void __settilebgcgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilebgcgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. Transfers use access checks.
void __settileattr_bulk(u16 dest, const u8* src, u8 count);
// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. The caller supplies writable VRAM timing.
void __settileattr_bulk_fast(u16 dest, const u8* src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. Transfers use access checks.
void __settilecgb_bulk(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. The caller supplies writable VRAM timing.
void __settilecgb_bulk_fast(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);

kitaqgb/lib/cgb_tile.h

chain.h — Ringpuffer für Positionsverläufe
c
#pragma once

typedef __packed struct {
    s16 x;
    s16 y;
} ChainPoint;

typedef __packed struct {
    ChainPoint* points;
    u8 capacity;
    u8 count;
    u8 head;
} Chain;

// Attach caller-owned ring storage and start with no recorded points.
// The storage must remain valid for the lifetime of the chain.
// Use a valid chain pointer and capacity entries of caller-owned storage.
// Capacity at most 128 keeps every head+age sum in the byte range used by the reader.
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);
// Forget the recorded points without clearing or freeing the backing storage.
void chain_clear(Chain* chain);
// Move the ring head backward and store the newest point. Once full, each push
// replaces the oldest point; zero capacity is a no-op.
void chain_push_head(Chain* chain, s16 x, s16 y);
// Read a point by age, with index zero denoting the newest point. Return zero
// for an invalid request and clear a non-null output first. Keep head + index
// within the 8-bit range: addition is narrowed before the capacity wrap.
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);
// Return the number of stored points, or zero for a null chain.
u8 chain_get_count(const Chain* chain);

// Return target minus current along the shortest wrapped route.
// Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized.
// Exactly half a field retains the direct displacement sign.
s16 chain_wrap_delta(u8 target, u8 current, u16 size);

// Articulated body: one current pose per joint, including the head at index 0.
// Caller-owned byte arrays keep the inner loop compact on both GB and FC.
// Heading sectors run clockwise: 0=right, 4=down, 8=left, 12=up.
// Coordinates are pixels; each wrapped dimension accepts 1..256 pixels.
typedef __packed struct {
    u8* x;
    u8* y;
    u8* heading;
    u8 capacity;
    u8 count;
    u16 width;
    u16 height;
} ChainBody;

// Attach three non-overlapping capacity-byte arrays. Return 1 on success.
// Invalid storage, zero capacity or dimensions outside 1..256 disable the body.
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);
// Seed count joints in a straight pose behind the head; count includes the head.
// Return 0 without changing the pose if count is zero or exceeds capacity.
// Coordinates wrap to the playfield and headings are masked to 0..15.
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);
// Install the caller's head pose, then pull joints from front to rear.
// Each joint aims four pixels behind its updated predecessor and receives that
// predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4.
// Call once per simulation tick; this does not advance head physics or render.
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);
// Append a copy of the current tail; later steps separate the new joint.
// Return 1 on growth, or 0 for an empty, disabled or full body.
u8 chain_body_grow(ChainBody* body);
// Remove all joints while retaining caller-owned storage and playfield settings.
void chain_body_clear(ChainBody* body);

kitaqgb/lib/chain.h

danmaku.h — Geschosspools, Fächermuster, Treffer und Streiferkennung
c
#pragma once

// Fixed-capacity, allocation-free bullet field for a 160 x 128 play area.
// Positions/velocities are signed Q12.4 / Q4.4; +Y points down.
// Tile ids 0..15 encode the four 4x4 quadrants of an 8x8 tile.
// Reserve those tiles in VRAM, with a 3x3 bullet centered at (2,2)
// in every set quadrant. Other tile ids in the map are decoration.
#define DANMAKU_MAX 96
#define DANMAKU_MAP_BYTES 576
typedef __packed struct {
    s16 x;
    s16 y;
    s8 vx;
    s8 vy;
    u8 active;
    u8 grazed;
} DanmakuBullet;

extern DanmakuBullet dm_bullets[DANMAKU_MAX];
extern __wram __aligned(16) u8 dm_map[DANMAKU_MAP_BYTES];
extern u8 dm_count;
extern u8 dm_peak;
// Per-step hit is a Boolean latch; graze counts newly grazed bullets this step. Spawn/rejection counters wrap at 65536.
extern u8 dm_hit;
extern u8 dm_graze;
extern u8 dm_player_x;
extern u8 dm_player_y;
extern u8 dm_invulnerable;
extern u16 dm_spawned;
extern u16 dm_rejected;

// Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.
void danmaku_reset();
// Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.
void danmaku_clear();
// Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);
// Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);
// 32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px.
// Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.
void danmaku_clear_map();
// Caller fills decoration after clear_map, then calls step to overlay bullets.
// hit and graze are events for this step. Collision uses rendered centers.
void danmaku_step();
// Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0.
// Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.
void danmaku_present_now();

kitaqgb/lib/danmaku.h

debug.h — RAM-Protokolle und Zusicherungen
c
#pragma once

// Use a capacity from 1 through 255; the length counter is a byte.
// Compile every unit with the same override so the array declaration and storage agree.
#ifndef DEBUG_TRACE_MAX
#define DEBUG_TRACE_MAX 32
#endif

// Each packed entry retains a name pointer and two 16-bit values; name text is not copied.
typedef __packed struct {
    const u8* name;
    u16 value;
    u16 frame;
} DebugTraceEntry;

extern DebugTraceEntry kq_debug_trace_log[DEBUG_TRACE_MAX];
extern u8 kq_debug_trace_count;
extern u16 kq_debug_frame;
extern u16 kq_debug_last_assert;

// Reset log length, frame tag and last assertion code; existing entry bytes are not erased.
void debug_init();
// Set the frame tag copied into subsequently recorded entries.
void debug_set_frame(u16 frame);
// Append a named frame marker using 0xFFFF as its value.
void debug_mark_frame(const u8* label);
// Append an unsigned byte value, widened to the log's 16-bit value field.
void debug_trace_u8(const u8* name, u8 value);
// Append a 16-bit value with the current frame tag.
void debug_trace_u16(const u8* name, u16 value);
// Record the assertion code and attempt to append an ASSERT entry. This helper
// does not halt execution, and the code is retained even if the log is full.
void debug_assert_fail(u16 code);
// Return the number of valid entries in the fixed trace buffer.
u8 debug_get_trace_count();
// Expose the internal trace array for inspection; use the count to bound reads.
const DebugTraceEntry* debug_get_trace_log();
// Read the last recorded assertion code, or the zero value installed by initialization.
u16 debug_get_last_assert();

#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)

kitaqgb/lib/debug.h

dmg3d.h — Monochrome Drahtgitterdarstellung mit 128×120 Pixeln für DMG
c
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 120
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"

// The aliases below add no calls or storage. Their contracts are documented at the corresponding wire3d_dmg.h declarations.
#define DMG3D_ANGLE_STEPS WIRE3D_DMG_ANGLE_STEPS
#define DMG3D_AUX_COL_BYTES WIRE3D_DMG_AUX_COL_BYTES
#define DMG3D_AUX_ROWS WIRE3D_DMG_AUX_ROWS
#define DMG3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define DMG3D_BeginFrame Wire3DDMG_BeginFrame
#define DMG3D_CENTER_X WIRE3D_DMG_CENTER_X
#define DMG3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define DMG3D_DrawIndexedEdges Wire3DDMG_DrawIndexedEdges
#define DMG3D_DrawLine2D Wire3DDMG_DrawLine2D
#define DMG3D_DrawLine3D Wire3DDMG_DrawLine3D
#define DMG3D_DrawModel Wire3DDMG_DrawModel
#define DMG3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define DMG3D_DrawScene Wire3DDMG_DrawScene
#define DMG3D_Edge Wire3DDMG_Edge
#define DMG3D_EdgeFaces Wire3DDMG_EdgeFaces
#define DMG3D_EndFrame Wire3DDMG_EndFrame
#define DMG3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define DMG3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define DMG3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define DMG3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define DMG3D_FAR_Z WIRE3D_DMG_FAR_Z
#define DMG3D_Face Wire3DDMG_Face
#define DMG3D_Init Wire3DDMG_Init
#define DMG3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define DMG3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define DMG3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define DMG3D_Model Wire3DDMG_Model
#define DMG3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define DMG3D_Object Wire3DDMG_Object
#define DMG3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define DMG3D_ProjectPoint Wire3DDMG_ProjectPoint
#define DMG3D_PutBgTile Wire3DDMG_PutBgTile
#define DMG3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define DMG3D_RotatePoint Wire3DDMG_RotatePoint
#define DMG3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define DMG3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define DMG3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define DMG3D_SetAuxTransfer Wire3DDMG_SetAuxTransfer
#define DMG3D_SetCamera Wire3DDMG_SetCamera
#define DMG3D_SetDirtyTransfer Wire3DDMG_SetDirtyTransfer
#define DMG3D_SetPalette Wire3DDMG_SetPalette
#define DMG3D_TILE_H WIRE3D_DMG_TILE_H
#define DMG3D_TILE_W WIRE3D_DMG_TILE_W
#define DMG3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define DMG3D_TransferAuxNow Wire3DDMG_TransferAuxNow
#define DMG3D_TransferMainNow Wire3DDMG_TransferMainNow
#define DMG3D_Vec3 Wire3DDMG_Vec3
// The remaining aliases retain internal identifiers for source compatibility; they do not define an independent renderer.
#define DMG3D_abs_i16 w3ddmg_abs_i16
#define DMG3D_angle_index w3ddmg_angle_index
#define DMG3D_aux_transfer_enabled w3ddmg_aux_transfer_enabled
#define DMG3D_bg_map_9800 w3ddmg_bg_map_9800
#define DMG3D_bgq_addr_hi w3ddmg_bgq_addr_hi
#define DMG3D_bgq_addr_lo w3ddmg_bgq_addr_lo
#define DMG3D_bgq_count w3ddmg_bgq_count
#define DMG3D_bgq_tile w3ddmg_bgq_tile
#define DMG3D_bgq_value w3ddmg_bgq_value
#define DMG3D_bgq_x w3ddmg_bgq_x
#define DMG3D_bgq_y w3ddmg_bgq_y
#define DMG3D_bit_mask w3ddmg_bit_mask
#define DMG3D_build_face_visibility w3ddmg_build_face_visibility
#define DMG3D_cam_pitch w3ddmg_cam_pitch
#define DMG3D_cam_roll w3ddmg_cam_roll
#define DMG3D_cam_x w3ddmg_cam_x
#define DMG3D_cam_y w3ddmg_cam_y
#define DMG3D_cam_yaw w3ddmg_cam_yaw
#define DMG3D_cam_z w3ddmg_cam_z
#define DMG3D_clamp_i16 w3ddmg_clamp_i16
#define DMG3D_clamp_screen w3ddmg_clamp_screen
#define DMG3D_clear_dirty_tables w3ddmg_clear_dirty_tables
#define DMG3D_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define DMG3D_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define DMG3D_clear_stage_asm w3ddmg_clear_stage_asm
#define DMG3D_clear_stage_aux_asm w3ddmg_clear_stage_aux_asm
#define DMG3D_clear_triangle w3ddmg_clear_triangle
#define DMG3D_clear_vram_asm w3ddmg_clear_vram_asm
#define DMG3D_cos_q6 w3ddmg_cos_q6
#define DMG3D_dirty_dst_hi w3ddmg_dirty_dst_hi
#define DMG3D_dirty_dst_lo w3ddmg_dirty_dst_lo
#define DMG3D_dirty_src_hi w3ddmg_dirty_src_hi
#define DMG3D_dirty_src_lo w3ddmg_dirty_src_lo
#define DMG3D_dirty_tiles w3ddmg_dirty_tiles
#define DMG3D_dirty_transfer_enabled w3ddmg_dirty_transfer_enabled
#define DMG3D_edge_area w3ddmg_edge_area
#define DMG3D_face_visible w3ddmg_face_visible
#define DMG3D_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define DMG3D_flush_bg_queue w3ddmg_flush_bg_queue
#define DMG3D_i16 w3ddmg_i16
#define DMG3D_i8 w3ddmg_i8
#define DMG3D_inv_depth w3ddmg_inv_depth
#define DMG3D_is_edge_visible w3ddmg_is_edge_visible
#define DMG3D_line_dx w3ddmg_line_dx
#define DMG3D_line_dy w3ddmg_line_dy
#define DMG3D_line_err w3ddmg_line_err
#define DMG3D_line_stage_asm w3ddmg_line_stage_asm
#define DMG3D_line_stage_masked_c w3ddmg_line_stage_masked_c
#define DMG3D_line_sx w3ddmg_line_sx
#define DMG3D_line_sy w3ddmg_line_sy
#define DMG3D_line_x w3ddmg_line_x
#define DMG3D_line_x0 w3ddmg_line_x0
#define DMG3D_line_x1 w3ddmg_line_x1
#define DMG3D_line_y w3ddmg_line_y
#define DMG3D_line_y0 w3ddmg_line_y0
#define DMG3D_line_y1 w3ddmg_line_y1
#define DMG3D_mark_line_dirty w3ddmg_mark_line_dirty
#define DMG3D_mark_model_occluder w3ddmg_mark_model_occluder
#define DMG3D_mark_rect_dirty w3ddmg_mark_rect_dirty
#define DMG3D_mark_tile_dirty w3ddmg_mark_tile_dirty
#define DMG3D_mark_triangle w3ddmg_mark_triangle
#define DMG3D_mask_get w3ddmg_mask_get
#define DMG3D_mask_offset w3ddmg_mask_offset
#define DMG3D_mask_set w3ddmg_mask_set
#define DMG3D_mask_set_span w3ddmg_mask_set_span
#define DMG3D_neg_angle w3ddmg_neg_angle
#define DMG3D_occlusion_active w3ddmg_occlusion_active
#define DMG3D_occlusion_mask w3ddmg_occlusion_mask
#define DMG3D_plot_stage_asm w3ddmg_plot_stage_asm
#define DMG3D_plot_tx w3ddmg_plot_tx
#define DMG3D_plot_x w3ddmg_plot_x
#define DMG3D_plot_y w3ddmg_plot_y
#define DMG3D_prev_dirty_tiles w3ddmg_prev_dirty_tiles
#define DMG3D_project_camera_space w3ddmg_project_camera_space
#define DMG3D_project_world w3ddmg_project_world
#define DMG3D_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define DMG3D_reg_bgp w3ddmg_reg_bgp
#define DMG3D_reg_lcdc w3ddmg_reg_lcdc
#define DMG3D_reg_ly w3ddmg_reg_ly
#define DMG3D_reg_scx w3ddmg_reg_scx
#define DMG3D_reg_scy w3ddmg_reg_scy
#define DMG3D_rotate_x w3ddmg_rotate_x
#define DMG3D_rotate_y w3ddmg_rotate_y
#define DMG3D_rotate_z w3ddmg_rotate_z
#define DMG3D_scene_depth w3ddmg_scene_depth
#define DMG3D_scene_object_depth w3ddmg_scene_object_depth
#define DMG3D_scene_order w3ddmg_scene_order
#define DMG3D_screen_delta w3ddmg_screen_delta
#define DMG3D_screen_visible w3ddmg_screen_visible
#define DMG3D_screen_x w3ddmg_screen_x
#define DMG3D_screen_y w3ddmg_screen_y
#define DMG3D_sin_q6 w3ddmg_sin_q6
#define DMG3D_stage w3ddmg_stage
#define DMG3D_stage_clear_pixel w3ddmg_stage_clear_pixel
#define DMG3D_stage_clear_span w3ddmg_stage_clear_span
#define DMG3D_transfer_dirty_stage w3ddmg_transfer_dirty_stage
#define DMG3D_transfer_dirty_tile_asm w3ddmg_transfer_dirty_tile_asm
#define DMG3D_transfer_stage_asm w3ddmg_transfer_stage_asm
#define DMG3D_transfer_stage_aux_asm w3ddmg_transfer_stage_aux_asm
#define DMG3D_u16 w3ddmg_u16
#define DMG3D_u8 w3ddmg_u8
#define DMG3D_vram_tiles w3ddmg_vram_tiles
#define DMG3D_wait_vblank_start w3ddmg_wait_vblank_start
#define dmg3d w3ddmg
#define dmg3d_pair_aux_block w3ddmg_pair_aux_block
#define dmg3d_pair_aux_done w3ddmg_pair_aux_done
#define dmg3d_pair_aux_wait_0 w3ddmg_pair_aux_wait_0
#define dmg3d_pair_aux_wait_1 w3ddmg_pair_aux_wait_1
#define dmg3d_pair_aux_wait_10 w3ddmg_pair_aux_wait_10
#define dmg3d_pair_aux_wait_11 w3ddmg_pair_aux_wait_11
#define dmg3d_pair_aux_wait_12 w3ddmg_pair_aux_wait_12
#define dmg3d_pair_aux_wait_13 w3ddmg_pair_aux_wait_13
#define dmg3d_pair_aux_wait_14 w3ddmg_pair_aux_wait_14
#define dmg3d_pair_aux_wait_15 w3ddmg_pair_aux_wait_15
#define dmg3d_pair_aux_wait_16 w3ddmg_pair_aux_wait_16
#define dmg3d_pair_aux_wait_17 w3ddmg_pair_aux_wait_17
#define dmg3d_pair_aux_wait_18 w3ddmg_pair_aux_wait_18
#define dmg3d_pair_aux_wait_19 w3ddmg_pair_aux_wait_19
#define dmg3d_pair_aux_wait_2 w3ddmg_pair_aux_wait_2
#define dmg3d_pair_aux_wait_20 w3ddmg_pair_aux_wait_20
#define dmg3d_pair_aux_wait_21 w3ddmg_pair_aux_wait_21
#define dmg3d_pair_aux_wait_22 w3ddmg_pair_aux_wait_22
#define dmg3d_pair_aux_wait_23 w3ddmg_pair_aux_wait_23
#define dmg3d_pair_aux_wait_24 w3ddmg_pair_aux_wait_24
#define dmg3d_pair_aux_wait_25 w3ddmg_pair_aux_wait_25
#define dmg3d_pair_aux_wait_26 w3ddmg_pair_aux_wait_26
#define dmg3d_pair_aux_wait_27 w3ddmg_pair_aux_wait_27
#define dmg3d_pair_aux_wait_3 w3ddmg_pair_aux_wait_3
#define dmg3d_pair_aux_wait_4 w3ddmg_pair_aux_wait_4
#define dmg3d_pair_aux_wait_5 w3ddmg_pair_aux_wait_5
#define dmg3d_pair_aux_wait_6 w3ddmg_pair_aux_wait_6
#define dmg3d_pair_aux_wait_7 w3ddmg_pair_aux_wait_7
#define dmg3d_pair_aux_wait_8 w3ddmg_pair_aux_wait_8
#define dmg3d_pair_aux_wait_9 w3ddmg_pair_aux_wait_9
#define dmg3d_pair_main_block w3ddmg_pair_main_block
#define dmg3d_pair_main_wait_0 w3ddmg_pair_main_wait_0
#define dmg3d_pair_main_wait_1 w3ddmg_pair_main_wait_1
#define dmg3d_pair_main_wait_10 w3ddmg_pair_main_wait_10
#define dmg3d_pair_main_wait_11 w3ddmg_pair_main_wait_11
#define dmg3d_pair_main_wait_12 w3ddmg_pair_main_wait_12
#define dmg3d_pair_main_wait_13 w3ddmg_pair_main_wait_13
#define dmg3d_pair_main_wait_14 w3ddmg_pair_main_wait_14
#define dmg3d_pair_main_wait_2 w3ddmg_pair_main_wait_2
#define dmg3d_pair_main_wait_3 w3ddmg_pair_main_wait_3
#define dmg3d_pair_main_wait_4 w3ddmg_pair_main_wait_4
#define dmg3d_pair_main_wait_5 w3ddmg_pair_main_wait_5
#define dmg3d_pair_main_wait_6 w3ddmg_pair_main_wait_6
#define dmg3d_pair_main_wait_7 w3ddmg_pair_main_wait_7
#define dmg3d_pair_main_wait_8 w3ddmg_pair_main_wait_8
#define dmg3d_pair_main_wait_9 w3ddmg_pair_main_wait_9
#define dmg3dac_col w3ddmgac_col
#define dmg3dac_enter w3ddmgac_enter
#define dmg3dac_row w3ddmgac_row
#define dmg3dbg_enter w3ddmgbg_enter
#define dmg3dco_enter w3ddmgco_enter
#define dmg3dco_loop w3ddmgco_loop
#define dmg3dco_page w3ddmgco_page
#define dmg3dcs_enter w3ddmgcs_enter
#define dmg3dcs_inner w3ddmgcs_inner
#define dmg3dcs_outer w3ddmgcs_outer
#define dmg3dcv_enter w3ddmgcv_enter
#define dmg3dcv_loop w3ddmgcv_loop
#define dmg3dcv_page w3ddmgcv_page
#define dmg3ddt_enter w3ddmgdt_enter
#define dmg3ddt_loop w3ddmgdt_loop
#define dmg3dfb_enter w3ddmgfb_enter
#define dmg3dfb_loop w3ddmgfb_loop
#define dmg3dfb_page w3ddmgfb_page
#define dmg3dls_branch w3ddmgls_branch
#define dmg3dls_done w3ddmgls_done
#define dmg3dls_enter w3ddmgls_enter
#define dmg3dls_shallow w3ddmgls_shallow
#define dmg3dls_shallow_loop w3ddmgls_shallow_loop
#define dmg3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define dmg3dls_steep w3ddmgls_steep
#define dmg3dls_steep_loop w3ddmgls_steep_loop
#define dmg3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define dmg3dls_x_reverse w3ddmgls_x_reverse
#define dmg3dls_y_reverse w3ddmgls_y_reverse
#define dmg3dls_y_start w3ddmgls_y_start
#define dmg3dps_enter w3ddmgps_enter
#define dmg3dps_ret w3ddmgps_ret

kitaqgb/lib/dmg3d.h

entity.h — Objektpools mit festen Arrays
c
#pragma once

// Keep capacity in 1..255: IDs and scan counters are bytes and FF is reserved for failure.
// Use the same definition in every compilation unit.
#ifndef ENTITY_MAX
#define ENTITY_MAX ((u8)16)
#endif

// Position, velocity, state and timer units are game-defined; the pool does not advance them.
// The sprite field is only bookkeeping and does not allocate or release OAM entries.
typedef __packed struct {
    u8 active;
    u8 type;
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    u8 state;
    u8 timer;
    u8 sprite;
} Entity;

// An entity callback receives a slot ID, not a persistent object handle.
typedef void (*EntityFn)(u8 id);

// Reset every slot before the game starts using the pool.
void entity_init();
// Returns a reusable slot ID, or 0xFF if no slot is free.
u8 entity_create(u8 type, s16 x, s16 y);
// Release a valid slot without clearing its payload. Reallocation resets the payload;
// a saved pointer or ID must not be treated as a persistent entity identity.
void entity_destroy(u8 id);
// Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.
Entity* entity_get(u8 id);
// Call fn for each slot that is active when the scan reaches it; null is a no-op.
// Callbacks may change the pool, so newly activated later slots can run in this pass.
void entity_update_all(EntityFn fn);
// Use the same active-slot traversal for drawing; the callback supplies all rendering.
void entity_draw_all(EntityFn fn);
// Count occupied slots without changing entity state.
u8 entity_count_active();
// Release every entity and restore deterministic defaults, including the no-sprite sentinel.
void entity_clear_all();

kitaqgb/lib/entity.h

fixed.h — Q8.8-Festkommaarithmetik und Rechtecke
c
#pragma once

// Signed Q8.8 uses 256 units per pixel/value: the range is -128 to 127 + 255/256.
typedef s16 fix8;

#define FIX_ONE ((fix8)256)
#define FIX_HALF ((fix8)128)

typedef __packed struct {
    fix8 x;
    fix8 y;
} Vec2;

typedef __packed struct {
    s16 x;
    s16 y;
    s16 w;
    s16 h;
} KQRect;

// Convert an integer to signed 8.8 fixed point by moving it into the high byte.
// The caller must keep the result within the representable 16-bit range.
fix8 fix_from_int(s16 n);
// Discard the eight fractional bits using a signed right shift.
s16 fix_to_int(fix8 x);
// Approximate 8.8 multiplication by discarding four low bits from each operand
// before multiplying. This trades precision for a smaller intermediate product.
fix8 fix_mul(fix8 a, fix8 b);
// Scale the reduced-precision quotient back to 8.8 and return zero for b == 0.
// Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b.
// The intermediate product must fit the compiler's integer arithmetic.
fix8 fix_div(fix8 a, fix8 b);
// Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low
// bits, so small changes may vanish and a weight of 255 need not reach b.
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);
// Return the magnitude in s16. The most-negative s16 has no positive s16
// representation and must be excluded by callers needing a nonnegative result.
s16 kq_abs_s16(s16 v);
// Select the smaller signed value.
s16 kq_min_s16(s16 a, s16 b);
// Select the larger signed value.
s16 kq_max_s16(s16 a, s16 b);
// Clamp to an inclusive interval; callers must provide lo <= hi.
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);
// Test overlap using exclusive right/bottom edges; touching edges do not collide.
// Require positive dimensions and edge sums that fit s16; zero-sized rectangles
// are not explicitly rejected and may be reported as overlapping.
u8 kq_rect_intersect(KQRect a, KQRect b);
// Test a half-open rectangle: left/top edges are included, right/bottom excluded.
// The coordinate-plus-size sums must remain representable as s16.
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);

kitaqgb/lib/fixed.h

input.h — Tastenzustand, Drücken, Loslassen und Wiederholung
c
#pragma once

#define BTN_RIGHT  ((u8)0x01)
#define BTN_LEFT   ((u8)0x02)
#define BTN_UP     ((u8)0x04)
#define BTN_DOWN   ((u8)0x08)
#define BTN_A      ((u8)0x10)
#define BTN_B      ((u8)0x20)
#define BTN_SELECT ((u8)0x40)
#define BTN_START  ((u8)0x80)

// A fresh press pulses immediately. The next pulse occurs DELAY + 1 updates later.
#ifndef INPUT_REPEAT_DELAY
#define INPUT_REPEAT_DELAY ((u8)18)
#endif

// Subsequent pulses are RATE + 1 updates apart; zero repeats on every held update.
#ifndef INPUT_REPEAT_RATE
#define INPUT_REPEAT_RATE ((u8)5)
#endif

extern u8 kq_input_prev_keys;
extern u8 kq_input_keys;
extern u8 kq_input_press_keys;
extern u8 kq_input_release_keys;
extern u8 kq_input_repeat_keys;

u16 __readpadex(u8 prev_keys);

// Clear sampled/edge state and initialize an independent repeat timer for each button.
void input_init();
// Sample input once per game tick and derive press, release and repeat masks.
// Repeat delays are measured in calls to this function, not elapsed wall-clock time.
void input_update();
// Return whether any masked button is currently held.
u8 input_down(u8 mask);
// Return whether any masked button became pressed in the latest sample.
u8 input_pressed(u8 mask);
// Return whether any masked button became released in the latest sample.
u8 input_released(u8 mask);
// Return whether any masked button produced a fresh press or scheduled repeat pulse.
u8 input_repeat(u8 mask);
// Return the complete held-button mask from the latest update.
u8 input_current();
// Return the held-button mask that preceded the latest update.
u8 input_previous();

#define btn_down input_down
#define btn_pressed input_pressed
#define btn_released input_released
#define btn_repeat input_repeat

kitaqgb/lib/input.h

link.h — Serielle Kommunikation und logische Pakete
c
#pragma once

// Shared Game Boy serial link library for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before link.c / link_packet.c so SB, SC,
//   IF_REG, and IE_REG are already declared.
// - Call Link_InitMaster() on the clock-source side and Link_InitSlave() on the
//   other side.
// - Call Link_Poll() or Link_PollPacket() regularly from the main loop.
// - If you enable serial IRQ mode, call Link_OnSerialIRQ() from your own
//   serial interrupt handler at vector 0x0058.
// - The packet layer is intentionally small and one-deep. It works best as a
//   master-driven command/response layer. The low-level byte API remains the
//   escape hatch for custom protocols.

#define LINK_MODE_SLAVE   ((u8)0)
#define LINK_MODE_MASTER  ((u8)1)

#define LINK_CLOCK_NORMAL ((u8)0)
#define LINK_CLOCK_FAST   ((u8)1)

#define LINK_ERR_NONE        ((u8)0)
#define LINK_ERR_BUSY        ((u8)1)
#define LINK_ERR_TIMEOUT     ((u8)2)
#define LINK_ERR_OVERFLOW    ((u8)3)
#define LINK_ERR_PROTOCOL    ((u8)4)
#define LINK_ERR_DISCONNECT  ((u8)5)

#define LINK_PKT_MAX_PAYLOAD ((u8)24)
#define LINK_RX_QUEUE_SIZE   ((u8)8)
#define LINK_TX_QUEUE_SIZE   ((u8)8)

#define LINK4_MODE_NONE      ((u8)0)
#define LINK4_MODE_HOST      ((u8)1)
#define LINK4_MODE_PEER      ((u8)2)
#define LINK4_MAX_PLAYERS    ((u8)4)
#define LINK4_HOST_SLOT      ((u8)0)
#define LINK4_INVALID_SLOT   ((u8)0xFF)

// Reset byte queues, packet mailboxes, cooperative-peer state and errors, then
// disable serial transfers and serial IRQ delivery. Existing data is discarded.
void Link_InitCommon();
// Reset link state and select the internal-clock role for subsequent transfers.
void Link_InitMaster();
// Reset link state and select the external-clock role for subsequent transfers.
void Link_InitSlave();
// Enable or disable serial IRQ delivery and clear its pending flag. Enabling
// does not install the handler. Leaving its outer critical section enables CPU interrupts.
void __stackcall Link_SetUseInterrupt(u8 on);
// Select the fast-clock bit for future master transfers; this does not restart
// an active transfer or verify that the hardware supports CGB fast mode.
void __stackcall Link_SetFastClock(u8 on);

// Poll once before returning busy state, so this query may collect a completed byte.
u8 Link_IsBusy();
// Read the ordinary receive-ready flag without polling hardware.
u8 Link_HasByte();
// Return the latest latched error without clearing it.
u8 Link_LastError();
// Clear the error latch without resetting queues or an active transfer.
void Link_ClearError();

// Start one full-duplex byte exchange, or return BUSY without replacing an
// active transfer. Slave mode arms reception and waits for external clocks.
u8 __stackcall Link_BeginTransfer(u8 out);
// Collect a pending transfer only after hardware clears the SC start bit.
void Link_Poll();
// Stop the hardware transfer under interrupt protection. Queued receive bytes
// and packet-layer state remain available; this is not a full protocol reset.
void Link_Cancel();
// Acknowledge serial IRQ and finish a software-busy transfer. Call this from
// the actual serial interrupt handler, not an unrelated interrupt.
void Link_OnSerialIRQ();

// Pop the ordinary receive queue without waiting or polling hardware; null discards a byte.
u8 __stackcall Link_TryReadByte(u8 *out);
// Pop one byte, returning zero when empty. Use Link_TryReadByte when a received
// zero byte must be distinguished from an empty queue.
u8 Link_ReadByte();
// Require an output pointer, poll immediately, then wait at most timeout_frames
// VBlanks for a byte. Zero timeout still performs the initial poll and read.
u8 __stackcall Link_WaitByte(u16 timeout_frames, u8 *out);

// Validate payload size and idle packet state, copy payload bytes into owned
// storage and schedule transmission. Return success means queued, not acknowledged;
// keep polling to progress the exchange and inspect the error latch.
u8 __stackcall Link_SendPacket(const u8 *data, u8 len, u8 cmd);
// Drain received bytes, advance one outgoing exchange and update the retry
// timer. Timeout ticks count calls without progress, not hardware frames; call
// with a controlled cadence and avoid mixing raw reads with packet consumption.
void Link_PollPacket();
// Inspect the shared completed-packet flag without advancing the protocol.
u8 Link_HasPacket();
// Consume the shared packet mailbox and its matching peer flag. Any output
// may be null; a nonnull destination needs room for the received payload because
// there is no destination-capacity argument.
u8 __stackcall Link_ReadPacket(u8 *cmd, u8 *len, u8 *dst);

// Cooperative 4-player adapter helpers.
//
// This layer models the common host-selected adapter pattern:
// - Slot 0 is always the host.
// - The host selects one active peer slot at a time.
// - Packet mailboxes stay one-deep per peer.
// - The original Link_* API remains available for normal 2-player projects.
// Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.
u8 __stackcall Link4_InitHost(u8 slot_count);
// Reset as slave and validate the local nonzero slot and total slot count.
// An invalid configuration still discards the previous link state.
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);
// Return the configured cooperative role; this is not a hardware connection probe.
u8 Link4_GetMode();
// Return the configured zero-based local slot.
u8 Link4_GetLocalSlot();
// Return the configured number of logical slots, not a live connection count.
u8 Link4_GetSlotCount();
// Return the current logical destination, or the invalid-slot sentinel when unset.
u8 Link4_GetSelectedPeer();
// Return the peer attributed to the last completed byte transfer.
u8 Link4_GetLastRxPeer();
// Return the peer attributed when the last byte transfer was started.
u8 Link4_GetLastTxPeer();
// Poll completion, then change the logical destination only while byte and
// packet state are idle. A peer can select only the host. No adapter-routing
// command is sent here; the transport must provide the matching physical route.
u8 __stackcall Link4_SelectPeer(u8 peer_slot);
// Select the logical peer and start a byte exchange, returning the first error.
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);
// Inspect a valid peer ring without polling the hardware.
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);
// Pop one byte from the selected peer ring; null output discards it.
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);
// Scan remote rings in increasing slot order and return the first available
// byte. Null output pointers are allowed; lower slots have polling priority.
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);
// Select a logical peer, then copy and schedule a packet; return the first error.
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);
// Advance the shared packet engine; this does not poll every logical peer in turn.
void Link4_PollPacket();
// Inspect the one-packet mailbox for a valid remote slot without consuming it.
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);
// Consume a peer mailbox, copying to optional outputs. A nonnull destination
// needs room for the entire payload. Clear the shared mailbox only when it
// refers to this same peer.
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);

kitaqgb/lib/link.h

link_dmg07.h — DMG-07-Kommunikation mit externem Takt
c
#pragma once

// Polling driver for the physical Nintendo DMG-07 Four Player Adapter.
//
// The adapter supplies every serial clock.  LinkDmg07_Poll() must therefore be
// called frequently enough to re-arm the serial port between adapter bytes;
// calling it only once per video frame is not sufficient.  Call
// LinkDmg07_TickFrame() exactly once per frame for timeout accounting.
//
// Transmission uses SIZE=1: every adapter packet contains four bytes, one for
// each physical player slot.  A console sends its local byte during byte 0 and
// sends zero during bytes 1..3, except while emitting an aligned FF restart
// packet.  The adapter broadcasts those four submitted bytes in the following
// packet.  The initial broadcast contains undefined adapter data and is
// discarded by this driver.

#define LINK_DMG07_PHASE_PING       ((u8)0)
#define LINK_DMG07_PHASE_REQUEST_AA ((u8)1)
#define LINK_DMG07_PHASE_WAIT_CC    ((u8)2)
#define LINK_DMG07_PHASE_TRANSFER   ((u8)3)

#define LINK_DMG07_MAX_PLAYERS  ((u8)4)
#define LINK_DMG07_PACKET_BYTES ((u8)4)
#define LINK_DMG07_SIZE         ((u8)1)
// Physical slots here are one-based; do not substitute the zero-based Link4 cooperative slot identifiers.
#define LINK_DMG07_NO_SLOT      ((u8)0)

// RATE $10 gives the shortest documented packet period for SIZE=1 while
// retaining the adapter's normal inter-byte pacing.  RATE $00 is not used.
#define LINK_DMG07_DEFAULT_RATE ((u8)0x10)

#ifndef LINK_DMG07_TIMEOUT_FRAMES
#define LINK_DMG07_TIMEOUT_FRAMES ((u8)12)
#endif

#define LINK_DMG07_ERR_NONE        ((u8)0)
#define LINK_DMG07_ERR_STATE       ((u8)1)
#define LINK_DMG07_ERR_NOT_PLAYER1 ((u8)2)
#define LINK_DMG07_ERR_NOT_READY   ((u8)3)
#define LINK_DMG07_ERR_TIMEOUT     ((u8)4)
#define LINK_DMG07_ERR_PROTOCOL    ((u8)5)
#define LINK_DMG07_ERR_OVERFLOW    ((u8)6)

#define LINK_DMG07_RESTART_NONE    ((u8)0)
#define LINK_DMG07_RESTART_PENDING ((u8)1)
#define LINK_DMG07_RESTART_SENDING ((u8)2)

// Initializes polling-only external-clock operation.  A zero RATE is replaced
// with LINK_DMG07_DEFAULT_RATE.  This driver disables only the serial IRQ bit.
void __stackcall LinkDmg07_Init(u8 rate);

// Services at most one completed serial byte and immediately re-arms SC=$80.
// Call continuously from the main loop, including between VBlanks.
void LinkDmg07_Poll();

// Advances saturating frame-based silence and handshake timeout counters.
void LinkDmg07_TickFrame();

// Return the discovery, start-handshake or transfer phase without polling.
u8 LinkDmg07_GetPhase();
// Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.
u8 LinkDmg07_GetLocalSlot();

// Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.
u8 LinkDmg07_GetConnectedMask();
// Return the last validated raw adapter status byte.
u8 LinkDmg07_GetLastStatus();
// Read the completed-discovery status flag without clearing it.
u8 LinkDmg07_HasPingStatus();
// Clear and report the completed-discovery flag; return zero if no new status exists.
u8 LinkDmg07_ConsumePingStatus();

// Only physical player 1 may request AA AA AA AA.  The bytes are aligned to
// the next FE/status/status/status ping packet.  All consoles enter transfer
// mode only after receiving four consecutive CC bytes.
u8 LinkDmg07_RequestTransmission();

// Any physical slot may schedule FF FF FF FF at the next four-byte packet
// boundary while remaining in TRANSFER phase.  The driver keeps sending aligned
// FF bytes until it sees the adapter's complete all-FF indicator packet, then
// returns to PING.  A transfer-phase silence timeout schedules the same recovery
// automatically and preserves the current byte position for clocks that resume.
u8 LinkDmg07_RequestRestart();
// Return whether aligned recovery is absent, pending or sending control traffic.
u8 LinkDmg07_GetRestartState();

// Sets the byte sampled when byte 0 of the next adapter packet is armed.
// Set it before the current packet completes (and before requesting start for
// the first submission).  During normal transfer, bytes 1..3 are sent as zero.
void __stackcall LinkDmg07_SetLocalByte(u8 value);

// The first incoming adapter data packet is discarded.  Thereafter ReadPacket
// copies four bytes in physical slot order (players 1..4).
u8 LinkDmg07_IsPipelinePrimed();
// Inspect the one-packet receive mailbox without consuming it.
u8 LinkDmg07_HasPacket();
// Consume the latest four-byte packet. A nonnull destination must hold four
// bytes; null discards the packet. Packet storage remains after the flag clears.
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);
// Read one cached player byte using a one-based slot. Invalid slots return
// zero; the function neither requires readiness nor consumes the packet.
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);

// SentSequence increments when this console's packet byte is clocked out.
// PacketSequence labels the returned four-byte packet.  For a valid packet it
// is one less than SentSequence, making the DMG-07 one-packet delay explicit.
u8 LinkDmg07_GetSentSequence();
// Return the modulo-256 sequence associated with the most recently published packet.
u8 LinkDmg07_GetPacketSequence();

// SilenceFrames is reset by every completed serial byte.  TimeoutCount counts
// distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts
// adapter-silence outages and ping-status membership drops.  All saturate.
u8 LinkDmg07_GetSilenceFrames();
// Return the saturating lifetime timeout count, preserved across protocol restarts.
u8 LinkDmg07_GetTimeoutCount();
// Return the saturating count of removed-player and previously-seen-adapter timeout events.
u8 LinkDmg07_GetDisconnectCount();
// Return the saturating protocol/overflow error count. Timeout and request
// validation paths use separate counters or latches and do not increment this value.
u8 LinkDmg07_GetErrorCount();
// Return the latest error latch without clearing counters or restarting the protocol.
u8 LinkDmg07_LastError();
// Clear only the latest error code, preserving counters and protocol state.
void LinkDmg07_ClearError();

kitaqgb/lib/link_dmg07.h

physics2d.h — 2D-Bewegung und Kollisionen
c
#pragma once

// Position and velocity use caller-selected integer units with one integration
// step per call; no hidden pixel or time conversion occurs. Keep intermediate
// signed arithmetic in range. World/body storage is owned by the caller.
#include "fixed.h"

// Multiply a signed word by a signed byte; divide by 256, truncating toward zero.
s16 __smul16x8(s16 a, s8 b);

// Lightweight deterministic 2D physics for KITAQGB.
// Integer pixels per step are one possible unit convention; inv_mass is Q8.

typedef struct {
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    s16 half_x;
    s16 half_y;
    s16 inv_mass_q8;      // 0 means static body.
    s16 restitution_q8;   // 0..255 (reserved for future tuning).
    u8 active;
} KQBody2D;

typedef struct {
    KQBody2D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    u8 solver_iterations;
    s16 max_speed;
} KQWorld2D;

// Retain the caller-owned body array without initializing its elements.
// Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512.
// A null world is ignored; the array must outlive subsequent world operations.
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);
// Advance active dynamic bodies, then visit each active unordered pair for
// the configured contact passes (zero means one). Static bodies still participate
// as obstacles. The world borrows its array and shares non-reentrant ASM scratch.
// This is discrete integration; fast bodies can pass through thin obstacles.
void kq2d_step(KQWorld2D* world);
// For one active dynamic body, add gravity, clamp each velocity axis and then
// add velocity to position. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and keep additions in signed 16-bit range.
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);
// Test strict overlap of two centered boxes; touching edges return false.
// Both pointers must be valid. Active/mass flags are ignored, and coordinate
// differences and extent sums must fit the signed 16-bit calculations.
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);
// Initialize an active unit-inverse-mass body at the supplied center and half
// extents, with zero velocity and reserved restitution set to zero. Null is ignored.
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);
// Replace the center without altering velocity, extents or activity. Null is ignored.
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);
// Replace velocity without clamping or checking activity/mass. Null is ignored.
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);
// Add gravity and clamp each velocity axis separately for an active dynamic
// body. Null, inactive and static bodies are ignored. Supply a nonnegative limit
// and avoid overflow in the additions before clamping; position is unchanged.
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);
// Scale both velocities through the signed 8-bit coefficient intrinsic.
// Despite the unsigned parameter, values 128..255 become negative coefficients;
// this is not a full-range unsigned Q8 damping helper. Null is ignored.
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);
// Delegate strict rectangle overlap to the fixed-point utility; edge-only
// contact is false. Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_rect_intersect(KQRect a, KQRect b);
// Delegate the half-open point test: include left/top and exclude right/bottom.
// Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);

// Opt-in surface solver. Velocities/threshold/kick share the caller's units.
// Normal must be unit length in Q8; coefficients are 0..255.
typedef struct {
    s16 nx_q8;
    s16 ny_q8;
    s16 vx;
    s16 vy;
    s16 bounce_threshold;
    s16 kick;
    u8 restitution_q8;
    u8 friction_q8;
} KQSurface2D;

// Truncates toward zero, including negative values; coefficient is -256..256.
s16 kq2d_scale_q8(s16 value, s16 coefficient);
// Conservative circular bound, with a shared Q8 scale for both components.
// Quantizes toward zero; very small limits relative to input may yield zero.
// Components and positive max_speed must be <= 16383 in magnitude.
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);
// Kinematic surface response; returns incoming normal speed, or zero if separating.
// Caller resolves penetration separately. Relative components must fit +/-8191.
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);
// Linear crossing time in Q8 (0..256); positive separation is outside.
// Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);

kitaqgb/lib/physics2d.h

physics2d_circle.h — Kreisphysik
c
#pragma once

// Deterministic 2D circle physics for KITAQGB.
// Intended for top-down ball games such as billiards, air hockey, and marbles.

// Use consistent caller-selected units for centers, radii and per-step velocity.
// The implementation uses 16-bit arithmetic: reduced squared-distance sums and
// weight products must fit their types. Reduction to byte-sized components alone
// is insufficient to guarantee this. Body storage remains caller-owned.
typedef struct {
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    s16 radius;
    s16 inv_mass_q8;      // 0 means static body.
    u8 restitution_q8;    // 0..255, higher means bouncier.
    u8 friction_q8;       // 0..255, higher removes more tangential motion.
    u8 active;
} KQCircleBody2D;

typedef struct {
    KQCircleBody2D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    u8 solver_iterations;
    s16 max_speed;
    u8 linear_damping_q8;   // 255 is almost no damping, lower values damp faster.
    u8 use_bounds;
    s16 min_x;
    s16 min_y;
    s16 max_x;
    s16 max_y;
    u8 wall_restitution_q8;
    u8 wall_friction_q8;
} KQCircleWorld2D;

// Retain a caller-owned array without initializing bodies. Set zero gravity,
// four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled.
// A null world is ignored. Keep the array alive for subsequent steps.
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);
// Store and enable bounds without validating their order or fitting bodies
// immediately. Supply extents large enough for body diameters. Null is ignored.
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);
// Integrate active dynamic bodies, apply bounds, solve contacts, then damp
// velocity and snap components in -1..1 to zero. Zero solver iterations means one.
// Pairs with both velocities zero are skipped, so resting overlaps can remain.
// Bounds can reposition static bodies; null world/array inputs are ignored.
void kq2dc_step(KQCircleWorld2D* world);
// Compare a reduced integer center distance with the reduced radius sum.
// Valid pointers and positive radii are required; activity and mass are ignored.
// This approximate test requires representable differences, radius sums and
// squared-distance sum. Touching at the computed distance returns false.
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);

kitaqgb/lib/physics2d_circle.h

physics3d.h — Physik für achsenparallele 3D-Quader
c
#pragma once

// Lightweight deterministic 3D physics for KITAQGB.
// AABB contacts, acceleration, mass-weighted bounce, and impact state flags.

// The game owns break decisions: the solver records impact speeds but never
// sets this flag or deactivates a body based on break_speed. Positions, extents,
// velocities and acceleration use consistent caller-selected per-step units.
#define KQ3D_BODY_BROKEN ((u8)0x01)

typedef struct {
    s16 x;
    s16 y;
    s16 z;
    s16 vx;
    s16 vy;
    s16 vz;
    s16 ax;
    s16 ay;
    s16 az;
    s16 half_x;
    s16 half_y;
    s16 half_z;
    s16 mass_q8;        // 256 means mass 1.0.
    s16 inv_mass_q8;    // 0 means static body.
    s16 restitution_q8; // 256 means perfectly elastic.
    s16 break_speed;    // Reserved for game-side impact thresholds.
    s16 last_impact_speed;
    u8 active;
    u8 flags;
} KQBody3D;

typedef struct {
    KQBody3D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    s16 gravity_z;
    u8 solver_iterations;
    s16 max_speed;
} KQWorld3D;

// Borrow the body array without initializing it. Set gravity (0,24,0), four
// contact passes and a per-axis speed limit of 512. Null world is ignored;
// the caller retains ownership and must keep the array alive.
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);
// Initialize an active centered box with zero velocity/acceleration,
// restitution 224, cleared impact/flags and mass set through the weight helper.
// The caller supplies valid half extents. Null body is ignored.
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);
// Store the requested mass; nonpositive mass makes the body static.
// For positive mass compute inverse weight as max(1,32767/max(mass,64)).
// The stored mass retains the original input; this is a relative solver weight,
// not an exact Q8 reciprocal. Null body is ignored.
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);
// Integrate active dynamic bodies and reset their impact values, then solve
// each active unordered pair for the configured passes (zero means one).
// Static bodies retain previous impact maxima until the game clears them.
// Acceleration persists; flags and break thresholds remain game-owned.
// This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.
void kq3d_step(KQWorld3D* world);
// Reset impact for one active dynamic body, add gravity and persistent body
// acceleration, clamp velocity per axis and advance position. Static/inactive
// bodies retain impact state. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and avoid overflow before clamping.
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);
// Test strict overlap on all three axes; face-only contact returns false.
// Valid pointers are required and flags are ignored. Center differences and
// extent sums must fit the signed 16-bit magnitude calculations.
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);

// Sum three signed products, shifting each by eight bits before addition.
// Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);

kitaqgb/lib/physics3d.h

raster.h — Scrolltabellen für Bildstreifen und Bildschirmzeilen
c
#pragma once

#include "scroll.h"

// Keep wrapper capacity consistent with the compiler split-table capacity; wrapper checks do not enlarge it.
#define KQ_RASTER_MAX_BANDS 8

#define KQ_RASTER_OK        0
#define KQ_RASTER_FULL      1
#define KQ_RASTER_BAD_LY    2
#define KQ_RASTER_UNSORTED  3
#define KQ_RASTER_BAD_RANGE 4

#define KQ_RASTER_BG        KQ_SCROLL_SPLIT_USE_BG
#define KQ_RASTER_WIN       KQ_SCROLL_SPLIT_USE_WIN
#define KQ_RASTER_WIN_SHOW  KQ_SCROLL_SPLIT_WIN_SHOW
#define KQ_RASTER_WIN_HIDE  KQ_SCROLL_SPLIT_WIN_HIDE
#define KQ_RASTER_BG_COLOR0 KQ_SCROLL_SPLIT_BG_COLOR0
#define KQ_RASTER_FLAG_MASK 0x1F

#define KQ_RASTER_LINE_FLAT        0
#define KQ_RASTER_LINE_X_TITLE     1
#define KQ_RASTER_LINE_TRAVEL_GATE 2

// Caller-owned wave state. Initialize it before use and keep it non-null for every LineX operation.
// frame_counter measures RunFrame calls, not an independent hardware clock.
typedef struct RasterLineX {
    u8 profile;
    u8 base_x;
    u8 phase;
    u8 phase_step;
    u8 frame_divider;
    u8 frame_counter;
} RasterLineX;

// Stop split scheduling, empty the shared table and clear error/count state.
void Raster_Init();
// Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.
void Raster_Clear();
// Commit an empty split table so no raster bands remain active.
void Raster_Disable();

// Read the number of bands currently recorded by this wrapper.
u8 Raster_GetCount();
// Read the last stored status without clearing it.
u8 Raster_GetLastError();

// Append a validated background-scroll band and advance the monotonic-LY
// bookkeeping. A successful append clears the previous error.
u8 Raster_Push(u8 ly, u8 scx, u8 scy);
// Append a validated extended band after masking flags to supported operations.
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

// Enable window updates and pass hardware WX/WY values without coordinate conversion.
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);
// Convert screen X to hardware WX by adding seven, then queue a window band.
// The byte addition wraps if callers supply an excessive X coordinate.
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);
// Queue both background and window updates, converting window screen X to WX.
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);
// Pack a 15-bit color into the extended band's two scroll-byte fields and select
// the color-zero operation, which interprets those fields as color data.
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);

// Publish pending splits and return the stored status. This commits even if an
// earlier append failed; callers should inspect errors while building the table.
u8 Raster_Commit();

// Validate the HUD height, then replace pending splits with a fixed top band
// and scrolling playfield. The new table still requires an explicit commit.
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);
// Build a scrolling upper playfield and fixed bottom HUD after validating the split.
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);

// Build two horizontal-scroll bands sharing one vertical scroll value.
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);
// Build three horizontal-scroll bands at ordered visible split lines. Invalid
// parameters leave the previous pending table intact and set the error status.
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);

// Initialize a scanline-wave state with phase zero and one phase step per frame.
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);
// Change the wave profile and restart its phase/divider counter.
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);
// Configure the phase increment and frame interval; clamp a zero interval to one.
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);
// Set the byte phase directly without resetting the frame-divider counter.
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);
// Look up the selected periodic profile at LY + phase and add base X modulo
// 256. An unknown profile returns the unmodified base X.
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);
// Render all 144 visible lines with one SCX write per line, then advance phase.
// This foreground renderer masks interrupts during the visible frame. Do game
// and audio work between calls; do not combine it with a STAT raster driver.
// Returns without changing the effect when the LCD is off.
void Raster_LineXRunFrame(RasterLineX* effect);

kitaqgb/lib/raster.h

rpg.h — Zufallszahlen, Text, Karten, Spielstände und RPG-/ADV-/SLG-Funktionen
c
#pragma once

// The application supplies frame/cursor/font tiles at these indices; these constants do not load graphics.
#ifndef TEXT_TILE_FILL
#define TEXT_TILE_FILL ((u8)0)
#endif
#ifndef TEXT_TILE_FRAME_TL
#define TEXT_TILE_FRAME_TL ((u8)1)
#endif
#ifndef TEXT_TILE_FRAME_TR
#define TEXT_TILE_FRAME_TR ((u8)2)
#endif
#ifndef TEXT_TILE_FRAME_BL
#define TEXT_TILE_FRAME_BL ((u8)3)
#endif
#ifndef TEXT_TILE_FRAME_BR
#define TEXT_TILE_FRAME_BR ((u8)4)
#endif
#ifndef TEXT_TILE_FRAME_H
#define TEXT_TILE_FRAME_H ((u8)5)
#endif
#ifndef TEXT_TILE_FRAME_V
#define TEXT_TILE_FRAME_V ((u8)6)
#endif
#ifndef TEXT_TILE_CURSOR
#define TEXT_TILE_CURSOR ((u8)7)
#endif
#ifndef TEXT_TILE_PAGE_WAIT
#define TEXT_TILE_PAGE_WAIT ((u8)8)
#endif
#ifndef TEXT_DIGIT_BASE
#define TEXT_DIGIT_BASE ((u8)'0')
#endif

#define TEXT_CTRL_END       ((u8)0x00)
#define TEXT_CTRL_NEWLINE   ((u8)0x0A)
#define TEXT_CTRL_WAIT      ((u8)0x01)
#define TEXT_CTRL_PAGE_WAIT ((u8)0x02)

#define PAD_KEY_RIGHT  ((u8)0x01)
#define PAD_KEY_LEFT   ((u8)0x02)
#define PAD_KEY_UP     ((u8)0x04)
#define PAD_KEY_DOWN   ((u8)0x08)
#define PAD_KEY_A      ((u8)0x10)
#define PAD_KEY_B      ((u8)0x20)
#define PAD_KEY_SELECT ((u8)0x40)
#define PAD_KEY_START  ((u8)0x80)

// Default layout: four 512-byte slots, each with a six-byte header and at most 506 payload bytes.
#define SAVE_SLOT_COUNT ((u8)4)
#define SAVE_SLOT_SIZE  ((u16)512)
#define SAVE_MAGIC0     ((u8)0x4B)
#define SAVE_MAGIC1     ((u8)0x51)
#define SAVE_VERSION    ((u8)1)

#define SAVE_OK         ((u8)1)
#define SAVE_ERR        ((u8)0)

// A bank byte plus a CPU-visible address forms this data reference; it does not switch banks by itself.
typedef __packed struct {
    u8 bank;
    const u8* ptr;
} far_ptr_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    const u8* const* items;
    u8 count;
    u8 cursor;
} menu_t;

typedef __packed struct {
    u8 id;
    u8 qty;
    const u8* name;
} item_t;

// Packed nine-byte ordinary-map descriptor. Tile IDs use bank_tiles; collision bits and event bytes
// use the descriptor bank. Width/height are tile cells, with row-major data.
typedef __packed struct {
    u8 width;
    u8 height;
    u8 bank_tiles;
    const u8* tiles;
    const u8* collision_bits;
    const void* events;
} map_t;

// One 2x2 metatile: four tile IDs plus collision, palette metadata and event ID.
// The map drawing routine uses tile IDs only; it does not apply palette attributes.
typedef __packed struct {
    u8 tile_tl;
    u8 tile_tr;
    u8 tile_bl;
    u8 tile_br;
    u8 collision;
    u8 palette;
    u8 event;
} metatile_t;

// Metatile dimensions count 2x2 cells. bank_tiles=0 means use the descriptor bank;
// nonzero bank_tiles supplies both ID-array and definition-table reads.
typedef __packed struct {
    u8 width;
    u8 height;
    u8 bank_tiles;
    const u8* metatile_ids;
    const metatile_t* metatiles;
} metatile_map_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    const u8* const* items;
    u8 count;
    u8 cursor;
    u8 prev_keys;
    u8 selected;
    u8 cancelled;
} menu_state_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 hp;
    u8 move;
    u8 atk_min;
    u8 atk_max;
    u8 team;
    u8 acted;
} unit_t;

void __wait_vblank();
u16 __readpadex(u8 prev_keys);
u16 __getbgmapbase();
void __memset(void* dst, u8 value, u16 count);
void __memcpy(void* dst, const void* src, u16 count);
void __settile(u8 x, u8 y, u8 tile);
void __settilebg(u8 x, u8 y, u8 tile);
void __settileat(u16 base, u8 x, u8 y, u8 tile);
void __vram_memcpy(u16 dst, const void* src, u16 len);
void __vram_memset(u16 dst, u8 value, u16 len);
void __far_memcpy(void* dst, u8 bank, const void* src, u16 len);
u8 __rng8();
void __rng_seed(u16 seed);
void __scroll_bg_set(u8 scx, u8 scy);

void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settile_row(u8 x, u8 y, const u8* src, u8 len);
void __settile_col(u8 x, u8 y, const u8* src, u8 len);
void __fill_tilemap(u16 base, u8 tile, u16 count);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);

void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);
void __vram_copy_hblank(u16 dst, const void* src, u16 len);
void __vram_copy_dma(u16 dst, const void* src, u16 len);

u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
// The current GB backend evaluates/discards these arguments but emits no indirect call.
void __farcall_ptr(u8 bank, const void* func);

#define far_read8(p) __farpeek8((p).bank, (p).ptr)
#define far_read16(p) __farpeek16((p).bank, (p).ptr)
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))

void __memcpy_small(void* dst, const void* src, u8 len);
void __memset_small(void* dst, u8 value, u8 len);
void __copy16(void* dst, const void* src);
void __copy32(void* dst, const void* src);

u16 __tile_addr(u16 base, u8 x, u8 y);
u16 __map_index(u8 x, u8 y, u8 width);
u8 __xy_in_rect(u8 x, u8 y, u8 rx, u8 ry, u8 rw, u8 rh);
u8 __manhattan(u8 x1, u8 y1, u8 x2, u8 y2);

u8 __bit_test(const u8* p, u16 bit_index);
void __bit_set(u8* p, u16 bit_index);
void __bit_clear(u8* p, u16 bit_index);
void __bit_toggle(u8* p, u16 bit_index);

// Compiler intrinsic, separate from the RAM rle_decode helpers below; it is not a bounded-stream API.
u16 __rle_decode_vram(u16 dst, u8 bank, const void* src);

// Advance the compiler-provided pseudorandom generator and return one byte.
u8 rng8();
// Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.
u16 rng16();
// Reduce a random byte modulo max; zero returns zero without consuming randomness.
// Modulo reduction is biased unless max divides the generator range.
u8 rand_range(u8 max);
// Select an index from cumulative byte weights using a 16-bit random draw.
// A zero total, including an empty list, returns zero; callers must distinguish
// that case from a valid index. Modulo reduction can introduce a small bias.
u8 weighted_choice(const u8* weights, u8 count);
// Replace the generator seed so subsequent calls can reproduce a sequence.
void rng_seed(u16 seed);
// Alias the byte generator; this consumes one generator step.
u8 rng_next8();
// Alias the two-step 16-bit generator.
u16 rng_next16();
// Alias rand_range and return a value in [0,max), or zero when max is zero.
u8 rng_range(u8 max);
// Return false for zero and true for values at least 100. Intermediate values
// use the modulo-based range generator, so percentages are approximate.
u8 rng_chance(u8 percent);

// Set the tile-space window, reset its cursor and redraw it immediately.
// Opening does not reset the existing character speed or load font tiles.
void text_open(u8 x, u8 y, u8 w, u8 h);
// Erase the open window with the fill tile and disable windowed character output.
void text_close();
// Decode an END-terminated stream of tile bytes and newline/wait/page controls.
// WAIT consumes a following frame-count byte. The source must remain readable
// through blocking waits; the routine does not validate stream length.
void text_print(const u8* str);
// Decode the same text controls while fetching each byte from the specified
// ROM bank. The pointer advances within that bank; it does not roll into the next bank.
void text_print_far(u8 bank, const u8* str);
// Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A
// accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings
// use raw tile bytes, and the caller must fit them inside the available rows.
u8 text_choice(const u8* const* choices, u8 count);
// Set VBlank waits per windowed character; zero prints without character delays.
void text_set_speed(u8 speed);
// Open and redraw a window using the same tile-space arguments as text_open.
void text_window(u8 x, u8 y, u8 w, u8 h);
// Fill the supplied tile rectangle without changing the active text window or cursor.
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);
// Draw a zero-terminated tile string at absolute tile coordinates, without
// window clipping, control codes or the windowed printing delay.
void text_print_xy(u8 x, u8 y, const u8* str);
// Print an unsigned byte in decimal using only the required number of cells.
void text_print_u8(u8 x, u8 y, u8 value);
// Print an unsigned word in decimal using only the required number of cells.
void text_print_u16(u8 x, u8 y, u16 value);
// Print a minus tile for negative values, followed by the unsigned magnitude.
// Positive values use the unsigned decimal path; no plus sign is emitted.
void text_print_s16(u8 x, u8 y, s16 value);

// Replace the active script and clear wait, choice and saved-return state.
void script_run(u8 bank, const u8* script);
// Execute commands until an output/choice yields (0), a wait yields (1), or
// execution ends (2). Control/flag commands continue within the same call, so
// a script loop without a yielding command can block the game loop indefinitely.
u8 script_step();
// Set the number of subsequent script_step calls to spend waiting. Frame-based
// timing requires the application to call script_step once per frame.
void script_wait_frames(u8 n);

// Run a blocking menu loop with wraparound up/down selection, A to accept
// and B to cancel. Return 0xFF for an empty menu or cancellation. Item strings
// and menu dimensions must fit the visible tile area.
u8 menu_run(const menu_t* menu);
// Open a two-choice dialog and return the text-choice result (YES first, NO second).
u8 menu_yesno();
// Run a blocking item menu, drawing names and two-digit quantities. Return
// the selected index or 0xFF on empty input/B; this does not consume an item.
u8 menu_inventory(const item_t* items, u8 count);
// Initialize a nonblocking menu state that borrows the item pointer table.
// Selection starts unset (0xFF), and the cancellation flag starts clear.
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count);
// Draw the current menu and cursor without waiting or sampling input. The
// caller schedules suitable display timing and keeps item text within bounds.
void menu_draw(menu_state_t* state);
// Sample new button presses and update cursor/selection state without drawing.
// Selected and cancelled results remain latched; a B press in the same update
// as A clears selection and leaves cancellation set.
void menu_update(menu_state_t* state);
// Read the latched selection without clearing it; null state returns 0xFF.
u8 menu_get_selected(menu_state_t* state);
// Read the latched cancellation flag; null state returns false.
u8 menu_was_cancelled(menu_state_t* state);

// Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles
// from its top-left corner. Drawing does not upload tile graphics or clear
// background cells beyond smaller map dimensions.
void map_load(u8 bank, const map_t* map);
// Use metatile collision when that mode is active; otherwise read one packed
// collision bit. Missing maps/out-of-range cells block movement, but a valid
// ordinary map without a collision array is entirely passable.
u8 map_is_blocked(u8 x, u8 y);
// Report whether an event exists at the cell. Ordinary maps expose a Boolean
// byte-presence test; metatile maps reduce their event ID to a Boolean here.
u8 map_trigger_at(u8 x, u8 y);
// Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp
// the scroll origin to its edges. This adjusts scroll registers only; it does
// not stream newly exposed map rows into VRAM.
void camera_center(u8 x, u8 y);
// Select metatile mode, copy its descriptor and draw the initial viewport
// with the camera at cell (0,0).
void map_load_metatile(u8 bank, const metatile_map_t* map);
// Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles.
// Out-of-range cells use definition zero; palette attributes are not written.
// Remember the camera and clear the dirty flag after the full redraw.
void map_draw_visible(u8 camera_tx, u8 camera_ty);
// Read a row-major metatile ID, returning ID zero for inactive or out-of-range
// lookups. Callers must provide a usable definition for metatile zero.
u8 map_get_metatile(u8 tx, u8 ty);
// Return the selected definition's palette byte. An out-of-range coordinate
// uses the metatile-zero fallback; this function does not write CGB attributes.
u8 map_get_attr(u8 tx, u8 ty);
// Treat out-of-range metatile cells as solid; otherwise inspect the definition
// collision flag. In ordinary-map mode, delegate to its packed collision bits.
u8 map_is_solid(u8 tx, u8 ty);
// Return a metatile event ID, or the ordinary-map Boolean trigger result.
// Missing/out-of-range metatile cells have no event.
u8 map_get_event(u8 tx, u8 ty);
// Mark the viewport for a full redraw when a valid metatile cell changes.
// The coordinate is validated but no per-cell dirty list is retained.
void map_mark_dirty(u8 tx, u8 ty);
// Redraw the remembered metatile viewport only when the shared dirty flag is set.
void map_flush_dirty();

// Validate slot and payload length, write payload bytes, then write the header
// and checksum. Return one after completing the writes; interruption can leave
// a partially replaced slot, so this is not transactional save storage.
u8 save_write(u8 slot, const void* data, u16 len);
// Require matching magic/version, exact requested length and a valid checksum
// before copying data into the destination. Validation failure leaves the
// destination unchanged. An invalid slot returns before touching RAM control;
// validation failures after enabling RAM disable it before returning zero.
u8 save_read(u8 slot, void* data, u16 len);
// Validate a slot's header, payload bounds and checksum without copying the
// payload out. A nonzero result means the stored record passes these checks.
u8 save_exists(u8 slot);
// Initialize the expected RAM access state and leave cartridge RAM disabled.
// Existing slot contents are preserved.
void save_init();
// Alias the checked save_read operation.
u8 save_load(u8 slot, void* data, u16 len);
// Alias save_exists, including its header and checksum validation.
u8 save_check(u8 slot);
// Zero the complete selected slot, including header and payload; invalid slot
// IDs are ignored. Cartridge RAM is disabled when clearing finishes.
void save_clear(u8 slot);

// Build movement costs, then convert reachable cells to one and unreachable
// 0xFF cells to zero. The caller provides one output byte per current-map cell
// and a valid unit origin; path-search workspace limits also apply.
u8 unit_move_range(unit_t* u, u8* out_mask);
// Mark cells whose Manhattan distance falls within the inclusive attack range.
// This geometric mask does not test obstacles, line of sight or other units.
u8 unit_attack_range(unit_t* u, u8* out_mask);
// A unit can act only while HP is nonzero and its acted flag is clear.
// The unit pointer must refer to a valid record.
u8 unit_can_act(const unit_t* u);

// Find a shortest cardinal path with BFS and write direction codes 0=up,
// 1=right, 2=down, 3=left. Return its byte length, or zero for failure or an
// already-reached goal. The caller supplies max_len output bytes and respects
// the shared workspace/distance limits; excessive paths are not truncated.
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);
// Flood cardinal neighbors at unit cost, stopping expansion at the movement
// limit and rejecting blocked destinations. Initialize output to 0xFF only
// after validating the map and origin; invalid input leaves output unchanged.
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);

// Read a bit from the flag array. Callers must keep id below 2048.
u8 flag_get(u16 id);
// Set a flag bit without disturbing adjacent flags; id must be below 2048.
void flag_set(u16 id);
// Clear a flag bit; id must be below 2048.
void flag_clear(u16 id);
// Read a quest-state byte; quest_id must be below 64.
u8 quest_state(u8 quest_id);
// Replace a quest-state byte without validating its game-specific meaning.
// The caller must keep quest_id below 64.
void quest_set_state(u8 quest_id, u8 state);

// Expand count/value byte pairs until a zero count terminates the stream.
// The caller must provide a valid terminator and sufficient destination storage;
// there are no source or destination bounds parameters. Return the 16-bit byte count.
u16 rle_decode(void* dst, const void* src);
// Decode the same count/value format using bank-qualified reads for every source
// byte. Keep the encoded stream within the supplied bank/address mapping and
// provide enough destination space; a zero count ends the stream.
u16 rle_decode_far(void* dst, u8 bank, const void* src);

// Return the active map width in its own cell units, or zero when no map is loaded.
u8 map_current_width();
// Return the active map height in its own cell units, or zero when no map is loaded.
u8 map_current_height();

kitaqgb/lib/rpg.h

scene.h — Szenenregistrierung, -wechsel und -aktualisierung
c
#pragma once

typedef void (*SceneFunc)();

// Callbacks may be null. Keep the table and non-null targets readable for its lifetime.
// These plain function pointers do not carry a ROM bank number.
typedef __packed struct {
    SceneFunc enter;
    SceneFunc update;
    SceneFunc draw;
    SceneFunc exit;
} SceneDef;

// Attach the caller-owned scene table and clear current-scene state without invoking callbacks.
void scene_init(const SceneDef* scenes, u8 count);
// Replace the table by resetting scene state; this does not call the old scene's exit handler.
void scene_set_table(const SceneDef* scenes, u8 count);
// Ignore invalid IDs; otherwise exit the current scene and enter the requested one.
// Selecting the current ID still performs exit/enter. Callbacks run synchronously.
void scene_change(u8 scene_id);
// Clear the change flag before calling the active scene's update handler, so a
// transition made during that handler is visible afterward.
void scene_update();
// Call the active scene's draw handler if one exists; no current scene is a no-op.
void scene_draw();
// Return the stored scene ID; zero is also returned before the first transition.
u8 scene_get_current();
// Read the transition flag, which is cleared at the start of an active scene update.
u8 scene_was_changed();

kitaqgb/lib/scene.h

scroll.h — Hintergrund, Fenster und geteiltes Scrollen
c
#pragma once

// Flags select operations in a raster split; raw window X includes the hardware +7 offset.
#define KQ_SCROLL_SPLIT_USE_BG   0x01
#define KQ_SCROLL_SPLIT_USE_WIN  0x02
#define KQ_SCROLL_SPLIT_WIN_SHOW 0x04
#define KQ_SCROLL_SPLIT_WIN_HIDE 0x08
#define KQ_SCROLL_SPLIT_BG_COLOR0 0x10

void __scroll_bg_set(u8 scx, u8 scy);
void __scroll_bg_x_set(u8 scx);
void __scroll_bg_y_set(u8 scy);
u8 __scroll_bg_x_get();
u8 __scroll_bg_y_get();

void __scroll_win_set(u8 wx, u8 wy);
void __scroll_win_x_set(u8 wx);
void __scroll_win_y_set(u8 wy);
u8 __scroll_win_x_get();
u8 __scroll_win_y_get();

void __scroll_bg_set_buffered(u8 scx, u8 scy);
void __scroll_bg_x_set_buffered(u8 scx);
void __scroll_bg_y_set_buffered(u8 scy);
void __scroll_win_set_buffered(u8 wx, u8 wy);
void __scroll_win_x_set_buffered(u8 wx);
void __scroll_win_y_set_buffered(u8 wy);
void __scroll_flush();

void __scroll_split_reset();
void __scroll_split_push(u8 ly, u8 scx, u8 scy);
void __scroll_split_push_ex(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
void __scroll_split_commit();

void __scroll_win_show();
void __scroll_win_hide();
void __scroll_bg_add(s8 dx, s8 dy);
void __scroll_win_add(s8 dx, s8 dy);

// Reset background scroll to zero and place the window at screen origin
// using hardware WX=7 and WY=0.
void Scroll_Init();
// Write both hardware background-scroll bytes immediately.
void Scroll_SetBg(u8 scx, u8 scy);
// Write horizontal background scroll while leaving vertical scroll unchanged.
void Scroll_SetBgX(u8 scx);
// Write vertical background scroll while leaving horizontal scroll unchanged.
void Scroll_SetBgY(u8 scy);
// Read the tracked current background X; this is not a direct SCX register read.
u8 Scroll_GetBgX();
// Read the tracked current background Y; pending and raster-only values are excluded.
u8 Scroll_GetBgY();

// Write raw hardware WX/WY values; callers add seven to a screen-space window X.
void Scroll_SetWindow(u8 wx, u8 wy);
// Write raw hardware WX without converting a screen-space X coordinate.
void Scroll_SetWindowX(u8 wx);
// Write the window Y coordinate through the intrinsic.
void Scroll_SetWindowY(u8 wy);
// Read tracked current WX, including its seven-pixel offset; not a live hardware read.
u8 Scroll_GetWindowX();
// Read tracked current WY; pending and raster-only values are excluded.
u8 Scroll_GetWindowY();

// Stage background-scroll values in the intrinsic buffer for a later flush.
void Scroll_SetBgBuffered(u8 scx, u8 scy);
// Stage raw window-coordinate values for a later flush.
void Scroll_SetWindowBuffered(u8 wx, u8 wy);
// Apply the buffered scroll/window state through the compiler runtime.
void Scroll_Flush();

// Apply signed deltas to the byte-sized background-scroll coordinates.
void Scroll_BgAdd(s8 dx, s8 dy);
// Apply signed deltas to the byte-sized hardware window coordinates.
void Scroll_WindowAdd(s8 dx, s8 dy);
// Request window visibility through the compiler intrinsic.
void Scroll_WindowShow();
// Request that the window be hidden through the compiler intrinsic.
void Scroll_WindowHide();

// Clear the pending split table before building a new raster configuration.
void Scroll_SplitReset();
// Append a background-scroll split directly. Use Raster_Push when caller-side
// scanline ordering and capacity validation are desired.
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);
// Append an extended split with raw background/window fields and operation flags.
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
// Reuse the two background-scroll fields to carry the low/high RGB15 bytes
// for a split whose operation flag selects background color zero.
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);
// Publish the pending split configuration through the compiler runtime.
void Scroll_SplitCommit();

kitaqgb/lib/scroll.h

slg.h — Spielbretter, Zuglisten und Rücknahme
c
#pragma once

// A row-major byte board. Storage is borrowed; cell values and coordinates have game-defined meaning.
typedef __packed struct {
    u8 width;
    u8 height;
    u8* cells;
} SLGBoard;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 value;
} SLGMove;

typedef __packed struct {
    SLGMove* items;
    u8 count;
    u8 capacity;
} SLGMoveList;

// Undo records are retained cell values only; popping one does not apply it to a board.
typedef __packed struct {
    SLGMove* items;
    u8 count;
    u8 capacity;
} SLGUndoStack;

// Attach width * height bytes of caller-owned cell storage without clearing it.
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);
// Fill every cell with value; a null board is ignored. A valid board must own
// enough accessible cell storage for its declared dimensions.
void slg_board_clear(SLGBoard* board, u8 value);
// Return zero for a null board or out-of-range coordinate; otherwise read the
// cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);
// Write a cell only when the board and coordinate are valid.
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);
// Attach caller-owned move storage and reset the list length.
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);
// Forget the moves without erasing their storage; a null list is ignored.
void slg_move_list_clear(SLGMoveList* list);
// Append coordinates and a value to the bounded move list. Return zero on a
// null/full list without replacing any existing move.
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);
// Attach caller-owned undo records and initialize an empty stack.
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);
// Record a cell's previous value for later undo. Return zero if the stack is
// null or full; this function does not change the board itself.
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);
// Remove the newest undo record and optionally copy it out. A null output
// still discards the record; a null or empty stack returns zero.
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);

kitaqgb/lib/slg.h

sprite.h — OBJ-Reservierung, Positionierung, Metasprites und Animation
c
#pragma once

// Keep the default 40 for the standard DMA path. Hardware always transfers 160 bytes,
// even if this array is shortened; a custom layout must provide valid bytes for that full transfer.
#ifndef SPRITE_MAX
#define SPRITE_MAX 40
#endif

#define SPRITE_FLAG_PAL1     ((u8)0x10)
#define SPRITE_FLAG_XFLIP    ((u8)0x20)
#define SPRITE_FLAG_YFLIP    ((u8)0x40)
#define SPRITE_FLAG_PRIORITY ((u8)0x80)

// Packed hardware order is Y, X, tile, flags; screen coordinates need the GB OAM offsets.
typedef __packed struct {
    u8 y;
    u8 x;
    u8 tile;
    u8 flags;
} SpriteOamEntry;

extern __wram __aligned(256) SpriteOamEntry kq_sprite_oam[SPRITE_MAX];
extern u8 kq_sprite_active[SPRITE_MAX];
extern u8 kq_sprite_used;
extern u8 kq_sprite_height;

// Signed pixel displacements from a common origin; final byte coordinates wrap rather than clip.
typedef __packed struct {
    s8 dx;
    s8 dy;
    u8 tile;
    u8 flags;
} MetaSpritePart;

// Initialize frame/ticks within their configured ranges. This animation selects consecutive tile IDs;
// it does not change sprite size or automatically step by two tiles in 8x16 mode.
typedef __packed struct {
    u8 first_tile;
    u8 frame_count;
    u8 frame;
    u8 ticks;
    u8 ticks_per_frame;
} SpriteAnim;

void __wait_vblank();
void __oam_dma(u16 src_ptr);

// Clear allocation and shadow OAM state and reset the DMA-stub installation flag.
// The default height is eight pixels; the hardware display mode is configured elsewhere.
void sprite_init();
// Claim the first free slot, hide it, and return its ID; return 0xFF when full.
// Previously stored tile/flag bytes are retained until the caller replaces them.
u8 sprite_alloc();
// Release an allocated valid slot and hide it. Repeated frees do not decrement the count.
void sprite_free(u8 id);
// Convert screen coordinates to OAM coordinates by adding X=8 and Y=16.
// The byte additions wrap; this updates shadow storage even for an unallocated slot.
void sprite_set_pos(u8 id, u8 x, u8 y);
// Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.
void sprite_set_tile(u8 id, u8 tile);
// Replace a valid shadow slot's complete hardware attribute byte.
void sprite_set_flags(u8 id, u8 flags);
// Move a valid shadow slot off screen without freeing it.
void sprite_hide(u8 id);
// Install the HRAM stub lazily and execute OAM DMA with interrupts disabled.
// This routine does not wait for VBlank and always enables interrupts afterward;
// it does not restore the caller's previous interrupt-enable state.
void sprite_flush_oam_now();
// Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.
void sprite_flush_oam();
// Return the number of active slots, including slots activated by metasprite_draw.
// Hidden allocated slots remain active until sprite_free releases them.
u8 sprite_count_used();
// Report whether the software overlap estimate exceeds ten sprites on a scanline.
u8 sprite_warn_scanline_overflow();
// Estimate the largest overlap of active, non-hidden shadow sprites across
// visible scanlines using the configured sprite height. This is a software
// overlap count, not a rendered-pixel or hardware-priority simulation.
u8 sprite_max_scanline_count();
// Place consecutive parts, counting each newly activated slot once. Existing
// active slots are overwritten without increasing the allocation count. Return
// the number written; an invalid first slot or zero count writes nothing.
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);
// Advance animation ticks/frame with wrapping frame selection and return the
// resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.
u8 anim_update(SpriteAnim* anim);

kitaqgb/lib/sprite.h

sprite_order.h — Spriteauswahl nach Priorität und Rotation
c
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.

// Hardware-compatible layout without requiring the sprite allocator or its
// global storage. Cast a sprite.h shadow buffer to this type when combining
// the libraries; both layouts contain exactly Y, X, tile and flags bytes.
typedef __packed struct {
    u8 y;
    u8 x;
    u8 tile;
    u8 flags;
} SpriteOrderOamEntry;

#define SPRITE_ORDER_LEVELS 4
#define SPRITE_ORDER_OAM_COUNT 40

// One submitted, visible sprite. Attributes retain their hardware meaning;
// priority 0..3 controls OAM selection order, not the BG-over-OBJ flag.
typedef __packed struct {
    SpriteOrderOamEntry oam;
    u8 priority;
} SpriteOrderItem;

// Caller-owned foreground state. Capacity is 1..255 items; count includes only
// accepted submissions. Rebuild the same logical submission list each frame so
// phase rotation distributes selection among equal-priority sprites.
typedef struct {
    SpriteOrderItem* items;
    u8 capacity;
    u8 count;
    u8 height;
    u8 phase;
} SpriteOrder;

// Bind writable item storage and select the hardware sprite height (8 or 16).
// Return 1 on success. Invalid storage, zero capacity or another height returns
// 0 and leaves a non-null state disabled. A null state returns 0 without writes.
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);

// Discard this frame's submissions while preserving storage, height and phase.
// A null state is ignored. Call once before submitting the next frame's sprites.
void sprite_order_begin(SpriteOrder* order);

// Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the
// tile and attribute bytes; use priority 0 (first) through 3 (last). Fully
// off-screen sprites, invalid priorities, disabled state and full storage return
// 0 without consuming a slot. Partly visible sprites are accepted. Return 1 on
// acceptance. Hardware 8x16 mode still ignores the tile index's low bit.
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);

// Write a complete 160-byte shadow OAM: ascending priority, then cyclic order
// within each priority. Clamp limit to 40, return the number emitted and zero
// all unused entries (including Y) so they cannot consume scanline slots.
// Advance phase once for a nonempty valid queue, even when limit is zero.
// Empty queues reset phase to zero. Null/disabled/corrupt state or null output
// returns 0 without modifying output or phase.
// Output must provide 40 entries and must not overlap item/state storage.
// This only writes RAM. Build in foreground, then transfer during VBlank.
// DMG overlap priority also depends on X: this cannot override that hardware
// rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB.
// It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);

kitaqgb/lib/sprite_order.h

system.h — Start, Bildzähler, Wartefunktionen und Interrupts
c
#pragma once

// This callback runs in the caller of system_wait_vblank, not as an installed ISR.
// Its plain pointer has no ROM bank component; keep the target callable in that mapping.
typedef void (*SystemCallback)();

extern u16 kq_system_frame;

void __wait_vblank();

// Reset the software frame counter and remove any registered callback.
void system_init();
// Wait for VBlank, count this wrapper call, then invoke the callback synchronously.
// The counter wraps at 16 bits and is not an independent hardware frame clock.
void system_wait_vblank();
// Replace the callback used by system_wait_vblank; null disables the callback.
void system_set_vblank_callback(SystemCallback callback);
// Read the software count of completed system_wait_vblank calls.
u16 system_get_frame();
// Return the low byte of the software frame counter for wrapping 8-bit timing.
u8 system_get_frame8();
// Enable CPU interrupts and return using the inline-assembly function body.
void system_enable_interrupts();
// Disable CPU interrupts and return; callers must explicitly re-enable them later.
void system_disable_interrupts();

#define gb_init system_init
#define gb_wait_vblank system_wait_vblank
#define gb_set_vblank_callback system_set_vblank_callback
#define gb_frame_count system_get_frame
#define gb_enable_interrupts system_enable_interrupts
#define gb_disable_interrupts system_disable_interrupts

kitaqgb/lib/system.h

vram.h — VRAM-Aktualisierungen und Übertragung per Warteschlange
c
#pragma once

// Keep this capacity in 1..255 in all units; counts and capacity/free return values are bytes.
#ifndef VRAM_QUEUE_MAX
#define VRAM_QUEUE_MAX 32
#endif

#define VRAM_CMD_BG_TILE   ((u8)1)
#define VRAM_CMD_BG_RECT   ((u8)2)
#define VRAM_CMD_BG_BLOCK  ((u8)3)
#define VRAM_CMD_MEMCPY    ((u8)4)
#define VRAM_CMD_MEMSET    ((u8)5)

// A command owns metadata only. src is a retained near pointer with no bank number or copied payload.
typedef __packed struct {
    u8 kind;
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    u8 value;
    u16 dst;
    const u8* src;
    u16 len;
} VramCommand;

extern VramCommand kq_vram_queue[VRAM_QUEUE_MAX];
extern u8 kq_vram_queue_used;
extern u8 kq_vram_queue_overflowed;

void __wait_vblank();
void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);

// Start with an empty command queue and a clear overflow flag.
void vram_init();
// Discard pending commands and clear the latched overflow flag without writing VRAM.
void vram_clear_queue();
// Queue a single background tile write; return zero if no command slot is available.
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);
// Provide the short alias for a queued background tile write.
u8 vram_queue_tile(u8 x, u8 y, u8 tile);
// Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
// Queue a tile-map rectangle while retaining src rather than copying its bytes.
// Keep the source data and its ROM bank accessible until the queue is flushed.
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
// Queue a byte transfer and retain the source pointer. The source must remain
// valid and visible until flush; len is measured in bytes, not tiles.
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);
// Alias the queued byte-copy operation; this does not convert a tile count to bytes.
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);
// Queue a byte fill and return zero if the command queue is full.
u8 vram_queue_memset(u16 dst, u8 value, u16 len);
// Execute pending commands in insertion order without waiting for VBlank here.
// The caller must arrange suitable VRAM access timing and a sufficient transfer budget.
// Only the used count is cleared; overflow stays latched until an explicit reset.
void vram_flush_now();
// Wait for VBlank before executing the queue. Waiting once does not itself limit
// the queued workload to the available VBlank duration.
void vram_flush();
// Return the number of queued commands, not the number of transfer bytes.
u8 vram_get_queue_used();
// Return the total number of command slots, independent of queue usage.
// This is command-buffer capacity, not free space in hardware VRAM.
u8 vram_get_queue_capacity();
// Return the remaining command-slot capacity.
u8 vram_get_queue_free();
// Read the overflow latch without clearing it.
u8 vram_get_overflowed();

kitaqgb/lib/vram.h

wire3d.h — Drahtgitterdarstellung für DMG
c
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 96
#endif
#if WIRE3D_DMG_HEIGHT != 96
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"

#define W3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define W3D_CENTER_X WIRE3D_DMG_CENTER_X
#define W3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define W3D_FAR_Z WIRE3D_DMG_FAR_Z
#define W3D_HUD_TILE_BASE WIRE3D_DMG_HUD_TILE_BASE
#define W3D_HUD_TILE_BLANK WIRE3D_DMG_HUD_TILE_BLANK
#define W3D_HUD_TILE_COUNT WIRE3D_DMG_HUD_TILE_COUNT
#define W3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define W3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define W3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define W3D_TILE_H WIRE3D_DMG_TILE_H
#define W3D_TILE_W WIRE3D_DMG_TILE_W
#define W3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define WIRE3D_EDGE_MASK_BINS_16 WIRE3D_DMG_EDGE_MASK_BINS_16
#define WIRE3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define WIRE3D_MODEL_EDGE_LIMIT WIRE3D_DMG_MODEL_EDGE_LIMIT
#define WIRE3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define WIRE3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define WIRE3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define WIRE3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define WIRE3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define WIRE3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define Wire3D_BeginFrame Wire3DDMG_BeginFrame
#define Wire3D_DrawLine2D Wire3DDMG_DrawLine2D
#define Wire3D_DrawLine3D Wire3DDMG_DrawLine3D
#define Wire3D_DrawModel Wire3DDMG_DrawModel
#define Wire3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define Wire3D_DrawScene Wire3DDMG_DrawScene
#define Wire3D_Edge Wire3DDMG_Edge
#define Wire3D_EdgeFaces Wire3DDMG_EdgeFaces
#define Wire3D_EndFrame Wire3DDMG_EndFrame
#define Wire3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define Wire3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define Wire3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define Wire3D_Face Wire3DDMG_Face
#define Wire3D_Init Wire3DDMG_Init
#define Wire3D_Model Wire3DDMG_Model
#define Wire3D_Object Wire3DDMG_Object
#define Wire3D_ProjectPoint Wire3DDMG_ProjectPoint
#define Wire3D_PutBgTile Wire3DDMG_PutBgTile
#define Wire3D_SelectEdgeMask Wire3DDMG_SelectEdgeMask
#define Wire3D_SetCamera Wire3DDMG_SetCamera
#define Wire3D_SetPalette Wire3DDMG_SetPalette
#define Wire3D_Vec3 Wire3DDMG_Vec3
#define w3d_abs_i16 w3ddmg_abs_i16
#define w3d_bg_map_9800 w3ddmg_bg_map_9800
#define w3d_bgq_addr_hi w3ddmg_bgq_addr_hi
#define w3d_bgq_addr_lo w3ddmg_bgq_addr_lo
#define w3d_bgq_count w3ddmg_bgq_count
#define w3d_bgq_tile w3ddmg_bgq_tile
#define w3d_bgq_value w3ddmg_bgq_value
#define w3d_bgq_x w3ddmg_bgq_x
#define w3d_bgq_y w3ddmg_bgq_y
#define w3d_bit_mask w3ddmg_bit_mask
#define w3d_build_edge_flags w3ddmg_build_edge_flags
#define w3d_build_face_visibility w3ddmg_build_face_visibility
#define w3d_cam_pitch w3ddmg_cam_pitch
#define w3d_cam_roll w3ddmg_cam_roll
#define w3d_cam_x w3ddmg_cam_x
#define w3d_cam_y w3ddmg_cam_y
#define w3d_cam_yaw w3ddmg_cam_yaw
#define w3d_cam_z w3ddmg_cam_z
#define w3d_clamp_i16 w3ddmg_clamp_i16
#define w3d_clamp_screen w3ddmg_clamp_screen
#define w3d_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define w3d_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define w3d_clear_stage_asm w3ddmg_clear_stage_asm
#define w3d_clear_triangle w3ddmg_clear_triangle
#define w3d_clear_vram_asm w3ddmg_clear_vram_asm
#define w3d_cos_q6 w3ddmg_cos_q6
#define w3d_edge_area w3ddmg_edge_area
#define w3d_edge_flags w3ddmg_edge_flags
#define w3d_face_visible w3ddmg_face_visible
#define w3d_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define w3d_flush_bg_queue w3ddmg_flush_bg_queue
#define w3d_hud_tiles w3ddmg_hud_tiles
#define w3d_i16 w3ddmg_i16
#define w3d_i8 w3ddmg_i8
#define w3d_inv_depth w3ddmg_inv_depth
#define w3d_is_edge_visible w3ddmg_is_edge_visible
#define w3d_line_dx w3ddmg_line_dx
#define w3d_line_dy w3ddmg_line_dy
#define w3d_line_err w3ddmg_line_err
#define w3d_line_stage_asm w3ddmg_line_stage_asm
#define w3d_line_stage_masked_c w3ddmg_line_stage_masked_c
#define w3d_line_sx w3ddmg_line_sx
#define w3d_line_sy w3ddmg_line_sy
#define w3d_line_x w3ddmg_line_x
#define w3d_line_x0 w3ddmg_line_x0
#define w3d_line_x1 w3ddmg_line_x1
#define w3d_line_y w3ddmg_line_y
#define w3d_line_y0 w3ddmg_line_y0
#define w3d_line_y1 w3ddmg_line_y1
#define w3d_load_hud_tiles w3ddmg_load_hud_tiles
#define w3d_mark_model_occluder w3ddmg_mark_model_occluder
#define w3d_mark_triangle w3ddmg_mark_triangle
#define w3d_mask_get w3ddmg_mask_get
#define w3d_mask_offset w3ddmg_mask_offset
#define w3d_mask_set w3ddmg_mask_set
#define w3d_mask_set_span w3ddmg_mask_set_span
#define w3d_neg_angle w3ddmg_neg_angle
#define w3d_occlusion_active w3ddmg_occlusion_active
#define w3d_occlusion_mask w3ddmg_occlusion_mask
#define w3d_pair_block w3ddmg_pair_block
#define w3d_pair_wait_0 w3ddmg_pair_wait_0
#define w3d_pair_wait_1 w3ddmg_pair_wait_1
#define w3d_pair_wait_10 w3ddmg_pair_wait_10
#define w3d_pair_wait_11 w3ddmg_pair_wait_11
#define w3d_pair_wait_12 w3ddmg_pair_wait_12
#define w3d_pair_wait_13 w3ddmg_pair_wait_13
#define w3d_pair_wait_14 w3ddmg_pair_wait_14
#define w3d_pair_wait_15 w3ddmg_pair_wait_15
#define w3d_pair_wait_2 w3ddmg_pair_wait_2
#define w3d_pair_wait_3 w3ddmg_pair_wait_3
#define w3d_pair_wait_4 w3ddmg_pair_wait_4
#define w3d_pair_wait_5 w3ddmg_pair_wait_5
#define w3d_pair_wait_6 w3ddmg_pair_wait_6
#define w3d_pair_wait_7 w3ddmg_pair_wait_7
#define w3d_pair_wait_8 w3ddmg_pair_wait_8
#define w3d_pair_wait_9 w3ddmg_pair_wait_9
#define w3d_plot_stage_asm w3ddmg_plot_stage_asm
#define w3d_plot_tx w3ddmg_plot_tx
#define w3d_plot_x w3ddmg_plot_x
#define w3d_plot_y w3ddmg_plot_y
#define w3d_project_camera_space w3ddmg_project_camera_space
#define w3d_project_world w3ddmg_project_world
#define w3d_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define w3d_reg_bgp w3ddmg_reg_bgp
#define w3d_reg_lcdc w3ddmg_reg_lcdc
#define w3d_reg_ly w3ddmg_reg_ly
#define w3d_reg_scx w3ddmg_reg_scx
#define w3d_reg_scy w3ddmg_reg_scy
#define w3d_rotate_x w3ddmg_rotate_x
#define w3d_rotate_y w3ddmg_rotate_y
#define w3d_rotate_z w3ddmg_rotate_z
#define w3d_scene_depth w3ddmg_scene_depth
#define w3d_scene_object_depth w3ddmg_scene_object_depth
#define w3d_scene_order w3ddmg_scene_order
#define w3d_screen_delta w3ddmg_screen_delta
#define w3d_screen_visible w3ddmg_screen_visible
#define w3d_screen_x w3ddmg_screen_x
#define w3d_screen_y w3ddmg_screen_y
#define w3d_sin_q6 w3ddmg_sin_q6
#define w3d_stage w3ddmg_stage
#define w3d_stage_clear_pixel w3ddmg_stage_clear_pixel
#define w3d_stage_clear_span w3ddmg_stage_clear_span
#define w3d_transfer_stage_asm w3ddmg_transfer_stage_asm
#define w3d_u16 w3ddmg_u16
#define w3d_u8 w3ddmg_u8
#define w3d_vram_tiles w3ddmg_vram_tiles
#define w3d_wait_vblank_start w3ddmg_wait_vblank_start
#define w3dbg_enter w3ddmgbg_enter
#define w3dco_enter w3ddmgco_enter
#define w3dco_loop w3ddmgco_loop
#define w3dco_page w3ddmgco_page
#define w3dcs_enter w3ddmgcs_enter
#define w3dcs_inner w3ddmgcs_inner
#define w3dcs_outer w3ddmgcs_outer
#define w3dcv_enter w3ddmgcv_enter
#define w3dcv_loop w3ddmgcv_loop
#define w3dcv_page w3ddmgcv_page
#define w3dfb_enter w3ddmgfb_enter
#define w3dfb_loop w3ddmgfb_loop
#define w3dfb_page w3ddmgfb_page
#define w3dls_branch w3ddmgls_branch
#define w3dls_done w3ddmgls_done
#define w3dls_enter w3ddmgls_enter
#define w3dls_shallow w3ddmgls_shallow
#define w3dls_shallow_loop w3ddmgls_shallow_loop
#define w3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define w3dls_steep w3ddmgls_steep
#define w3dls_steep_loop w3ddmgls_steep_loop
#define w3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define w3dls_x_reverse w3ddmgls_x_reverse
#define w3dls_y_reverse w3ddmgls_y_reverse
#define w3dls_y_start w3ddmgls_y_start
#define w3dps_enter w3ddmgps_enter
#define w3dps_ret w3ddmgps_ret

kitaqgb/lib/wire3d.h

wire3d_cgb.h — Farbige Drahtgitterdarstellung für CGB
c
#pragma once

#ifndef KITAQGB_WIRE3D_CGB_H
#define KITAQGB_WIRE3D_CGB_H

#define WIRE3DCGB_SCREEN_W 128
#ifndef WIRE3DCGB_HEIGHT
#define WIRE3DCGB_HEIGHT 96
#endif
#if WIRE3DCGB_HEIGHT != 88 && WIRE3DCGB_HEIGHT != 96
#error WIRE3DCGB_HEIGHT must be 88 or 96
#endif
#define WIRE3DCGB_SCREEN_H WIRE3DCGB_HEIGHT
#if WIRE3DCGB_HEIGHT == 88
#define WIRE3DCGB_TILE_ROWS 11
#define WIRE3DCGB_TILE_COUNT 176
#define WIRE3DCGB_COLUMN_BYTES 176
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF50
#define WIRE3DCGB_STAGE_RIGHT 0xDD50
#define WIRE3DCGB_STAGE_BOTTOM 0xD3AE
#define WIRE3DCGB_SECOND_DMA 0xAF
#else
#define WIRE3DCGB_TILE_ROWS 12
#define WIRE3DCGB_TILE_COUNT 192
#define WIRE3DCGB_COLUMN_BYTES 192
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF40
#define WIRE3DCGB_STAGE_RIGHT 0xDE40
#define WIRE3DCGB_STAGE_BOTTOM 0xD3BE
#define WIRE3DCGB_SECOND_DMA 0xBF
#endif
// Reserve 3072 bytes in either profile for full-screen compatibility.
#define WIRE3DCGB_UPLOAD_BYTES (WIRE3DCGB_TILE_COUNT * 16)
#define WIRE3DCGB_FULL_SCREEN_W 160
#define WIRE3DCGB_FULL_SCREEN_H 144
#define WIRE3DCGB_FULL_TILE_LIMIT 127
#define WIRE3DCGB_STAGE_BASE 0xD300
#define WIRE3DCGB_STAGE_WRAM_BANK 2
#define WIRE3DCGB_STAGE_BYTES 3072
#define WIRE3DCGB_MODEL_VERTEX_LIMIT 24
#define WIRE3DCGB_MODEL_FACE_LIMIT 16
#define WIRE3DCGB_MODEL_EDGE_LIMIT 64
#define WIRE3DCGB_SCENE_OBJECT_LIMIT 8
#define WIRE3DCGB_FACE_NONE 255
#define WIRE3DCGB_MODEL_HIDDEN_LINES 1
#define WIRE3DCGB_COLOR_LOW 1
#define WIRE3DCGB_COLOR_MAIN 2
#define WIRE3DCGB_COLOR_HIGH 3
#define WIRE3DCGB_COLOR_DEFAULT WIRE3DCGB_COLOR_MAIN

#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))

typedef s8 w3dcgb_i8;
typedef s16 w3dcgb_i16;
typedef u8 w3dcgb_u8;
typedef u16 w3dcgb_u16;

typedef struct {
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
} Wire3DCGB_Vec3;

typedef struct {
    w3dcgb_u8 a;
    w3dcgb_u8 b;
} Wire3DCGB_Edge;

typedef struct {
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
} Wire3DCGB_Face;

typedef struct {
    w3dcgb_u8 f0;
    w3dcgb_u8 f1;
} Wire3DCGB_EdgeFaces;

typedef struct {
    const Wire3DCGB_Vec3* vertices;
    const Wire3DCGB_Edge* edges;
    const Wire3DCGB_Face* faces;
    const Wire3DCGB_EdgeFaces* edge_faces;
    w3dcgb_u8 vertex_count;
    w3dcgb_u8 edge_count;
    w3dcgb_u8 face_count;
    w3dcgb_u8 flags;
} Wire3DCGB_Model;

typedef struct {
    const Wire3DCGB_Model* model;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
    w3dcgb_i8 rx;
    w3dcgb_i8 ry;
    w3dcgb_i8 rz;
    w3dcgb_i16 scale_q8;
    w3dcgb_u8 visible;
    w3dcgb_u8 color;
} Wire3DCGB_Object;

typedef struct {
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
    w3dcgb_i8 rx;
    w3dcgb_i8 ry;
    w3dcgb_i8 rz;
    w3dcgb_u8 color;
} Wire3DCGB_FastCube;

void Wire3DCGB_Init();
void Wire3DCGB_InitFullScreen();
void Wire3DCGB_InitFastMapLite();
void Wire3DCGB_EnableDoubleSpeed();
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);
void Wire3DCGB_SetLineColor(w3dcgb_u8 color);
w3dcgb_u8 Wire3DCGB_GetLineColor();
void Wire3DCGB_ClearFrameTiles();
void Wire3DCGB_BeginFrame();
void Wire3DCGB_BeginFrameFast();
void Wire3DCGB_BeginFrameSparse();
void Wire3DCGB_ClearSparseStageFast();
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);
/* Signed endpoints, clipped before conversion to the rasterizer's u8 ABI. */
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
                               w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
    const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
    w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);
void Wire3DCGB_InvalidateFrameHistory();
/* Startup-only: reserves both BG maps; queued HUD tiles are mirrored. */
void Wire3DCGB_EnableAtomicMaps();
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);
void Wire3DCGB_EraseLeftGuard24Fast();
void Wire3DCGB_DrawWhiteBorderFast();
void Wire3DCGB_ClearOcclusionMask();
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                     w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                      w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);
void Wire3DCGB_FastMapBegin();
void Wire3DCGB_FastMapBeginTilesOnly();
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);
void Wire3DCGB_FastMapFlush();
void Wire3DCGB_FastMapFlushTilesOnly();
// Project camera-space coordinates without subtracting/rotating the camera.
// Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
/* Fast path for games whose camera pitch, yaw, and roll stay at zero. */
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
                               w3dcgb_u8 turn, w3dcgb_u8 color);
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
                                 const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                                 const w3dcgb_u8* edge_mask,
                                 w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
                              const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                              w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
                                  w3dcgb_u8 line_count, w3dcgb_u8 color);
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);
void Wire3DCGB_EndFrame();
void Wire3DCGB_EndFrameFast();
void Wire3DCGB_EndFrameSparse();
void Wire3DCGB_EndFrameSparseNow();
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount();
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow();

#endif

kitaqgb/lib/wire3d_cgb.h

wire3d_dmg.h — Drahtgitterdarstellung für DMG
c
#pragma once

// Select the viewport at build time before including this header or source.
// Default: 128x120 with consuming uploads and optional dirty/auxiliary transfer.
// Heights 88 and 96 retain the HUD and yaw-mask profile with BeginFrame clearing.
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 88 && WIRE3D_DMG_HEIGHT != 96 && WIRE3D_DMG_HEIGHT != 120
#error WIRE3D_DMG_HEIGHT must be 88, 96 or 120
#endif


#ifndef KITAQGB_WIRE3D_DMG_H
#define KITAQGB_WIRE3D_DMG_H

#if WIRE3D_DMG_HEIGHT != 120
// Monochrome 128x88/96 wireframe renderer with global, non-reentrant state.
// It takes over LCD tile data/map and reserves WRAM 0xD000..0xDFFF for staging.
// Angles wrap every 16 steps; scale 256 is unity. Scene occlusion is a coarse
// face-bounding-box/five-line-sample heuristic, not per-pixel depth testing.
#else
// Monochrome 128x120 staged renderer with global non-reentrant state.
// Reserve WRAM 0xD000..0xDFFF and the renderer's tile/map VRAM regions.
// BeginFrame does not clear pixels: uploads consume the stage. Auxiliary source
// strips alias the main stage, and dirty transfer relies on current/previous flags.
#endif
#define WIRE3D_DMG_SCREEN_W 128
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_SCREEN_H WIRE3D_DMG_HEIGHT
#else
#define WIRE3D_DMG_SCREEN_H 120
#endif
#define WIRE3D_DMG_MODEL_VERTEX_LIMIT 24
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_MODEL_EDGE_LIMIT 16
#endif
#define WIRE3D_DMG_MODEL_FACE_LIMIT 16
#define WIRE3D_DMG_SCENE_OBJECT_LIMIT 8
#define WIRE3D_DMG_FACE_NONE 255
#define WIRE3D_DMG_MODEL_HIDDEN_LINES 1
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_EDGE_MASK_BINS_16 16
#else
#define WIRE3D_DMG_ANGLE_STEPS 16
#endif

typedef s8 w3ddmg_i8;
typedef s16 w3ddmg_i16;
typedef u8 w3ddmg_u8;
typedef u16 w3ddmg_u16;

typedef struct {
    w3ddmg_i16 x;
    w3ddmg_i16 y;
    w3ddmg_i16 z;
} Wire3DDMG_Vec3;

typedef struct {
    w3ddmg_u8 a;
    w3ddmg_u8 b;
} Wire3DDMG_Edge;

typedef struct {
    w3ddmg_u8 a;
    w3ddmg_u8 b;
    w3ddmg_u8 c;
} Wire3DDMG_Face;

typedef struct {
    w3ddmg_u8 f0;
    w3ddmg_u8 f1;
} Wire3DDMG_EdgeFaces;

#if WIRE3D_DMG_HEIGHT != 120
// Model tables are borrowed for drawing, never copied or bank-switched.
// Counts are capped at 24 vertices, 16 edges and 16 faces; each supplied table
// must contain the referenced entries. Triangle winding with positive projected
// area is front-facing. FACE_NONE denotes a missing adjacent face.
#else
// Model tables are borrowed and must remain readable in the active bank.
// At most 24 vertices and 16 faces are processed; the model edge count is not
// limited to 16. Supply all declared edge and adjacency entries. Positive
// projected triangle area is front-facing; FACE_NONE means missing adjacency.
#endif
typedef struct {
    const Wire3DDMG_Vec3* vertices;
    const Wire3DDMG_Edge* edges;
    const Wire3DDMG_Face* faces;
    const Wire3DDMG_EdgeFaces* edge_faces;
#if WIRE3D_DMG_HEIGHT != 120
    /* Keep edge mask tables in RAM for pointer-indirect access on current KITAQGB. */
    const w3ddmg_u16* edge_masks;
#endif
    w3ddmg_u8 vertex_count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;
#if WIRE3D_DMG_HEIGHT != 120
    w3ddmg_u8 edge_mask_count;
#endif
    w3ddmg_u8 flags;
} Wire3DDMG_Model;

typedef struct {
    const Wire3DDMG_Model* model;
    w3ddmg_i16 x;
    w3ddmg_i16 y;
    w3ddmg_i16 z;
#if WIRE3D_DMG_HEIGHT != 120
    w3ddmg_i8 rx;
    w3ddmg_i8 ry;
    w3ddmg_i8 rz;
#else
    w3ddmg_u8 rx;
    w3ddmg_u8 ry;
    w3ddmg_u8 rz;
#endif
    w3ddmg_i16 scale_q8;
    w3ddmg_u8 visible;
} Wire3DDMG_Object;

#if WIRE3D_DMG_HEIGHT != 120
// Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and
// the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable
// BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage.
// Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping.
// Call BeginFrame before drawing to initialize the occlusion state as well.
#else
// Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
// viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
// Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
// 0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
// Call BeginFrame before drawing to establish occlusion state.
#endif
void Wire3DDMG_Init();
#if WIRE3D_DMG_HEIGHT != 120
// Clear staged pixels and occlusion mask and disable occlusion filtering.
// This leaves the displayed VRAM frame and pending BG tile queue unchanged.
#else
// Disable occlusion filtering only. Stage clearing normally happens during
// transfer, and Init supplies the first clean stage. This does not discard an
// unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.
#endif
void Wire3DDMG_BeginFrame();
/* Validate depth and project coordinates already in camera space. */
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);
// Store camera position and angles for later draws; a full turn is 16 angle
// steps. No existing drawing is reprojected and no input range validation occurs.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);
#else
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);
#endif
// Draw an unscaled model by delegating to DrawModelScaled with scale 256.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Scale, rotate in Y/X/Z order, translate and project at most 24 vertices;
// then draw up to 16 edges filtered by yaw masks and optional front-facing faces.
// Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are
// ignored; referenced tables must remain readable. Keep scale products and
// translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
// Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
// all edge_count entries (a byte count) with optional adjacent-face filtering.
// Face scratch is capped at 16; edge tables must contain all declared entries.
// Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
// Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Project up to 24 vertices and erase front-facing triangle interiors from
// the stage for a model with hidden-line flags and face data. Nonpositive scale
// means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
// skipped. This also replaces shared projection caches, but does not update VRAM.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Erase a triangle from staged pixels using integer scanline intersections.
// Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
// mask and VRAM are unchanged.
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);
// Order the X endpoints and erase the inclusive staged span. Both endpoints
// must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);
#if WIRE3D_DMG_HEIGHT != 120
// Process at most the first eight objects, sorted near to far by transformed
// origin depth. Draw visible valid models, then mark their front-face bounding
// rectangles to reject fully sampled later lines. This approximates inter-object
// occlusion, not a depth buffer. It clears its mask but retains existing staged
// pixels. Null arrays are ignored; objects and their data must remain readable.
#else
// Sort at most eight object origins by camera depth, near to far. Draw visible
// valid models and mark front-face bounding rectangles for later objects. The
// first sorted slot bypasses mask tests and the last needs no new occluder.
// This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
// caller data and the current projection cache must remain valid during traversal.
#endif
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);
#if WIRE3D_DMG_HEIGHT != 120
// Select a precomputed mask from the low four bits of object yaw; pitch,
// roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
// counts select entry zero (counts >=16 use the first 16). Missing data returns
// 0xFFFF. Keep the mask table readable through the current data-pointer mapping.
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Project a world point with the current camera. Return zero for rejected
// depth, leaving outputs unchanged; success writes clamped coordinates for the selected height.
// Output pointers must be valid. Screen clamping is not geometric clipping.
#else
// Project a world point with the current camera. Return zero for invalid
// depth without changing outputs; success writes clamped 128x120 coordinates.
// Both output pointers must be valid. Coordinate differences must fit s16.
#endif
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Rotate in place in Y/X/Z order using 16 steps per full turn. A null
// component pointer makes the whole call a no-op; use distinct pointers.
// Each axis rotation clamps its inputs to +/-220.
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
#endif
// Project both world endpoints and draw only when both pass the depth range.
// Do not intersect a crossing segment with near/far planes; projected endpoints
// are independently clamped to the screen edges.
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);
#if WIRE3D_DMG_HEIGHT != 120
// Draw a connected line into the 128x96 stage, including endpoints. During
// DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly.
// Supply viewport coordinates. VRAM is updated only by EndFrame.
#else
// Mark the bounding tile rectangle when dirty transfer is enabled, then draw
// a connected staged line. Scene drawing may reject it using five mask samples.
// Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
// the segment geometrically.
#endif
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);
#if WIRE3D_DMG_HEIGHT == 120
// Draw a wireframe rectangle directly into the staged bitplane. Endpoints are
// inclusive screen pixels in 0..127 x 0..119; both horizontal and vertical
// edges are written with byte masks and only touched tiles are uploaded.
void Wire3DDMG_DrawRect2D(w3ddmg_u8 x0, w3ddmg_u8 y0, w3ddmg_u8 x1, w3ddmg_u8 y1);
#endif
// Draw the canonical 12 edges of an 8-vertex projected box in one call.
// Vertex order is near-face corners 0..3, then far-face corners 4..7.
void Wire3DDMG_DrawBoxEdges2D(const w3ddmg_u8* sx, const w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Draw byte-pair edge indices after integer scaling and translation; scale
// zero means one, and there is no object rotation or face filtering. Project at
// most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
// after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
// are ignored. Keep coordinate products/sums representable as s16.
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);
#endif
// Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
// coordinates and submissions beyond 48 pending writes are silently ignored.
// This queue is separate from the general vram library queue.
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);
// Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);
#if WIRE3D_DMG_HEIGHT != 120
// Wait for the next VBlank, flush pending BG map writes, then copy the stage
// to VRAM while polling access windows. Copying consumes the staged pixels.
// The transfer may extend beyond VBlank; this is not an atomic frame swap.
#else
// Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
// No data is copied or cleared here. Auxiliary source bytes alias the main stage.
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);
// Store the dirty-transfer gate and clear both dirty histories and the main
// stage, even if the value is unchanged. VRAM is retained; enabling this over an
// old image can leave unmarked old tiles, so arrange a clean displayed baseline.
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);
// Upload and consume the full main stage immediately, polling STAT but not
// waiting for the next VBlank. Ignore transfer gates and leave dirty histories
// and BG tile queue unchanged; the caller coordinates the frame lifecycle.
void Wire3DDMG_TransferMainNow();
// Upload and consume auxiliary source strips immediately, independent of the
// auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
// The source overlaps the main stage and must be coordinated with its upload.
void Wire3DDMG_TransferAuxNow();
// Wait for the next VBlank and flush BG writes, then optionally consume the
// auxiliary strips before uploading either dirty tiles or the entire main stage.
// Auxiliary/main source overlap makes that ordering significant. STAT polling
// continues across access windows; the update need not fit one VBlank.
#endif
void Wire3DDMG_EndFrame();
// Same queue/gate/history lifecycle, without the initial fresh-VBlank wait.
// Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.
void Wire3DDMG_EndFrameNow();

#endif
#if WIRE3D_DMG_HEIGHT == 120

#endif

kitaqgb/lib/wire3d_dmg.h

zx0.h —
c
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.
// ZX0-compatible forward v2 streams; format designed by Einar Saukas.
#define ZX0_OK 0
#define ZX0_BAD_ARGUMENT 1
#define ZX0_TRUNCATED 2
#define ZX0_BAD_STREAM 3
#define ZX0_OUTPUT_FULL 4
#define ZX0_DISPLAY_ACTIVE 5
// Shared last-call status. These foreground routines are not reentrant.
extern u8 zx0_error;
// Return decoded bytes, or zero on error (possibly after partial writes).
// Source and output must not overlap or cross their current CPU bank windows.
// Capacity and packed_size are byte counts. No prefix/backward/v1 streams.
u16 zx0_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto.
// Empty raw assets return zero with zx0_error==ZX0_OK.
u16 asset_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off.
// Preserve LCDC, VBK and interrupt state. Output must fit before $A000.
u16 zx0_decompress_vram(u16 vram_addr, const void* src, u16 packed_size);

kitaqgb/lib/zx0.h